agent-enderun 1.1.10 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. package/README.md +294 -19
  2. package/bin/cli.js +7 -0
  3. package/bin/enderun-dashboard.js +16 -857
  4. package/bin/validate-agent-army.js +12 -12
  5. package/dist/framework-mcp/src/index.js +14 -2
  6. package/dist/framework-mcp/src/index.js.map +1 -1
  7. package/dist/framework-mcp/src/tools/file_system/batch_surgical_edit.js +2 -1
  8. package/dist/framework-mcp/src/tools/file_system/batch_surgical_edit.js.map +1 -1
  9. package/dist/framework-mcp/src/tools/file_system/replace_text.js +2 -1
  10. package/dist/framework-mcp/src/tools/file_system/replace_text.js.map +1 -1
  11. package/dist/framework-mcp/src/tools/file_system/write_file.js +3 -3
  12. package/dist/framework-mcp/src/tools/file_system/write_file.js.map +1 -1
  13. package/dist/framework-mcp/src/utils/fs.d.ts +16 -0
  14. package/dist/framework-mcp/src/utils/fs.js +45 -0
  15. package/dist/framework-mcp/src/utils/fs.js.map +1 -0
  16. package/dist/framework-mcp/src/utils/metrics.js.map +1 -1
  17. package/dist/src/cli/adapters/core.js.map +1 -1
  18. package/dist/src/cli/adapters/scaffold.js +4 -3
  19. package/dist/src/cli/adapters/scaffold.js.map +1 -1
  20. package/dist/src/cli/commands/app.js +20 -5
  21. package/dist/src/cli/commands/app.js.map +1 -1
  22. package/dist/src/cli/commands/approve.d.ts +1 -1
  23. package/dist/src/cli/commands/approve.js +7 -7
  24. package/dist/src/cli/commands/approve.js.map +1 -1
  25. package/dist/src/cli/commands/check.d.ts +1 -1
  26. package/dist/src/cli/commands/check.js +35 -4
  27. package/dist/src/cli/commands/check.js.map +1 -1
  28. package/dist/src/cli/commands/compliance.d.ts +1 -1
  29. package/dist/src/cli/commands/compliance.js +1 -1
  30. package/dist/src/cli/commands/compliance.js.map +1 -1
  31. package/dist/src/cli/commands/contract.d.ts +2 -2
  32. package/dist/src/cli/commands/contract.js +8 -14
  33. package/dist/src/cli/commands/contract.js.map +1 -1
  34. package/dist/src/cli/commands/dashboard/data-service.d.ts +33 -0
  35. package/dist/src/cli/commands/dashboard/data-service.js +120 -0
  36. package/dist/src/cli/commands/dashboard/data-service.js.map +1 -0
  37. package/dist/src/cli/commands/dashboard/html-template.d.ts +4 -0
  38. package/dist/src/cli/commands/dashboard/html-template.js +697 -0
  39. package/dist/src/cli/commands/dashboard/html-template.js.map +1 -0
  40. package/dist/src/cli/commands/dashboard/server.d.ts +2 -0
  41. package/dist/src/cli/commands/dashboard/server.js +38 -0
  42. package/dist/src/cli/commands/dashboard/server.js.map +1 -0
  43. package/dist/src/cli/commands/dashboard.d.ts +4 -0
  44. package/dist/src/cli/commands/dashboard.js +10 -0
  45. package/dist/src/cli/commands/dashboard.js.map +1 -0
  46. package/dist/src/cli/commands/explorer.d.ts +2 -2
  47. package/dist/src/cli/commands/explorer.js +2 -2
  48. package/dist/src/cli/commands/explorer.js.map +1 -1
  49. package/dist/src/cli/commands/git.d.ts +2 -2
  50. package/dist/src/cli/commands/git.js +2 -2
  51. package/dist/src/cli/commands/git.js.map +1 -1
  52. package/dist/src/cli/commands/init/scaffold-core.d.ts +4 -0
  53. package/dist/src/cli/commands/init/scaffold-core.js +65 -0
  54. package/dist/src/cli/commands/init/scaffold-core.js.map +1 -0
  55. package/dist/src/cli/commands/init/scaffold-ops.d.ts +1 -0
  56. package/dist/src/cli/commands/init/scaffold-ops.js +83 -0
  57. package/dist/src/cli/commands/init/scaffold-ops.js.map +1 -0
  58. package/dist/src/cli/commands/init/scaffold-standards.d.ts +2 -0
  59. package/dist/src/cli/commands/init/scaffold-standards.js +58 -0
  60. package/dist/src/cli/commands/init/scaffold-standards.js.map +1 -0
  61. package/dist/src/cli/commands/init.js +14 -275
  62. package/dist/src/cli/commands/init.js.map +1 -1
  63. package/dist/src/cli/commands/knowledge.d.ts +2 -2
  64. package/dist/src/cli/commands/knowledge.js +4 -3
  65. package/dist/src/cli/commands/knowledge.js.map +1 -1
  66. package/dist/src/cli/commands/lint.d.ts +1 -1
  67. package/dist/src/cli/commands/lint.js +2 -3
  68. package/dist/src/cli/commands/lint.js.map +1 -1
  69. package/dist/src/cli/commands/log.d.ts +1 -1
  70. package/dist/src/cli/commands/log.js +3 -2
  71. package/dist/src/cli/commands/log.js.map +1 -1
  72. package/dist/src/cli/commands/memory.d.ts +1 -1
  73. package/dist/src/cli/commands/memory.js +1 -1
  74. package/dist/src/cli/commands/memory.js.map +1 -1
  75. package/dist/src/cli/commands/orchestrate.js +169 -140
  76. package/dist/src/cli/commands/orchestrate.js.map +1 -1
  77. package/dist/src/cli/commands/plan.d.ts +1 -1
  78. package/dist/src/cli/commands/plan.js +1 -1
  79. package/dist/src/cli/commands/plan.js.map +1 -1
  80. package/dist/src/cli/commands/script.d.ts +1 -1
  81. package/dist/src/cli/commands/script.js +1 -1
  82. package/dist/src/cli/commands/script.js.map +1 -1
  83. package/dist/src/cli/commands/security.d.ts +1 -1
  84. package/dist/src/cli/commands/security.js +1 -1
  85. package/dist/src/cli/commands/security.js.map +1 -1
  86. package/dist/src/cli/commands/status.d.ts +1 -1
  87. package/dist/src/cli/commands/status.js +1 -1
  88. package/dist/src/cli/commands/status.js.map +1 -1
  89. package/dist/src/cli/commands/trace.d.ts +1 -1
  90. package/dist/src/cli/commands/trace.js +1 -1
  91. package/dist/src/cli/commands/trace.js.map +1 -1
  92. package/dist/src/cli/index.js +36 -21
  93. package/dist/src/cli/index.js.map +1 -1
  94. package/dist/src/cli/shims.js +6 -6
  95. package/dist/src/cli/utils/app-backend.js +7 -0
  96. package/dist/src/cli/utils/app-backend.js.map +1 -1
  97. package/dist/src/cli/utils/app-docs.js +23 -5
  98. package/dist/src/cli/utils/app-docs.js.map +1 -1
  99. package/dist/src/cli/utils/app-frontend.js +5 -0
  100. package/dist/src/cli/utils/app-frontend.js.map +1 -1
  101. package/dist/src/cli/utils/app-inferrer.d.ts +1 -0
  102. package/dist/src/cli/utils/app-inferrer.js +12 -1
  103. package/dist/src/cli/utils/app-inferrer.js.map +1 -1
  104. package/dist/src/cli/utils/app-mobile.d.ts +2 -0
  105. package/dist/src/cli/utils/app-mobile.js +106 -0
  106. package/dist/src/cli/utils/app-mobile.js.map +1 -0
  107. package/dist/src/cli/utils/app-types.js +8 -4
  108. package/dist/src/cli/utils/app-types.js.map +1 -1
  109. package/dist/src/cli/utils/app.d.ts +1 -0
  110. package/dist/src/cli/utils/app.js +1 -0
  111. package/dist/src/cli/utils/app.js.map +1 -1
  112. package/dist/src/cli/utils/claude.js +2 -1
  113. package/dist/src/cli/utils/claude.js.map +1 -1
  114. package/dist/src/cli/utils/compliance.js +37 -6
  115. package/dist/src/cli/utils/compliance.js.map +1 -1
  116. package/dist/src/cli/utils/config-schema.d.ts +3 -3
  117. package/dist/src/cli/utils/config-schema.js +3 -3
  118. package/dist/src/cli/utils/config-schema.js.map +1 -1
  119. package/dist/src/cli/utils/fs.d.ts +2 -2
  120. package/dist/src/cli/utils/fs.js +9 -13
  121. package/dist/src/cli/utils/fs.js.map +1 -1
  122. package/dist/src/cli/utils/memory.d.ts +9 -2
  123. package/dist/src/cli/utils/memory.js +87 -16
  124. package/dist/src/cli/utils/memory.js.map +1 -1
  125. package/dist/src/cli/utils/pkg.js +14 -13
  126. package/dist/src/cli/utils/pkg.js.map +1 -1
  127. package/dist/src/cli/utils/string.js +1 -1
  128. package/dist/src/cli/utils/string.js.map +1 -1
  129. package/dist/src/cli/utils/ui.d.ts +1 -1
  130. package/dist/src/cli/utils/ui.js +1 -1
  131. package/dist/src/modules/adapters/shared.js +7 -7
  132. package/dist/src/modules/adapters/shared.js.map +1 -1
  133. package/dist/src/modules/agents/definitions.d.ts +3 -34
  134. package/dist/src/modules/agents/definitions.js +35 -511
  135. package/dist/src/modules/agents/definitions.js.map +1 -1
  136. package/dist/src/modules/agents/registry/analyst.d.ts +2 -0
  137. package/dist/src/modules/agents/registry/analyst.js +36 -0
  138. package/dist/src/modules/agents/registry/analyst.js.map +1 -0
  139. package/dist/src/modules/agents/registry/architect.d.ts +2 -0
  140. package/dist/src/modules/agents/registry/architect.js +42 -0
  141. package/dist/src/modules/agents/registry/architect.js.map +1 -0
  142. package/dist/src/modules/agents/registry/backend.d.ts +2 -0
  143. package/dist/src/modules/agents/registry/backend.js +43 -0
  144. package/dist/src/modules/agents/registry/backend.js.map +1 -0
  145. package/dist/src/modules/agents/registry/database.d.ts +2 -0
  146. package/dist/src/modules/agents/registry/database.js +38 -0
  147. package/dist/src/modules/agents/registry/database.js.map +1 -0
  148. package/dist/src/modules/agents/registry/devops.d.ts +2 -0
  149. package/dist/src/modules/agents/registry/devops.js +38 -0
  150. package/dist/src/modules/agents/registry/devops.js.map +1 -0
  151. package/dist/src/modules/agents/registry/explorer.d.ts +2 -0
  152. package/dist/src/modules/agents/registry/explorer.js +36 -0
  153. package/dist/src/modules/agents/registry/explorer.js.map +1 -0
  154. package/dist/src/modules/agents/registry/frontend.d.ts +2 -0
  155. package/dist/src/modules/agents/registry/frontend.js +44 -0
  156. package/dist/src/modules/agents/registry/frontend.js.map +1 -0
  157. package/dist/src/modules/agents/registry/git.d.ts +2 -0
  158. package/dist/src/modules/agents/registry/git.js +35 -0
  159. package/dist/src/modules/agents/registry/git.js.map +1 -0
  160. package/dist/src/modules/agents/registry/manager.d.ts +2 -0
  161. package/dist/src/modules/agents/registry/manager.js +49 -0
  162. package/dist/src/modules/agents/registry/manager.js.map +1 -0
  163. package/dist/src/modules/agents/registry/mobile.d.ts +2 -0
  164. package/dist/src/modules/agents/registry/mobile.js +40 -0
  165. package/dist/src/modules/agents/registry/mobile.js.map +1 -0
  166. package/dist/src/modules/agents/registry/native.d.ts +2 -0
  167. package/dist/src/modules/agents/registry/native.js +36 -0
  168. package/dist/src/modules/agents/registry/native.js.map +1 -0
  169. package/dist/src/modules/agents/registry/quality.d.ts +2 -0
  170. package/dist/src/modules/agents/registry/quality.js +41 -0
  171. package/dist/src/modules/agents/registry/quality.js.map +1 -0
  172. package/dist/src/modules/agents/registry/security.d.ts +2 -0
  173. package/dist/src/modules/agents/registry/security.js +37 -0
  174. package/dist/src/modules/agents/registry/security.js.map +1 -0
  175. package/dist/src/modules/agents/types.d.ts +31 -0
  176. package/dist/src/modules/agents/types.js +2 -0
  177. package/dist/src/modules/agents/types.js.map +1 -0
  178. package/dist/src/modules/skills/definitions.d.ts +1 -1
  179. package/dist/src/modules/skills/definitions.js +1 -1
  180. package/dist/src/shared/errors.d.ts +8 -6
  181. package/dist/src/shared/errors.js +13 -10
  182. package/dist/src/shared/errors.js.map +1 -1
  183. package/dist/src/shared/fs.d.ts +4 -0
  184. package/dist/src/shared/fs.js +17 -2
  185. package/dist/src/shared/fs.js.map +1 -1
  186. package/dist/src/shared/types.d.ts +19 -0
  187. package/dist/src/shared/types.js +13 -0
  188. package/dist/src/shared/types.js.map +1 -0
  189. package/package.json +3 -5
  190. package/src/cli/adapters/core.ts +0 -1
  191. package/src/cli/adapters/scaffold.ts +4 -3
  192. package/src/cli/commands/app.ts +23 -5
  193. package/src/cli/commands/approve.ts +15 -7
  194. package/src/cli/commands/check.ts +38 -5
  195. package/src/cli/commands/compliance.ts +1 -1
  196. package/src/cli/commands/contract.ts +20 -14
  197. package/src/cli/commands/dashboard/data-service.ts +119 -0
  198. package/src/cli/commands/dashboard/html-template.ts +696 -0
  199. package/src/cli/commands/dashboard/server.ts +43 -0
  200. package/src/cli/commands/dashboard.ts +11 -0
  201. package/src/cli/commands/explorer.ts +2 -2
  202. package/src/cli/commands/git.ts +2 -2
  203. package/src/cli/commands/init/scaffold-core.ts +71 -0
  204. package/src/cli/commands/init/scaffold-ops.ts +86 -0
  205. package/src/cli/commands/init/scaffold-standards.ts +59 -0
  206. package/src/cli/commands/init.ts +21 -292
  207. package/src/cli/commands/knowledge.ts +5 -3
  208. package/src/cli/commands/lint.ts +2 -4
  209. package/src/cli/commands/log.ts +4 -2
  210. package/src/cli/commands/memory.ts +1 -1
  211. package/src/cli/commands/orchestrate.ts +177 -142
  212. package/src/cli/commands/plan.ts +1 -1
  213. package/src/cli/commands/script.ts +1 -1
  214. package/src/cli/commands/security.ts +1 -1
  215. package/src/cli/commands/status.ts +1 -1
  216. package/src/cli/commands/trace.ts +1 -1
  217. package/src/cli/index.ts +37 -21
  218. package/src/cli/shims.ts +6 -6
  219. package/src/cli/utils/app-backend.ts +8 -0
  220. package/src/cli/utils/app-docs.ts +23 -5
  221. package/src/cli/utils/app-frontend.ts +6 -0
  222. package/src/cli/utils/app-inferrer.ts +11 -1
  223. package/src/cli/utils/app-mobile.ts +113 -0
  224. package/src/cli/utils/app-types.ts +9 -4
  225. package/src/cli/utils/app.ts +1 -0
  226. package/src/cli/utils/claude.ts +2 -1
  227. package/src/cli/utils/compliance.ts +38 -7
  228. package/src/cli/utils/config-schema.ts +4 -4
  229. package/src/cli/utils/fs.ts +9 -14
  230. package/src/cli/utils/memory.ts +103 -20
  231. package/src/cli/utils/pkg.ts +14 -13
  232. package/src/cli/utils/string.ts +1 -1
  233. package/src/cli/utils/ui.ts +1 -1
  234. package/src/modules/adapters/shared.ts +7 -7
  235. package/src/modules/agents/definitions.ts +39 -598
  236. package/src/modules/agents/registry/analyst.ts +40 -0
  237. package/src/modules/agents/registry/architect.ts +46 -0
  238. package/src/modules/agents/registry/backend.ts +47 -0
  239. package/src/modules/agents/registry/database.ts +42 -0
  240. package/src/modules/agents/registry/devops.ts +42 -0
  241. package/src/modules/agents/registry/explorer.ts +40 -0
  242. package/src/modules/agents/registry/frontend.ts +48 -0
  243. package/src/modules/agents/registry/git.ts +39 -0
  244. package/src/modules/agents/registry/manager.ts +53 -0
  245. package/src/modules/agents/registry/mobile.ts +44 -0
  246. package/src/modules/agents/registry/native.ts +40 -0
  247. package/src/modules/agents/registry/quality.ts +45 -0
  248. package/src/modules/agents/registry/security.ts +41 -0
  249. package/src/modules/agents/types.ts +37 -0
  250. package/src/modules/skills/definitions.ts +1 -1
  251. package/src/shared/errors.ts +13 -10
  252. package/src/shared/fs.ts +17 -2
  253. package/src/shared/types.ts +20 -0
  254. package/bin/utils/docgen.ts +0 -24
