agent-enderun 1.1.5 → 1.1.7

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 (253) hide show
  1. package/ENDERUN.md +13 -10
  2. package/README.md +14 -31
  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 +21 -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 +45 -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 +1 -1
  58. package/dist/src/cli/adapters.js +45 -77
  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 +184 -106
  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 +129 -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/framework-mcp/dist/tools/dashboard/start_dashboard.js +29 -0
  166. package/framework-mcp/dist/tools/definitions.js +118 -0
  167. package/framework-mcp/dist/tools/file_system/batch_surgical_edit.js +50 -0
  168. package/framework-mcp/dist/tools/file_system/replace_text.js +8 -4
  169. package/framework-mcp/dist/tools/file_system/write_file.js +3 -0
  170. package/framework-mcp/dist/tools/framework/audit_deps.js +41 -0
  171. package/framework-mcp/dist/tools/framework/run_tests.js +25 -0
  172. package/framework-mcp/dist/tools/index.js +24 -0
  173. package/framework-mcp/dist/tools/memory/get_insights.js +34 -0
  174. package/framework-mcp/dist/tools/memory/read_memory.js +28 -0
  175. package/framework-mcp/dist/tools/messaging/send_message.js +1 -1
  176. package/framework-mcp/dist/tools/observability/check_ports.js +26 -0
  177. package/framework-mcp/dist/tools/observability/get_health.js +20 -0
  178. package/framework-mcp/dist/tools/search/get_gaps.js +48 -0
  179. package/framework-mcp/dist/tools/search/get_map.js +44 -0
  180. package/framework-mcp/dist/tools/search/grep_search.js +59 -0
  181. package/framework-mcp/dist/tools/search/list_dir.js +28 -0
  182. package/framework-mcp/dist/utils/compliance.js +29 -0
  183. package/framework-mcp/package.json +1 -1
  184. package/framework-mcp/src/tools/dashboard/start_dashboard.ts +33 -0
  185. package/framework-mcp/src/tools/definitions.ts +118 -0
  186. package/framework-mcp/src/tools/file_system/batch_surgical_edit.ts +70 -0
  187. package/framework-mcp/src/tools/file_system/replace_text.ts +10 -4
  188. package/framework-mcp/src/tools/file_system/write_file.ts +5 -0
  189. package/framework-mcp/src/tools/framework/audit_deps.ts +49 -0
  190. package/framework-mcp/src/tools/framework/run_tests.ts +28 -0
  191. package/framework-mcp/src/tools/index.ts +24 -0
  192. package/framework-mcp/src/tools/memory/get_insights.ts +41 -0
  193. package/framework-mcp/src/tools/memory/read_memory.ts +31 -0
  194. package/framework-mcp/src/tools/messaging/send_message.ts +1 -1
  195. package/framework-mcp/src/tools/observability/check_ports.ts +30 -0
  196. package/framework-mcp/src/tools/observability/get_health.ts +25 -0
  197. package/framework-mcp/src/tools/search/get_gaps.ts +54 -0
  198. package/framework-mcp/src/tools/search/get_map.ts +50 -0
  199. package/framework-mcp/src/tools/search/grep_search.ts +66 -0
  200. package/framework-mcp/src/tools/search/list_dir.ts +34 -0
  201. package/framework-mcp/src/tools/types.ts +11 -1
  202. package/framework-mcp/src/utils/compliance.ts +37 -0
  203. package/framework-mcp/tests/tools/messaging/send_message.test.ts +5 -5
  204. package/package.json +3 -3
  205. package/src/cli/adapters/types.ts +2 -2
  206. package/src/cli/adapters.ts +45 -80
  207. package/src/cli/commands/check.ts +52 -6
  208. package/src/cli/commands/init.ts +193 -114
  209. package/src/cli/commands/orchestrate.ts +14 -8
  210. package/src/cli/commands/status.ts +3 -2
  211. package/src/cli/index.ts +4 -3
  212. package/src/cli/shims.ts +6 -6
  213. package/src/cli/utils/app-backend.ts +249 -0
  214. package/src/cli/utils/app-docs.ts +65 -0
  215. package/src/cli/utils/app-frontend.ts +257 -0
  216. package/src/cli/utils/app-inferrer.ts +53 -0
  217. package/src/cli/utils/app-types.ts +243 -0
  218. package/src/cli/utils/app.ts +5 -849
  219. package/src/cli/utils/memory.ts +8 -4
  220. package/src/modules/adapters/definitions.ts +125 -0
  221. package/src/modules/agents/definitions.ts +26 -27
  222. package/src/shared/logger.ts +8 -5
  223. package/templates/prompts/bug-fix-recipe.md +20 -0
  224. package/templates/prompts/new-feature-recipe.md +19 -0
  225. package/templates/prompts/refactoring-recipe.md +21 -0
  226. package/templates/standards/architecture-standards.md +23 -0
  227. package/templates/standards/crud-governance.md +21 -0
  228. package/templates/standards/frontend-standards.md +38 -0
  229. package/templates/standards/i18n-standards.md +17 -0
  230. package/templates/standards/logging-and-secrets.md +29 -0
  231. package/templates/standards/mobile-standards.md +24 -0
  232. package/templates/standards/quality-standards.md +31 -0
  233. package/templates/standards/security-standards.md +21 -0
  234. package/templates/standards/tailwind-standards.md +20 -0
  235. package/templates/standards/testing-standards.md +31 -0
  236. package/src/modules/adapters/antigravity-cli.ts +0 -25
  237. package/src/modules/adapters/claude.ts +0 -36
  238. package/src/modules/adapters/codex.ts +0 -22
  239. package/src/modules/adapters/cursor.ts +0 -22
  240. package/src/modules/adapters/gemini.ts +0 -27
  241. package/src/modules/adapters/grok.ts +0 -20
  242. package/templates/architecture/agents-manifest.md +0 -79
  243. package/templates/architecture/approval-flows.md +0 -61
  244. package/templates/architecture/enterprise-architecture.md +0 -69
  245. package/templates/architecture/standards/crud-governance.md +0 -46
  246. package/templates/architecture/standards/data-fetching-patterns.md +0 -13
  247. package/templates/architecture/standards/design-system.md +0 -31
  248. package/templates/architecture/standards/documentation-ownership.md +0 -21
  249. package/templates/architecture/standards/logging.md +0 -7
  250. package/templates/architecture/standards/mobile-standards.md +0 -48
  251. package/templates/architecture/standards/tech-stack.md +0 -9
  252. package/templates/backend/error-handling.md +0 -74
  253. package/templates/frontend/component-patterns.md +0 -91
