agent-enderun 0.6.0 → 0.6.5

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 (75) hide show
  1. package/.enderun/PROJECT_MEMORY.md +117 -3
  2. package/.enderun/STATUS.md +4 -4
  3. package/.enderun/agents/analyst.md +98 -12
  4. package/.enderun/agents/backend.md +258 -14
  5. package/.enderun/agents/explorer.md +67 -2
  6. package/.enderun/agents/frontend.md +404 -66
  7. package/.enderun/agents/git.md +19 -2
  8. package/.enderun/agents/manager.md +412 -45
  9. package/.enderun/agents/mobile.md +63 -19
  10. package/.enderun/agents/native.md +61 -11
  11. package/.enderun/blueprints/backend/errors/blueprint.json +11 -0
  12. package/.enderun/blueprints/backend/errors/domain-error.ts +34 -55
  13. package/.enderun/docs/tech-stack.md +7 -8
  14. package/.enderun/knowledge/contract_versioning.md +1 -1
  15. package/.enderun/knowledge/framework_vs_user_project_boundary.md +52 -0
  16. package/.enderun/knowledge/frontend_professionalization_guidelines.md +108 -0
  17. package/.enderun/knowledge/hermes_live_test_guidelines.md +90 -0
  18. package/.enderun/knowledge/manager_authority_audit_enforcement.md +104 -0
  19. package/.enderun/knowledge/project_scaffold_guidelines.md +99 -0
  20. package/.enderun/knowledge/reference_application_guidelines.md +90 -0
  21. package/.enderun/messages/2026-05-23-backend-to-manager-auth-errors-reply.json +23 -0
  22. package/.enderun/messages/2026-05-23-manager-to-backend-auth-errors.json +26 -0
  23. package/ENDERUN.md +12 -4
  24. package/README.md +185 -626
  25. package/antigravity.md +15 -0
  26. package/bin/cli.js +105 -30
  27. package/bin/update-contract.js +2 -2
  28. package/docs/README.md +33 -3
  29. package/docs/getting-started.md +497 -0
  30. package/docs/roadmap.md +200 -0
  31. package/framework-mcp/README.md +1 -1
  32. package/framework-mcp/dist/index.js +0 -0
  33. package/framework-mcp/dist/tools/academy.js +6 -8
  34. package/framework-mcp/dist/tools/codebase.js +6 -6
  35. package/framework-mcp/dist/tools/contract.js +94 -4
  36. package/framework-mcp/dist/tools/database.js +1 -1
  37. package/framework-mcp/dist/tools/framework.js +8 -12
  38. package/framework-mcp/dist/tools/git.js +2 -2
  39. package/framework-mcp/dist/tools/knowledge.js +4 -4
  40. package/framework-mcp/dist/tools/memory.js +5 -7
  41. package/framework-mcp/dist/tools/messages.js +6 -6
  42. package/framework-mcp/dist/tools/repository.js +4 -4
  43. package/framework-mcp/dist/tools/scaffold.js +6 -3
  44. package/framework-mcp/dist/tools/security.js +4 -4
  45. package/framework-mcp/dist/utils.js +2 -2
  46. package/framework-mcp/package.json +1 -1
  47. package/framework-mcp/src/schemas.ts +7 -0
  48. package/framework-mcp/src/tools/academy.ts +5 -9
  49. package/framework-mcp/src/tools/codebase.ts +6 -6
  50. package/framework-mcp/src/tools/contract.ts +114 -4
  51. package/framework-mcp/src/tools/database.ts +1 -1
  52. package/framework-mcp/src/tools/framework.ts +9 -12
  53. package/framework-mcp/src/tools/git.ts +2 -2
  54. package/framework-mcp/src/tools/knowledge.ts +5 -6
  55. package/framework-mcp/src/tools/memory.ts +5 -6
  56. package/framework-mcp/src/tools/messages.ts +94 -28
  57. package/framework-mcp/src/tools/repository.ts +5 -6
  58. package/framework-mcp/src/tools/scaffold.ts +9 -6
  59. package/framework-mcp/src/tools/security.ts +4 -4
  60. package/framework-mcp/src/utils.ts +2 -2
  61. package/gemini.md +4 -4
  62. package/package.json +11 -7
  63. package/panda.config.ts +3 -1
  64. package/.enderun/benchmarks/.gitkeep +0 -0
  65. package/.enderun/blueprints/backend/middleware/error-handler.ts +0 -24
  66. package/.enderun/blueprints/backend/types/api.ts +0 -20
  67. package/.enderun/blueprints/backend/types/brands.ts +0 -12
  68. package/.enderun/blueprints/backend/types/constants.ts +0 -34
  69. package/.enderun/blueprints/backend/types/index.ts +0 -49
  70. package/.enderun/blueprints/backend/types/logs.ts +0 -16
  71. package/.enderun/blueprints/backend/types/models.ts +0 -65
  72. package/.enderun/blueprints/frontend/ui/Button.tsx +0 -60
  73. package/.enderun/blueprints/frontend/ui/Input.tsx +0 -43
  74. package/.enderun/monitoring/.gitkeep +0 -0
  75. package/gemini-extension.json +0 -13
@@ -1,7 +1,7 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
3
  import { getFrameworkDir } from "../utils.js";
