agent-enderun 1.1.6 → 1.1.8

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/ENDERUN.md +12 -9
  2. package/README.md +12 -29
  3. package/bin/run-multi-test.js +77 -0
  4. package/dist/framework-mcp/src/tools/dashboard/start_dashboard.d.ts +5 -0
  5. package/dist/framework-mcp/src/tools/dashboard/start_dashboard.js +30 -0
  6. package/dist/framework-mcp/src/tools/dashboard/start_dashboard.js.map +1 -0
  7. package/dist/framework-mcp/src/tools/definitions.js +118 -0
  8. package/dist/framework-mcp/src/tools/definitions.js.map +1 -1
  9. package/dist/framework-mcp/src/tools/file_system/batch_surgical_edit.d.ts +5 -0
  10. package/dist/framework-mcp/src/tools/file_system/batch_surgical_edit.js +51 -0
  11. package/dist/framework-mcp/src/tools/file_system/batch_surgical_edit.js.map +1 -0
  12. package/dist/framework-mcp/src/tools/file_system/replace_text.js +8 -4
  13. package/dist/framework-mcp/src/tools/file_system/replace_text.js.map +1 -1
  14. package/dist/framework-mcp/src/tools/file_system/write_file.js +3 -0
  15. package/dist/framework-mcp/src/tools/file_system/write_file.js.map +1 -1
  16. package/dist/framework-mcp/src/tools/framework/audit_deps.d.ts +6 -0
  17. package/dist/framework-mcp/src/tools/framework/audit_deps.js +42 -0
  18. package/dist/framework-mcp/src/tools/framework/audit_deps.js.map +1 -0
  19. package/dist/framework-mcp/src/tools/framework/run_tests.d.ts +5 -0
  20. package/dist/framework-mcp/src/tools/framework/run_tests.js +26 -0
  21. package/dist/framework-mcp/src/tools/framework/run_tests.js.map +1 -0
  22. package/dist/framework-mcp/src/tools/index.js +24 -0
  23. package/dist/framework-mcp/src/tools/index.js.map +1 -1
  24. package/dist/framework-mcp/src/tools/memory/get_insights.d.ts +6 -0
  25. package/dist/framework-mcp/src/tools/memory/get_insights.js +35 -0
  26. package/dist/framework-mcp/src/tools/memory/get_insights.js.map +1 -0
  27. package/dist/framework-mcp/src/tools/memory/read_memory.d.ts +6 -0
  28. package/dist/framework-mcp/src/tools/memory/read_memory.js +29 -0
  29. package/dist/framework-mcp/src/tools/memory/read_memory.js.map +1 -0
  30. package/dist/framework-mcp/src/tools/messaging/send_message.js +1 -1
  31. package/dist/framework-mcp/src/tools/messaging/send_message.js.map +1 -1
  32. package/dist/framework-mcp/src/tools/observability/check_ports.d.ts +5 -0
  33. package/dist/framework-mcp/src/tools/observability/check_ports.js +27 -0
  34. package/dist/framework-mcp/src/tools/observability/check_ports.js.map +1 -0
  35. package/dist/framework-mcp/src/tools/observability/get_health.d.ts +5 -0
  36. package/dist/framework-mcp/src/tools/observability/get_health.js +20 -0
  37. package/dist/framework-mcp/src/tools/observability/get_health.js.map +1 -0
  38. package/dist/framework-mcp/src/tools/search/get_gaps.d.ts +6 -0
  39. package/dist/framework-mcp/src/tools/search/get_gaps.js +49 -0
  40. package/dist/framework-mcp/src/tools/search/get_gaps.js.map +1 -0
  41. package/dist/framework-mcp/src/tools/search/get_map.d.ts +6 -0
  42. package/dist/framework-mcp/src/tools/search/get_map.js +44 -0
  43. package/dist/framework-mcp/src/tools/search/get_map.js.map +1 -0
  44. package/dist/framework-mcp/src/tools/search/grep_search.d.ts +5 -0
  45. package/dist/framework-mcp/src/tools/search/grep_search.js +60 -0
  46. package/dist/framework-mcp/src/tools/search/grep_search.js.map +1 -0
  47. package/dist/framework-mcp/src/tools/search/list_dir.d.ts +5 -0
  48. package/dist/framework-mcp/src/tools/search/list_dir.js +29 -0
  49. package/dist/framework-mcp/src/tools/search/list_dir.js.map +1 -0
  50. package/dist/framework-mcp/src/tools/types.d.ts +10 -5
  51. package/dist/framework-mcp/src/utils/compliance.d.ts +5 -0
  52. package/dist/framework-mcp/src/utils/compliance.js +30 -0
  53. package/dist/framework-mcp/src/utils/compliance.js.map +1 -0
  54. package/dist/framework-mcp/tests/tools/messaging/send_message.test.js +5 -5
  55. package/dist/framework-mcp/tests/tools/messaging/send_message.test.js.map +1 -1
  56. package/dist/src/cli/adapters/types.d.ts +2 -2
  57. package/dist/src/cli/adapters.d.ts +3 -3
  58. package/dist/src/cli/adapters.js +53 -79
  59. package/dist/src/cli/adapters.js.map +1 -1
  60. package/dist/src/cli/commands/check.js +52 -6
  61. package/dist/src/cli/commands/check.js.map +1 -1
  62. package/dist/src/cli/commands/init.d.ts +5 -1
  63. package/dist/src/cli/commands/init.js +186 -172
  64. package/dist/src/cli/commands/init.js.map +1 -1
  65. package/dist/src/cli/commands/orchestrate.d.ts +3 -3
  66. package/dist/src/cli/commands/orchestrate.js +14 -8
  67. package/dist/src/cli/commands/orchestrate.js.map +1 -1
  68. package/dist/src/cli/commands/status.js +3 -2
  69. package/dist/src/cli/commands/status.js.map +1 -1
  70. package/dist/src/cli/index.js +4 -3
  71. package/dist/src/cli/index.js.map +1 -1
  72. package/dist/src/cli/shims.js +6 -6
  73. package/dist/src/cli/utils/app-backend.d.ts +2 -0
  74. package/dist/src/cli/utils/app-backend.js +236 -0
  75. package/dist/src/cli/utils/app-backend.js.map +1 -0
  76. package/dist/src/cli/utils/app-docs.d.ts +3 -0
  77. package/dist/src/cli/utils/app-docs.js +59 -0
  78. package/dist/src/cli/utils/app-docs.js.map +1 -0
  79. package/dist/src/cli/utils/app-frontend.d.ts +2 -0
  80. package/dist/src/cli/utils/app-frontend.js +248 -0
  81. package/dist/src/cli/utils/app-frontend.js.map +1 -0
  82. package/dist/src/cli/utils/app-inferrer.d.ts +14 -0
  83. package/dist/src/cli/utils/app-inferrer.js +39 -0
  84. package/dist/src/cli/utils/app-inferrer.js.map +1 -0
  85. package/dist/src/cli/utils/app-types.d.ts +3 -0
  86. package/dist/src/cli/utils/app-types.js +233 -0
  87. package/dist/src/cli/utils/app-types.js.map +1 -0
  88. package/dist/src/cli/utils/app.d.ts +5 -32
  89. package/dist/src/cli/utils/app.js +5 -794
  90. package/dist/src/cli/utils/app.js.map +1 -1
  91. package/dist/src/cli/utils/memory.js +8 -4
  92. package/dist/src/cli/utils/memory.js.map +1 -1
  93. package/dist/src/modules/adapters/antigravity-cli.js +3 -3
  94. package/dist/src/modules/adapters/antigravity-cli.js.map +1 -1
  95. package/dist/src/modules/adapters/claude.js +1 -1
  96. package/dist/src/modules/adapters/claude.js.map +1 -1
  97. package/dist/src/modules/adapters/codex.js +2 -2
  98. package/dist/src/modules/adapters/codex.js.map +1 -1
  99. package/dist/src/modules/adapters/cursor.js +1 -1
  100. package/dist/src/modules/adapters/cursor.js.map +1 -1
  101. package/dist/src/modules/adapters/definitions.d.ts +9 -0
  102. package/dist/src/modules/adapters/definitions.js +124 -0
  103. package/dist/src/modules/adapters/definitions.js.map +1 -0
  104. package/dist/src/modules/adapters/gemini.js +2 -2
  105. package/dist/src/modules/adapters/gemini.js.map +1 -1
  106. package/dist/src/modules/adapters/grok.js +1 -1
  107. package/dist/src/modules/adapters/grok.js.map +1 -1
  108. package/dist/src/modules/agents/definitions.js +26 -27
  109. package/dist/src/modules/agents/definitions.js.map +1 -1
  110. package/dist/src/shared/config.d.ts +3 -3
  111. package/dist/src/shared/logger.js +8 -5
  112. package/dist/src/shared/logger.js.map +1 -1
  113. package/dist/tests/adapter.test.d.ts +1 -0
  114. package/dist/tests/adapter.test.js +128 -0
  115. package/dist/tests/adapter.test.js.map +1 -0
  116. package/dist/tests/agents-definitions.test.d.ts +1 -0
  117. package/dist/tests/agents-definitions.test.js +54 -0
  118. package/dist/tests/agents-definitions.test.js.map +1 -0
  119. package/dist/tests/approve.test.d.ts +1 -0
  120. package/dist/tests/approve.test.js +88 -0
  121. package/dist/tests/approve.test.js.map +1 -0
  122. package/dist/tests/config.test.d.ts +1 -0
  123. package/dist/tests/config.test.js +58 -0
  124. package/dist/tests/config.test.js.map +1 -0
  125. package/dist/tests/container.runner.d.ts +1 -0
  126. package/dist/tests/container.runner.js +68 -0
  127. package/dist/tests/container.runner.js.map +1 -0
  128. package/dist/tests/container.test.d.ts +1 -0
  129. package/dist/tests/container.test.js +73 -0
  130. package/dist/tests/container.test.js.map +1 -0
  131. package/dist/tests/errors.test.d.ts +1 -0
  132. package/dist/tests/errors.test.js +64 -0
  133. package/dist/tests/errors.test.js.map +1 -0
  134. package/dist/tests/fs-utils.test.d.ts +1 -0
  135. package/dist/tests/fs-utils.test.js +101 -0
  136. package/dist/tests/fs-utils.test.js.map +1 -0
  137. package/dist/tests/logger.test.d.ts +1 -0
  138. package/dist/tests/logger.test.js +81 -0
  139. package/dist/tests/logger.test.js.map +1 -0
  140. package/dist/tests/memory-utils.test.d.ts +1 -0
  141. package/dist/tests/memory-utils.test.js +173 -0
  142. package/dist/tests/memory-utils.test.js.map +1 -0
  143. package/dist/tests/orchestrate.test.d.ts +1 -0
  144. package/dist/tests/orchestrate.test.js +131 -0
  145. package/dist/tests/orchestrate.test.js.map +1 -0
  146. package/dist/tests/skills-definitions.test.d.ts +1 -0
  147. package/dist/tests/skills-definitions.test.js +34 -0
  148. package/dist/tests/skills-definitions.test.js.map +1 -0
  149. package/dist/tests/status.test.d.ts +1 -0
  150. package/dist/tests/status.test.js +105 -0
  151. package/dist/tests/status.test.js.map +1 -0
  152. package/dist/tests/string.test.d.ts +1 -0
  153. package/dist/tests/string.test.js +89 -0
  154. package/dist/tests/string.test.js.map +1 -0
  155. package/dist/tests/time.test.d.ts +1 -0
  156. package/dist/tests/time.test.js +48 -0
  157. package/dist/tests/time.test.js.map +1 -0
  158. package/dist/tests/trace.test.d.ts +1 -0
  159. package/dist/tests/trace.test.js +61 -0
  160. package/dist/tests/trace.test.js.map +1 -0
  161. package/dist/vitest.config.js +1 -0
  162. package/dist/vitest.config.js.map +1 -1
  163. package/docs/getting-started.md +4 -0
  164. package/docs/user/corporate-governance.md +25 -0
  165. package/eslint.config.js +25 -3
  166. package/framework-mcp/dist/tools/dashboard/start_dashboard.js +29 -0
  167. package/framework-mcp/dist/tools/definitions.js +118 -0
  168. package/framework-mcp/dist/tools/file_system/batch_surgical_edit.js +50 -0
  169. package/framework-mcp/dist/tools/file_system/replace_text.js +8 -4
  170. package/framework-mcp/dist/tools/file_system/write_file.js +3 -0
  171. package/framework-mcp/dist/tools/framework/audit_deps.js +41 -0
  172. package/framework-mcp/dist/tools/framework/run_tests.js +25 -0
  173. package/framework-mcp/dist/tools/index.js +24 -0
  174. package/framework-mcp/dist/tools/memory/get_insights.js +34 -0
  175. package/framework-mcp/dist/tools/memory/read_memory.js +28 -0
  176. package/framework-mcp/dist/tools/messaging/send_message.js +1 -1
  177. package/framework-mcp/dist/tools/observability/check_ports.js +26 -0
  178. package/framework-mcp/dist/tools/observability/get_health.js +19 -0
  179. package/framework-mcp/dist/tools/search/get_gaps.js +48 -0
  180. package/framework-mcp/dist/tools/search/get_map.js +43 -0
  181. package/framework-mcp/dist/tools/search/grep_search.js +59 -0
  182. package/framework-mcp/dist/tools/search/list_dir.js +28 -0
  183. package/framework-mcp/dist/utils/compliance.js +29 -0
  184. package/framework-mcp/package.json +2 -2
  185. package/framework-mcp/src/tools/dashboard/start_dashboard.ts +33 -0
  186. package/framework-mcp/src/tools/definitions.ts +118 -0
  187. package/framework-mcp/src/tools/file_system/batch_surgical_edit.ts +70 -0
  188. package/framework-mcp/src/tools/file_system/replace_text.ts +10 -4
  189. package/framework-mcp/src/tools/file_system/write_file.ts +5 -0
  190. package/framework-mcp/src/tools/framework/audit_deps.ts +49 -0
  191. package/framework-mcp/src/tools/framework/run_tests.ts +28 -0
  192. package/framework-mcp/src/tools/index.ts +24 -0
  193. package/framework-mcp/src/tools/memory/get_insights.ts +41 -0
  194. package/framework-mcp/src/tools/memory/read_memory.ts +31 -0
  195. package/framework-mcp/src/tools/messaging/send_message.ts +1 -1
  196. package/framework-mcp/src/tools/observability/check_ports.ts +30 -0
  197. package/framework-mcp/src/tools/observability/get_health.ts +24 -0
  198. package/framework-mcp/src/tools/search/get_gaps.ts +54 -0
  199. package/framework-mcp/src/tools/search/get_map.ts +48 -0
  200. package/framework-mcp/src/tools/search/grep_search.ts +65 -0
  201. package/framework-mcp/src/tools/search/list_dir.ts +34 -0
  202. package/framework-mcp/src/tools/types.ts +11 -1
  203. package/framework-mcp/src/utils/compliance.ts +37 -0
  204. package/framework-mcp/tests/tools/messaging/send_message.test.ts +5 -5
  205. package/package.json +3 -3
  206. package/src/cli/adapters/types.ts +2 -2
  207. package/src/cli/adapters.ts +57 -86
  208. package/src/cli/commands/check.ts +52 -6
  209. package/src/cli/commands/init.ts +202 -193
  210. package/src/cli/commands/orchestrate.ts +14 -8
  211. package/src/cli/commands/status.ts +3 -2
  212. package/src/cli/index.ts +4 -3
  213. package/src/cli/shims.ts +6 -6
  214. package/src/cli/utils/app-backend.ts +249 -0
  215. package/src/cli/utils/app-docs.ts +65 -0
  216. package/src/cli/utils/app-frontend.ts +257 -0
  217. package/src/cli/utils/app-inferrer.ts +53 -0
  218. package/src/cli/utils/app-types.ts +243 -0
  219. package/src/cli/utils/app.ts +5 -849
  220. package/src/cli/utils/memory.ts +8 -4
  221. package/src/modules/adapters/definitions.ts +125 -0
  222. package/src/modules/agents/definitions.ts +26 -27
  223. package/src/shared/logger.ts +8 -5
  224. package/templates/prompts/bug-fix-recipe.md +20 -0
  225. package/templates/prompts/new-feature-recipe.md +19 -0
  226. package/templates/prompts/refactoring-recipe.md +21 -0
  227. package/templates/standards/architecture-standards.md +23 -0
  228. package/templates/standards/crud-governance.md +21 -0
  229. package/templates/standards/frontend-standards.md +38 -0
  230. package/templates/standards/i18n-standards.md +17 -0
  231. package/templates/standards/logging-and-secrets.md +29 -0
  232. package/templates/standards/mobile-standards.md +24 -0
  233. package/templates/standards/quality-standards.md +31 -0
  234. package/templates/standards/security-standards.md +21 -0
  235. package/templates/standards/tailwind-standards.md +20 -0
  236. package/templates/standards/testing-standards.md +31 -0
  237. package/src/modules/adapters/antigravity-cli.ts +0 -25
  238. package/src/modules/adapters/claude.ts +0 -36
  239. package/src/modules/adapters/codex.ts +0 -22
  240. package/src/modules/adapters/cursor.ts +0 -22
  241. package/src/modules/adapters/gemini.ts +0 -27
  242. package/src/modules/adapters/grok.ts +0 -20
  243. package/templates/architecture/agents-manifest.md +0 -79
  244. package/templates/architecture/approval-flows.md +0 -61
  245. package/templates/architecture/enterprise-architecture.md +0 -69
  246. package/templates/architecture/standards/crud-governance.md +0 -46
  247. package/templates/architecture/standards/data-fetching-patterns.md +0 -13
  248. package/templates/architecture/standards/design-system.md +0 -31
  249. package/templates/architecture/standards/documentation-ownership.md +0 -21
  250. package/templates/architecture/standards/logging.md +0 -7
  251. package/templates/architecture/standards/mobile-standards.md +0 -48
  252. package/templates/architecture/standards/tech-stack.md +0 -9
  253. package/templates/backend/error-handling.md +0 -74
  254. package/templates/frontend/component-patterns.md +0 -91