package/src/cli/shims.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export const SHIM_TEMPLATES: Record<string, string> = {
2
- gemini: `# 🎖️ Enderun Core — GEMINI Strategy
2
+ gemini: `# 🎖️ Agent Enderun — GEMINI Strategy
3
3
 
4
4
  You are the **Gemini Commander** (Strategic Decision Center).
5
5
 
@@ -8,7 +8,7 @@ You are the **Gemini Commander** (Strategic Decision Center).
8
8
  - **State Persistence:** Read \`{{FRAMEWORK_DIR}}/memory/PROJECT_MEMORY.md\` to restore session memory.
9
9
  - **Zero-Request Logging:** Write logs to \`{{FRAMEWORK_DIR}}/logs/\` at the end of every turn.
10
10
  `,
11
- "antigravity-cli": `# 🎖️ Enderun Core — ANTIGRAVITY-CLI Strategy
11
+ "antigravity-cli": `# 🎖️ Agent Enderun — ANTIGRAVITY-CLI Strategy
12
12
 
13
13
  You are the **Antigravity Specialist** (Preserve Coding Standards).
14
14
 
@@ -17,7 +17,7 @@ You are the **Antigravity Specialist** (Preserve Coding Standards).
17
17
  - **State Persistence:** Read \`{{FRAMEWORK_DIR}}/memory/PROJECT_MEMORY.md\` to restore session memory.
18
18
  - **Standard Check:** Run health checks regularly to preserve framework integrity.
19
19
  `,
20
- claude: `# 🎖️ Enderun Core — CLAUDE Strategy
20
+ claude: `# 🎖️ Agent Enderun — CLAUDE Strategy
21
21
 
22
22
  You are the **Claude Field Engineer** (Surgical Operations).
23
23
 
@@ -26,7 +26,7 @@ You are the **Claude Field Engineer** (Surgical Operations).
26
26
  - **State Persistence:** Read \`{{FRAMEWORK_DIR}}/memory/PROJECT_MEMORY.md\` to restore session memory.
27
27
  - **Surgical Precision:** Do not rewrite files. Execute surgical edits.
28
28
  `,
29
- grok: `# 🎖️ Enderun Core — GROK Strategy
29
+ grok: `# 🎖️ Agent Enderun — GROK Strategy
30
30
 
31
31
  You are the **Grok Explorer** (Experimental Protocols).
32
32
 
@@ -34,7 +34,7 @@ You are the **Grok Explorer** (Experimental Protocols).
34
34
  - **Constitutional Supremacy:** Read \`{{FRAMEWORK_DIR}}/ENDERUN.md\` first.
35
35
  - **State Persistence:** Read \`{{FRAMEWORK_DIR}}/memory/PROJECT_MEMORY.md\` to restore session memory.
36
36
  `,
37
- cursor: `# 🎖️ Enderun Core — CURSOR Strategy
37
+ cursor: `# 🎖️ Agent Enderun — CURSOR Strategy
38
38
 
39
39
  You are the **Cursor Implementer** (IDE Integration).
40
40
 
@@ -42,7 +42,7 @@ You are the **Cursor Implementer** (IDE Integration).
42
42
  - **Constitutional Supremacy:** Read \`{{FRAMEWORK_DIR}}/ENDERUN.md\` first.
43
43
  - **State Persistence:** Read \`{{FRAMEWORK_DIR}}/memory/PROJECT_MEMORY.md\` to restore session memory.
44
44
  `,
45
- codex: `# 🎖️ Enderun Core — COPILOT Strategy
45
+ codex: `# 🎖️ Agent Enderun — COPILOT Strategy
46
46
 
47
47
  You are the **Copilot Implementer** (GitHub Copilot Integration).
48
48
 
@@ -235,6 +235,14 @@ export function createBackendFiles(spec: AppSpec): void {
235
235
  "await app.listen({ port, host: \"0.0.0.0\" });",
236
236
  ].join("\n"));