4
- import { GET_ACADEMY_PERFORMANCE_ARGS_SCHEMA, GENERATE_ACADEMY_PROGRESS_REPORT_ARGS_SCHEMA, GET_AGENT_AUDIT_REPORT_ARGS_SCHEMA, LOG_AGENT_ACTION_ARGS_SCHEMA } from "../schemas.js";
4
+ import { GET_ACADEMY_PERFORMANCE_ARGS_SCHEMA, GET_AGENT_AUDIT_REPORT_ARGS_SCHEMA, LOG_AGENT_ACTION_ARGS_SCHEMA } from "../schemas.js";
5
5
  export const academyTools = [
6
6
  {
7
7
  name: "get_academy_performance",
@@ -101,7 +101,7 @@ export const academyHandlers = {
101
101
  }).filter(s => s.actions > 0);
102
102
  return { content: [{ type: "text", text: `### GLOBAL ACADEMY PERFORMANCE REPORT\n\n- **Analysis Period:** Last ${days} days\n- **Global Success Rate:** ${((totalSuccess / (totalActions || 1)) * 100).toFixed(1)}%\n\n**Agent Breakdown:**\n` + agentStats.map(s => `- **@${s.agent}:** ${s.actions} actions (${s.successRate.toFixed(1)}% success)`).join("\n") }] };
103
103
  }
104
- catch (error) {
104
+ catch {
105
105
  return { content: [{ type: "text", text: "Failed to generate global performance report." }] };
106
106
  }
107
107
  },
@@ -120,13 +120,11 @@ export const academyHandlers = {
120
120
  const successRate = (successCount / (totalActions || 1)) * 100;
121
121
  return { content: [{ type: "text", text: `# 🏛️ ACADEMY STRATEGIC BRIEFING\n\n- **Academy Health:** ${successRate.toFixed(1)}% Success Rate over ${totalActions} actions.\n**Status:** READY FOR PHASE_1 COMPLETION.` }] };
122
122
  }
123
- catch (error) {
123
+ catch {
124
124
  return { content: [{ type: "text", text: "Strategic briefing generation failed." }] };
125
125
  }
126
126
  },
