agent-enderun 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/.enderun/BRAIN_DASHBOARD.md +46 -0
  2. package/.enderun/PROJECT_MEMORY.md +46 -0
  3. package/.enderun/STATUS.md +62 -0
  4. package/.enderun/agents/agent_army_schema.json +85 -0
  5. package/.enderun/agents/analyst/agent.json +23 -0
  6. package/.enderun/agents/analyst/prompt.md +213 -0
  7. package/.enderun/agents/backend/agent.json +24 -0
  8. package/.enderun/agents/backend/prompt.md +327 -0
  9. package/.enderun/agents/devops/agent.json +61 -0
  10. package/.enderun/agents/devops/prompt.md +127 -0
  11. package/.enderun/agents/explorer/agent.json +22 -0
  12. package/.enderun/agents/explorer/prompt.md +115 -0
  13. package/.enderun/agents/frontend/agent.json +24 -0
  14. package/.enderun/agents/frontend/prompt.md +313 -0
  15. package/.enderun/agents/git/agent.json +22 -0
  16. package/.enderun/agents/git/prompt.md +99 -0
  17. package/.enderun/agents/manager/agent.json +48 -0
  18. package/.enderun/agents/manager/prompt.md +231 -0
  19. package/.enderun/agents/mobile/agent.json +21 -0
  20. package/.enderun/agents/mobile/prompt.md +81 -0
  21. package/.enderun/agents/native/agent.json +21 -0
  22. package/.enderun/agents/native/prompt.md +86 -0
  23. package/.enderun/agents/orchestrator/agent.json +53 -0
  24. package/.enderun/agents/orchestrator/prompt.md +124 -0
  25. package/.enderun/agents/qa/agent.json +57 -0
  26. package/.enderun/agents/qa/prompt.md +69 -0
  27. package/.enderun/agents/schema/agent-lifecycle-schema.json +65 -0
  28. package/.enderun/agents/security/agent.json +54 -0
  29. package/.enderun/agents/security/prompt.md +154 -0
  30. package/.enderun/claude.md +19 -0
  31. package/.enderun/cursor.md +19 -0
  32. package/.enderun/gemini.md +19 -0
  33. package/.enderun/knowledge/corporate-governance/analyst-contract-integrity-guide.md +92 -0
  34. package/.enderun/knowledge/corporate-governance/audit-logging-standard.md +59 -0
  35. package/.enderun/knowledge/corporate-governance/backend-high-risk-endpoint-guide.md +125 -0
  36. package/.enderun/knowledge/corporate-governance/branded-types-law.md +77 -0
  37. package/.enderun/knowledge/corporate-governance/contract-drift-detection-simulation.md +92 -0
  38. package/.enderun/knowledge/corporate-governance/corporate-governance-playbook.md +89 -0
  39. package/.enderun/knowledge/corporate-governance/corporate-project-kickoff-checklist.md +56 -0
  40. package/.enderun/knowledge/corporate-governance/corporate-project-kickoff-simulation.md +144 -0
  41. package/.enderun/knowledge/corporate-governance/corporate-project-scaffolding-sop.md +103 -0
  42. package/.enderun/knowledge/corporate-governance/domain-error-handling-standard.md +75 -0
  43. package/.enderun/knowledge/corporate-governance/frontend-high-risk-modal-guide.md +211 -0
  44. package/.enderun/knowledge/corporate-governance/governance-baseline-briefing-template.md +54 -0
  45. package/.enderun/knowledge/corporate-governance/high-risk-action-approval-flow-simulation.md +167 -0
  46. package/.enderun/knowledge/corporate-governance/high-risk-actions-managerapproval.md +76 -0
  47. package/.enderun/knowledge/corporate-governance/high-risk-security-modal-hermes-flow.md +49 -0
  48. package/.enderun/knowledge/corporate-governance/manager-first-30-days-guide.md +112 -0
  49. package/.enderun/knowledge/corporate-governance/manager-first-three-briefings.md +79 -0
  50. package/.enderun/knowledge/deployment_checklist.md +7 -0
  51. package/{.antigravitycli → .enderun}/knowledge/framework_vs_user_project_boundary.md +3 -3
  52. package/{.antigravitycli → .enderun}/knowledge/frontend_professionalization_guidelines.md +17 -20
  53. package/{.antigravitycli → .enderun}/knowledge/hermes_live_test_guidelines.md +9 -9
  54. package/{.antigravitycli → .enderun}/knowledge/hermes_protocol.md +2 -2
  55. package/{.antigravitycli → .enderun}/knowledge/manager_authority_audit_enforcement.md +11 -11
  56. package/{.antigravitycli → .enderun}/knowledge/project_scaffold_guidelines.md +8 -8
  57. package/{.antigravitycli → .enderun}/knowledge/reference_application_guidelines.md +7 -7
  58. package/.enderun/logs/analyst.json +1 -0
  59. package/.enderun/logs/backend.json +1 -0
  60. package/.enderun/logs/devops.json +1 -0
  61. package/.enderun/logs/explorer.json +1 -0
  62. package/.enderun/logs/frontend.json +1 -0
  63. package/.enderun/logs/git.json +1 -0
  64. package/.enderun/logs/manager.json +1 -0
  65. package/.enderun/logs/mobile.json +1 -0
  66. package/.enderun/logs/native.json +1 -0
  67. package/.enderun/logs/orchestrator.json +1 -0
  68. package/.enderun/logs/qa.json +1 -0
  69. package/.enderun/logs/security.json +1 -0
  70. package/.enderun/memory-graph/agent-contexts/analyst.json +1 -0
  71. package/.enderun/memory-graph/agent-contexts/backend.json +1 -0
  72. package/.enderun/memory-graph/agent-contexts/devops.json +1 -0
  73. package/.enderun/memory-graph/agent-contexts/explorer.json +1 -0
  74. package/.enderun/memory-graph/agent-contexts/frontend.json +1 -0
  75. package/.enderun/memory-graph/agent-contexts/git.json +1 -0
  76. package/.enderun/memory-graph/agent-contexts/manager.json +1 -0
  77. package/.enderun/memory-graph/agent-contexts/mobile.json +1 -0
  78. package/.enderun/memory-graph/agent-contexts/native.json +1 -0
  79. package/.enderun/memory-graph/agent-contexts/orchestrator.json +1 -0
  80. package/.enderun/memory-graph/agent-contexts/qa.json +1 -0
  81. package/.enderun/memory-graph/agent-contexts/security.json +1 -0
  82. package/.enderun/memory-graph/graph.json +26 -0
  83. package/.enderun/memory-graph/shared-facts.json +52 -0
  84. package/.enderun/monitoring/.gitkeep +0 -0
  85. package/.enderun/queue/README.md +36 -0
  86. package/ENDERUN.md +4 -4
  87. package/README.md +233 -109
  88. package/bin/cli.js +13 -2138
  89. package/bin/hermes-sandbox.js +0 -0
  90. package/bin/validate-agent-army.js +3 -3
  91. package/claude.md +19 -0
  92. package/cursor.md +19 -0
  93. package/docs/architecture/approval-flows.md +2 -37
  94. package/docs/backend/error-handling.md +2 -51
  95. package/docs/frontend/component-patterns.md +2 -47
  96. package/docs/getting-started.md +7 -15
  97. package/docs/roadmap.md +2 -2
  98. package/framework-mcp/README.md +3 -9
  99. package/framework-mcp/dist/index.js +0 -0
  100. package/framework-mcp/dist/schemas.js +3 -3
  101. package/framework-mcp/dist/tools/framework.js +17 -10
  102. package/framework-mcp/dist/tools/governance.js +696 -0
  103. package/framework-mcp/dist/tools/index.js +14 -12
  104. package/framework-mcp/dist/tools/memory.js +106 -0
  105. package/framework-mcp/dist/tools/monitoring.js +294 -0
  106. package/framework-mcp/dist/tools/orchestration.js +368 -0
  107. package/framework-mcp/dist/tools/pipeline.js +267 -0
  108. package/framework-mcp/dist/utils.js +25 -3
  109. package/framework-mcp/package.json +3 -3
  110. package/framework-mcp/src/schemas.ts +3 -45
  111. package/framework-mcp/src/tools/framework.ts +18 -10
  112. package/framework-mcp/src/tools/governance.ts +891 -0
  113. package/framework-mcp/src/tools/index.ts +14 -12
  114. package/framework-mcp/src/tools/memory.ts +103 -0
  115. package/framework-mcp/src/tools/monitoring.ts +351 -0
  116. package/framework-mcp/src/tools/orchestration.ts +439 -0
  117. package/framework-mcp/src/tools/pipeline.ts +353 -0
  118. package/framework-mcp/src/utils.ts +24 -3
  119. package/framework-mcp/tsconfig.json +2 -1
  120. package/gemini.md +19 -0
  121. package/package.json +16 -20
  122. package/.antigravitycli/BRAIN_DASHBOARD.md +0 -43
  123. package/.antigravitycli/ENDERUN.md +0 -253
  124. package/.antigravitycli/PROJECT_MEMORY.md +0 -78
  125. package/.antigravitycli/STATUS.md +0 -21
  126. package/.antigravitycli/agents/agent_army_schema.json +0 -79
  127. package/.antigravitycli/agents/analyst/agent.json +0 -55
  128. package/.antigravitycli/agents/backend/agent.json +0 -58
  129. package/.antigravitycli/agents/explorer/agent.json +0 -50
  130. package/.antigravitycli/agents/frontend/agent.json +0 -56
  131. package/.antigravitycli/agents/git/agent.json +0 -53
  132. package/.antigravitycli/agents/manager/agent.json +0 -82
  133. package/.antigravitycli/agents/mobile/agent.json +0 -52
  134. package/.antigravitycli/agents/native/agent.json +0 -56
  135. package/.antigravitycli/assets/manager.png +0 -0
  136. package/.antigravitycli/blueprints/README.md +0 -82
  137. package/.antigravitycli/blueprints/backend/errors/config/meta.json +0 -16
  138. package/.antigravitycli/blueprints/backend/errors/domain-error.ts +0 -64
  139. package/.antigravitycli/knowledge/README.md +0 -22
  140. package/.antigravitycli/knowledge/database_governance_guidelines.md +0 -118
  141. package/.antigravitycli/knowledge/deployment_checklist.md +0 -133
  142. package/.antigravitycli/knowledge/documentation_ownership.md +0 -122
  143. package/.antigravitycli/knowledge/documentation_ownership_status.md +0 -122
  144. package/.antigravitycli/knowledge/enterprise_capabilities_reference.md +0 -149
  145. package/.antigravitycli/knowledge/enterprise_frontend_adaptation.md +0 -232
  146. package/.antigravitycli/knowledge/enterprise_project_adaptation.md +0 -168
  147. package/.antigravitycli/knowledge/frontend_real_battle_test_protocol.md +0 -162
  148. package/antigravity.md +0 -15
  149. package/docs/architecture/decisions/README.md +0 -31
  150. package/docs/architecture/notification-strategy.md +0 -38
  151. package/docs/backend/audit-logging.md +0 -34
  152. package/docs/frontend/forms.md +0 -40
  153. package/docs/frontend/notifications.md +0 -37
  154. package/framework-mcp/dist/tools/academy.js +0 -182
  155. package/framework-mcp/dist/tools/database.js +0 -57
  156. package/framework-mcp/dist/tools/repository.js +0 -101
  157. package/framework-mcp/dist/tools/scaffold.js +0 -132
  158. package/framework-mcp/src/tools/academy.ts +0 -180
  159. package/framework-mcp/src/tools/database.ts +0 -54
  160. package/framework-mcp/src/tools/repository.ts +0 -101
  161. package/framework-mcp/src/tools/scaffold.ts +0 -150
  162. /package/{.antigravitycli/messages → .enderun/benchmarks}/.gitkeep +0 -0
  163. /package/{.antigravitycli → .enderun}/cli-commands.json +0 -0
  164. /package/{.antigravitycli → .enderun}/config.json +0 -0
  165. /package/{.antigravitycli → .enderun}/knowledge/api_design_rules.md +0 -0
  166. /package/{.antigravitycli → .enderun}/knowledge/async_error_handling.md +0 -0
  167. /package/{.antigravitycli → .enderun}/knowledge/blueprint_driven_construction.md +0 -0
  168. /package/{.antigravitycli → .enderun}/knowledge/branded_types_pattern.md +0 -0
  169. /package/{.antigravitycli → .enderun}/knowledge/code_review_checklist.md +0 -0
  170. /package/{.antigravitycli → .enderun}/knowledge/contract_versioning.md +0 -0
  171. /package/{.antigravitycli → .enderun}/knowledge/database_migration.md +0 -0
  172. /package/{.antigravitycli → .enderun}/knowledge/git_commit_strategy.md +0 -0
  173. /package/{.antigravitycli → .enderun}/knowledge/legacy_onboarding.md +0 -0
  174. /package/{.antigravitycli → .enderun}/knowledge/monitoring_setup.md +0 -0
  175. /package/{.antigravitycli → .enderun}/knowledge/performance_guidelines.md +0 -0
  176. /package/{.antigravitycli → .enderun}/knowledge/repository_patterns.md +0 -0
  177. /package/{.antigravitycli → .enderun}/knowledge/responsive_design_standards.md +0 -0
  178. /package/{.antigravitycli → .enderun}/knowledge/security_scanning.md +0 -0
  179. /package/{.antigravitycli → .enderun}/knowledge/testing_standards.md +0 -0
  180. /package/{.antigravitycli → .enderun}/knowledge/troubleshooting_guide.md +0 -0
  181. /package/{.antigravitycli → .enderun}/knowledge/zero_ui_library_policy.md +0 -0