@@ -0,0 +1,54 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { safePath } from "../../utils/security.js";
4
+ import { ToolArgs, ToolResult } from "../types.js";
5
+
6
+ /**
7
+ * Scans the codebase for TODOs, FIXMEs, and empty function bodies.
8
+ * Helps identify what's left and where the agent might have skipped logic.
9
+ */
10
+ export function handleGetProjectGaps(projectRoot: string, args: ToolArgs): ToolResult {
11
+ const srcDir = safePath(projectRoot, args.path as string || "src");
12
+ const results: string[] = [];
13
+
14
+ const walk = (dir: string) => {
15
+ if (!fs.existsSync(dir)) return;
16
+ const files = fs.readdirSync(dir);
17
+ for (const file of files) {
18
+ const fullPath = path.join(dir, file);
19
+ const relativePath = path.relative(projectRoot, fullPath);
20
+
21
+ if (fs.statSync(fullPath).isDirectory()) {
22
+ if (file !== "node_modules" && file !== "dist" && !file.startsWith(".")) {
23
+ walk(fullPath);
24
+ }
25
+ } else if (file.endsWith(".ts") || file.endsWith(".tsx")) {
26
+ const content = fs.readFileSync(fullPath, "utf8");
27
+ const lines = content.split("\n");
28
+
29
+ lines.forEach((line, index) => {
30
+ // 1. Scan for markers
31
+ if (line.includes("TODO") || line.includes("FIXME") || line.includes("!!!")) {
32
+ results.push(`[${relativePath}:${index + 1}] Marker found: ${line.trim()}`);
33
+ }
34
+
35
+ // 2. Scan for empty function placeholders (heuristic)
36
+ if (line.includes("throw new Error(\"Not implemented") || line.includes("// ... rest of code")) {
37
+ results.push(`[${relativePath}:${index + 1}] Gap found: ${line.trim()}`);
38
+ }
39
+ });
40
+ }
41
+ }
42
+ };
43
+
44
+ walk(srcDir);
45
+
46
+ return {
47
+ content: [{
48
+ type: "text",
49
+ text: results.length > 0
50
+ ? `Found ${results.length} gaps/todos:\n\n${results.join("\n")}`
51
+ : "✅ No major gaps or TODOs found in the scanned directory."
52
+ }]
53
+ };
54
+ }
@@ -0,0 +1,48 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { ToolArgs, ToolResult } from "../types.js";
4
+
5
+ /**
6
+ * Generates a tree-view map of the project structure.
7
+ * Helps agents visualize the entire project layout quickly.
8
+ */
9
+ export function handleGetProjectMap(projectRoot: string, args: ToolArgs): ToolResult {
10
+ const maxDepth = Number(args.maxDepth) || 3;
11
+ const includeFiles = args.includeFiles !== false;
12
+
13
+ const buildTree = (dir: string, depth: number): string[] => {
14
+ if (depth > maxDepth) return [];
15
+
16
+ const results: string[] = [];
17
+ const files = fs.readdirSync(dir);
18
+
19
+ files.forEach(file => {
20
+ if (file === "node_modules" || file === ".git" || file === "dist" || file.startsWith(".")) return;
21
+
22
+ const fullPath = path.join(dir, file);
23
+ const stat = fs.statSync(fullPath);
24
+ const indent = " ".repeat(depth);
25
+
26
+ if (stat.isDirectory()) {
27
+ results.push(`${indent}📁 ${file}/`);
28
+ results.push(...buildTree(fullPath, depth + 1));
29
+ } else if (includeFiles) {
30
+ results.push(`${indent}📄 ${file}`);
31
+ }
32
+ });
33
+
34
+ return results;
35
+ };
36
+
37
+ try {
38
+ const tree = buildTree(projectRoot, 0);
39
+ return {
40
+ content: [{
41
+ type: "text",
42
+ text: `🗺️ **Project Map (Depth: ${maxDepth})**\n\n${tree.join("\n")}`
43
+ }]
44
+ };
45
+ } catch (e) {
46
+ return { isError: true, content: [{ type: "text", text: `Failed to map project: ${String(e)}` }] };
47
+ }
48
+ }
@@ -0,0 +1,65 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { ToolArgs, ToolResult } from "../types.js";
4
+
5
+ /**
6
+ * Searches for a regex pattern within files in the project.
7
+ */
8
+ export function handleGrepSearch(projectRoot: string, args: ToolArgs): ToolResult {
9
+ const pattern = args.pattern as string;
10
+ const includePattern = args.includePattern as string || ""; // e.g., ".ts"
11
+ const excludePattern = args.excludePattern as string || "node_modules";
12
+
13
+ if (!pattern) {
14
+ throw new Error("Search pattern is required.");
15
+ }
16
+
17
+ const results: string[] = [];
18
+ const regex = new RegExp(pattern, "g");
19
+
20
+ const walk = (dir: string) => {
21
+ const files = fs.readdirSync(dir);
22
+ for (const file of files) {
23
+ const fullPath = path.join(dir, file);
24
+ const relativePath = path.relative(projectRoot, fullPath);
25
+
26
+ // Skip excluded directories/files
27
+ if (relativePath.includes(excludePattern)) continue;
28
+
29
+ try {
30
+ const stat = fs.statSync(fullPath);
31
+ if (stat.isDirectory()) {
32
+ walk(fullPath);
33
+ } else if (stat.isFile()) {
34
+ // Check include pattern
35
+ if (includePattern && !file.endsWith(includePattern)) continue;
36
+
37
+ const content = fs.readFileSync(fullPath, "utf8");
38
+ const lines = content.split("\n");
39
+ lines.forEach((line, index) => {
40
+ if (regex.test(line)) {
41
+ results.push(`${relativePath}:${index + 1}: ${line.trim()}`);
42
+ // Reset regex lastIndex because of 'g' flag
43
+ regex.lastIndex = 0;
44
+ }
45
+ });
46
+ }
47
+ } catch {
48
+ // Ignore read errors
49
+ }
50
+
51
+ if (results.length > 100) break; // Limit results
52
+ }
53
+ };
54
+
55
+ walk(projectRoot);
56
+
57
+ return {
58
+ content: [{
59
+ type: "text",
60
+ text: results.length > 0
61
+ ? `Found ${results.length} matches:\n\n${results.join("\n")}`
62
+ : "No matches found."
63
+ }]
64
+ };
65
+ }
@@ -0,0 +1,34 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { safePath } from "../../utils/security.js";
4
+ import { ToolArgs, ToolResult } from "../types.js";
5
+
6
+ /**
7
+ * Lists the contents of a directory.
8
+ */
9
+ export function handleListDir(projectRoot: string, args: ToolArgs): ToolResult {
10
+ const dirPath = safePath(projectRoot, args.path as string || ".");
11
+
12
+ if (!fs.existsSync(dirPath)) {
13
+ throw new Error(`Directory not found: ${args.path}`);
14
+ }
15
+
16
+ const stats = fs.statSync(dirPath);
17
+ if (!stats.isDirectory()) {
18
+ throw new Error(`Path is not a directory: ${args.path}`);
19
+ }
20
+
21
+ const files = fs.readdirSync(dirPath);
22
+ const results = files.map(file => {
23
+ const fullPath = path.join(dirPath, file);
24
+ const isDir = fs.statSync(fullPath).isDirectory();
25
+ return `${isDir ? "[DIR] " : " "}${file}`;
26
+ });
27
+
28
+ return {
29
+ content: [{
30
+ type: "text",
31
+ text: `Directory listing for ${args.path || "."}:\n\n${results.join("\n")}`
32
+ }]
33
+ };
34
+ }
@@ -3,7 +3,7 @@ export interface ToolDefinition {
3
3
  description: string;
4
4
  inputSchema: {
5
5
  type: "object";
6
- properties: Record<string, { type: string; description?: string; enum?: string[] }>;
6
+ properties: Record<string, unknown>;
7
7
  required?: string[];
8
8
  };
9
9
  }