127
127
  generate_academy_progress_report: async (args, projectRoot) => {
128
- const parsed = GENERATE_ACADEMY_PROGRESS_REPORT_ARGS_SCHEMA.safeParse(args ?? {});
129
- const days = parsed.success ? parsed.data.days : 7;
130
128
  try {
131
129
  const frameworkDir = getFrameworkDir(projectRoot);
132
130
  const memoryPath = path.join(projectRoot, frameworkDir, "PROJECT_MEMORY.md");
@@ -135,7 +133,7 @@ export const academyHandlers = {
135
133
  const milestones = Array.from(historySection.matchAll(/### (.*)\n\n- \*\*Agent:\*\* (.*)\n- \*\*Trace ID:\*\* (.*)\n- \*\*Action:\*\* (.*)/g)).slice(0, 5).map(m => `- [${m[1]}] **${m[2]}:** ${m[4]}`).join("\n");
136
134
  return { content: [{ type: "text", text: `# 🎓 AGENT ACADEMY PROGRESS REPORT\n\n## 🏆 Key Milestones Achieved\n${milestones}` }] };
137
135
  }
138
- catch (error) {
136
+ catch {
139
137
  return { content: [{ type: "text", text: "Failed to generate progress report." }] };
140
138
  }
141
139
  },
@@ -153,7 +151,7 @@ export const academyHandlers = {
153
151
  const successCount = logs.filter((l) => l.status === "SUCCESS").length;
154
152
  return { content: [{ type: "text", text: `### AGENT AUDIT REPORT: ${parsed.data.agent.toUpperCase()}\n\n- **Total Actions:** ${logs.length}\n- **Success Rate:** ${((successCount / (logs.length || 1)) * 100).toFixed(1)}%` }] };
155
153
  }
156
- catch (error) {
154
+ catch {
157
155
  return { content: [{ type: "text", text: "Failed to generate audit report." }] };
158
156
  }
159
157
  },
@@ -177,7 +175,7 @@ export const academyHandlers = {
177
175
  fs.writeFileSync(logPath, JSON.stringify(logs, null, 2));
178
176
  return { content: [{ type: "text", text: `SUCCESS: Logged action to ${parsed.data.agent}.json` }] };
179
177
  }
180
- catch (error) {
178
+ catch {
181
179
  return { content: [{ type: "text", text: "Failed to log action." }] };
182
180
  }
183
181
  },
@@ -135,7 +135,7 @@ export const codebaseHandlers = {
135
135
  try {
136
136
  queryRegex = new RegExp(query, "i");
137
137
  }
138
- catch (error) {
138
+ catch {
139
139
  return { content: [{ type: "text", text: "Invalid regex pattern in query." }] };
140
140
  }
141
141
  const matches = [];
@@ -157,7 +157,7 @@ export const codebaseHandlers = {
157
157
  }
158
158
  return { content: [{ type: "text", text: matches.join("\n") || "No matches found." }] };
159
159
  }
160
- catch (error) {
160
+ catch {
161
161
  return { content: [{ type: "text", text: "Search failed." }] };
162
162
  }
163
163
  },
@@ -223,7 +223,7 @@ export const codebaseHandlers = {
223
223
  }
224
224
  return { content: [{ type: "text", text: `### CODEBASE INTELLIGENCE REPORT\n\n**Complexity Spikes (>300 lines):**\n${complexitySpikes.length > 0 ? complexitySpikes.map(s => `- ${s}`).join("\n") : "- None detected"}\n\n**Potential Dead Code (Unused Exports):**\n${potentialDeadCode.length > 0 ? potentialDeadCode.map(d => `- ${d}`).join("\n") : "- None detected (within scanned scope)"}` }] };
225
225
  }
226
- catch (error) {
226
+ catch {
227
227
  return { content: [{ type: "text", text: "Intelligence scan failed." }] };
228
228
  }
229
229
  },
@@ -253,8 +253,8 @@ export const codebaseHandlers = {
253
253
  deviations.push("Reference uses 'get' prefix for functions, target does not.");
254
254
  return { content: [{ type: "text", text: deviations.length > 0 ? `### PROCEDURAL CONTINUITY DEVIATIONS\n\n${deviations.map(d => `- ${d}`).join("\n")}` : "No major structural or stylistic deviations detected based on reference." }] };
255
255
  }
256
- catch (error) {
257
- return { content: [{ type: "text", text: "Continuity analysis failed." }] };
256
+ catch {
257
+ return { content: [{ type: "text", text: "Dependency analysis failed." }] };
258
258
  }
259
259
  },
260
260
  generate_dependency_graph: async (args, projectRoot) => {
@@ -287,7 +287,7 @@ export const codebaseHandlers = {
287
287
  mermaid += uniqueEdges.join("\n");
288
288
  return { content: [{ type: "text", text: `### VISUAL ARCHITECTURE MAP: ${targetPath}\n\n\`\`\`mermaid\n${mermaid}\n\`\`\`\n\n**Total Nodes:** ${new Set(edges.flatMap(e => [e.from, e.to])).size} | **Total Edges:** ${uniqueEdges.length}` }] };
289
289
  }
290
- catch (error) {
290
+ catch {
291
291
  return { content: [{ type: "text", text: "Dependency graph generation failed." }] };
292
292
  }
293
293
  },
@@ -40,6 +40,23 @@ export const contractTools = [
40
40
  required: ["domain"],
41
41
  },
42
42
  },
43
+ {
44
+ name: "validate_frontend_api_contract",
45
+ description: "Scans frontend hooks for API calls and compares them against backend API documentation and contracts. Returns mismatches (missing endpoints, type issues, etc.).",
46
+ inputSchema: {
47
+ type: "object",
48
+ properties: {
49
+ frontendHooksPath: {
50
+ type: "string",
51
+ description: "Relative path to frontend hooks directory (default: apps/web/src/pages)",
52
+ },
53
+ backendApiDocsPath: {
54
+ type: "string",
55
+ description: "Relative path to backend API documentation (default: docs/api)",
56
+ },
57
+ },
58
+ },
59
+ },
43
60
  ];
44
61
  export const contractHandlers = {
45
62
  verify_api_contract: async (args, projectRoot) => {
@@ -52,8 +69,8 @@ export const contractHandlers = {
52
69
  const storedHash = JSON.parse(fs.readFileSync(contractJsonPath, "utf-8")).contract_hash;
53
70
  return { content: [{ type: "text", text: currentHash === storedHash ? "✅ MATCH: Contract is valid and synchronized." : `❌ MISMATCH: Current hash (${currentHash.slice(0, 8)}...) does not match stored hash (${storedHash.slice(0, 8)}...).` }] };
54
71
  }
55
- catch (error) {
56
- return { content: [{ type: "text", text: "Failed to verify contract." }] };
72
+ catch {
73
+ return { content: [{ type: "text", text: "Contract integrity check failed." }] };
57
74
  }
58
75
  },
59
76
  update_contract_hash: async (args, projectRoot) => {
@@ -72,7 +89,7 @@ export const contractHandlers = {
72
89
  fs.writeFileSync(contractJsonPath, JSON.stringify(contractJson, null, 2));
73
90
  return { content: [{ type: "text", text: `SUCCESS: Contract hash updated to ${currentHash}` }] };
74
91
  }
75
- catch (error) {
92
+ catch {
76
93
  return { content: [{ type: "text", text: "Failed to update contract hash." }] };
77
94
  }
78
95
  },
@@ -100,8 +117,81 @@ export const contractHandlers = {
100
117
  });
101
118
  return { content: [{ type: "text", text: `### CONTRACT INTEGRITY SHIELD: ${parsed.data.domain.toUpperCase()}\n\n` + `- **Missing/Undefined Types:** ${missingTypes.length > 0 ? `⚠️ ${missingTypes.join(", ")}` : "✅ All types synchronized"}\n\n` + `**Result:** ${missingTypes.length === 0 ? "PASSED" : "FAILED"}` }] };
102
119
  }
103
- catch (error) {
120
+ catch {
104
121
  return { content: [{ type: "text", text: "Contract verification failed." }] };
105
122
  }
106
123
  },
124
+ validate_frontend_api_contract: async (args, projectRoot) => {
125
+ const a = args;
126
+ const frontendPath = a?.frontendHooksPath || "apps/web/src/pages";
127
+ const backendDocsPath = a?.backendApiDocsPath || "docs/api";
128
+ try {
129
+ const fullFrontendPath = path.join(projectRoot, frontendPath);
130
+ const fullBackendDocsPath = path.join(projectRoot, backendDocsPath);
131
+ if (!fs.existsSync(fullFrontendPath)) {
132
+ return { content: [{ type: "text", text: `Frontend hooks path not found: ${frontendPath}` }] };
133
+ }
134
+ const hookFiles = collectFilesRecursively(fullFrontendPath, new Set(["ts", "tsx"]));
135
+ const apiCalls = [];
136
+ // Hook dosyalarındaki fetch çağrılarını ve response tiplerini çıkar
137
+ for (const file of hookFiles) {
138
+ const content = fs.readFileSync(file, "utf-8");
139
+ // Basit regex ile endpoint + response tipi yakala
140
+ const matches = content.matchAll(/(?:const\s+\w+\s*[:=]\s*await\s+)?fetch\(['"`](\/api\/[^'"`]+)['"`][^)]*\)\s*(?:\.then[^;]+)?(?:\s*as\s+([A-Z][a-zA-Z0-9]+)|:\s*([A-Z][a-zA-Z0-9]+))?/g);
141
+ for (const match of matches) {
142
+ const endpoint = match[1];
143
+ const responseType = match[2] || match[3];
144
+ apiCalls.push({ endpoint, responseType });
145
+ }
146
+ }
147
+ const uniqueEndpoints = Array.from(new Set(apiCalls.map(c => c.endpoint)));
148
+ if (!fs.existsSync(fullBackendDocsPath)) {
149
+ return { content: [{ type: "text", text: `Backend API docs path not found: ${backendDocsPath}` }] };
150
+ }
151
+ const backendDocFiles = collectFilesRecursively(fullBackendDocsPath, new Set(["md"]));
152
+ const documentedEndpoints = [];
153
+ for (const file of backendDocFiles) {
154
+ const content = fs.readFileSync(file, "utf-8");
155
+ const matches = content.matchAll(/`?(\/api\/[a-zA-Z0-9/_-]+)`?/g);
156
+ for (const match of matches) {
157
+ documentedEndpoints.push(match[1]);
158
+ }
159
+ }
160
+ const missingInDocs = uniqueEndpoints.filter(ep => !documentedEndpoints.some(d => ep.startsWith(d)));
161
+ const missingInHooks = documentedEndpoints.filter(d => !uniqueEndpoints.some(e => e.startsWith(d)));
162
+ let report = `### FRONTEND ↔ BACKEND CONTRACT VALIDATION REPORT\n\n`;
163
+ report += `**Scanned Frontend Hooks:** ${uniqueEndpoints.length} unique endpoints found\n`;
164
+ report += `**Scanned Backend API Docs:** ${documentedEndpoints.length} endpoints documented\n\n`;
165
+ if (missingInDocs.length > 0) {
166
+ report += `⚠️ **Endpoints called from frontend but NOT documented in backend:**\n${missingInDocs.map(e => `- ${e}`).join("\n")}\n\n`;
167
+ }
168
+ else {
169
+ report += `✅ All frontend-called endpoints are documented in backend.\n\n`;
170
+ }
171
+ if (missingInHooks.length > 0) {
172
+ report += `ℹ️ **Endpoints documented in backend but NOT used in scanned frontend hooks:**\n${missingInHooks.map(e => `- ${e}`).join("\n")}\n\n`;
173
+ }
174
+ // Basit tip karşılaştırması (eğer responseType varsa)
175
+ const typeMismatches = [];
176
+ for (const call of apiCalls) {
177
+ if (call.responseType) {
178
+ const docContent = backendDocFiles
179
+ .map(f => fs.readFileSync(f, "utf-8"))
180
+ .join("\n");
181
+ if (!docContent.includes(call.responseType)) {
182
+ typeMismatches.push(`${call.endpoint} → expected type "${call.responseType}" not found in docs`);
183
+ }
184
+ }
185
+ }
186
+ if (typeMismatches.length > 0) {
187
+ report += `⚠️ **Potential Type Mismatches:**\n${typeMismatches.map(m => `- ${m}`).join("\n")}\n\n`;
188
+ }
189
+ report += `**Result:** ${missingInDocs.length === 0 && typeMismatches.length === 0 ? "PASSED" : "FAILED (see mismatches above)"}`;
190
+ return { content: [{ type: "text", text: report }] };
191
+ }
192
+ catch (err) {
193
+ const message = err instanceof Error ? err.message : String(err);
194
+ return { content: [{ type: "text", text: `Validation failed: ${message}` }] };
195
+ }
196
+ },
107
197
  };
@@ -45,7 +45,7 @@ export const databaseHandlers = {
45
45
  return { content: [{ type: "text", text: "No database tables detected." }] };
46
46
  return { content: [{ type: "text", text: `### DATABASE SCHEMA MAP\n\n\`\`\`mermaid\n${mermaid}\n\`\`\`\n\n**Total Tables Detected:** ${tablesFound}` }] };
47
47
  }
48
- catch (error) {
48
+ catch {
49
49
  return { content: [{ type: "text", text: "Database schema analysis failed." }] };
50
50
  }
51
51
  },
@@ -2,7 +2,6 @@ import fs from "fs";
2
2
  import path from "path";
3
3
  import { execSync } from "child_process";
4
4
  import { getFrameworkDir, collectMarkdownArtifacts, FRAMEWORK_VERSION } from "../utils.js";
5
- import { VERIFY_FRAMEWORK_HEALTH_ARGS_SCHEMA } from "../schemas.js";
6
5
  export const frameworkTools = [
7
6
  {
8
7
  name: "get_framework_status",
@@ -70,8 +69,6 @@ export const frameworkHandlers = {
70
69
  if (detected.length > 0)
71
70
  techStack = detected.join(", ");
72
71
  }
73
- const rootDirs = fs.readdirSync(projectRoot).filter(f => fs.lstatSync(path.join(projectRoot, f)).isDirectory() && !f.startsWith("."));
74
- const isMonorepo = rootDirs.includes("apps") || rootDirs.includes("packages");
75
72
  const date = new Date().toISOString().split("T")[0];
76
73
  const bootstrapContent = `# PROJECT MEMORY — Legacy Onboarding\n\n## CURRENT STATUS\n\n| Active Phase | Profile | Last Update | Active Trace ID | Blockers |\n| PHASE_1 | Full | ${date} | — | Legacy Onboarding |`;
77
74
  if (fs.existsSync(memoryPath))
@@ -79,8 +76,8 @@ export const frameworkHandlers = {
79
76
  fs.writeFileSync(memoryPath, bootstrapContent);
80
77
  return { content: [{ type: "text", text: `Legacy Codebase Bootstrap complete. Detected Stack: ${techStack}.` }] };
81
78
  }
82
- catch (error) {
83
- return { content: [{ type: "text", text: "Failed to bootstrap legacy memory." }] };
79
+ catch {
80
+ return { content: [{ type: "text", text: "Failed to get project gaps." }] };
84
81
  }
85
82
  },
86
83
  get_framework_status: async (args, projectRoot) => {
@@ -95,8 +92,8 @@ export const frameworkHandlers = {
95
92
  content: [{ type: "text", text: `Framework active (v${FRAMEWORK_VERSION}). Phase: ${phase}. Profile: ${profile}.` }],
96
93
  };
97
94
  }
98
- catch (error) {
99
- return { content: [{ type: "text", text: "Framework active. Memory unreadable." }] };
95
+ catch {
96
+ return { content: [{ type: "text", text: "Failed to get memory insights." }] };
100
97
  }
101
98
  },
102
99
  get_project_gaps: async (args, projectRoot) => {
@@ -150,8 +147,8 @@ export const frameworkHandlers = {
150
147
  content: [{ type: "text", text: `### LIVE MEMORY INSIGHTS\n\n**Active Tasks:**\n${activeTasks.trim()}\n\n**Recent History:**\n${history.trim().substring(0, 1000)}...\n\n**Brain Snapshot:**\n${dashboardAgents.trim().substring(0, 500)}...` }],
151
148
  };
152
149
  }
153
- catch (error) {
154
- return { content: [{ type: "text", text: "Failed to gather memory insights." }] };
150
+ catch {
151
+ return { content: [{ type: "text", text: "Failed to get framework status." }] };
155
152
  }
156
153
  },
157
154
  codebase_context: async (args, projectRoot) => {
@@ -164,15 +161,14 @@ export const frameworkHandlers = {
164
161
  content: [{ type: "text", text: "### CONTEXT ARTIFACTS\n\n" + `PROJECT_MEMORY: ${fs.existsSync(memoryPath) ? "present" : "missing"}\n` + `BRAIN_DASHBOARD: ${fs.existsSync(dashboardPath) ? "present" : "missing"}\n` + `Docs:\n${artifacts.length > 0 ? artifacts.join("\n") : "No markdown artifacts found."}` }],
165
162
  };
166
163
  }
167
- catch (error) {
168
- return { content: [{ type: "text", text: "Context discovery failed." }] };
164
+ catch {
165
+ return { content: [{ type: "text", text: "Failed to bootstrap legacy memory." }] };
169
166
  }
170
167
  },
171
168
  get_system_time: async () => {
172
169
  return { content: [{ type: "text", text: new Date().toISOString() }] };
173
170
  },
174
171
  verify_framework_health: async (args, projectRoot) => {
175
- const parsed = VERIFY_FRAMEWORK_HEALTH_ARGS_SCHEMA.safeParse(args ?? {});
176
172
  try {
177
173
  // Run the internal CLI check command via tsx to ensure we test current state
178
174
  // If the CLI is not yet linked, we might need a relative path
@@ -44,8 +44,8 @@ export const gitHandlers = {
44
44
  const summary = files.length === 1 ? `update ${path.basename(files[0])}` : `update ${files.length} files`;
45
45
  return { content: [{ type: "text", text: `### SUGGESTED SEMANTIC COMMIT MESSAGE\n\n\`[${parsed.data.traceId}] ${type}(${scope}): ${summary}\`\n\n**Files Analyzed:**\n${files.map(f => `- ${f}`).join("\n")}` }] };
46
46
  }
47
- catch (error) {
48
- return { content: [{ type: "text", text: "Failed to generate commit message." }] };
47
+ catch {
48
+ return { content: [{ type: "text", text: "Failed to generate semantic commit message." }] };
49
49
  }
50
50
  },
51
51
  };
@@ -76,7 +76,7 @@ export const knowledgeHandlers = {
76
76
  }).filter(Boolean);
77
77
  return { content: [{ type: "text", text: results.length > 0 ? `### KNOWLEDGE BASE SEARCH RESULTS\n\n${results.join("\n\n---\n\n")}` : "No matching knowledge entries found." }] };
78
78
  }
79
- catch (error) {
79
+ catch {
80
80
  return { content: [{ type: "text", text: "Knowledge base search failed." }] };
81
81
  }
82
82
  },
@@ -99,7 +99,7 @@ export const knowledgeHandlers = {
99
99
  fs.writeFileSync(path.join(kbDir, fileName), finalContent);
100
100
  return { content: [{ type: "text", text: `Obsidian Wiki updated: ${parsed.data.topic}` }] };
101
101
  }
102
- catch (error) {
102
+ catch {
103
103
  return { content: [{ type: "text", text: "Failed to update knowledge base." }] };
104
104
  }
105
105
  },
@@ -126,8 +126,8 @@ export const knowledgeHandlers = {
126
126
  });
127
127
  return { content: [{ type: "text", text: `### KNOWLEDGE GRAPH (Mermaid)\n\n\`\`\`mermaid\n${mermaid}\n\`\`\`` }] };
128
128
  }
129
- catch (error) {
130
- return { content: [{ type: "text", text: "Failed to generate knowledge graph." }] };
129
+ catch {
130
+ return { content: [{ type: "text", text: "Failed to get knowledge graph." }] };
131
131
  }
132
132
  }
133
133
  };
@@ -57,7 +57,7 @@ export const memoryHandlers = {
57
57
  updated = true;
58
58
  break;
59
59
  }
60
- catch (e) {
60
+ catch {
61
61
  // Ignore section not found
62
62
  }
63
63
  }
@@ -75,10 +75,8 @@ export const memoryHandlers = {
75
75
  fs.unlinkSync(lockPath);
76
76
  return { content: [{ type: "text", text: `Section ${section} updated successfully.` }] };
77
77
  }
78
- catch (error) {
79
- if (fs.existsSync(lockPath) && fs.readFileSync(lockPath, "utf-8").includes(lockOwner))
80
- fs.unlinkSync(lockPath);
81
- return { content: [{ type: "text", text: `Memory update failed: ${error instanceof Error ? error.message : "Unknown error"}` }] };
78
+ catch {
79
+ return { content: [{ type: "text", text: "Failed to read project memory." }] };
82
80
  }
83
81
  },
84
82
  read_project_memory: async (args, projectRoot) => {
@@ -89,8 +87,8 @@ export const memoryHandlers = {
89
87
  return { content: [{ type: "text", text: `ERROR: ${frameworkDir}/PROJECT_MEMORY.md not found.` }] };
90
88
  return { content: [{ type: "text", text: fs.readFileSync(memoryPath, "utf-8") }] };
91
89
  }
92
- catch (error) {
93
- return { content: [{ type: "text", text: "ERROR: Failed to read PROJECT_MEMORY.md" }] };
90
+ catch {
91
+ return { content: [{ type: "text", text: "Failed to update project memory." }] };
94
92
  }
95
93
  },
96
94
  };
@@ -73,8 +73,8 @@ export const messageHandlers = {
73
73
  fs.writeFileSync(messagePath, JSON.stringify(messages, null, 2));
74
74
  return { content: [{ type: "text", text: `Hermes: Message sent to @${recipient} [${parsed.data.category} | ${parsed.data.priority}].` }] };
75
75
  }
76
- catch (error) {
77
- return { content: [{ type: "text", text: "Failed to send message via Hermes." }] };
76
+ catch {
77
+ return { content: [{ type: "text", text: "Failed to get message statistics." }] };
78
78
  }
79
79
  },
80
80
  read_agent_messages: async (args, projectRoot) => {
@@ -97,8 +97,8 @@ export const messageHandlers = {
97
97
  const formatted = unread.map((m) => `- [${m.priority}] **${m.from}** (${m.category}): ${m.content} *(Trace: ${m.traceId})*`).join("\n");
98
98
  return { content: [{ type: "text", text: `### HERMES INBOX: @${agentName}\n\n${formatted}` }] };
99
99
  }
100
- catch (error) {
101
- return { content: [{ type: "text", text: "Failed to read messages." }] };
100
+ catch {
101
+ return { content: [{ type: "text", text: "Failed to send agent message." }] };
102
102
  }
103
103
  },
104
104
  get_agent_inbox_stats: async (args, projectRoot) => {
@@ -126,8 +126,8 @@ export const messageHandlers = {
126
126
  }]
127
127
  };
128
128
  }
129
- catch (error) {
130
- return { content: [{ type: "text", text: "Failed to get inbox stats." }] };
129
+ catch {
130
+ return { content: [{ type: "text", text: "Failed to read agent messages." }] };
131
131
  }
132
132
  }
133
133
  };
@@ -66,8 +66,8 @@ export const repositoryHandlers = {
66
66
  results.push(runScript("build"));
67
67
  return { content: [{ type: "text", text: `### REPOSITORY HEALTH REPORT\n\n` + results.map(r => `- **${r.name.toUpperCase()}** (${r.script}): ${r.status}${r.status === "FAILED" && r.details ? `\n ${r.details}` : ""}`).join("\n") }] };
68
68
  }
69
- catch (error) {
70
- return { content: [{ type: "text", text: "Health validation failed." }] };
69
+ catch {
70
+ return { content: [{ type: "text", text: "Failed to analyze repository health." }] };
71
71
  }
72
72
  },
73
73
  analyze_documentation_debt: async (args, projectRoot) => {
@@ -94,8 +94,8 @@ export const repositoryHandlers = {
94
94
  const majorDirs = ["apps/backend", "apps/web", "framework-mcp"], missingREADME = majorDirs.filter(dir => fs.existsSync(path.join(projectRoot, dir)) && !fs.existsSync(path.join(projectRoot, dir, "README.md")));
95
95
  return { content: [{ type: "text", text: `### DOCUMENTATION DEBT REPORT\n\n**Missing JSDoc:**\n${missingJSDoc.slice(0, 10).join("\n")}\n\n**Missing README.md:**\n${missingREADME.join("\n")}` }] };
96
96
  }
97
- catch (error) {
98
- return { content: [{ type: "text", text: "Documentation debt scan failed." }] };
97
+ catch {
98
+ return { content: [{ type: "text", text: "Failed to analyze documentation debt." }] };
99
99
  }
100
100
  },
101
101
  };
@@ -60,7 +60,8 @@ export const scaffoldHandlers = {
60
60
  return { content: [{ type: "text", text: `Successfully instantiated blueprint '${blueprintPath}' into '${targetPath}'` }] };
61
61
  }
62
62
  catch (error) {
63
- return { content: [{ type: "text", text: `Scaffold failed: ${error.message}` }] };
63
+ const message = error instanceof Error ? error.message : "Unknown error";
64
+ return { content: [{ type: "text", text: `Scaffold failed: ${message}` }] };
64
65
  }
65
66
  },
66
67
  save_as_blueprint: async (args, projectRoot) => {
@@ -83,7 +84,8 @@ export const scaffoldHandlers = {
83
84
  return { content: [{ type: "text", text: `Successfully saved blueprint to '${blueprintPath}'` }] };
84
85
  }
85
86
  catch (error) {
86
- return { content: [{ type: "text", text: `Failed to save blueprint: ${error.message}` }] };
87
+ const message = error instanceof Error ? error.message : "Unknown error";
88
+ return { content: [{ type: "text", text: `Failed to save blueprint: ${message}` }] };
87
89
  }
88
90
  },
89
91
  list_blueprints: async (args, projectRoot) => {
@@ -123,7 +125,8 @@ export const scaffoldHandlers = {
123
125
  return { content: [{ type: "text", text: `### AVAILABLE BLUEPRINTS\n\n` + available.map(b => `- ${b}`).join("\n") }] };
124
126
  }
125
127
  catch (error) {
126
- return { content: [{ type: "text", text: `Listing blueprints failed: ${error.message}` }] };
128
+ const message = error instanceof Error ? error.message : "Unknown error";
129
+ return { content: [{ type: "text", text: `Listing blueprints failed: ${message}` }] };
127
130
  }
128
131
  },
129
132
  };
@@ -77,8 +77,8 @@ export const securityHandlers = {
77
77
  }
78
78
  return { content: [{ type: "text", text: vulnerabilities.length > 0 ? `### ADVANCED SECURITY AUDIT RESULTS\n\n${Array.from(new Set(vulnerabilities)).join("\n\n")}` : "No security patterns or rule violations detected (Regex & AST verified)." }] };
79
79
  }