@@ -1,34 +0,0 @@
1
- # Backend Audit Logging & Observability
2
-
3
- This document defines the schema, storage criteria, and compliance guidelines for transactional database audit logs.
4
-
5
- ---
6
-
7
- ## 🔒 Audit Log Schema
8
-
9
- Every state-changing transaction (Insert, Update, Delete) must generate a secure, untamperable audit record with this exact schema:
10
-
11
- ```json
12
- {
13
- "timestamp": "2026-05-24T12:00:00.000Z",
14
- "userId": "usr_91a0b3...",
15
- "operation": "UPDATE",
16
- "targetTable": "users",
17
- "targetRowId": "42",
18
- "previousState": {
19
- "role": "User",
20
- "status": "Active"
21
- },
22
- "newState": {
23
- "role": "SuperAdmin",
24
- "status": "Active"
25
- },
26
- "traceId": "01H...",
27
- "managerApprovalSignature": "approved_sig_payload_hash"
28
- }
29
- ```
30
-
31
- ---
32
-
33
- > [!WARNING]
34
- > **Data Privacy:** Audit logs must never contain raw PII (Personally Identifiable Information) such as unhashed passwords, credit card tokens, or cleartext social security numbers.
@@ -1,40 +0,0 @@
1
- # Type-Safe Forms with Zod Validations
2
-
3
- Guidelines for building highly responsive, type-safe web forms using React state hooks and Zod validation schemas.
4
-
5
- ---
6
-
7
- ## 📝 Form Validation Pattern
8
-
9
- Always decouple validation schemas from the component render context:
10
-
11
- ```typescript
12
- import { z } from "zod";
13
-
14
- export const CreateUserFormSchema = z.object({
15
- email: z.string().email("Invalid email address"),
16
- role: z.enum(["admin", "editor", "user"]),
17
- fullName: z.string().min(2, "Full name must be at least 2 characters")
18
- });
19
- ```
20
-
21
- Verify states on submit:
22
-
23
- ```tsx
24
- const onSubmit = (data: unknown) => {
25
- const result = CreateUserFormSchema.safeParse(data);
26
- if (!result.success) {
27
- const fieldErrors = result.error.formErrors.fieldErrors;
28
- setErrors(fieldErrors);
29
- return;
30
- }
31
-
32
- // Submit verified payload
33
- submitPayload(result.data);
34
- };
35
- ```
36
-
37
- ---
38
-
39
- > [!IMPORTANT]
40
- > **Keyboard Traps:** Ensure form fields support keyboard navigation (`Tab` index navigation) and submit correctly upon hitting `Enter` when inside an active field.
@@ -1,37 +0,0 @@
1
- # Frontend Notifications & Sonner Toaster Integration
2
-
3
- This document defines the integration steps, design tokens, and accessibility standards for frontend notifications inside your React/Vite applications.
4
-
5
- ---
6
-
7
- ## 💻 Toaster Configuration
8
-
9
- Place the custom Sonner Toaster container in your root layout:
10
-
11
- ```tsx
12
- import { Toaster } from "sonner";
13
-
14
- export const RootLayout = ({ children }) => {
15
- return (
16
- <>
17
- <Toaster
18
- theme="dark"
19
- position="bottom-right"
20
- toastOptions={{
21
- style: {
22
- background: "#121214",
23
- border: "1px solid #29292e",
24
- color: "#e1e1e6"
25
- }
26
- }}
27
- />
28
- <main>{children}</main>
29
- </>
30
- );
31
- };
32
- ```
33
-
34
- ---
35
-
36
- > [!TIP]
37
- > **Dynamic Action Toasts:** For high-risk administrative operations (such as user suspends), toast messages must present a valid action hook button to undo the action instantly.
@@ -1,182 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { getFrameworkDir } from "../utils.js";
4
- import { GET_ACADEMY_PERFORMANCE_ARGS_SCHEMA, GET_AGENT_AUDIT_REPORT_ARGS_SCHEMA, LOG_AGENT_ACTION_ARGS_SCHEMA } from "../schemas.js";
5
- export const academyTools = [
6
- {
7
- name: "get_academy_performance",
8
- description: "Aggregates performance data from all agents to provide a global overview of the Academy's health and intelligence growth.",
9
- inputSchema: {
10
- type: "object",
11
- properties: {
12
- periodDays: {
13
- type: "number",
14
- description: "Number of days to include in the report",
15
- default: 30,
16
- },
17
- },
18
- },
19
- },
20
- {
21
- name: "generate_strategic_briefing",
22
- description: "Generates a high-level strategic briefing for the user, summarizing Academy health, progress, and future strategy.",
23
- inputSchema: {
24
- type: "object",
25
- properties: {
26
- focusArea: {
27
- type: "string",
28
- description: "Optional area to focus on (e.g. 'quality', 'velocity', 'architecture')",
29
- },
30
- },
31
- },
32
- },
33
- {
34
- name: "generate_academy_progress_report",
35
- description: "Generates a comprehensive narrative report on the Academy's progress, milestones, and challenges.",
36
- inputSchema: {
37
- type: "object",
38
- properties: {
39
- days: {
40
- type: "number",
41
- description: "Number of days to include in the report",
42
- default: 7,
43
- },
44
- },
45
- },
46
- },
47
- {
48
- name: "get_agent_audit_report",
49
- description: "Generates a summary report of an agent's activities based on their logs. Useful for self-improvement and progress tracking.",
50
- inputSchema: {
51
- type: "object",
52
- properties: {
53
- agent: {
54
- type: "string",
55
- description: "Agent name (e.g. analyst, backend)",
56
- },
57
- days: {
58
- type: "number",
59
- description: "Number of recent days to analyze",
60
- default: 7,
61
- },
62
- },
63
- required: ["agent"],
64
- },
65
- },
66
- {
67
- name: "log_agent_action",
68
- description: "Safely append a structured log entry to the agent's log file.",
69
- inputSchema: {
70
- type: "object",
71
- properties: {
72
- agent: { type: "string", description: "Agent name" },
73
- action: { type: "string", description: "Action performed" },
74
- requestId: { type: "string", description: "Trace ID or Request ID" },
75
- files: { type: "array", items: { type: "string" }, description: "Files affected" },
76
- status: { type: "string", enum: ["SUCCESS", "FAILURE"], description: "Action status" },
77
- summary: { type: "string", description: "Short English summary" },
78
- details: { type: "object", description: "Additional details" },
79
- },
80
- required: ["agent", "action", "requestId", "status", "summary"],
81
- },
82
- },
83
- ];
84
- export const academyHandlers = {
85
- get_academy_performance: async (args, projectRoot) => {
86
- const parsed = GET_ACADEMY_PERFORMANCE_ARGS_SCHEMA.safeParse(args ?? {});
87
- const days = parsed.success ? parsed.data.periodDays : 30;
88
- try {
89
- const frameworkDir = getFrameworkDir(projectRoot);
90
- const logsDir = path.join(projectRoot, frameworkDir, "logs");
91
- if (!fs.existsSync(logsDir))
92
- return { content: [{ type: "text", text: "No logs found." }] };
93
- const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
94
- let totalActions = 0, totalSuccess = 0;
95
- const agentStats = fs.readdirSync(logsDir).filter(f => f.endsWith(".json")).map(file => {
96
- const logs = JSON.parse(fs.readFileSync(path.join(logsDir, file), "utf-8")).filter((l) => new Date(l.timestamp) >= cutoff);
97
- const success = logs.filter((l) => l.status === "SUCCESS").length;
98
- totalActions += logs.length;
99
- totalSuccess += success;
100
- return { agent: file.replace(".json", ""), actions: logs.length, successRate: (success / (logs.length || 1)) * 100 };
101
- }).filter(s => s.actions > 0);
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
- }
104
- catch {
105
- return { content: [{ type: "text", text: "Failed to generate global performance report." }] };
106
- }
107
- },
108
- generate_strategic_briefing: async (args, projectRoot) => {
109
- try {
110
- const frameworkDir = getFrameworkDir(projectRoot);
111
- const logsDir = path.join(projectRoot, frameworkDir, "logs");
112
- let totalActions = 0, successCount = 0;
113
- if (fs.existsSync(logsDir)) {
114
- fs.readdirSync(logsDir).filter(f => f.endsWith(".json")).forEach(file => {
115
- const logs = JSON.parse(fs.readFileSync(path.join(logsDir, file), "utf-8"));
116
- totalActions += logs.length;
117
- successCount += logs.filter((l) => l.status === "SUCCESS").length;
118
- });
119
- }
120
- const successRate = (successCount / (totalActions || 1)) * 100;
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
- }
123
- catch {
124
- return { content: [{ type: "text", text: "Strategic briefing generation failed." }] };
125
- }
126
- },
127
- generate_academy_progress_report: async (args, projectRoot) => {
128
- try {
129
- const frameworkDir = getFrameworkDir(projectRoot);
130
- const memoryPath = path.join(projectRoot, frameworkDir, "PROJECT_MEMORY.md");
131
- const memoryContent = fs.existsSync(memoryPath) ? fs.readFileSync(memoryPath, "utf-8") : "";
132
- const historySection = memoryContent.match(/## HISTORY[\s\S]*$/m)?.[0] ?? "";
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");
134
- return { content: [{ type: "text", text: `# 🎓 AGENT ACADEMY PROGRESS REPORT\n\n## 🏆 Key Milestones Achieved\n${milestones}` }] };
135
- }
136
- catch {
137
- return { content: [{ type: "text", text: "Failed to generate progress report." }] };
138
- }
139
- },
140
- get_agent_audit_report: async (args, projectRoot) => {
141
- const parsed = GET_AGENT_AUDIT_REPORT_ARGS_SCHEMA.safeParse(args ?? {});
142
- if (!parsed.success)
143
- return { content: [{ type: "text", text: "Invalid agent or days argument." }] };
144
- try {
145
- const frameworkDir = getFrameworkDir(projectRoot);
146
- const logPath = path.join(projectRoot, frameworkDir, "logs", `${parsed.data.agent}.json`);
147
- if (!fs.existsSync(logPath))
148
- return { content: [{ type: "text", text: `No logs found for agent: ${parsed.data.agent}` }] };
149
- const cutoff = new Date(Date.now() - parsed.data.days * 24 * 60 * 60 * 1000);
150
- const logs = JSON.parse(fs.readFileSync(logPath, "utf-8")).filter((l) => new Date(l.timestamp) >= cutoff);
151
- const successCount = logs.filter((l) => l.status === "SUCCESS").length;
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)}%` }] };
153
- }
154
- catch {
155
- return { content: [{ type: "text", text: "Failed to generate audit report." }] };
156
- }
157
- },
158
- log_agent_action: async (args, projectRoot) => {
159
- const parsed = LOG_AGENT_ACTION_ARGS_SCHEMA.safeParse(args ?? {});
160
- if (!parsed.success)
161
- return { content: [{ type: "text", text: "Invalid arguments for log_agent_action." }] };
162
- try {
163
- const frameworkDir = getFrameworkDir(projectRoot);
164
- const logsDir = path.join(projectRoot, frameworkDir, "logs");
165
- if (!fs.existsSync(logsDir))
166
- fs.mkdirSync(logsDir, { recursive: true });
167
- const logPath = path.join(logsDir, `${parsed.data.agent}.json`);
168
- let logs = fs.existsSync(logPath) ? JSON.parse(fs.readFileSync(logPath, "utf-8")) : [];
169
- if (!Array.isArray(logs))
170
- logs = [];
171
- const requestId = parsed.data.requestId;
172
- if (requestId !== "—" && !/^[0-9A-Z]{26}$/.test(requestId))
173
- return { content: [{ type: "text", text: "ERROR: requestId MUST be a 26-character ULID." }] };
174
- logs.push({ timestamp: new Date().toISOString(), ...parsed.data });
175
- fs.writeFileSync(logPath, JSON.stringify(logs, null, 2));
176
- return { content: [{ type: "text", text: `SUCCESS: Logged action to ${parsed.data.agent}.json` }] };
177
- }
178
- catch {
179
- return { content: [{ type: "text", text: "Failed to log action." }] };
180
- }
181
- },
182
- };
@@ -1,57 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { Project } from "ts-morph";
4
- import { resolveSafePath } from "../utils.js";
5
- import { ANALYZE_DATABASE_SCHEMA_ARGS_SCHEMA } from "../schemas.js";
6
- export const databaseTools = [
7
- {
8
- name: "analyze_database_schema",
9
- description: "Scans the backend codebase (e.g., Kysely migrations or Prisma schemas) to extract and visualize the database schema as a Mermaid ER diagram.",
10
- inputSchema: {
11
- type: "object",
12
- properties: {
13
- path: { type: "string", description: "Path to scan for DB definitions", default: "apps/backend" },
14
- },
15
- },
16
- },
17
- ];
18
- export const databaseHandlers = {
19
- analyze_database_schema: async (args, projectRoot) => {
20
- const parsed = ANALYZE_DATABASE_SCHEMA_ARGS_SCHEMA.safeParse(args ?? {});
21
- const targetPath = parsed.success ? parsed.data.path : "apps/backend";
22
- try {
23
- const safeTargetPath = resolveSafePath(projectRoot, targetPath);
24
- if (!fs.existsSync(safeTargetPath))
25
- return { content: [{ type: "text", text: "Database path not found." }] };
26
- const tsProject = new Project();
27
- tsProject.addSourceFilesAtPaths(path.join(safeTargetPath, "**/*.{ts,tsx}"));
28
- let mermaid = "erDiagram\n", tablesFound = 0;
29
- for (const sourceFile of tsProject.getSourceFiles()) {
30
- const text = sourceFile.getFullText();
31
- const tableMatches = Array.from(text.matchAll(/\.createTable\(['"]([^'"]+)['"]\)/g));
32
- for (let i = 0; i < tableMatches.length; i++) {
33
- const match = tableMatches[i];
34
- const tableName = match[1];
35
- tablesFound++;
36
- mermaid += ` ${tableName} {\n`;
37
- const startIndex = match.index ?? 0;
38
- const nextMatch = tableMatches[i + 1];
39
- const endIndex = nextMatch ? (nextMatch.index ?? text.length) : text.length;
40
- const tableBlockText = text.substring(startIndex, endIndex);
41
- const colRegex = /\.addColumn\(['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g;
42
- let colMatch;
43
- while ((colMatch = colRegex.exec(tableBlockText)) !== null) {
44
- mermaid += ` ${colMatch[2].replace(/[^a-zA-Z0-9]/g, '_')} ${colMatch[1]}\n`;
45
- }
46
- mermaid += ` }\n`;
47
- }
48
- }
49
- if (tablesFound === 0)
50
- return { content: [{ type: "text", text: "No database tables detected." }] };
51
- return { content: [{ type: "text", text: `### DATABASE SCHEMA MAP\n\n\`\`\`mermaid\n${mermaid}\n\`\`\`\n\n**Total Tables Detected:** ${tablesFound}` }] };
52
- }
53
- catch {
54
- return { content: [{ type: "text", text: "Database schema analysis failed." }] };
55
- }
56
- },
57
- };
@@ -1,101 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { spawnSync } from "child_process";
4
- import { Project } from "ts-morph";
5
- import { resolveSafePath } from "../utils.js";
6
- import { VALIDATE_REPOSITORY_HEALTH_ARGS_SCHEMA, ANALYZE_DOCUMENTATION_DEBT_ARGS_SCHEMA } from "../schemas.js";
7
- export const repositoryTools = [
8
- {
9
- name: "validate_repository_health",
10
- description: "Runs project health checks (lint, test, build) before critical actions like commits.",
11
- inputSchema: {
12
- type: "object",
13
- properties: {
14
- scope: { type: "string", enum: ["full", "lint", "test", "build"], default: "full" },
15
- },
16
- },
17
- },
18
- {
19
- name: "analyze_documentation_debt",
20
- description: "Scans the codebase for missing documentation, including JSDoc, READMEs, and API contracts.",
21
- inputSchema: {
22
- type: "object",
23
- properties: {
24
- path: { type: "string", description: "Path to scan (relative to project root)", default: "." },
25
- },
26
- },
27
- },
28
- ];
29
- export const repositoryHandlers = {
30
- validate_repository_health: async (args, projectRoot) => {
31
- const parsed = VALIDATE_REPOSITORY_HEALTH_ARGS_SCHEMA.safeParse(args ?? {});
32
- const scope = parsed.success ? parsed.data.scope : "full";
33
- try {
34
- const pkgPath = path.join(projectRoot, "package.json");
35
- if (!fs.existsSync(pkgPath))
36
- return { content: [{ type: "text", text: "package.json not found." }] };
37
- const scripts = JSON.parse(fs.readFileSync(pkgPath, "utf-8")).scripts || {};
38
- const scriptCandidates = {
39
- lint: ["lint", "enderun:lint"],
40
- test: ["test", "enderun:test"],
41
- build: ["build", "enderun:build"],
42
- };
43
- const runScript = (name) => {
44
- const scriptName = scriptCandidates[name].find((candidate) => scripts[candidate]);
45
- if (!scriptName)
46
- return { name, script: "-", status: "SKIPPED", details: "No matching script found." };
47
- const result = spawnSync("npm", ["run", scriptName], {
48
- cwd: projectRoot,
49
- encoding: "utf-8",
50
- stdio: "pipe",
51
- });
52
- const output = `${result.stdout || ""}${result.stderr || ""}`.trim();
53
- return {
54
- name,
55
- script: scriptName,
56
- status: result.status === 0 ? "PASSED" : "FAILED",
57
- details: output.split("\n").slice(-5).join("\n"),
58
- };
59
- };
60
- const results = [];
61
- if (scope === "full" || scope === "lint")
62
- results.push(runScript("lint"));
63
- if (scope === "full" || scope === "test")
64
- results.push(runScript("test"));
65
- if (scope === "full" || scope === "build")
66
- results.push(runScript("build"));
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
- }
69
- catch {
70
- return { content: [{ type: "text", text: "Failed to analyze repository health." }] };
71
- }
72
- },
73
- analyze_documentation_debt: async (args, projectRoot) => {
74
- const parsed = ANALYZE_DOCUMENTATION_DEBT_ARGS_SCHEMA.safeParse(args ?? {});
75
- const targetPath = parsed.success ? parsed.data.path : ".";
76
- try {
77
- const safeTargetPath = resolveSafePath(projectRoot, targetPath);
78
- const tsProject = new Project();
79
- tsProject.addSourceFilesAtPaths(path.join(safeTargetPath, "**/*.{ts,tsx}"));
80
- const missingJSDoc = [];
81
- for (const sourceFile of tsProject.getSourceFiles()) {
82
- const relativePath = path.relative(projectRoot, sourceFile.getFilePath());
83
- if (relativePath.includes("node_modules") || relativePath.includes("dist"))
84
- continue;
85
- sourceFile.getExportedDeclarations().forEach((declarations, name) => {
86
- declarations.forEach(decl => {
87
- const d = decl;
88
- if (typeof d.getJsDocs === "function" && d.getJsDocs().length === 0) {
89
- missingJSDoc.push(`${relativePath} -> ${name}`);
90
- }
91
- });
92
- });
93
- }
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
- 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
- }
97
- catch {
98
- return { content: [{ type: "text", text: "Failed to analyze documentation debt." }] };
99
- }
100
- },
101
- };
@@ -1,132 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { resolveSafePath, getFrameworkDir } from "../utils.js";
4
- import { INSTANTIATE_BLUEPRINT_ARGS_SCHEMA, LIST_BLUEPRINTS_ARGS_SCHEMA, SAVE_AS_BLUEPRINT_ARGS_SCHEMA } from "../schemas.js";
5
- export const scaffoldTools = [
6
- {
7
- name: "instantiate_blueprint",
8
- description: "Clones a Gold Standard capability from .enderun/blueprints into the application source.",
9
- inputSchema: {
10
- type: "object",
11
- properties: {
12
- blueprintPath: { type: "string", description: "Relative path within blueprints/ (e.g., backend/errors)" },
13
- targetPath: { type: "string", description: "Target directory in the app (e.g., apps/backend/src/errors)" },
14
- },
15
- required: ["blueprintPath", "targetPath"],
16
- },
17
- },
18
- {
19
- name: "save_as_blueprint",
20
- description: "Saves or updates a high-quality code pattern as a Gold Standard blueprint for reuse.",
21
- inputSchema: {
22
- type: "object",
23
- properties: {
24
- blueprintPath: { type: "string", description: "Target relative path in blueprints/ (e.g., frontend/ui/Button.tsx)" },
25
- content: { type: "string", description: "The full source code of the blueprint" },
26
- description: { type: "string", description: "Brief description of what this blueprint provides" },
27
- },
28
- required: ["blueprintPath", "content"],
29
- },
30
- },
31
- {
32
- name: "list_blueprints",
33
- description: "Lists all available Gold Standard blueprints in the framework.",
34
- inputSchema: {
35
- type: "object",
36
- properties: {
37
- category: { type: "string", enum: ["backend", "frontend"], description: "Optional category to filter blueprints" },
38
- },
39
- },
40
- },
41
- ];
42
- export const scaffoldHandlers = {
43
- instantiate_blueprint: async (args, projectRoot) => {
44
- const parsed = INSTANTIATE_BLUEPRINT_ARGS_SCHEMA.safeParse(args);
45
- if (!parsed.success)
46
- return { content: [{ type: "text", text: `Invalid arguments: ${parsed.error.message}` }] };
47
- const { blueprintPath, targetPath } = parsed.data;
48
- const frameworkDir = getFrameworkDir(projectRoot);
49
- const sourceDir = resolveSafePath(projectRoot, path.join(frameworkDir, "blueprints", blueprintPath));
50
- const destDir = resolveSafePath(projectRoot, targetPath);
51
- try {
52
- if (!fs.existsSync(sourceDir)) {
53
- return { content: [{ type: "text", text: `Blueprint not found: ${blueprintPath}` }] };
54
- }
55
- // Create target directory if it doesn't exist
56
- fs.mkdirSync(path.dirname(destDir), { recursive: true });
57
- // Copy recursively
58
- // Using cpSync which is available in Node.js 16.7.0+
59
- fs.cpSync(sourceDir, destDir, { recursive: true });
60
- return { content: [{ type: "text", text: `Successfully instantiated blueprint '${blueprintPath}' into '${targetPath}'` }] };
61
- }
62
- catch (error) {
63
- const message = error instanceof Error ? error.message : "Unknown error";
64
- return { content: [{ type: "text", text: `Scaffold failed: ${message}` }] };
65
- }
66
- },
67
- save_as_blueprint: async (args, projectRoot) => {
68
- const parsed = SAVE_AS_BLUEPRINT_ARGS_SCHEMA.safeParse(args);
69
- if (!parsed.success)
70
- return { content: [{ type: "text", text: `Invalid arguments: ${parsed.error.message}` }] };
71
- const { blueprintPath, content, description } = parsed.data;
72
- const frameworkDir = getFrameworkDir(projectRoot);
73
- const targetFile = resolveSafePath(projectRoot, path.join(frameworkDir, "blueprints", blueprintPath));
74
- try {
75
- // Ensure the blueprints subdirectory exists
76
- fs.mkdirSync(path.dirname(targetFile), { recursive: true });
77
- // Write the blueprint content
78
- fs.writeFileSync(targetFile, content, "utf-8");
79
- // Optionally write a .metadata file if description provided
80
- if (description) {
81
- const metaFile = `${targetFile}.metadata.json`;
82
- fs.writeFileSync(metaFile, JSON.stringify({ description, savedAt: new Date().toISOString() }, null, 2), "utf-8");
83
- }
84
- return { content: [{ type: "text", text: `Successfully saved blueprint to '${blueprintPath}'` }] };
85
- }
86
- catch (error) {
87
- const message = error instanceof Error ? error.message : "Unknown error";
88
- return { content: [{ type: "text", text: `Failed to save blueprint: ${message}` }] };
89
- }
90
- },
91
- list_blueprints: async (args, projectRoot) => {
92
- const parsed = LIST_BLUEPRINTS_ARGS_SCHEMA.safeParse(args ?? {});
93
- const category = parsed.success ? parsed.data.category : undefined;
94
- const frameworkDir = getFrameworkDir(projectRoot);
95
- const blueprintsRoot = path.join(projectRoot, frameworkDir, "blueprints");
96
- try {
97
- if (!fs.existsSync(blueprintsRoot)) {
98
- return { content: [{ type: "text", text: "Blueprints directory not found." }] };
99
- }
100
- const walk = (dir) => {
101
- const results = [];
102
- if (!fs.existsSync(dir))
103
- return results;
104
- const entries = fs.readdirSync(dir, { withFileTypes: true });
105
- for (const entry of entries) {
106
- const res = path.join(dir, entry.name);
107
- if (entry.isDirectory()) {
108
- // If it's a leaf directory containing files, or we want to show all dirs
109
- const subEntries = fs.readdirSync(res);
110
- const hasFiles = subEntries.some(e => !fs.lstatSync(path.join(res, e)).isDirectory());
111
- if (hasFiles) {
112
- results.push(path.relative(blueprintsRoot, res));
113
- }
114
- results.push(...walk(res));
115
- }
116
- }
117
- return results;
118
- };
119
- let available = walk(blueprintsRoot);
120
- if (category) {
121
- available = available.filter(b => b.startsWith(category));
122
- }
123
- // Remove duplicates
124
- available = Array.from(new Set(available));
125
- return { content: [{ type: "text", text: `### AVAILABLE BLUEPRINTS\n\n` + available.map(b => `- ${b}`).join("\n") }] };
126
- }
127
- catch (error) {
128
- const message = error instanceof Error ? error.message : "Unknown error";
129
- return { content: [{ type: "text", text: `Listing blueprints failed: ${message}` }] };
130
- }
131
- },
132
- };