@@ -0,0 +1,66 @@
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
+ * Searches for a regex pattern within files in the project.
8
+ */
9
+ export function handleGrepSearch(projectRoot: string, args: ToolArgs): ToolResult {
10
+ const pattern = args.pattern as string;
11
+ const includePattern = args.includePattern as string || ""; // e.g., ".ts"
12
+ const excludePattern = args.excludePattern as string || "node_modules";
13
+
14
+ if (!pattern) {
15
+ throw new Error("Search pattern is required.");
16
+ }
17
+
18
+ const results: string[] = [];
19
+ const regex = new RegExp(pattern, "g");
20
+
21
+ const walk = (dir: string) => {
22
+ const files = fs.readdirSync(dir);
23
+ for (const file of files) {
24
+ const fullPath = path.join(dir, file);
25
+ const relativePath = path.relative(projectRoot, fullPath);
26
+
27
+ // Skip excluded directories/files
28
+ if (relativePath.includes(excludePattern)) continue;
29
+
30
+ try {
31
+ const stat = fs.statSync(fullPath);
32
+ if (stat.isDirectory()) {
33
+ walk(fullPath);
34
+ } else if (stat.isFile()) {
35
+ // Check include pattern
36
+ if (includePattern && !file.endsWith(includePattern)) continue;
37
+
38
+ const content = fs.readFileSync(fullPath, "utf8");
39
+ const lines = content.split("\n");
40
+ lines.forEach((line, index) => {
41
+ if (regex.test(line)) {
42
+ results.push(`${relativePath}:${index + 1}: ${line.trim()}`);
43
+ // Reset regex lastIndex because of 'g' flag
44
+ regex.lastIndex = 0;
45
+ }
46
+ });
47
+ }
48
+ } catch {
49
+ // Ignore read errors
50
+ }
51
+
52
+ if (results.length > 100) break; // Limit results
53
+ }
54
+ };
55
+
56
+ walk(projectRoot);
57
+
58
+ return {
59
+ content: [{
60
+ type: "text",
61
+ text: results.length > 0
62
+ ? `Found ${results.length} matches:\n\n${results.join("\n")}`
63
+ : "No matches found."
64
+ }]
65
+ };
66
+ }
@@ -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, any>;
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?: any[];
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.5",
4
- "description": "The Supreme AI Governance & Orchestration Framework for Enterprise Development",
3
+ "version": "1.1.7",
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.5",
87
+ "version": "1.1.6",
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
  }