80
- catch (error) {
81
- return { content: [{ type: "text", text: "Security scan failed." }] };
80
+ catch {
81
+ return { content: [{ type: "text", text: "Security audit failed." }] };
82
82
  }
83
83
  },
84
84
  analyze_constitution_compliance: async (args, projectRoot) => {
@@ -130,8 +130,8 @@ export const securityHandlers = {
130
130
  }
131
131
  return { content: [{ type: "text", text: `### CONSTITUTION COMPLIANCE REPORT\n\n` + (violations.length > 0 ? `⚠️ **VIOLATIONS FOUND:**\n${violations.map(v => `- ${v}`).join("\n")}` : "✅ **ALL SYSTEMS COMPLIANT:** AST and Regex scans passed. No rule violations detected.") }] };
132
132
  }
133
- catch (error) {
134
- return { content: [{ type: "text", text: "Compliance analysis failed." }] };
133
+ catch {
134
+ return { content: [{ type: "text", text: "Constitution compliance check failed." }] };
135
135
  }
136
136
  },
137
137
  };
@@ -1,8 +1,8 @@
1
1
  import path from "path";
2
2
  import fs from "fs";
3
- export const FRAMEWORK_VERSION = "0.6.0";
3
+ export const FRAMEWORK_VERSION = "0.6.1";
4
4
  export function getFrameworkDir(projectRoot) {
5
- const adapters = [".gemini", ".claude", ".cursor", ".enderun", ".codex"];
5
+ const adapters = [".antigravitycli", ".claude", ".cursor", ".enderun", ".codex"];
6
6
  for (const adp of adapters) {
7
7
  const fullPath = path.join(projectRoot, adp);
8
8
  if (fs.existsSync(fullPath) && fs.lstatSync(fullPath).isDirectory()) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-enderun-mcp",
3
- "version": "0.6.0",
3
+ "version": "0.6.5",
4
4
  "description": "Enterprise-grade MCP Server for AI Agent Framework",
5
5
  "author": "Yusuf BEKAR",
6
6
  "license": "MIT",
@@ -32,6 +32,7 @@ export const LOG_AGENT_ACTION_ARGS_SCHEMA = z.object({
32
32
  });
33
33
 
34
34
  export const SEND_AGENT_MESSAGE_ARGS_SCHEMA = z.object({
35
+ from: z.string().min(1),
35
36
  to: z.string().min(1),
36
37
  message: z.string().min(1),
37
38
  traceId: z.string().min(1),
@@ -39,6 +40,12 @@ export const SEND_AGENT_MESSAGE_ARGS_SCHEMA = z.object({
39
40
  priority: z.enum(["LOW", "MEDIUM", "HIGH", "URGENT"]).default("MEDIUM"),
40
41
  });
41
42
 
43
+ export const UPDATE_AGENT_MESSAGE_STATUS_ARGS_SCHEMA = z.object({
44
+ agent: z.string().min(1),
45
+ traceId: z.string().min(1),
46
+ newStatus: z.enum(["ACKNOWLEDGED", "COMPLETED", "REJECTED"]),
47
+ });
48
+
42
49
  export const SEARCH_KNOWLEDGE_BASE_ARGS_SCHEMA = z.object({
43
50
  query: z.string().min(1),
44
51
  });
@@ -3,8 +3,6 @@ import path from "path";
3
3
  import { getFrameworkDir } from "../utils.js";
4
4
  import {
5
5
  GET_ACADEMY_PERFORMANCE_ARGS_SCHEMA,
6
- GENERATE_STRATEGIC_BRIEFING_ARGS_SCHEMA,
7
- GENERATE_ACADEMY_PROGRESS_REPORT_ARGS_SCHEMA,
8
6
  GET_AGENT_AUDIT_REPORT_ARGS_SCHEMA,
9
7
  LOG_AGENT_ACTION_ARGS_SCHEMA
10
8
  } from "../schemas.js";
@@ -112,7 +110,7 @@ export const academyHandlers = {
112
110
  return { agent: file.replace(".json", ""), actions: logs.length, successRate: (success / (logs.length || 1)) * 100 };
113
111
  }).filter(s => s.actions > 0);
114
112
  return { content: [{ type: "text", text: `### GLOBAL ACADEMY PERFORMANCE REPORT\n\n- **Analysis Period:** Last ${days} days\n- **Global Success Rate:** ${((totalSuccess / (totalActions || 1)) * 100).toFixed(1)}%\n\n**Agent Breakdown:**\n` + agentStats.map(s => `- **@${s.agent}:** ${s.actions} actions (${s.successRate.toFixed(1)}% success)`).join("\n") }] };
115
- } catch (error) {
113
+ } catch {
116
114
  return { content: [{ type: "text", text: "Failed to generate global performance report." }] };
117
115
  }
118
116
  },
@@ -129,13 +127,11 @@ export const academyHandlers = {
129
127
  }
130
128
  const successRate = (successCount / (totalActions || 1)) * 100;
131
129
  return { content: [{ type: "text", text: `# 🏛️ ACADEMY STRATEGIC BRIEFING\n\n- **Academy Health:** ${successRate.toFixed(1)}% Success Rate over ${totalActions} actions.\n**Status:** READY FOR PHASE_1 COMPLETION.` }] };
132
- } catch (error) {
130
+ } catch {
133
131
  return { content: [{ type: "text", text: "Strategic briefing generation failed." }] };
134
132
  }