@@ -36,6 +36,16 @@ export interface ToolArgs {
36
36
  timeout?: number;
37
37
  from?: string;
38
38
  priority?: "HIGH" | "NORMAL" | "LOW";
39
+ // Added for new tools
40
+ port?: number;
41
+ pattern?: string;
42
+ includePattern?: string;
43
+ excludePattern?: string;
44
+ maxDepth?: number;
45
+ includeFiles?: boolean;
46
+ edits?: unknown[];
47
+ command?: string;
48
+ filter?: string;
39
49
  }
40
50
 
41
51
  export interface ToolResult {
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Enterprise Compliance Guardrail
3
+ * Checks content against corporate standards before allowing file mutations.
4
+ */
5
+ export function verifyCorporateCompliance(content: string, filePath: string): void {
6
+ // 1. Zero Console Policy
7
+ if (content.includes("console.log(") || content.includes("console.warn(") || content.includes("console.error(")) {
8
+ if (!filePath.includes("logger.ts") && !filePath.includes("check.ts") && !filePath.includes("cli.ts")) {
9
+ throw new Error(
10
+ "❌ Corporate Compliance Breach: 'console.log/warn/error' usage is forbidden. " +
11
+ "Use the 'logger' system from '@/shared/logger' instead."
12
+ );
13
+ }
14
+ }
15
+
16
+ // 2. No Explicit Any Policy
17
+ const anyRegex = /[:<]\s*any\b|\bas\s+any\b/g;
18
+ if (anyRegex.test(content)) {
19
+ if (!filePath.includes("definitions.ts") && !filePath.includes("types.ts")) {
20
+ throw new Error(
21
+ "❌ Corporate Compliance Breach: 'any' type is forbidden. " +
22
+ "Use 'unknown', 'generics', or proper interfaces for type safety."
23
+ );
24
+ }
25
+ }
26
+
27
+ // 3. Hardcoded Secrets Guard (Simple heuristic)
28
+ const secretKeywords = [/API_KEY\s*=\s*['"][^'"]+['"]/i, /SECRET\s*=\s*['"][^'"]+['"]/i, /PASSWORD\s*=\s*['"][^'"]+['"]/i];
29
+ for (const regex of secretKeywords) {
30
+ if (regex.test(content) && !filePath.endsWith(".env.example")) {
31
+ throw new Error(
32
+ "❌ Corporate Compliance Breach: Hardcoded secrets detected. " +
33
+ "All sensitive data must be managed via '.env' files."
34
+ );
35
+ }
36
+ }
37
+ }
@@ -6,7 +6,7 @@ import { ToolArgs } from "../../../src/tools/types.js";
6
6
 
7
7
  const TEST_DIR = path.resolve(__dirname, "../../_temp_messaging_tests");
8
8
  const MESSAGES_DIR = path.join(TEST_DIR, ".gemini/messages");
9
- const LOCK_FILE = path.join(MESSAGES_DIR, ".lock");
9
+ const BACKEND_LOCK_FILE = path.join(MESSAGES_DIR, "backend.lock");
10
10
 
11
11
  beforeEach(() => {
12
12
  fs.mkdirSync(TEST_DIR, { recursive: true });
@@ -56,7 +56,7 @@ describe("Hermes Lock Protocol & Message sending", () => {
56
56
  it("should retry and fail to send message if lock is kept busy", async () => {
57
57
  // Prepare a busy lock file
58
58
  fs.mkdirSync(MESSAGES_DIR, { recursive: true });
59
- fs.writeFileSync(LOCK_FILE, "Locked by @test at " + new Date().toISOString(), "utf8");
59
+ fs.writeFileSync(BACKEND_LOCK_FILE, "Locked by @test at " + new Date().toISOString(), "utf8");
60
60
 
61
61
  const args: ToolArgs = {
62
62
  to: "@backend",
@@ -79,9 +79,9 @@ describe("Hermes Lock Protocol & Message sending", () => {
79
79
  it("should bypass and acquire lock if existing lock is stale (older than 5s)", async () => {
80
80
  fs.mkdirSync(MESSAGES_DIR, { recursive: true });
81
81
  // Set lock file mtime to 10 seconds ago
82
- fs.writeFileSync(LOCK_FILE, "Locked by @test at " + new Date().toISOString(), "utf8");
82
+ fs.writeFileSync(BACKEND_LOCK_FILE, "Locked by @test at " + new Date().toISOString(), "utf8");
83
83
  const tenSecondsAgo = new Date(Date.now() - 10000);
84
- fs.utimesSync(LOCK_FILE, tenSecondsAgo, tenSecondsAgo);
84
+ fs.utimesSync(BACKEND_LOCK_FILE, tenSecondsAgo, tenSecondsAgo);
85
85
 
86
86
  const args: ToolArgs = {
87
87
  to: "@backend",
@@ -93,7 +93,7 @@ describe("Hermes Lock Protocol & Message sending", () => {
93
93
 
94
94
  const result = await handleSendAgentMessage(TEST_DIR, args);
95
95
  expect(result.content[0].text).toContain("✅ Message sent to @backend");
96
- expect(fs.existsSync(LOCK_FILE)).toBe(false); // Lock should have been unlinked in finally
96
+ expect(fs.existsSync(BACKEND_LOCK_FILE)).toBe(false); // Lock should have been unlinked in finally
97
97
  });
98
98
 
99
99
  it("should safely resolve concurrent messages and execute them in sequence", async () => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-enderun",
3
- "version": "1.1.6",
4
- "description": "The Supreme AI Governance & Orchestration Framework for Enterprise Development",
3
+ "version": "1.1.8",
4
+ "description": "The Supreme AI Governance & Autonomous Orchestration Framework for Enterprise Development. Acts as a Corporate AL Management Assistant.",
5
5
  "author": "Yusuf BEKAR",
6
6
  "license": "MIT",
7
7
  "readme": "README.md",
@@ -84,7 +84,7 @@
84
84
  "vitest": "^4.1.7"
85
85
  },
86
86
  "enderun": {
87
- "version": "1.1.6",
87
+ "version": "1.1.8",
88
88
  "initializedAt": "2026-06-04T18:51:28.970Z",
89
89
  "frameworkDir": ".gemini"
90
90
  },
@@ -11,6 +11,6 @@ export interface AdapterConfig {
11
11
  role: AdapterRole;
12
12
  templateDir: ".enderun";
13
13
  nestedDirs?: string[];
14
- rulesDir?: string; // Directory to write individual rules, relative to projectRoot
15
- rulesExt?: string; // Extensions for rules files (.md or .mdc)
14
+ agentsDir?: string; // Directory to write individual agents/rules, relative to projectRoot
15
+ agentsExt?: string; // Extensions for agent files (.md or .mdc)
16
16
  }
@@ -1,36 +1,19 @@
1
- import path from "path";
2
1
  import fs from "fs";
2
+ import path from "path";
3
+ import { ALL_AGENTS, buildAgentJson } from "../modules/agents/definitions.js";
4
+ import { logger } from "../shared/logger.js";
3
5
  import { writeJsonFile } from "./utils/fs.js";
4
6
  import { getPackageRoot } from "./utils/pkg.js";
5
- import { ALL_AGENTS } from "../modules/agents/definitions.js";
6
-
7
- import type { AdapterId, AdapterConfig } from "./adapters/types.js";
8
- export { ADAPTER_IDS, type AdapterId, type AdapterRole, type AdapterConfig } from "./adapters/types.js";
9
-
10
- import * as gemini from "../modules/adapters/gemini.js";
11
- import * as claude from "../modules/adapters/claude.js";
12
- import * as grok from "../modules/adapters/grok.js";
13
- import * as cursor from "../modules/adapters/cursor.js";
14
- import * as codex from "../modules/adapters/codex.js";
15
- import * as antigravityCli from "../modules/adapters/antigravity-cli.js";
16
-
17
- export const ADAPTERS: Record<AdapterId, AdapterConfig> = {
18
- gemini: gemini.config,
19
- claude: claude.config,
20
- grok: grok.config,
21
- cursor: cursor.config,
22
- codex: codex.config,
23
- "antigravity-cli": antigravityCli.config,
24
- };
25
-
26
- const POST_INIT_MAP: Record<AdapterId, (projectRoot: string, mcpBlock: unknown) => void> = {
27
- gemini: gemini.postInit,
28
- claude: claude.postInit,
29
- grok: grok.postInit,
30
- cursor: cursor.postInit,
31
- codex: codex.postInit,
32
- "antigravity-cli": antigravityCli.postInit,
33
- };
7
+ import { UI } from "./utils/ui.js";
8
+
9
+ import type { AdapterConfig, AdapterId } from "./adapters/types.js";
10
+ export { ADAPTER_IDS, type AdapterConfig, type AdapterId, type AdapterRole } from "./adapters/types.js";
11
+
12
+ import { ADAPTER_CONFIGS, POST_INIT_HANDLERS } from "../modules/adapters/definitions.js";
13
+
14
+ export const ADAPTERS: Record<AdapterId, AdapterConfig> = ADAPTER_CONFIGS;
15
+
16
+ const POST_INIT_MAP: Record<AdapterId, (projectRoot: string, mcpBlock: unknown) => void> = POST_INIT_HANDLERS;
34
17
 
35
18
  export const FRAMEWORK_DIR_CANDIDATES = [
36
19
  ".enderun",
@@ -60,41 +43,10 @@ export function resolveAdapter(input?: string): AdapterConfig {
60
43
  if (normalized in ADAPTERS) {
61
44
  config = { ...ADAPTERS[normalized as AdapterId] };
62
45
  } else {
63
- console.warn(`⚠️ Unknown adapter "${input}". Falling back to gemini.`);
46
+ UI.warning(`Unknown adapter "${input}". Falling back to gemini.`);
64
47
  config = { ...ADAPTERS.gemini };
65
48
  }
66
49
 
67
- const targetDir = process.cwd();
68
- const enderunExists = fs.existsSync(path.join(targetDir, ".enderun"));
69
- const hasUnifiedFlag = process.argv.includes("--unified");
70
- const isTesting = process.env.VITEST === "true" || process.env.NODE_ENV === "test";
71
-
72
- let forceEnderun = (enderunExists && !isTesting) || hasUnifiedFlag;
73
- try {
74
- const pkgPath = path.join(targetDir, "package.json");
75
- if (fs.existsSync(pkgPath)) {
76
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
77
- if (pkg.enderun && (pkg.enderun.frameworkDir === ".enderun" || pkg.enderun.frameworkDir === "unified")) {
78
- if (isTesting && config.frameworkDir !== ".enderun") {
79
- if (config.id !== "cursor" && config.id !== "codex") {
80
- forceEnderun = false;
81
- } else {
82
- forceEnderun = true;
83
- }
84
- } else {
85
- forceEnderun = true;
86
- }
87
- }
88
- }
89
- } catch {
90
- // ignore
91
- }
92
-
93
- if (forceEnderun) {
94
- config.frameworkDir = ".enderun";
95
- config.nestedDirs = ["agents", "skills", "knowledge"];
96
- }
97
-
98
50
  return config;
99
51
  }
100
52
 
@@ -147,8 +99,8 @@ export function remapFrameworkContent(
147
99
  if (config.paths.tests) tests = config.paths.tests;
148
100
  }
149
101
  }
150
- } catch {
151
- // ignore
102
+ } catch (err) {
103
+ logger.debug("Failed to read config.json in remapFrameworkContent", err);
152
104
  }
153
105
 
154
106
  result = result.replace(/\{\{BACKEND_DIR\}\}/g, backend);
@@ -160,24 +112,29 @@ export function remapFrameworkContent(
160
112
  }
161
113
 
162
114
  export function buildMcpServerEntry(projectRoot: string) {
115
+ const packageRoot = getPackageRoot();
116
+ const mcpServerPath = path.join(packageRoot, "framework-mcp/dist/index.js");
117
+ const relativePath = path.relative(projectRoot, mcpServerPath) || mcpServerPath;
118
+
163
119
  return {
164
120
  command: "node",
165
- args: [path.join(getPackageRoot(), "framework-mcp/dist/index.js")],
121
+ args: [relativePath],
166
122
  env: {
167
123
  ENDERUN_PROJECT_ROOT: projectRoot,
168
124
  },
169
125
  };
170
126
  }
171
127
 
172
- export function generateAdapterAgentRules(projectRoot: string, frameworkDir: string, adapterId: AdapterId): void {
128
+ export function scaffoldAgents(projectRoot: string, adapterId: AdapterId, dryRun: boolean, agentsToScaffold?: string[]): void {
173
129
  const adapter = ADAPTERS[adapterId];
174
- if (!adapter || !adapter.rulesDir || !adapter.rulesExt) return;
130
+ if (!adapter || !adapter.agentsDir || !adapter.agentsExt) return;
175
131
 
176
- const destRulesDir = path.join(projectRoot, adapter.rulesDir);
177
- const fileExt = adapter.rulesExt;
132
+ const allowedAgents = agentsToScaffold ? new Set(agentsToScaffold) : undefined;
133
+ const destAgentsDir = path.join(projectRoot, adapter.agentsDir);
134
+ const fileExt = adapter.agentsExt;
178
135
 
179
136
  try {
180
- fs.mkdirSync(destRulesDir, { recursive: true });
137
+ if (!dryRun) fs.mkdirSync(destAgentsDir, { recursive: true });
181
138
 
182
139
  const GLOB_MAP: Record<string, string> = {
183
140
  backend: "apps/backend/**/*",
@@ -195,16 +152,23 @@ export function generateAdapterAgentRules(projectRoot: string, frameworkDir: str
195
152
  };
196
153
 
197
154
  for (const agent of ALL_AGENTS) {
155
+ if (allowedAgents && !allowedAgents.has(agent.name)) continue;
198
156
  const name = agent.name;
199
157
  const displayName = agent.displayName || name;
200
158
  const description = agent.description || "";
201
159
  const systemPrompt = agent.instructions || "";
202
160
  const glob = GLOB_MAP[name] || "*";
203
- const ruleDestPath = path.join(destRulesDir, `${name}${fileExt}`);
204
161
 
205
- let mdcContent: string;
162
+ // Support nested format for Antigravity-CLI standard if needed
163
+ const isAntigravity = adapterId === "antigravity-cli";
164
+ const agentDir = isAntigravity ? path.join(destAgentsDir, name) : destAgentsDir;
165
+ const agentFileName = isAntigravity ? "agent.md" : `${name}${fileExt}`;
166
+
167
+ if (isAntigravity && !dryRun) fs.mkdirSync(agentDir, { recursive: true });
168
+
169
+ let content: string;
206
170
  if (fileExt === ".mdc") {
207
- mdcContent = `---
171
+ content = `---
208
172
  description: Agent Enderun — @${name} rules for ${displayName}. ${description.slice(0, 100)}
209
173
  globs: ${glob}
210
174
  alwaysApply: false
@@ -215,9 +179,9 @@ alwaysApply: false
215
179
  You are the **${displayName}** of the Agent Enderun Army.
216
180
 
217
181
  ## 🏛️ Hierarchy of Authority
218
- 1. **Supreme Law:** [\`${frameworkDir}/ENDERUN.md\`](\`${frameworkDir}/ENDERUN.md\`)
219
- 2. **Global Rules:** [\`${frameworkDir}/knowledge/ARCHITECTURE.md\`](\`${frameworkDir}/knowledge/ARCHITECTURE.md\`), [\`${frameworkDir}/knowledge/SECURITY.md\`](\`${frameworkDir}/knowledge/SECURITY.md\`)
220
- 3. **Project Memory:** [\`${frameworkDir}/memory/PROJECT_MEMORY.md\`](\`${frameworkDir}/memory/PROJECT_MEMORY.md\`)
182
+ 1. **Supreme Law:** [\`.enderun/ENDERUN.md\`](\`.enderun/ENDERUN.md\`)
183
+ 2. **Global Rules:** [\`.enderun/knowledge/architecture-standards.md\`](\`.enderun/knowledge/architecture-standards.md\`), [\`.enderun/knowledge/security-standards.md\`](\`.enderun/knowledge/security-standards.md\`)
184
+ 3. **Project Memory:** [\`.enderun/memory/PROJECT_MEMORY.md\`](\`.enderun/memory/PROJECT_MEMORY.md\`)
221
185
 
222
186
  ## 🤖 Specialist Directive (Role: @${name})
223
187
  ${systemPrompt}
@@ -227,15 +191,21 @@ ${systemPrompt}
227
191
  - **Traceability:** Inherit and pass the active Trace ID across all delegations.
228
192
  - **Approval Signature:** High-risk actions require manager approval signature.
229
193
  `;
194
+ } else if (isAntigravity) {
195
+ // Antigravity-CLI specific JSON
196
+ content = buildAgentJson(agent);
197
+ if (!dryRun) fs.writeFileSync(path.join(agentDir, "agent.json"), content);
198
+ // Also write MD rule
199
+ content = `# 🎖️ Agent Enderun — @${name} (${displayName})\n\n${systemPrompt}`;
230
200
  } else {
231
- mdcContent = `# 🎖️ Agent Enderun — @${name} (${displayName})
201
+ content = `# 🎖️ Agent Enderun — @${name} (${displayName})
232
202
 
233
203
  You are the **${displayName}** of the Agent Enderun Army.
234
204
 
235
205
  ## 🏛️ Hierarchy of Authority
236
- 1. **Supreme Law:** [\`${frameworkDir}/ENDERUN.md\`](\`${frameworkDir}/ENDERUN.md\`)
237
- 2. **Global Rules:** [\`${frameworkDir}/knowledge/ARCHITECTURE.md\`](\`${frameworkDir}/knowledge/ARCHITECTURE.md\`), [\`${frameworkDir}/knowledge/SECURITY.md\`](\`${frameworkDir}/knowledge/SECURITY.md\`)
238
- 3. **Project Memory:** [\`${frameworkDir}/memory/PROJECT_MEMORY.md\`](\`${frameworkDir}/memory/PROJECT_MEMORY.md\`)
206
+ 1. **Supreme Law:** [\`.enderun/ENDERUN.md\`](\`.enderun/ENDERUN.md\`)
207
+ 2. **Global Rules:** [\`.enderun/knowledge/architecture-standards.md\`](\`.enderun/knowledge/architecture-standards.md\`)
208
+ 3. **Project Memory:** [\`.enderun/memory/PROJECT_MEMORY.md\`](\`.enderun/memory/PROJECT_MEMORY.md\`)
239
209
 
240
210
  ## 🤖 Specialist Directive (Role: @${name})
241
211
  ${systemPrompt}
@@ -243,19 +213,20 @@ ${systemPrompt}
243
213
  ## 🛡️ Core Mandates
244
214
  - **Surgical Precision:** Enforce replace_text / replace_file_content for all code modifications.
245
215
  - **Traceability:** Inherit and pass the active Trace ID across all delegations.
246
- - **Approval Signature:** High-risk actions require manager approval signature.
247
216
  `;
248
217
  }
249
218
 
250
- fs.writeFileSync(ruleDestPath, mdcContent);
219
+ if (!dryRun) {
220
+ const finalPath = isAntigravity ? path.join(agentDir, "agent.md") : path.join(agentDir, agentFileName);
221
+ fs.writeFileSync(finalPath, content);
222
+ }
251
223
  }
252
- console.warn(`✅ Generated 13 Agent Rules under ${path.relative(projectRoot, destRulesDir)}/`);
224
+ console.warn(`✅ Generated 13 Agent/Rule definitions under ${path.relative(projectRoot, destAgentsDir)}/`);
253
225
  } catch (e) {
254
- console.warn(`⚠️ Failed to generate Agent rules: ${e}`);
226
+ console.warn(`⚠️ Failed to scaffold agents: ${e}`);
255
227
  }
256
228
  }
257
229
 
258
-
259
230
  export function runAdapterPostInit(adapter: AdapterConfig, projectRoot: string): void {
260
231
  const mcpEntry = buildMcpServerEntry(projectRoot);
261
232
  const mcpBlock = { mcpServers: { "agent-enderun": mcpEntry } };
@@ -263,7 +234,7 @@ export function runAdapterPostInit(adapter: AdapterConfig, projectRoot: string):
263
234
  const postInitFn = POST_INIT_MAP[adapter.id];
264
235
  if (postInitFn) {
265
236
  postInitFn(projectRoot, mcpBlock);
266
- generateAdapterAgentRules(projectRoot, adapter.frameworkDir, adapter.id);
237
+ // We handle agent scaffolding centrally now in initCommand
267
238
  }
268
239
 
269
240
  const rootMcpPath = path.join(projectRoot, "mcp.json");