@@ -2,35 +2,18 @@ import path from "path";
2
2
  import fs from "fs";
3
3
  import { writeJsonFile } from "./utils/fs.js";
4
4
  import { getPackageRoot } from "./utils/pkg.js";
5
- import { ALL_AGENTS } from "../modules/agents/definitions.js";
5
+ import { UI } from "./utils/ui.js";
6
+ import { ALL_AGENTS, buildAgentJson } from "../modules/agents/definitions.js";
7
+ import { logger } from "../shared/logger.js";
6
8
 
7
9
  import type { AdapterId, AdapterConfig } from "./adapters/types.js";
8
10
  export { ADAPTER_IDS, type AdapterId, type AdapterRole, type AdapterConfig } from "./adapters/types.js";
9
11
 
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
- };
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);
@@ -169,15 +121,15 @@ export function buildMcpServerEntry(projectRoot: string) {
169
121
  };
170
122
  }
171
123
 
172
- export function generateAdapterAgentRules(projectRoot: string, frameworkDir: string, adapterId: AdapterId): void {
124
+ export function scaffoldAgents(projectRoot: string, adapterId: AdapterId, dryRun: boolean): void {
173
125
  const adapter = ADAPTERS[adapterId];
174
- if (!adapter || !adapter.rulesDir || !adapter.rulesExt) return;
126
+ if (!adapter || !adapter.agentsDir || !adapter.agentsExt) return;
175
127
 
176
- const destRulesDir = path.join(projectRoot, adapter.rulesDir);
177
- const fileExt = adapter.rulesExt;
128
+ const destAgentsDir = path.join(projectRoot, adapter.agentsDir);
129
+ const fileExt = adapter.agentsExt;
178
130
 
179
131
  try {
180
- fs.mkdirSync(destRulesDir, { recursive: true });
132
+ if (!dryRun) fs.mkdirSync(destAgentsDir, { recursive: true });
181
133
 
182
134
  const GLOB_MAP: Record<string, string> = {
183
135
  backend: "apps/backend/**/*",
@@ -200,11 +152,17 @@ export function generateAdapterAgentRules(projectRoot: string, frameworkDir: str
200
152
  const description = agent.description || "";
201
153
  const systemPrompt = agent.instructions || "";
202
154
  const glob = GLOB_MAP[name] || "*";
203
- const ruleDestPath = path.join(destRulesDir, `${name}${fileExt}`);
204
155
 
205
- let mdcContent: string;
156
+ // Support nested format for Antigravity-CLI standard if needed
157
+ const isAntigravity = adapterId === "antigravity-cli";
158
+ const agentDir = isAntigravity ? path.join(destAgentsDir, name) : destAgentsDir;
159
+ const agentFileName = isAntigravity ? "agent.md" : `${name}${fileExt}`;
160
+
161
+ if (isAntigravity && !dryRun) fs.mkdirSync(agentDir, { recursive: true });
162
+
163
+ let content: string;
206
164
  if (fileExt === ".mdc") {
207
- mdcContent = `---
165
+ content = `---
208
166
  description: Agent Enderun — @${name} rules for ${displayName}. ${description.slice(0, 100)}
209
167
  globs: ${glob}
210
168
  alwaysApply: false
@@ -215,9 +173,9 @@ alwaysApply: false
215
173
  You are the **${displayName}** of the Agent Enderun Army.
216
174
 
217
175
  ## 🏛️ 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\`)
176
+ 1. **Supreme Law:** [\`.enderun/ENDERUN.md\`](\`.enderun/ENDERUN.md\`)
177
+ 2. **Global Rules:** [\`.enderun/knowledge/architecture-standards.md\`](\`.enderun/knowledge/architecture-standards.md\`), [\`.enderun/knowledge/security-standards.md\`](\`.enderun/knowledge/security-standards.md\`)
178
+ 3. **Project Memory:** [\`.enderun/memory/PROJECT_MEMORY.md\`](\`.enderun/memory/PROJECT_MEMORY.md\`)
221
179
 
222
180
  ## 🤖 Specialist Directive (Role: @${name})
223
181
  ${systemPrompt}
@@ -227,15 +185,21 @@ ${systemPrompt}
227
185
  - **Traceability:** Inherit and pass the active Trace ID across all delegations.
228
186
  - **Approval Signature:** High-risk actions require manager approval signature.
229
187
  `;
188
+ } else if (isAntigravity) {
189
+ // Antigravity-CLI specific JSON
190
+ content = buildAgentJson(agent);
191
+ if (!dryRun) fs.writeFileSync(path.join(agentDir, "agent.json"), content);
192
+ // Also write MD rule
193
+ content = `# 🎖️ Agent Enderun — @${name} (${displayName})\n\n${systemPrompt}`;
230
194
  } else {
231
- mdcContent = `# 🎖️ Agent Enderun — @${name} (${displayName})
195
+ content = `# 🎖️ Agent Enderun — @${name} (${displayName})
232
196
 
233
197
  You are the **${displayName}** of the Agent Enderun Army.
234
198
 
235
199
  ## 🏛️ 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\`)
200
+ 1. **Supreme Law:** [\`.enderun/ENDERUN.md\`](\`.enderun/ENDERUN.md\`)
201
+ 2. **Global Rules:** [\`.enderun/knowledge/architecture-standards.md\`](\`.enderun/knowledge/architecture-standards.md\`)
202
+ 3. **Project Memory:** [\`.enderun/memory/PROJECT_MEMORY.md\`](\`.enderun/memory/PROJECT_MEMORY.md\`)
239
203
 
240
204
  ## 🤖 Specialist Directive (Role: @${name})
241
205
  ${systemPrompt}
@@ -243,19 +207,20 @@ ${systemPrompt}
243
207
  ## 🛡️ Core Mandates
244
208
  - **Surgical Precision:** Enforce replace_text / replace_file_content for all code modifications.
245
209
  - **Traceability:** Inherit and pass the active Trace ID across all delegations.
246
- - **Approval Signature:** High-risk actions require manager approval signature.
247
210
  `;
248
211
  }
249
212
 
250
- fs.writeFileSync(ruleDestPath, mdcContent);
213
+ if (!dryRun) {
214
+ const finalPath = isAntigravity ? path.join(agentDir, "agent.md") : path.join(agentDir, agentFileName);
215
+ fs.writeFileSync(finalPath, content);
216
+ }
251
217
  }
252
- console.warn(`✅ Generated 13 Agent Rules under ${path.relative(projectRoot, destRulesDir)}/`);
218
+ console.warn(`✅ Generated 13 Agent/Rule definitions under ${path.relative(projectRoot, destAgentsDir)}/`);
253
219
  } catch (e) {
254
- console.warn(`⚠️ Failed to generate Agent rules: ${e}`);
220
+ console.warn(`⚠️ Failed to scaffold agents: ${e}`);
255
221
  }
256
222
  }
257
223
 
258
-
259
224
  export function runAdapterPostInit(adapter: AdapterConfig, projectRoot: string): void {
260
225
  const mcpEntry = buildMcpServerEntry(projectRoot);
261
226
  const mcpBlock = { mcpServers: { "agent-enderun": mcpEntry } };
@@ -263,7 +228,7 @@ export function runAdapterPostInit(adapter: AdapterConfig, projectRoot: string):
263
228
  const postInitFn = POST_INIT_MAP[adapter.id];
264
229
  if (postInitFn) {
265
230
  postInitFn(projectRoot, mcpBlock);
266
- generateAdapterAgentRules(projectRoot, adapter.frameworkDir, adapter.id);
231
+ // We handle agent scaffolding centrally now in initCommand
267
232
  }
268
233
 
269
234
  const rootMcpPath = path.join(projectRoot, "mcp.json");
@@ -5,6 +5,7 @@ import { execSync } from "child_process";
5
5
  import { getFrameworkDir, getMemoryPath, getConfiguredPaths } from "../utils/memory.js";
6
6
  import { getPackageVersion, getValidatorPath } from "../utils/pkg.js";
7
7
  import { UI } from "../utils/ui.js";
8
+ import { logger } from "../../shared/logger.js";
8
9
 
9
10
  const FRAMEWORK_VERSION = getPackageVersion();
10
11
 
@@ -40,8 +41,8 @@ export function checkCommand() {
40
41
  isFrameworkDevelopment = true;
41
42
  }
42
43
  }
43
- } catch {
44
- // ignore
44
+ } catch (err) {
45
+ logger.debug("Failed to read package.json in checkCommand", err);
45
46
  }
46
47
 
47
48
  const checks = [
@@ -53,6 +54,17 @@ export function checkCommand() {
53
54
  { name: "MCP Config (mcp.json)", path: "mcp.json" },
54
55
  { name: "ESLint Config (eslint.config.js)", path: "eslint.config.js", optional: !isFrameworkDevelopment },
55
56
  { name: "ESLint Standards", path: path.join(frameworkDir, `${knowledgeDir}/eslint-standards.md`) },
57
+ { name: "CRUD Governance Standards", path: path.join(frameworkDir, `${knowledgeDir}/crud-governance.md`) },
58
+ { name: "Architecture Standards", path: path.join(frameworkDir, `${knowledgeDir}/architecture-standards.md`) },
59
+ { name: "Frontend Standards", path: path.join(frameworkDir, `${knowledgeDir}/frontend-standards.md`) },
60
+ { name: "Tailwind Standards", path: path.join(frameworkDir, `${knowledgeDir}/tailwind-standards.md`), optional: true },
61
+ { name: "Mobile Standards", path: path.join(frameworkDir, `${knowledgeDir}/mobile-standards.md`) },
62
+ { name: "Security Standards", path: path.join(frameworkDir, `${knowledgeDir}/security-standards.md`) },
63
+ { name: "Quality & Discipline Standards", path: path.join(frameworkDir, `${knowledgeDir}/quality-standards.md`) },
64
+ { name: "Logging & Secrets Standards", path: path.join(frameworkDir, `${knowledgeDir}/logging-and-secrets.md`) },
65
+ { name: "Testing Standards", path: path.join(frameworkDir, `${knowledgeDir}/testing-standards.md`) },
66
+ { name: "i18n Standards", path: path.join(frameworkDir, `${knowledgeDir}/i18n-standards.md`) },
67
+ { name: ".env.example", path: ".env.example" },
56
68
  ...(isFrameworkDevelopment ? [{ name: "MCP Server", path: "framework-mcp/package.json" }] : []),
57
69
  { name: "Panda CSS Config", path: appPandaPath, optional: true },
58
70
  { name: "Brain Dashboard", path: path.join(frameworkDir, "BRAIN_DASHBOARD.md") },
@@ -95,6 +107,14 @@ export function checkCommand() {
95
107
  UI.success("No forbidden 'console.log' detected.");
96
108
  }
97
109
 
110
+ const anyUsageIssues = checkAnyUsage();
111
+ if (anyUsageIssues.length > 0) {
112
+ UI.error(`Forbidden 'any' type usage found in ${anyUsageIssues.length} locations.`);
113
+ issues++;
114
+ } else {
115
+ UI.success("No forbidden 'any' type usage detected.");
116
+ }
117
+
98
118
  const rootTestFiles = checkRootTestFiles();
99
119
  if (rootTestFiles.length > 0) {
100
120
  UI.warning(`Test files found in the root directory: ${rootTestFiles.join(", ")}. It is recommended to place all test files under the 'tests/' folder or application-specific directories.`);
@@ -103,8 +123,9 @@ export function checkCommand() {
103
123
  try {
104
124
  execSync("npx tsc --noEmit", { stdio: "pipe" });
105
125
  UI.success("TypeScript type check PASSED.");
106
- } catch {
126
+ } catch (err) {
107
127
  UI.error("TypeScript type check FAILED.");
128
+ logger.debug("npx tsc --noEmit check failed", err);
108
129
  issues++;
109
130
  }
110
131
 
@@ -146,8 +167,9 @@ export function checkCommand() {
146
167
  } else {
147
168
  console.warn("\n📊 Token Consumption Report: No token usage logged yet.");
148
169
  }
149
- } catch {
170
+ } catch (err) {
150
171
  console.warn("\n📊 Token Consumption Report: Could not read or parse metrics file.");
172
+ logger.debug("Failed to read or parse metrics.json in checkCommand", err);
151
173
  }
152
174
  } else {
153
175
  console.warn("\n📊 Token Consumption Report: No token usage logged yet.");
@@ -184,6 +206,30 @@ function checkConsoleLogs(): string[] {
184
206
  return issues;
185
207
  }
186
208
 
209
+ function checkAnyUsage(): string[] {
210
+ const issues: string[] = [];
211
+ const srcDir = path.join(process.cwd(), "src");
212
+ if (!fs.existsSync(srcDir)) return [];
213
+
214
+ const walk = (dir: string) => {
215
+ const files = fs.readdirSync(dir);
216
+ for (const file of files) {
217
+ const fullPath = path.join(dir, file);
218
+ if (fs.statSync(fullPath).isDirectory()) walk(fullPath);
219
+ else if (file.endsWith(".ts") && !file.includes(".test.")) {
220
+ const content = fs.readFileSync(fullPath, "utf8");
221
+ // Match ": any", "<any>", "as any" but try to avoid false positives in comments if possible
222
+ const anyRegex = /[:<]\s*any\b|\bas\s+any\b/g;
223
+ if (anyRegex.test(content) && !fullPath.includes("check.ts") && !fullPath.includes("definitions.ts")) {
224
+ issues.push(fullPath);
225
+ }
226
+ }
227
+ }
228
+ };
229
+ walk(srcDir);
230
+ return issues;
231
+ }
232
+
187
233
  function checkRootTestFiles(): string[] {
188
234
  const rootDir = process.cwd();
189
235
  if (!fs.existsSync(rootDir)) return [];
@@ -197,8 +243,8 @@ function checkRootTestFiles(): string[] {
197
243
  testFiles.push(file);
198
244
  }
199
245
  }
200
- } catch {
201
- // Ignore stat errors for broken symlinks or permission issues
246
+ } catch (err) {
247
+ logger.debug(`Failed to stat file ${fullPath} in checkRootTestFiles`, err);
202
248
  }
203
249
  }
204
250
  return testFiles;