agent-enderun 0.5.9 → 0.6.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.
- package/.enderun/PROJECT_MEMORY.md +17 -32
- package/.enderun/STATUS.md +19 -10
- package/.enderun/agents/analyst.md +9 -2
- package/.enderun/agents/backend.md +23 -12
- package/.enderun/agents/explorer.md +2 -2
- package/.enderun/agents/frontend.md +21 -10
- package/.enderun/agents/git.md +1 -1
- package/.enderun/agents/manager.md +10 -2
- package/.enderun/agents/mobile.md +1 -1
- package/.enderun/agents/native.md +1 -1
- package/.enderun/blueprints/backend/types/index.ts +49 -0
- package/{packages/shared-types/src → .enderun/blueprints/backend/types}/models.ts +0 -1
- package/.enderun/docs/api/README.md +7 -12
- package/.enderun/docs/project-docs.md +17 -7
- package/.enderun/knowledge/blueprint_driven_construction.md +22 -0
- package/.enderun/knowledge/code_review_checklist.md +1 -1
- package/.enderun/knowledge/contract_versioning.md +5 -5
- package/ENDERUN.md +6 -6
- package/README.md +39 -22
- package/bin/cli.js +205 -27
- package/{packages/framework-mcp → framework-mcp}/dist/index.js +0 -0
- package/{packages/framework-mcp → framework-mcp}/dist/schemas.js +12 -0
- package/{packages/framework-mcp → framework-mcp}/dist/tools/contract.js +5 -5
- package/{packages/framework-mcp → framework-mcp}/dist/tools/framework.js +3 -2
- package/{packages/framework-mcp → framework-mcp}/dist/tools/git.js +2 -4
- package/{packages/framework-mcp → framework-mcp}/dist/tools/index.js +3 -0
- package/{packages/framework-mcp → framework-mcp}/dist/tools/repository.js +1 -1
- package/framework-mcp/dist/tools/scaffold.js +129 -0
- package/{packages/framework-mcp → framework-mcp}/dist/utils.js +1 -1
- package/{packages/framework-mcp → framework-mcp}/package.json +1 -1
- package/{packages/framework-mcp → framework-mcp}/src/schemas.ts +15 -0
- package/{packages/framework-mcp → framework-mcp}/src/tools/contract.ts +5 -5
- package/{packages/framework-mcp → framework-mcp}/src/tools/framework.ts +3 -2
- package/{packages/framework-mcp → framework-mcp}/src/tools/git.ts +2 -3
- package/{packages/framework-mcp → framework-mcp}/src/tools/index.ts +3 -0
- package/{packages/framework-mcp → framework-mcp}/src/tools/repository.ts +1 -1
- package/framework-mcp/src/tools/scaffold.ts +147 -0
- package/{packages/framework-mcp → framework-mcp}/src/utils.ts +1 -1
- package/package.json +7 -11
- package/.enderun/logs/manager.json +0 -1
- package/packages/shared-types/README.md +0 -61
- package/packages/shared-types/contract.version.json +0 -12
- package/packages/shared-types/dist/api.d.ts +0 -18
- package/packages/shared-types/dist/api.js +0 -2
- package/packages/shared-types/dist/api.js.map +0 -1
- package/packages/shared-types/dist/brands.d.ts +0 -13
- package/packages/shared-types/dist/brands.js +0 -2
- package/packages/shared-types/dist/brands.js.map +0 -1
- package/packages/shared-types/dist/constants.d.ts +0 -27
- package/packages/shared-types/dist/constants.js +0 -22
- package/packages/shared-types/dist/constants.js.map +0 -1
- package/packages/shared-types/dist/index.d.ts +0 -11
- package/packages/shared-types/dist/index.js +0 -12
- package/packages/shared-types/dist/index.js.map +0 -1
- package/packages/shared-types/dist/logs.d.ts +0 -15
- package/packages/shared-types/dist/logs.js +0 -2
- package/packages/shared-types/dist/logs.js.map +0 -1
- package/packages/shared-types/dist/models.d.ts +0 -60
- package/packages/shared-types/dist/models.js +0 -2
- package/packages/shared-types/dist/models.js.map +0 -1
- package/packages/shared-types/package.json +0 -36
- package/packages/shared-types/src/index.ts +0 -12
- package/packages/shared-types/tsconfig.json +0 -9
- /package/{packages/shared-types/src → .enderun/blueprints/backend/types}/api.ts +0 -0
- /package/{packages/shared-types/src → .enderun/blueprints/backend/types}/brands.ts +0 -0
- /package/{packages/shared-types/src → .enderun/blueprints/backend/types}/constants.ts +0 -0
- /package/{packages/shared-types/src → .enderun/blueprints/backend/types}/logs.ts +0 -0
- /package/{packages/framework-mcp → framework-mcp}/README.md +0 -0
- /package/{packages/framework-mcp → framework-mcp}/dist/tools/academy.js +0 -0
- /package/{packages/framework-mcp → framework-mcp}/dist/tools/codebase.js +0 -0
- /package/{packages/framework-mcp → framework-mcp}/dist/tools/database.js +0 -0
- /package/{packages/framework-mcp → framework-mcp}/dist/tools/knowledge.js +0 -0
- /package/{packages/framework-mcp → framework-mcp}/dist/tools/memory.js +0 -0
- /package/{packages/framework-mcp → framework-mcp}/dist/tools/messages.js +0 -0
- /package/{packages/framework-mcp → framework-mcp}/dist/tools/security.js +0 -0
- /package/{packages/framework-mcp → framework-mcp}/src/index.ts +0 -0
- /package/{packages/framework-mcp → framework-mcp}/src/tools/academy.ts +0 -0
- /package/{packages/framework-mcp → framework-mcp}/src/tools/codebase.ts +0 -0
- /package/{packages/framework-mcp → framework-mcp}/src/tools/database.ts +0 -0
- /package/{packages/framework-mcp → framework-mcp}/src/tools/knowledge.ts +0 -0
- /package/{packages/framework-mcp → framework-mcp}/src/tools/memory.ts +0 -0
- /package/{packages/framework-mcp → framework-mcp}/src/tools/messages.ts +0 -0
- /package/{packages/framework-mcp → framework-mcp}/src/tools/security.ts +0 -0
- /package/{packages/framework-mcp → framework-mcp}/tsconfig.json +0 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 🏛️ Agent Enderun (v0.
|
|
1
|
+
# 🏛️ Agent Enderun (v0.6.0) — The Supreme AI Governance Framework
|
|
2
2
|
|
|
3
3
|
**The Supreme AI Governance & Orchestration Framework for Enterprise Development**
|
|
4
4
|
|
|
@@ -317,28 +317,18 @@ agent-enderun/
|
|
|
317
317
|
├── bin/
|
|
318
318
|
│ └── cli.js ← CLI entry point
|
|
319
319
|
├── docs/ ← Your project docs (agents read these)
|
|
320
|
-
|
|
321
|
-
│ └──
|
|
322
|
-
├──
|
|
323
|
-
│
|
|
324
|
-
│
|
|
325
|
-
│
|
|
326
|
-
│ └── framework-mcp/ ← MCP server (40+ tools)
|
|
327
|
-
│ └── src/tools/
|
|
328
|
-
│ ├── academy.ts
|
|
329
|
-
│ ├── codebase.ts
|
|
330
|
-
│ ├── security.ts
|
|
331
|
-
│ ├── contract.ts
|
|
332
|
-
│ ├── git.ts
|
|
333
|
-
│ ├── knowledge.ts
|
|
334
|
-
│ ├── database.ts
|
|
335
|
-
│ ├── memory.ts
|
|
336
|
-
│ ├── messages.ts
|
|
337
|
-
│ ├── repository.ts
|
|
338
|
-
│ └── framework.ts
|
|
320
|
+
├── framework-mcp/ ← MCP server (40+ tools)
|
|
321
|
+
│ └── src/tools/
|
|
322
|
+
│ ├── scaffold.ts ← Blueprint construction
|
|
323
|
+
│ ├── academy.ts
|
|
324
|
+
│ ├── codebase.ts
|
|
325
|
+
│ └── [10 more...]
|
|
339
326
|
├── apps/ ← Your applications (start here)
|
|
340
|
-
│ ├── backend/
|
|
341
|
-
│
|
|
327
|
+
│ ├── backend/
|
|
328
|
+
│ │ ├── src/types/ ← App-local contract types
|
|
329
|
+
│ │ └── contract.version.json ← SHA-256 integrity hash
|
|
330
|
+
│ └── web/
|
|
331
|
+
│ └── src/types/ ← Frontend mirrors of backend types
|
|
342
332
|
└── {{FRAMEWORK_DIR}}/ ← Framework governance
|
|
343
333
|
├── ENDERUN.md ← Constitution (MANDATORY READ)
|
|
344
334
|
├── PROJECT_MEMORY.md ← State machine
|
|
@@ -748,3 +738,30 @@ All governance and engineering assets are consolidated under the framework direc
|
|
|
748
738
|
|
|
749
739
|
## 📜 License
|
|
750
740
|
MIT © 2026 Yusuf BEKAR — **Agent Enderun: The Future of AI Governance.**
|
|
741
|
+
unctional.
|
|
742
|
+
- **Branded Types:** IDs must be type-safe (e.g., `UserID` vs `string`).
|
|
743
|
+
- **Panda CSS Only:** Zero-runtime CSS-in-JS for high-performance UI.
|
|
744
|
+
- **Contract-First:** Schemas are defined in `shared-types` BEFORE implementation.
|
|
745
|
+
|
|
746
|
+
---
|
|
747
|
+
|
|
748
|
+
## 📜 License
|
|
749
|
+
MIT © 2026 Yusuf BEKAR — **Agent Enderun: The Future of AI Governance.**
|
|
750
|
+
/ # CLI Entry Point
|
|
751
|
+
├── packages/ # Shared Types & MCP Engine
|
|
752
|
+
└── apps/ # Production Modules (Backend, Web, Mobile)
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
---
|
|
756
|
+
|
|
757
|
+
## 🛡️ Engineering Standards
|
|
758
|
+
|
|
759
|
+
- **Zero Mock Policy:** Placeholders are forbidden. Every line of code must be functional.
|
|
760
|
+
- **Branded Types:** IDs must be type-safe (e.g., `UserID` vs `string`).
|
|
761
|
+
- **Panda CSS Only:** Zero-runtime CSS-in-JS for high-performance UI.
|
|
762
|
+
- **Contract-First:** Schemas are defined in `shared-types` BEFORE implementation.
|
|
763
|
+
|
|
764
|
+
---
|
|
765
|
+
|
|
766
|
+
## 📜 License
|
|
767
|
+
MIT © 2026 Yusuf BEKAR — **Agent Enderun: The Future of AI Governance.**
|
package/bin/cli.js
CHANGED
|
@@ -159,7 +159,7 @@ function mergePackageJson(targetPath, sourcePath) {
|
|
|
159
159
|
"enderun:check": "agent-enderun check",
|
|
160
160
|
"enderun:test": "vitest run",
|
|
161
161
|
"enderun:test:watch": "vitest",
|
|
162
|
-
"enderun:build": `${runCmd} build --prefix packages/shared-types && ${runCmd} build --prefix
|
|
162
|
+
"enderun:build": `${runCmd} build --prefix packages/shared-types && ${runCmd} build --prefix framework-mcp`,
|
|
163
163
|
};
|
|
164
164
|
|
|
165
165
|
const sourceDevDeps = sourcePkg.devDependencies || {};
|
|
@@ -337,8 +337,7 @@ async function initCommand(selectedAdapter) {
|
|
|
337
337
|
"package.json",
|
|
338
338
|
"tsconfig.json",
|
|
339
339
|
"panda.config.ts",
|
|
340
|
-
"
|
|
341
|
-
"packages/shared-types",
|
|
340
|
+
"framework-mcp",
|
|
342
341
|
];
|
|
343
342
|
|
|
344
343
|
const DIRS_TO_CREATE = [
|
|
@@ -353,8 +352,7 @@ async function initCommand(selectedAdapter) {
|
|
|
353
352
|
"apps/web",
|
|
354
353
|
"apps/backend",
|
|
355
354
|
"docs",
|
|
356
|
-
"
|
|
357
|
-
"packages/framework-mcp",
|
|
355
|
+
"framework-mcp",
|
|
358
356
|
];
|
|
359
357
|
|
|
360
358
|
console.log(`🚀 Installing Agent Enderun (Adapter: ${selectedAdapter || "all"})...`);
|
|
@@ -407,7 +405,7 @@ async function initCommand(selectedAdapter) {
|
|
|
407
405
|
let dest = path.join(targetDir, item);
|
|
408
406
|
|
|
409
407
|
// FORCED CLEANUP: Delete existing framework engine directory to ensure clean update
|
|
410
|
-
if (["
|
|
408
|
+
if (["framework-mcp"].includes(item)) {
|
|
411
409
|
if (fs.existsSync(dest)) {
|
|
412
410
|
try {
|
|
413
411
|
fs.rmSync(dest, { recursive: true, force: true });
|
|
@@ -432,7 +430,7 @@ async function initCommand(selectedAdapter) {
|
|
|
432
430
|
if (fs.existsSync(src)) {
|
|
433
431
|
if (fs.lstatSync(src).isDirectory()) {
|
|
434
432
|
const skipFiles = (item === ".enderun") ? ["logs", "PROJECT_MEMORY.md", "PROJECT_MEMORY.lock"] : [];
|
|
435
|
-
const nonDestructive = ["
|
|
433
|
+
const nonDestructive = ["docs", ".enderun"].includes(item);
|
|
436
434
|
copyDir(src, dest, new Set(skipFiles), nonDestructive, targetBase, targetScope);
|
|
437
435
|
} else {
|
|
438
436
|
if (item === "package.json") continue; // We merge it later
|
|
@@ -507,7 +505,7 @@ async function initCommand(selectedAdapter) {
|
|
|
507
505
|
ext.mcpServers = {
|
|
508
506
|
"agent-enderun": {
|
|
509
507
|
command: "node",
|
|
510
|
-
args: ["
|
|
508
|
+
args: ["framework-mcp/dist/index.js"]
|
|
511
509
|
}
|
|
512
510
|
};
|
|
513
511
|
fs.writeFileSync(geminiExtPath, JSON.stringify(ext, null, 2) + "\n");
|
|
@@ -519,7 +517,7 @@ async function initCommand(selectedAdapter) {
|
|
|
519
517
|
}
|
|
520
518
|
|
|
521
519
|
if (selectedAdapter === "claude") {
|
|
522
|
-
const mcpPath = path.join(targetDir, "
|
|
520
|
+
const mcpPath = path.join(targetDir, "framework-mcp/src/index.ts");
|
|
523
521
|
console.log("\n📝 Claude Code Setup:");
|
|
524
522
|
console.log("To enable Agent Enderun tools in Claude Code, run this command:");
|
|
525
523
|
console.log(`\x1b[36mclaude config add framework-mcp npx tsx ${mcpPath}\x1b[0m`);
|
|
@@ -612,8 +610,8 @@ function checkCommand() {
|
|
|
612
610
|
{ name: "Framework Config (config.json)", path: path.join(frameworkDir, "config.json") },
|
|
613
611
|
{ name: "Agent Status (STATUS.md)", path: path.join(frameworkDir, "STATUS.md") },
|
|
614
612
|
{ name: "MCP Config (mcp.json)", path: "mcp.json" },
|
|
615
|
-
{ name: "
|
|
616
|
-
{ name: "MCP Server", path: "
|
|
613
|
+
{ name: "Backend Contract", path: "apps/backend/contract.version.json" },
|
|
614
|
+
{ name: "MCP Server", path: "framework-mcp/package.json" },
|
|
617
615
|
{ name: "Tech Stack", path: path.join(frameworkDir, "docs/tech-stack.md") },
|
|
618
616
|
{ name: "Panda CSS Config", path: "panda.config.ts" },
|
|
619
617
|
{ name: "Requirements", path: path.join(frameworkDir, "docs/project-docs.md") },
|
|
@@ -633,7 +631,7 @@ function checkCommand() {
|
|
|
633
631
|
}
|
|
634
632
|
|
|
635
633
|
// Dependency Check
|
|
636
|
-
const mcpNodeModules = path.join(process.cwd(), "
|
|
634
|
+
const mcpNodeModules = path.join(process.cwd(), "framework-mcp/node_modules");
|
|
637
635
|
const rootNodeModules = path.join(process.cwd(), "node_modules");
|
|
638
636
|
if (!fs.existsSync(mcpNodeModules) && !fs.existsSync(rootNodeModules)) {
|
|
639
637
|
console.log("❌ Dependencies MISSING! (Run 'npm install')");
|
|
@@ -643,7 +641,7 @@ function checkCommand() {
|
|
|
643
641
|
}
|
|
644
642
|
|
|
645
643
|
// MCP Build Check
|
|
646
|
-
const mcpPath = path.join(process.cwd(), "
|
|
644
|
+
const mcpPath = path.join(process.cwd(), "framework-mcp/dist/index.js");
|
|
647
645
|
if (!fs.existsSync(mcpPath)) {
|
|
648
646
|
console.log("❌ MCP Build MISSING! (Run 'npm run enderun:build')");
|
|
649
647
|
issues++;
|
|
@@ -857,11 +855,11 @@ function traceNewCommand(description, agent = "manager", priority = "P2") {
|
|
|
857
855
|
* Verify the shared-types contract hash.
|
|
858
856
|
*/
|
|
859
857
|
function verifyContractCommand() {
|
|
860
|
-
const sharedDir = path.join(targetDir, "
|
|
861
|
-
const contractPath = path.join(targetDir, "
|
|
858
|
+
const sharedDir = path.join(targetDir, "apps/backend/src/types");
|
|
859
|
+
const contractPath = path.join(targetDir, "apps/backend/contract.version.json");
|
|
862
860
|
|
|
863
861
|
if (!fs.existsSync(sharedDir) || !fs.existsSync(contractPath)) {
|
|
864
|
-
console.error("❌ Error:
|
|
862
|
+
console.error("❌ Error: Backend types or contract.version.json not found.");
|
|
865
863
|
return;
|
|
866
864
|
}
|
|
867
865
|
|
|
@@ -953,7 +951,7 @@ function gitCommitCommand(traceId) {
|
|
|
953
951
|
const files = cp.execSync("git diff --staged --name-only", { encoding: "utf8" }).split("\n").filter(Boolean);
|
|
954
952
|
let type = "feat", scope = "code";
|
|
955
953
|
if (files.some(f => f.includes(".md"))) type = "docs";
|
|
956
|
-
else if (files.some(f => f.includes("
|
|
954
|
+
else if (files.some(f => f.includes("apps/backend/src/types"))) type = "arch";
|
|
957
955
|
else if (files.some(f => f.includes("bin/cli.js"))) type = "fix";
|
|
958
956
|
|
|
959
957
|
const summary = files.length === 1 ? `update ${path.basename(files[0])}` : `update ${files.length} files`;
|
|
@@ -1227,8 +1225,8 @@ function buildSharedTypesContent(existingContent) {
|
|
|
1227
1225
|
}
|
|
1228
1226
|
|
|
1229
1227
|
function updateContractHashFile() {
|
|
1230
|
-
const sharedDir = path.join(targetDir, "
|
|
1231
|
-
const contractPath = path.join(targetDir, "
|
|
1228
|
+
const sharedDir = path.join(targetDir, "apps/backend/src/types");
|
|
1229
|
+
const contractPath = path.join(targetDir, "apps/backend/contract.version.json");
|
|
1232
1230
|
if (!fs.existsSync(sharedDir) || !fs.existsSync(contractPath)) return;
|
|
1233
1231
|
|
|
1234
1232
|
const walk = (dir) => fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
@@ -1250,7 +1248,186 @@ function updateContractHashFile() {
|
|
|
1250
1248
|
fs.writeFileSync(contractPath, JSON.stringify(contract, null, 2));
|
|
1251
1249
|
}
|
|
1252
1250
|
|
|
1251
|
+
function createBaseTypeFiles(baseDir) {
|
|
1252
|
+
const typesDir = path.join(baseDir, "types");
|
|
1253
|
+
ensureDir(typesDir);
|
|
1254
|
+
|
|
1255
|
+
writeTextFile(path.join(typesDir, "api.ts"), `import { TraceID } from "./brands.js";
|
|
1256
|
+
|
|
1257
|
+
/**
|
|
1258
|
+
* API Response Wrappers
|
|
1259
|
+
*/
|
|
1260
|
+
export interface ApiResponse<T> {
|
|
1261
|
+
data: T;
|
|
1262
|
+
meta?: {
|
|
1263
|
+
requestId: TraceID;
|
|
1264
|
+
timestamp: string;
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
export interface ApiError {
|
|
1269
|
+
error: {
|
|
1270
|
+
code: string;
|
|
1271
|
+
message: string;
|
|
1272
|
+
details?: unknown;
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
`);
|
|
1276
|
+
|
|
1277
|
+
writeTextFile(path.join(typesDir, "brands.ts"), `/**
|
|
1278
|
+
* Branded Type Utility
|
|
1279
|
+
*/
|
|
1280
|
+
export type Brand<K, T> = K & { __brand: T };
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* Entity IDs (Branded)
|
|
1284
|
+
*/
|
|
1285
|
+
export type TraceID = Brand<string, "TraceID">;
|
|
1286
|
+
export type AgentID = Brand<string, "AgentID">;
|
|
1287
|
+
export type ProjectID = Brand<string, "ProjectID">;
|
|
1288
|
+
export type UserID = Brand<string, "UserID">;
|
|
1289
|
+
`);
|
|
1290
|
+
|
|
1291
|
+
writeTextFile(path.join(typesDir, "constants.ts"), `import { TraceID } from "./brands.js";
|
|
1292
|
+
|
|
1293
|
+
/**
|
|
1294
|
+
* Project Phases
|
|
1295
|
+
*/
|
|
1296
|
+
export const PROJECT_PHASES = ["PHASE_0", "PHASE_1", "PHASE_2", "PHASE_3", "PHASE_4"] as const;
|
|
1297
|
+
export type ProjectPhase = (typeof PROJECT_PHASES)[number];
|
|
1298
|
+
|
|
1299
|
+
/**
|
|
1300
|
+
* Execution Profiles
|
|
1301
|
+
*/
|
|
1302
|
+
export const EXECUTION_PROFILES = ["Lightweight", "Full"] as const;
|
|
1303
|
+
export type ExecutionProfile = (typeof EXECUTION_PROFILES)[number];
|
|
1304
|
+
|
|
1305
|
+
/**
|
|
1306
|
+
* Task Priorities
|
|
1307
|
+
*/
|
|
1308
|
+
export const TASK_PRIORITIES = ["P0", "P1", "P2", "P3"] as const;
|
|
1309
|
+
export type TaskPriority = (typeof TASK_PRIORITIES)[number];
|
|
1310
|
+
|
|
1311
|
+
/**
|
|
1312
|
+
* Task Statuses
|
|
1313
|
+
*/
|
|
1314
|
+
export const TASK_STATUSES = ["PENDING", "IN_PROGRESS", "BLOCKED", "COMPLETED", "FAILED"] as const;
|
|
1315
|
+
export type TaskStatus = (typeof TASK_STATUSES)[number];
|
|
1316
|
+
|
|
1317
|
+
/**
|
|
1318
|
+
* Action Types & Status
|
|
1319
|
+
*/
|
|
1320
|
+
export const ACTION_TYPES = ["CREATE", "MODIFY", "DELETE", "RESEARCH", "ORCHESTRATE"] as const;
|
|
1321
|
+
export type ActionType = (typeof ACTION_TYPES)[number];
|
|
1322
|
+
|
|
1323
|
+
export const ACTION_STATUSES = ["SUCCESS", "FAILURE", "WAITING"] as const;
|
|
1324
|
+
export type ActionStatus = (typeof ACTION_STATUSES)[number];
|
|
1325
|
+
`);
|
|
1326
|
+
|
|
1327
|
+
writeTextFile(path.join(typesDir, "index.ts"), `/**
|
|
1328
|
+
* Agent Enderun — App-Local Types (Modular)
|
|
1329
|
+
*/
|
|
1330
|
+
|
|
1331
|
+
export * from "./brands.js";
|
|
1332
|
+
export * from "./constants.js";
|
|
1333
|
+
export * from "./models.js";
|
|
1334
|
+
export * from "./api.js";
|
|
1335
|
+
export * from "./logs.js";
|
|
1336
|
+
`);
|
|
1337
|
+
|
|
1338
|
+
writeTextFile(path.join(typesDir, "logs.ts"), `import { TraceID, AgentID } from "./brands.js";
|
|
1339
|
+
import { ActionType, ActionStatus } from "./constants.js";
|
|
1340
|
+
|
|
1341
|
+
/**
|
|
1342
|
+
* Audit & Agent Logging Types
|
|
1343
|
+
*/
|
|
1344
|
+
export interface AgentActionLog {
|
|
1345
|
+
timestamp: string;
|
|
1346
|
+
agent: AgentID;
|
|
1347
|
+
action: ActionType;
|
|
1348
|
+
requestId: TraceID | "—";
|
|
1349
|
+
status: ActionStatus;
|
|
1350
|
+
summary: string;
|
|
1351
|
+
files?: string[];
|
|
1352
|
+
details?: Record<string, unknown>;
|
|
1353
|
+
}
|
|
1354
|
+
`);
|
|
1355
|
+
|
|
1356
|
+
writeTextFile(path.join(typesDir, "models.ts"), `import { UserID, TraceID, AgentID } from "./brands.js";
|
|
1357
|
+
import { ProjectPhase, ExecutionProfile, TaskPriority, TaskStatus } from "./constants.js";
|
|
1358
|
+
|
|
1359
|
+
/**
|
|
1360
|
+
* Base Entity Fields
|
|
1361
|
+
*/
|
|
1362
|
+
export interface BaseEntity {
|
|
1363
|
+
id: string; // Usually ULID
|
|
1364
|
+
createdAt: string;
|
|
1365
|
+
updatedAt: string;
|
|
1366
|
+
deletedAt?: string | null;
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
/**
|
|
1370
|
+
* Audit Log Model
|
|
1371
|
+
*/
|
|
1372
|
+
export interface AuditLog extends BaseEntity {
|
|
1373
|
+
entityName: string;
|
|
1374
|
+
entityId: string;
|
|
1375
|
+
action: "CREATE" | "UPDATE" | "DELETE" | "RESTORE";
|
|
1376
|
+
userId: UserID;
|
|
1377
|
+
previousState?: Record<string, unknown> | null;
|
|
1378
|
+
newState?: Record<string, unknown> | null;
|
|
1379
|
+
traceId: TraceID;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/**
|
|
1383
|
+
* User Model
|
|
1384
|
+
*/
|
|
1385
|
+
export interface User extends BaseEntity {
|
|
1386
|
+
id: UserID;
|
|
1387
|
+
email: string;
|
|
1388
|
+
fullName: string;
|
|
1389
|
+
role: "ADMIN" | "DEVELOPER" | "VIEWER";
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
export interface UserProfile extends User {
|
|
1393
|
+
avatarUrl?: string;
|
|
1394
|
+
bio?: string;
|
|
1395
|
+
preferences: Record<string, unknown>;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
/**
|
|
1399
|
+
* Project Status
|
|
1400
|
+
*/
|
|
1401
|
+
export interface ProjectStatus {
|
|
1402
|
+
phase: ProjectPhase;
|
|
1403
|
+
profile: ExecutionProfile;
|
|
1404
|
+
lastUpdate: string;
|
|
1405
|
+
activeTraceId: TraceID | null;
|
|
1406
|
+
blockers: string[];
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
/**
|
|
1410
|
+
* Task Model
|
|
1411
|
+
*/
|
|
1412
|
+
export interface Task {
|
|
1413
|
+
id: TraceID;
|
|
1414
|
+
description: string;
|
|
1415
|
+
agent: AgentID;
|
|
1416
|
+
priority: TaskPriority;
|
|
1417
|
+
status: TaskStatus;
|
|
1418
|
+
createdAt: string;
|
|
1419
|
+
updatedAt: string;
|
|
1420
|
+
}
|
|
1421
|
+
`);
|
|
1422
|
+
console.log(`✅ Base types created in ${path.relative(targetDir, typesDir)}`);
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1253
1425
|
function createBackendFiles(spec) {
|
|
1426
|
+
createBaseTypeFiles(path.join(targetDir, "apps/backend/src"));
|
|
1427
|
+
writeJsonFile(path.join(targetDir, "apps/backend/contract.version.json"), {
|
|
1428
|
+
"contract_hash": "initial_hash_placeholder",
|
|
1429
|
+
"last_updated": new Date().toISOString()
|
|
1430
|
+
});
|
|
1254
1431
|
writeJsonFile(path.join(targetDir, "apps/backend/package.json"), {
|
|
1255
1432
|
name: "@agent-enderun/backend",
|
|
1256
1433
|
version: "0.1.0",
|
|
@@ -1290,7 +1467,7 @@ function createBackendFiles(spec) {
|
|
|
1290
1467
|
});
|
|
1291
1468
|
|
|
1292
1469
|
writeTextFile(path.join(targetDir, "apps/backend/src/data.ts"), [
|
|
1293
|
-
'import type { Customer, DashboardSummary, ReportMetric, Role, User } from "
|
|
1470
|
+
'import type { Customer, DashboardSummary, ReportMetric, Role, User } from "./types/index.js";',
|
|
1294
1471
|
"",
|
|
1295
1472
|
'const now = new Date().toISOString();',
|
|
1296
1473
|
"",
|
|
@@ -1364,6 +1541,7 @@ function createBackendFiles(spec) {
|
|
|
1364
1541
|
}
|
|
1365
1542
|
|
|
1366
1543
|
function createWebFiles(spec) {
|
|
1544
|
+
createBaseTypeFiles(path.join(targetDir, "apps/web/src"));
|
|
1367
1545
|
writeJsonFile(path.join(targetDir, "apps/web/package.json"), {
|
|
1368
1546
|
name: "@agent-enderun/web",
|
|
1369
1547
|
version: "0.1.0",
|
|
@@ -1632,7 +1810,7 @@ function updateProjectDocs(spec) {
|
|
|
1632
1810
|
"",
|
|
1633
1811
|
"- `apps/backend`: Fastify API",
|
|
1634
1812
|
"- `apps/web`: React dashboard",
|
|
1635
|
-
"- `
|
|
1813
|
+
"- `apps/backend/src/types`: Contract-first backend TypeScript types",
|
|
1636
1814
|
].join("\n"));
|
|
1637
1815
|
|
|
1638
1816
|
writeTextFile(path.join(apiDir, "README.md"), [
|
|
@@ -1658,7 +1836,7 @@ function updateMemoryForGeneratedApp(spec, traceId) {
|
|
|
1658
1836
|
"- **Agent:** @manager",
|
|
1659
1837
|
`- **Trace ID:** ${traceId}`,
|
|
1660
1838
|
"- **Action:** Created full-stack starter from natural language request.",
|
|
1661
|
-
"- **Files:** apps/backend, apps/web,
|
|
1839
|
+
"- **Files:** apps/backend, apps/web, project docs",
|
|
1662
1840
|
].join("\n");
|
|
1663
1841
|
|
|
1664
1842
|
updateProjectMemoryCommand("HISTORY", history);
|
|
@@ -1693,10 +1871,10 @@ async function createAppCommand(args) {
|
|
|
1693
1871
|
createWebFiles(spec);
|
|
1694
1872
|
updateProjectDocs(spec);
|
|
1695
1873
|
|
|
1696
|
-
const
|
|
1697
|
-
if (fs.existsSync(
|
|
1698
|
-
const existing = fs.readFileSync(
|
|
1699
|
-
fs.writeFileSync(
|
|
1874
|
+
const backendTypesPath = path.join(targetDir, "apps/backend/src/types/index.ts");
|
|
1875
|
+
if (fs.existsSync(backendTypesPath)) {
|
|
1876
|
+
const existing = fs.readFileSync(backendTypesPath, "utf8");
|
|
1877
|
+
fs.writeFileSync(backendTypesPath, buildSharedTypesContent(existing));
|
|
1700
1878
|
updateContractHashFile();
|
|
1701
1879
|
}
|
|
1702
1880
|
|
|
@@ -1746,7 +1924,7 @@ async function main() {
|
|
|
1746
1924
|
verifyContractCommand();
|
|
1747
1925
|
break;
|
|
1748
1926
|
case "mcp": {
|
|
1749
|
-
const mcpServerPath = path.join(sourceDir, "
|
|
1927
|
+
const mcpServerPath = path.join(sourceDir, "framework-mcp/dist/index.js");
|
|
1750
1928
|
if (fs.existsSync(mcpServerPath)) {
|
|
1751
1929
|
const { spawn } = await import("child_process");
|
|
1752
1930
|
// Use node to execute the built MCP server
|
|
File without changes
|
|
@@ -98,3 +98,15 @@ export const SYNC_CONTRACT_HASH_ARGS_SCHEMA = z.object({
|
|
|
98
98
|
export const VERIFY_FRAMEWORK_HEALTH_ARGS_SCHEMA = z.object({
|
|
99
99
|
detailed: z.boolean().default(false),
|
|
100
100
|
});
|
|
101
|
+
export const INSTANTIATE_BLUEPRINT_ARGS_SCHEMA = z.object({
|
|
102
|
+
blueprintPath: z.string().min(1),
|
|
103
|
+
targetPath: z.string().min(1),
|
|
104
|
+
});
|
|
105
|
+
export const LIST_BLUEPRINTS_ARGS_SCHEMA = z.object({
|
|
106
|
+
category: z.enum(["backend", "frontend"]).optional(),
|
|
107
|
+
});
|
|
108
|
+
export const SAVE_AS_BLUEPRINT_ARGS_SCHEMA = z.object({
|
|
109
|
+
blueprintPath: z.string().min(1),
|
|
110
|
+
content: z.string().min(1),
|
|
111
|
+
description: z.string().optional(),
|
|
112
|
+
});
|
|
@@ -44,8 +44,8 @@ export const contractTools = [
|
|
|
44
44
|
export const contractHandlers = {
|
|
45
45
|
verify_api_contract: async (args, projectRoot) => {
|
|
46
46
|
try {
|
|
47
|
-
const sharedTypesDir = path.join(projectRoot, "
|
|
48
|
-
const contractJsonPath = path.join(projectRoot, "
|
|
47
|
+
const sharedTypesDir = path.join(projectRoot, "apps/backend/src/types");
|
|
48
|
+
const contractJsonPath = path.join(projectRoot, "apps/backend/contract.version.json");
|
|
49
49
|
if (!fs.existsSync(sharedTypesDir) || !fs.existsSync(contractJsonPath))
|
|
50
50
|
return { content: [{ type: "text", text: "Missing shared-types directory or contract.version.json" }] };
|
|
51
51
|
const currentHash = calculateContractHash(sharedTypesDir, projectRoot);
|
|
@@ -58,8 +58,8 @@ export const contractHandlers = {
|
|
|
58
58
|
},
|
|
59
59
|
update_contract_hash: async (args, projectRoot) => {
|
|
60
60
|
try {
|
|
61
|
-
const sharedTypesDir = path.join(projectRoot, "
|
|
62
|
-
const contractJsonPath = path.join(projectRoot, "
|
|
61
|
+
const sharedTypesDir = path.join(projectRoot, "apps/backend/src/types");
|
|
62
|
+
const contractJsonPath = path.join(projectRoot, "apps/backend/contract.version.json");
|
|
63
63
|
if (!fs.existsSync(sharedTypesDir))
|
|
64
64
|
return { content: [{ type: "text", text: "Missing shared-types directory" }] };
|
|
65
65
|
const files = collectFilesRecursively(sharedTypesDir, new Set(["ts"])).sort();
|
|
@@ -83,7 +83,7 @@ export const contractHandlers = {
|
|
|
83
83
|
try {
|
|
84
84
|
const frameworkDir = getFrameworkDir(projectRoot);
|
|
85
85
|
const apiDocPath = path.join(projectRoot, frameworkDir, "docs/api", `${parsed.data.domain}.md`);
|
|
86
|
-
const sharedTypesDir = path.join(projectRoot, "
|
|
86
|
+
const sharedTypesDir = path.join(projectRoot, "apps/backend/src/types");
|
|
87
87
|
if (!fs.existsSync(apiDocPath))
|
|
88
88
|
return { content: [{ type: "text", text: `API documentation not found for domain: ${parsed.data.domain}` }] };
|
|
89
89
|
if (!fs.existsSync(sharedTypesDir))
|
|
@@ -103,8 +103,9 @@ export const frameworkHandlers = {
|
|
|
103
103
|
const missing = [];
|
|
104
104
|
const frameworkDir = getFrameworkDir(projectRoot);
|
|
105
105
|
const checkPaths = [
|
|
106
|
-
{ path: "apps", type: "folder"
|
|
107
|
-
{ path: "
|
|
106
|
+
{ path: "apps/backend/src/types", type: "folder" },
|
|
107
|
+
{ path: "apps/web/src/types", type: "folder" },
|
|
108
|
+
{ path: "framework-mcp/src", type: "folder" },
|
|
108
109
|
{ path: path.join(frameworkDir, "docs/api"), type: "folder", optional: true },
|
|
109
110
|
{ path: ".env", type: "file", optional: true },
|
|
110
111
|
{ path: ".env.example", type: "file" },
|
|
@@ -27,7 +27,7 @@ export const gitHandlers = {
|
|
|
27
27
|
let type = "feat", scope = "code";
|
|
28
28
|
if (files.some(f => f.includes(".md")))
|
|
29
29
|
type = "docs";
|
|
30
|
-
else if (files.some(f => f.includes("
|
|
30
|
+
else if (files.some(f => f.includes("apps/backend/src/types")))
|
|
31
31
|
type = "arch";
|
|
32
32
|
else if (files.some(f => f.includes("framework-mcp")))
|
|
33
33
|
type = "chore";
|
|
@@ -39,9 +39,7 @@ export const gitHandlers = {
|
|
|
39
39
|
scope = "web";
|
|
40
40
|
else if (files.some(f => f.includes("apps/backend")))
|
|
41
41
|
scope = "backend";
|
|
42
|
-
else if (files.some(f => f.includes("
|
|
43
|
-
scope = "contract";
|
|
44
|
-
else if (files.some(f => f.includes("packages/framework-mcp")))
|
|
42
|
+
else if (files.some(f => f.includes("framework-mcp")))
|
|
45
43
|
scope = "mcp";
|
|
46
44
|
const summary = files.length === 1 ? `update ${path.basename(files[0])}` : `update ${files.length} files`;
|
|
47
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")}` }] };
|
|
@@ -9,6 +9,7 @@ import { gitTools, gitHandlers } from "./git.js";
|
|
|
9
9
|
import { databaseTools, databaseHandlers } from "./database.js";
|
|
10
10
|
import { knowledgeTools, knowledgeHandlers } from "./knowledge.js";
|
|
11
11
|
import { repositoryTools, repositoryHandlers } from "./repository.js";
|
|
12
|
+
import { scaffoldTools, scaffoldHandlers } from "./scaffold.js";
|
|
12
13
|
export const allTools = [
|
|
13
14
|
...codebaseTools,
|
|
14
15
|
...frameworkTools,
|
|
@@ -21,6 +22,7 @@ export const allTools = [
|
|
|
21
22
|
...databaseTools,
|
|
22
23
|
...knowledgeTools,
|
|
23
24
|
...repositoryTools,
|
|
25
|
+
...scaffoldTools,
|
|
24
26
|
];
|
|
25
27
|
export const allHandlers = {
|
|
26
28
|
...codebaseHandlers,
|
|
@@ -34,6 +36,7 @@ export const allHandlers = {
|
|
|
34
36
|
...databaseHandlers,
|
|
35
37
|
...knowledgeHandlers,
|
|
36
38
|
...repositoryHandlers,
|
|
39
|
+
...scaffoldHandlers,
|
|
37
40
|
};
|
|
38
41
|
// Add compatibility aliases
|
|
39
42
|
allHandlers.codebase_search = allHandlers.search_codebase;
|
|
@@ -91,7 +91,7 @@ export const repositoryHandlers = {
|
|
|
91
91
|
});
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
|
-
const majorDirs = ["apps/backend", "apps/web", "
|
|
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
97
|
catch (error) {
|