135
133
  },
136
134
  generate_academy_progress_report: async (args: unknown, projectRoot: string) => {
137
- const parsed = GENERATE_ACADEMY_PROGRESS_REPORT_ARGS_SCHEMA.safeParse(args ?? {});
138
- const days = parsed.success ? parsed.data.days : 7;
139
135
  try {
140
136
  const frameworkDir = getFrameworkDir(projectRoot);
141
137
  const memoryPath = path.join(projectRoot, frameworkDir, "PROJECT_MEMORY.md");
@@ -143,7 +139,7 @@ export const academyHandlers = {
143
139
  const historySection = memoryContent.match(/## HISTORY[\s\S]*$/m)?.[0] ?? "";
144
140
  const milestones = Array.from(historySection.matchAll(/### (.*)\n\n- \*\*Agent:\*\* (.*)\n- \*\*Trace ID:\*\* (.*)\n- \*\*Action:\*\* (.*)/g)).slice(0, 5).map(m => `- [${m[1]}] **${m[2]}:** ${m[4]}`).join("\n");
145
141
  return { content: [{ type: "text", text: `# 🎓 AGENT ACADEMY PROGRESS REPORT\n\n## 🏆 Key Milestones Achieved\n${milestones}` }] };
146
- } catch (error) {
142
+ } catch {
147
143
  return { content: [{ type: "text", text: "Failed to generate progress report." }] };
148
144
  }
149
145
  },
@@ -158,7 +154,7 @@ export const academyHandlers = {
158
154
  const logs = (JSON.parse(fs.readFileSync(logPath, "utf-8")) as AgentLog[]).filter((l) => new Date(l.timestamp) >= cutoff);
159
155
  const successCount = logs.filter((l) => l.status === "SUCCESS").length;
160
156
  return { content: [{ type: "text", text: `### AGENT AUDIT REPORT: ${parsed.data.agent.toUpperCase()}\n\n- **Total Actions:** ${logs.length}\n- **Success Rate:** ${((successCount / (logs.length || 1)) * 100).toFixed(1)}%` }] };
161
- } catch (error) {
157
+ } catch {
162
158
  return { content: [{ type: "text", text: "Failed to generate audit report." }] };
163
159
  }
164
160
  },
@@ -177,7 +173,7 @@ export const academyHandlers = {
177
173
  logs.push({ timestamp: new Date().toISOString(), ...parsed.data });
178
174
  fs.writeFileSync(logPath, JSON.stringify(logs, null, 2));
179
175
  return { content: [{ type: "text", text: `SUCCESS: Logged action to ${parsed.data.agent}.json` }] };
180
- } catch (error) {
176
+ } catch {
181
177
  return { content: [{ type: "text", text: "Failed to log action." }] };
182
178
  }
183
179
  },