237
237
 
238
+ writeTextFile(path.join(targetDir, backendDir, ".env.example"), [
239
+ "# Agent Enderun - Backend Environment Variables",
240
+ "PORT=4000",
241
+ "NODE_ENV=development",
242
+ "DATABASE_URL=sqlite://./dev.db",
243
+ "JWT_SECRET=your_secret_key_here",
244
+ ].join("\n"));
245
+
238
246
  writeTextFile(path.join(targetDir, backendDir, "README.md"), [
239
247
  `# ${spec.title} Backend`,
240
248
  "",
@@ -12,6 +12,18 @@ export function updateProjectDocs(spec: AppSpec): void {
12
12
  const apiDir = path.join(docsDir, "api");
13
13
  ensureDir(apiDir);
14
14
 
15
+ const architecture = [];
16
+ if (spec.platform === "full-stack" || spec.platform === "backend") {
17
+ architecture.push(`- \`${pathsMap.backend}\`: Fastify API`);
18
+ architecture.push(`- \`${pathsMap.backend}/src/types\`: Contract-first backend TypeScript types`);
19
+ }
20
+ if (spec.platform === "full-stack" || spec.platform === "web") {
21
+ architecture.push(`- \`${pathsMap.frontend}\`: React dashboard`);
22
+ }
23
+ if (spec.platform === "mobile") {
24
+ architecture.push(`- \`${pathsMap.mobile || "apps/mobile"}\`: Expo / React Native App`);
25
+ }
26
+
15
27
  writeTextFile(path.join(docsDir, "project-docs.md"), [
16
28
  `# ${spec.title} Requirements`,
17
29
  "",
@@ -21,6 +33,7 @@ export function updateProjectDocs(spec: AppSpec): void {
21
33
  "",
22
34
  "## Generated Scope",
23
35
  "",
36
+ `- Platform: ${spec.platform}`,
24
37
  `- Domain: ${spec.domain}`,
25
38
  `- Auth: ${spec.modules.auth ? "yes" : "no"}`,
26
39
  `- Users: ${spec.modules.users ? "yes" : "no"}`,
@@ -29,9 +42,7 @@ export function updateProjectDocs(spec: AppSpec): void {
29
42
  "",
30
43
  "## Architecture",
31
44
  "",
32
- `- \`${pathsMap.backend}\`: Fastify API`,
33
- `- \`${pathsMap.frontend}\`: React dashboard`,
34
- `- \`${pathsMap.backend}/src/types\`: Contract-first backend TypeScript types`,
45
+ ...architecture,
35
46
  ].join("\n"));
36
47
 
37
48
  writeTextFile(path.join(apiDir, "README.md"), [
@@ -52,13 +63,20 @@ export function updateMemoryForGeneratedApp(spec: AppSpec, traceId: string): voi
52
63
 
53
64
  const pathsMap = getConfiguredPaths();
54
65
  const today = new Date().toISOString().split("T")[0];
66
+
67
+ const impactedFiles = [];
68
+ if (spec.platform === "full-stack" || spec.platform === "backend") impactedFiles.push(pathsMap.backend);
69
+ if (spec.platform === "full-stack" || spec.platform === "web") impactedFiles.push(pathsMap.frontend);
70
+ if (spec.platform === "mobile") impactedFiles.push(pathsMap.mobile || "apps/mobile");
71
+ impactedFiles.push("project docs");
72
+
55
73
  const history = [
56
74
  `### ${today} — Generated ${spec.title}`,
57
75
  "",
58
76
  "- **Agent:** @manager",
59
77
  `- **Trace ID:** ${traceId}`,
60
- "- **Action:** Created full-stack starter from natural language request.",
61
- `- **Files:** ${pathsMap.backend}, ${pathsMap.frontend}, project docs`,
78
+ `- **Action:** Created ${spec.platform} starter from natural language request.`,
79
+ `- **Files:** ${impactedFiles.join(", ")}`,
62
80
  ].join("\n");
63
81
 
64
82
  updateProjectMemory("HISTORY", history);
@@ -243,6 +243,12 @@ export function createWebFiles(spec: AppSpec): void {
243
243
  "}",
244
244
  ].join("\n"));
245
245
 
246
+ writeTextFile(path.join(targetDir, frontendDir, ".env.example"), [
247
+ "# Agent Enderun - Web Environment Variables",
248
+ "VITE_API_URL=http://localhost:4000/api/v1",
249
+ "VITE_APP_TITLE=" + spec.title,
250
+ ].join("\n"));
251
+
246
252
  writeTextFile(path.join(targetDir, frontendDir, "README.md"), [
247
253
  `# ${spec.title} Web`,
248
254
  "",
@@ -5,6 +5,7 @@ export interface AppSpec {
5
5
  appName: string;
6
6
  title: string;
7
7
  domain: string;
8
+ platform: "web" | "mobile" | "backend" | "full-stack";
8
9
  modules: {
9
10
  auth: boolean;
10
11
  users: boolean;
@@ -19,13 +20,22 @@ export function inferAppSpec(description: string): AppSpec {
19
20
  const hasAuth = /auth|login|giris|giriş|signin|sign in|user|kullanici|kullanıcı|role|rol/.test(normalized);
20
21
  const hasRoles = /role|rol|permission|yetki|admin/.test(normalized);
21
22
  const hasReports = /report|rapor|analytics|dashboard|chart|metric/.test(normalized);
23
+ const isMobile = /mobile|ios|android|react native|expo/.test(normalized);
24
+ const isBackend = /backend|api|server|fastify|express/.test(normalized);
25
+ const isWeb = /web|frontend|react|vite/.test(normalized);
22
26
  const appName = isCrm ? "crm-dashboard" : slugifyName(description).split("-").slice(0, 4).join("-");
23
27
 
28
+ let platform: AppSpec["platform"] = "full-stack";
29
+ if (isMobile) platform = "mobile";
30
+ else if (isBackend && !isWeb) platform = "backend";
31
+ else if (isWeb && !isBackend) platform = "web";
32
+
24
33
  return {
25
34
  rawDescription: description,
26
35
  appName,
27
36
  title: isCrm ? "CRM Dashboard" : titleCase(appName),
28
37
  domain: isCrm ? "CRM" : "Business",
38
+ platform,
29
39
  modules: {
30
40
  auth: hasAuth || isCrm,
31
41
  users: hasAuth || hasRoles || isCrm,
@@ -43,7 +53,7 @@ export async function collectCreateAppDescription(args: string[]): Promise<strin
43
53
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
44
54
  try {
45
55
  const idea = await rl.question("What do you want to build? ");
46
- const platform = await rl.question("Platform? (full-stack/web/backend) ");
56
+ const platform = await rl.question("Platform? (full-stack/web/backend/mobile) ");
47
57
  const auth = await rl.question("Auth and roles? (yes/no) ");
48
58
  const reports = await rl.question("Reports/dashboard? (yes/no) ");
49
59
  return [idea, platform, auth.includes("y") ? "with auth and roles" : "", reports.includes("y") ? "with reports dashboard" : ""].filter(Boolean).join(" ");
@@ -0,0 +1,113 @@
1
+ import path from "path";
2
+ import type { AppSpec } from "./app-inferrer.js";
3
+ import { createBaseTypeFiles } from "./app-types.js";
4
+ import { writeJsonFile, writeTextFile } from "./fs.js";
5
+ import { getConfiguredPaths } from "./memory.js";
6
+
7
+ const targetDir = process.cwd();
8
+
9
+ export function createMobileFiles(spec: AppSpec): void {
10
+ const pathsMap = getConfiguredPaths();
11
+ // Defaulting mobile to apps/mobile if not configured
12
+ const mobileDir = pathsMap.mobile || "apps/mobile";
13
+
14
+ createBaseTypeFiles(path.join(targetDir, mobileDir, "src"));
15
+
16
+ writeJsonFile(path.join(targetDir, mobileDir, "package.json"), {
17
+ name: "@agent-enderun/mobile",
18
+ version: "0.1.0",
19
+ private: true,
20
+ scripts: {
21
+ "start": "expo start",
22
+ "android": "expo start --android",
23
+ "ios": "expo start --ios",
24
+ "web": "expo start --web"
25
+ },
26
+ dependencies: {
27
+ "expo": "~52.0.0",
28
+ "expo-status-bar": "~2.0.0",
29
+ "react": "18.3.1",
30
+ "react-native": "0.76.0",
31
+ "lucide-react-native": "^0.468.0"
32
+ },
33
+ devDependencies: {
34
+ "@babel/core": "^7.25.2",
35
+ "@types/react": "~18.3.12",
36
+ "typescript": "^5.3.3"
37
+ }
38
+ });
39
+
40
+ writeTextFile(path.join(targetDir, mobileDir, "App.tsx"), [
41
+ "import React from 'react';",
42
+ "import { StyleSheet, Text, View, SafeAreaView, ScrollView } from 'react-native';",
43
+ "import { StatusBar } from 'expo-status-bar';",
44
+ "import { BarChart3, Users, Shield } from 'lucide-react-native';",
45
+ "",
46
+ "export default function App() {",
47
+ " return (",
48
+ " <SafeAreaView style={styles.container}>",
49
+ " <StatusBar style=\"auto\" />",
50
+ " <View style={styles.header}>",
51
+ " <Text style={styles.subtitle}>{'" + spec.domain + "'}</Text>",
52
+ " <Text style={styles.title}>{'" + spec.title + "'}</Text>",
53
+ " </View>",
54
+ " <ScrollView style={styles.content}>",
55
+ " <View style={styles.metricRow}>",
56
+ " <View style={[styles.card, { borderLeftColor: '#49a078' }]}>",
57
+ " <BarChart3 color=\"#49a078\" size={20} />",
58
+ " <Text style={styles.cardLabel}>Pipeline</Text>",
59
+ " <Text style={styles.cardValue}>$261K</Text>",
60
+ " </View>",
61
+ " <View style={[styles.card, { borderLeftColor: '#3f7cac' }]}>",
62
+ " <Users color=\"#3f7cac\" size={20} />",
63
+ " <Text style={styles.cardLabel}>Customers</Text>",
64
+ " <Text style={styles.cardValue}>18</Text>",
65
+ " </View>",
66
+ " </View>",
67
+ " <View style={styles.panel}>",
68
+ " <Text style={styles.panelTitle}>Recent Activity</Text>",
69
+ " <View style={styles.row}>",
70
+ " <Text style={styles.rowText}>Northwind updated by Manager</Text>",
71
+ " </View>",
72
+ " <View style={styles.row}>",
73
+ " <Text style={styles.rowText}>Acme Corp status changed to Lead</Text>",
74
+ " </View>",
75
+ " </View>",
76
+ " </ScrollView>",
77
+ " </SafeAreaView>",
78
+ " );",
79
+ "}",
80
+ "",
81
+ "const styles = StyleSheet.create({",
82
+ " container: { flex: 1, backgroundColor: '#f4f7f6' },",
83
+ " header: { padding: 24, backgroundColor: '#fff', borderBottomWidth: 1, borderBottomColor: '#d9e3e0' },",
84
+ " subtitle: { fontSize: 14, color: '#58666a', marginBottom: 4 },",
85
+ " title: { fontSize: 28, fontWeight: '800', color: '#172026' },",
86
+ " content: { flex: 1, padding: 16 },",
87
+ " metricRow: { flexDirection: 'row', gap: 12, marginBottom: 16 },",
88
+ " card: { flex: 1, backgroundColor: '#fff', padding: 16, borderRadius: 12, borderLeftWidth: 4, elevation: 2, shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.1, shadowRadius: 2 },",
89
+ " cardLabel: { fontSize: 12, color: '#58666a', marginVertical: 4 },",
90
+ " cardValue: { fontSize: 20, fontWeight: '700', color: '#172026' },",
91
+ " panel: { backgroundColor: '#fff', padding: 16, borderRadius: 12, borderWidth: 1, borderColor: '#d9e3e0' },",
92
+ " panelTitle: { fontSize: 18, fontWeight: '700', color: '#172026', marginBottom: 12 },",
93
+ " row: { paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: '#f0f4f3' },",
94
+ " rowText: { color: '#58666a' }",
95
+ "});"
96
+ ].join("\n"));
97
+
98
+ writeTextFile(path.join(targetDir, mobileDir, ".env.example"), [
99
+ "# Agent Enderun - Mobile Environment Variables",
100
+ "EXPO_PUBLIC_API_URL=http://localhost:4000/api/v1",
101
+ "EXPO_PUBLIC_APP_VARIANT=development",
102
+ ].join("\n"));
103
+
104
+ writeTextFile(path.join(targetDir, mobileDir, "README.md"), [
105
+ `# ${spec.title} Mobile`,
106
+ "",
107
+ "Expo / React Native app generated by Agent Enderun.",
108
+ "",
109
+ "## Commands",
110
+ "",
111
+ "- `npx expo start`",
112
+ ].join("\n"));
113
+ }
@@ -1,6 +1,6 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import { computeTypesHash, ensureDir, writeTextFile } from "./fs.js";
3
+ import { computeTypesHash, ensureDir, writeTextFile, writeJsonFile } from "./fs.js";
4
4
  import { getConfiguredPaths } from "./memory.js";
5
5
  import { UI } from "./ui.js";
6
6
 
@@ -65,7 +65,7 @@ export function updateContractHashFile(): void {
65
65
  const contract = JSON.parse(fs.readFileSync(contractPath, "utf8"));
66
66
  contract.contract_hash = currentHash;
67
67
  contract.last_updated = new Date().toISOString();
68
- fs.writeFileSync(contractPath, JSON.stringify(contract, null, 2));
68
+ writeJsonFile(contractPath, contract);
69
69
  }
70
70
 
71
71
  export function createBaseTypeFiles(baseDir: string): void {
@@ -173,7 +173,8 @@ export interface AgentActionLog {
173
173
  }
174
174
  `);
175
175
 
176
- writeTextFile(path.join(typesDir, "models.ts"), `import { UserID, TraceID, AgentID } from "./brands.js";
176
+ const modelsPath = path.join(typesDir, "models.ts");
177
+ const baseModelsContent = `import { UserID, TraceID, AgentID } from "./brands.js";
177
178
  import { ProjectPhase, ExecutionProfile, TaskPriority, TaskStatus } from "./constants.js";
178
179
 
179
180
  /**
@@ -238,6 +239,10 @@ export interface Task {
238
239
  createdAt: string;
239
240
  updatedAt: string;
240
241
  }
241
- `);
242
+ `;
243
+ // Append generated application contract types
244
+ const finalModelsContent = buildSharedTypesContent(baseModelsContent);
245
+ writeTextFile(modelsPath, finalModelsContent);
246
+
242
247
  UI.success(`Base types created in ${path.relative(targetDir, typesDir)}`);
243
248
  }
@@ -2,4 +2,5 @@ export * from "./app-inferrer.js";
2
2
  export * from "./app-types.js";
3
3
  export * from "./app-backend.js";
4
4
  export * from "./app-frontend.js";
5
+ export * from "./app-mobile.js";
5
6
  export * from "./app-docs.js";
@@ -1,5 +1,6 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
+ import { writeTextFile } from "./fs.js";
3
4
 
4
5
  /**
5
6
  * Finds the Claude config file path (if it exists).
@@ -53,7 +54,7 @@ export function addMcpServerToClaude(configPath: string, serverName: string, ser
53
54
  fs.mkdirSync(dir, { recursive: true });
54
55
  }
55
56
 
56
- fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`);
57
+ writeTextFile(configPath, JSON.stringify(config, null, 2));
57
58
  return true;
58
59
  } catch (e) {
59
60
  console.error(`⚠️ Failed to add MCP server to Claude config at ${configPath}:`, e);
@@ -1,6 +1,5 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import { logger } from "../../shared/logger.js";
4
3
 
5
4
  interface ComplianceIssue {
6
5
  file: string;
@@ -10,9 +9,20 @@ interface ComplianceIssue {
10
9
 
11
10
  export function scanProjectCompliance(): ComplianceIssue[] {
12
11
  const issues: ComplianceIssue[] = [];
12
+ if (!fs.existsSync("src")) return [];
13
13
  const files = getAllFiles("src");
14
14
 
15
15
  for (const file of files) {
16
+ // Absolute skip for the scanner itself to avoid recursion/self-flagging
17
+ if (file.includes("compliance") ||
18
+ file.includes("definitions") ||
19
+ file.includes("agents/registry") || // Skip agent definitions
20
+ file.includes("app-backend.ts") || // Template generator
21
+ file.includes("scaffold-ops.ts") || // Template generator
22
+ file.includes("logger") ||
23
+ file.includes("errors") ||
24
+ file.includes("shared/fs")) continue;
25
+
16
26
  const content = fs.readFileSync(file, "utf8");
17
27
  const lines = content.split("\n");
18
28
 
@@ -24,26 +34,47 @@ export function scanProjectCompliance(): ComplianceIssue[] {
24
34
  if (trimmedLine.startsWith("//") ||
25
35
  trimmedLine.startsWith("*") ||
26
36
  trimmedLine.startsWith("-") ||
27
- trimmedLine.startsWith('"') || // Ignore strings
28
- trimmedLine.startsWith('`')) return; // Ignore template literals
37
+ trimmedLine.includes("\": \"") || // Ignore JSON-like values
38
+ trimmedLine.includes("default: ") || // Ignore default template values
39
+ trimmedLine.startsWith("`")) return; // Ignore template literals
29
40
 
30
41
  // Only check if it's NOT inside a UI/console message
31
42
  const isUIMessage = line.includes("console.warn") || line.includes("console.error") || line.includes("UI.");
43
+ const isTypeDefinition = line.includes("interface ") || line.includes("type ");
32
44
 
33
45
  // 1. Console.log check - only if it's actual code
34
46
  if (line.includes("console.log") && !isUIMessage) {
35
47
  issues.push({ file, line: lineNum, rule: "No console.log allowed" });
36
48
  }
37
49
 
38
- // 2. Secret check (Regex for simple API keys) - skip UI messages
39
- if (/API_KEY|SECRET|PASSWORD/i.test(line) && !file.includes(".env") && !isUIMessage) {
40
- issues.push({ file, line: lineNum, rule: "Potential hardcoded secret detected" });
50
+ // 2. Secret check (Regex for simple API keys/assignments) - skip UI messages and templates
51
+ if (/(API_KEY|SECRET|PASSWORD)\s*[:=]/i.test(line) &&
52
+ !file.includes(".env") &&
53
+ !isUIMessage &&
54
+ !trimmedLine.includes(".env.example") && // Skip template lines
55
+ !trimmedLine.includes("your_secret_key_here") && // Skip common placeholders
56
+ !trimmedLine.includes("pattern:")) {
57
+ issues.push({ file, line: lineNum, rule: "Potential hardcoded secret assignment detected" });
41
58
  }
42
59
 
43
60
  // 3. 'Any' type check
44
- if (/\bany\b/.test(line) && !line.includes('":')) {
61
+ if (/\bany\b/.test(line) && !isTypeDefinition && !trimmedLine.includes("\":")) {
45
62
  issues.push({ file, line: lineNum, rule: "Usage of 'any' type is forbidden" });
46
63
  }
64
+
65
+ // 4. Technical Debt Detection (TODO/FIXME)
66
+ if (/\b(TODO|FIXME)\b/i.test(line)) {
67
+ issues.push({ file, line: lineNum, rule: "Unresolved Technical Debt (TODO/FIXME) found" });
68
+ }
69
+
70
+ // 5. Raw fs write check (Atomic safety enforcement)
71
+ if ((line.includes("fs.writeFileSync") || line.includes("fs.appendFileSync")) &&
72
+ !file.includes("src/shared/fs.ts") && // Ignore the utility itself
73
+ !line.includes(".lock") && // Allow lock files
74
+ !line.includes("lockPath") && // Allow lock path variables
75
+ !file.includes("bin/")) { // Ignore standalone binary scripts
76
+ issues.push({ file, line: lineNum, rule: "Use internal atomic utilities (writeTextFile) instead of raw fs" });
77
+ }
47
78
  });
48
79
 
49
80
  }
@@ -10,10 +10,10 @@ export const ColorPaletteSchema = z.object({
10
10
  });
11
11
 
12
12
  /**
13
- * Enderun Core config.json Schema
13
+ * Agent Enderun config.json Schema
14
14
  */
15
- export const EnderunConfigSchema = z.object({
16
- name: z.string().default("Enderun Core"),
15
+ export const ConfigSchema = z.object({
16
+ name: z.string().default("Agent Enderun"),
17
17
  version: z.string(),
18
18
  frameworkDir: z.string().optional(),
19
19
  theme: z.object({
@@ -44,5 +44,5 @@ export const McpConfigSchema = z.object({
44
44
  }))
45
45
  });
46
46
 
47
- export type EnderunConfig = z.infer<typeof EnderunConfigSchema>;
47
+ export type EnderunConfig = z.infer<typeof ConfigSchema>;
48
48
  export type McpConfig = z.infer<typeof McpConfigSchema>;
@@ -4,13 +4,13 @@ import crypto from "crypto";
4
4
 
5
5
  import { remapFrameworkContent } from "../adapters/index.js"; // Import from the new adapters.js
6
6
  import type { AdapterId } from "../adapters/index.js";
7
- import { ensureDir, writeTextFile, writeJsonFile } from "../../shared/fs.js";
7
+ import { ensureDir, writeTextFile, writeJsonFile, appendFile } from "../../shared/fs.js";
8
8
 
9
- export { ensureDir, writeTextFile, writeJsonFile };
9
+ export { ensureDir, writeTextFile, writeJsonFile, appendFile };
10
10
 
11
11
  export function updateGitIgnore(targetPath: string, frameworkDir = ".gemini", dryRun = false): void {
12
12
  const IGNORE_LINES = [
13
- "# AI-Enderun",
13
+ "# Agent Enderun",
14
14
  `${frameworkDir}/logs/*.json`,
15
15
  `${frameworkDir}/*.lock`,
16
16
  `${frameworkDir}/memory/`,
@@ -37,7 +37,7 @@ export function updateGitIgnore(targetPath: string, frameworkDir = ".gemini", dr
37
37
  if (dryRun) {
38
38
  console.warn(`[DRY RUN] Would update .gitignore at ${targetPath}`);
39
39
  } else {
40
- fs.writeFileSync(targetPath, content);
40
+ writeTextFile(targetPath, content);
41
41
  console.warn("✅ .gitignore updated.");
42
42
  }
43
43
  }
@@ -114,20 +114,15 @@ export function copyDir(
114
114
  if (ext === ".json") {
115
115
  try {
116
116
  const json = JSON.parse(content);
117
- content = JSON.stringify(sanitizeJson(json, targetScope), null, 2);
117
+ writeJsonFile(destPath, sanitizeJson(json, targetScope), dryRun);
118
118
  } catch {
119
- content = content.replace(/workspace:[^"'\s]*/g, "*");
119
+ const fallback = content.replace(/workspace:[^"'\s]*/g, "*");
120
+ writeTextFile(destPath, fallback, dryRun);
120
121
  }
121
122
  } else {
122
123
  content = content.replace(/workspace:[^"'\s]*/g, "*");
123
- }
124
- content = remapFrameworkContent(content, frameworkDir, adapterId); // Apply remap once to the final content
125
-
126
-
127
- if (dryRun) {
128
- console.warn(`[DRY RUN] Would process and write: ${destPath}`);
129
- } else {
130
- fs.writeFileSync(destPath, content);
124
+ content = remapFrameworkContent(content, frameworkDir, adapterId); // Apply remap once to the final content
125
+ writeTextFile(destPath, content, dryRun);
131
126
  }
132
127
  } else {
133
128
  if (dryRun) {