agent-enderun 0.9.0 → 0.9.1

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 (93) hide show
  1. package/.enderun/BRAIN_DASHBOARD.md +2 -2
  2. package/.enderun/PROJECT_MEMORY.md +26 -4
  3. package/.enderun/STATUS.md +24 -28
  4. package/.enderun/agents/backend.md +37 -8
  5. package/.enderun/agents/database.md +55 -0
  6. package/.enderun/agents/devops.md +28 -14
  7. package/.enderun/agents/explorer.md +1 -1
  8. package/.enderun/agents/frontend.md +21 -7
  9. package/.enderun/agents/git.md +1 -1
  10. package/.enderun/agents/manager.md +41 -20
  11. package/.enderun/agents/mobile.md +1 -1
  12. package/.enderun/agents/native.md +1 -1
  13. package/.enderun/agents/quality.md +122 -0
  14. package/.enderun/cli-commands.json +3 -3
  15. package/.enderun/config.json +7 -1
  16. package/.enderun/knowledge/context_boundary_rules.md +57 -0
  17. package/.enderun/knowledge/corporate-governance/high-risk-action-approval-flow.md +29 -0
  18. package/.enderun/knowledge/documentation_ownership.md +53 -0
  19. package/.enderun/knowledge/frontend_professionalization_guidelines.md +7 -7
  20. package/.enderun/knowledge/hermes_live_test_guidelines.md +5 -5
  21. package/.enderun/knowledge/lessons-learned.md +14 -0
  22. package/.enderun/knowledge/manager_authority_audit_enforcement.md +8 -8
  23. package/.enderun/knowledge/project_scaffold_guidelines.md +4 -4
  24. package/.enderun/knowledge/reference_application_guidelines.md +6 -6
  25. package/.enderun/memory-graph/agent-contexts/quality.json +1 -0
  26. package/.enderun/queue/README.md +13 -13
  27. package/README.md +204 -102
  28. package/bin/cli.js +1 -1
  29. package/bin/init-check.js +69 -0
  30. package/bin/update-contract.js +24 -2
  31. package/docs/README.md +21 -32
  32. package/docs/architecture/README.md +9 -0
  33. package/docs/architecture/standards/data-fetching-patterns.md +13 -0
  34. package/docs/architecture/standards/design-system.md +31 -0
  35. package/docs/architecture/standards/logging.md +7 -0
  36. package/docs/architecture/standards/tech-stack.md +9 -0
  37. package/docs/getting-started.md +9 -259
  38. package/docs/user/README.md +35 -0
  39. package/docs/user/action-plan-2026.md +9 -0
  40. package/docs/user/getting-started.md +13 -0
  41. package/docs/user/roadmap.md +13 -0
  42. package/eslint.config.js +1 -1
  43. package/framework-mcp/dist/index.js +7 -13
  44. package/package.json +3 -1
  45. package/src/cli/adapters.ts +208 -0
  46. package/src/cli/commands/app.ts +38 -0
  47. package/src/cli/commands/check.ts +87 -0
  48. package/src/cli/commands/compliance.ts +55 -0
  49. package/src/cli/commands/contract.ts +45 -0
  50. package/src/cli/commands/explorer.ts +45 -0
  51. package/src/cli/commands/git.ts +39 -0
  52. package/src/cli/commands/init.ts +272 -0
  53. package/src/cli/commands/knowledge.ts +44 -0
  54. package/src/cli/commands/lint.ts +25 -0
  55. package/src/cli/commands/log.ts +37 -0
  56. package/src/cli/commands/memory.ts +78 -0
  57. package/src/cli/commands/orchestrate.ts +111 -0
  58. package/src/cli/commands/script.ts +20 -0
  59. package/src/cli/commands/security.ts +38 -0
  60. package/src/cli/commands/status.ts +59 -0
  61. package/src/cli/commands/trace.ts +46 -0
  62. package/src/cli/index.ts +107 -0
  63. package/src/cli/utils/app.ts +764 -0
  64. package/src/cli/utils/claude.ts +56 -0
  65. package/src/cli/utils/fs.ts +139 -0
  66. package/src/cli/utils/memory.ts +141 -0
  67. package/src/cli/utils/pkg.ts +215 -0
  68. package/src/cli/utils/string.ts +48 -0
  69. package/src/cli/utils/time.ts +27 -0
  70. package/.enderun/agents/analyst.md +0 -236
  71. package/.enderun/agents/orchestrator.md +0 -172
  72. package/.enderun/agents/qa.md +0 -121
  73. package/.enderun/agents/security.md +0 -202
  74. package/.enderun/knowledge/api_design_rules.md +0 -6
  75. package/.enderun/knowledge/branded_types_pattern.md +0 -8
  76. package/.enderun/knowledge/code_review_checklist.md +0 -7
  77. package/.enderun/knowledge/contract_versioning.md +0 -7
  78. package/.enderun/knowledge/database_migration.md +0 -6
  79. package/.enderun/knowledge/deployment_checklist.md +0 -7
  80. package/.enderun/knowledge/git_commit_strategy.md +0 -10
  81. package/.enderun/knowledge/monitoring_setup.md +0 -5
  82. package/.enderun/knowledge/performance_guidelines.md +0 -11
  83. package/.enderun/knowledge/repository_patterns.md +0 -9
  84. package/.enderun/knowledge/security_scanning.md +0 -6
  85. package/.enderun/knowledge/testing_standards.md +0 -7
  86. package/.enderun/knowledge/troubleshooting_guide.md +0 -5
  87. package/.enderun/memory-graph/agent-contexts/analyst.json +0 -1
  88. package/.enderun/memory-graph/agent-contexts/orchestrator.json +0 -1
  89. package/.enderun/memory-graph/agent-contexts/qa.json +0 -1
  90. package/.enderun/memory-graph/agent-contexts/security.json +0 -1
  91. package/docs/action-plan-2026.md +0 -119
  92. package/docs/roadmap.md +0 -142
  93. package/docs/tech-stack.md +0 -30
@@ -0,0 +1,78 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+
4
+ import { getMemoryPath, acquireMemoryLock, releaseMemoryLock } from "../utils/memory.js";
5
+
6
+ export function updateProjectMemoryCommand(section: string, content: string) {
7
+ const memoryPath = getMemoryPath();
8
+ if (!fs.existsSync(memoryPath)) {
9
+ console.error("❌ Error: PROJECT_MEMORY.md not found.");
10
+ return;
11
+ }
12
+
13
+ const lockPath = `${memoryPath}.lock`;
14
+ if (!acquireMemoryLock(lockPath)) {
15
+ console.error("❌ Error: Memory lock timeout.");
16
+ return;
17
+ }
18
+
19
+ try {
20
+ let memoryContent = fs.readFileSync(memoryPath, "utf8");
21
+
22
+ if (section === "HISTORY") {
23
+ const headers = ["## HISTORY (Persistent Memory)", "## HISTORY"];
24
+ let sectionIndex = -1;
25
+ for (const h of headers) {
26
+ sectionIndex = memoryContent.indexOf(h);
27
+ if (sectionIndex !== -1) {
28
+ break;
29
+ }
30
+ }
31
+
32
+ if (sectionIndex === -1) {
33
+ console.error("❌ Error: HISTORY section not found.");
34
+ return;
35
+ }
36
+ const headerEnd = memoryContent.indexOf("\n", sectionIndex) + 1;
37
+ memoryContent =
38
+ memoryContent.slice(0, headerEnd) +
39
+ `\n${content.trim()}\n` +
40
+ memoryContent.slice(headerEnd);
41
+
42
+ // --- Auto-Prune Logic ---
43
+ const historySplit = memoryContent.split("### ");
44
+ if (historySplit.length > 11) { // Title + 10 entries
45
+ const frameworkDir = path.dirname(memoryPath);
46
+ const archiveDir = path.join(frameworkDir, "archive/history");
47
+ if (!fs.existsSync(archiveDir)) fs.mkdirSync(archiveDir, { recursive: true });
48
+
49
+ const toArchive = historySplit.slice(11); // Keep the first 10 entries (newest)
50
+ const preserved = historySplit.slice(0, 11);
51
+
52
+ const archiveContent = "### " + toArchive.join("### ");
53
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
54
+ fs.writeFileSync(path.join(archiveDir, `history-${timestamp}.md`), archiveContent);
55
+
56
+ memoryContent = preserved.join("### ").trim() + "\n";
57
+ console.warn(`📦 Auto-Pruned: ${toArchive.length} old entries moved to archive.`);
58
+ }
59
+ // ------------------------
60
+ } else {
61
+ const escaped = section.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
62
+ const sectionRegex = new RegExp(`## ${escaped}[\\s\\S]*?(?=\\n## |$)`, "m");
63
+ if (!sectionRegex.test(memoryContent)) {
64
+ console.error(`❌ Error: Section not found: ${section}`);
65
+ return;
66
+ }
67
+ memoryContent = memoryContent.replace(
68
+ sectionRegex,
69
+ `## ${section}\n\n${content.trim()}\n`,
70
+ );
71
+ }
72
+
73
+ fs.writeFileSync(memoryPath, memoryContent);
74
+ console.warn(`✅ Section ${section} updated in PROJECT_MEMORY.md`);
75
+ } finally {
76
+ releaseMemoryLock(lockPath);
77
+ }
78
+ }
@@ -0,0 +1,111 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { execSync } from "child_process";
4
+ import { getFrameworkDir } from "../utils/memory.js";
5
+
6
+ interface HermesMessage {
7
+ timestamp: string;
8
+ from: string;
9
+ to: string;
10
+ category: "ACTION" | "DELEGATION" | "INFO" | "ALERT";
11
+ traceId: string;
12
+ content: string;
13
+ status: "PENDING" | "PROCESSED";
14
+ }
15
+
16
+ /**
17
+ * Start the live Hermes Orchestration & Message Loop
18
+ */
19
+ export function orchestrateCommand() {
20
+ const frameworkDir = getFrameworkDir();
21
+ const messagesDir = path.join(process.cwd(), frameworkDir, "messages");
22
+ const statusPath = path.join(process.cwd(), frameworkDir, "STATUS.md");
23
+
24
+ console.log(`\n================================================================`);
25
+ console.log(`🏛️ AGENT ENDERUN — DYNAMIC HERMES ORCHESTRATÖR DÖNGÜSÜ`);
26
+ console.log(`================================================================`);
27
+ console.log(`🛰️ Hermes Message Broker dinleniyor: ${frameworkDir}/messages/...`);
28
+
29
+ if (!fs.existsSync(messagesDir)) {
30
+ fs.mkdirSync(messagesDir, { recursive: true });
31
+ }
32
+
33
+ // Scan all JSON files in the messages directory
34
+ const messageFiles = fs.readdirSync(messagesDir).filter(f => f.endsWith(".json"));
35
+ const pendingMessages: HermesMessage[] = [];
36
+
37
+ for (const file of messageFiles) {
38
+ const filePath = path.join(messagesDir, file);
39
+ try {
40
+ const content = fs.readFileSync(filePath, "utf8").trim();
41
+ if (!content) continue;
42
+ // Messages are stored as newline-delimited JSON
43
+ const lines = content.split("\n");
44
+ lines.forEach((line, index) => {
45
+ if (!line.trim()) return;
46
+ const msg = JSON.parse(line) as HermesMessage;
47
+ if (msg.status === "PENDING") {
48
+ pendingMessages.push(msg);
49
+ }
50
+ });
51
+ } catch (e) {
52
+ // ignore malformed lines
53
+ }
54
+ }
55
+
56
+ if (pendingMessages.length === 0) {
57
+ console.log(`\n🟢 Kuyruk Temiz: İşlenecek aktif Hermes mesajı bulunamadı.`);
58
+ console.log(`💡 İpucu: Bir uzman ajanı tetiklemek için send_agent_message aracını kullanın.`);
59
+ return;
60
+ }
61
+
62
+ console.log(`\n📥 Kuyrukta ${pendingMessages.length} adet bekleyen Hermes mesajı tespit edildi:\n`);
63
+
64
+ // Process the first pending message
65
+ const activeMessage = pendingMessages[0];
66
+ const toAgent = activeMessage.to;
67
+ const fromAgent = activeMessage.from;
68
+
69
+ console.log(`✉️ [GÖNDEREN] : ${fromAgent}`);
70
+ console.log(`📥 [ALICI] : ${toAgent}`);
71
+ console.log(`🆔 [TRACE ID] : ${activeMessage.traceId}`);
72
+ console.log(`🏷️ [KATEGORİ] : ${activeMessage.category}`);
73
+ console.log(`💬 [MESAJ] : "${activeMessage.content}"`);
74
+ console.log(`----------------------------------------------------------------`);
75
+
76
+ // 1. Transition the target agent state to EXECUTING in STATUS.md
77
+ console.log(`⏳ Ajan Durum Geçişi: ${toAgent} durumu EXECUTING olarak kilitleniyor...`);
78
+ transitionAgentState(statusPath, toAgent, "EXECUTING", activeMessage.content);
79
+
80
+ console.log(`\n🤖 Görev Devredildi!`);
81
+ console.log(`👉 Lütfen ${toAgent} agent talimatlarını (${frameworkDir}/agents/${toAgent.replace("@", "")}.md) okuyun ve görevi yerine getirin.`);
82
+ console.log(`💡 Görev tamamlandığında, mesajı PROCESSED olarak işaretlemek ve ajanı boşa çıkarmak için:`);
83
+ console.log(` npx agent-enderun status komutuyla kontrol edin.`);
84
+ }
85
+
86
+ function transitionAgentState(statusPath: string, agent: string, state: string, task: string) {
87
+ if (!fs.existsSync(statusPath)) return;
88
+ try {
89
+ let content = fs.readFileSync(statusPath, "utf8");
90
+ const lines = content.split("\n");
91
+ const targetName = agent;
92
+
93
+ for (let i = 0; i < lines.length; i++) {
94
+ if (lines[i].includes(`| ${targetName} |`)) {
95
+ // e.g., | @backend | IDLE | — | — | 9.2/10 | — |
96
+ const parts = lines[i].split("|");
97
+ if (parts.length >= 7) {
98
+ parts[2] = ` ${state} `;
99
+ parts[3] = ` ${task.slice(0, 20)}... `;
100
+ lines[i] = parts.join("|");
101
+ break;
102
+ }
103
+ }
104
+ }
105
+
106
+ fs.writeFileSync(statusPath, lines.join("\n"));
107
+ console.log(`✅ STATUS.md üzerinde ${agent} durumu başarıyla '${state}' yapıldı.`);
108
+ } catch (e) {
109
+ console.error("❌ STATUS.md güncellenirken hata oluştu:", e);
110
+ }
111
+ }
@@ -0,0 +1,20 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import cp from "child_process";
4
+
5
+ const targetDir = process.cwd(); // Assuming targetDir is process.cwd() in the CLI context
6
+
7
+ export function runScriptCommand(script: string, projectPath: string) {
8
+ const fullPath = path.join(targetDir, projectPath);
9
+ if (!fs.existsSync(fullPath)) {
10
+ console.warn(`❌ Project path not found: ${projectPath}`);
11
+ return;
12
+ }
13
+ console.warn(`🚀 Running 'npm run ${script}' in ${projectPath}...`);
14
+ try {
15
+ cp.spawnSync("npm", ["run", script], { cwd: fullPath, stdio: "inherit", shell: true });
16
+ } catch (e: unknown) {
17
+ const message = e instanceof Error ? e.message : "Unknown error";
18
+ console.warn(`❌ Failed to run script: ${message}`);
19
+ }
20
+ }
@@ -0,0 +1,38 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+
4
+ import { collectFiles } from "../utils/fs.js";
5
+
6
+ const targetDir = process.cwd();
7
+
8
+ export function securityAuditCommand(targetPath: string) {
9
+ console.warn(`🔍 Running Advanced Security Audit on: ${targetPath}...`);
10
+ const scanRules = [
11
+ { pattern: /sql`/, message: "Potential Raw SQL usage detected", severity: "HIGH" },
12
+ {
13
+ pattern: /(password|secret|api_?key)\s*[:=]\s*['"][^'"]+['"]/i,
14
+ message: "Potential hardcoded secret detected",
15
+ severity: "CRITICAL",
16
+ },
17
+ { pattern: /:\s*any(?!\w)/, message: "Usage of 'any' type detected", severity: "MEDIUM" },
18
+ { pattern: /\.innerHTML\s*=/, message: "Unsafe innerHTML assignment detected", severity: "MEDIUM" },
19
+ ];
20
+ const issues: string[] = [];
21
+ const files = collectFiles(path.join(targetDir, targetPath), [".ts", ".tsx", ".js", ".jsx"]);
22
+ files.forEach((f) => {
23
+ const content = fs.readFileSync(f, "utf8");
24
+ const lines = content.split("\n");
25
+ lines.forEach((line, i) => {
26
+ scanRules.forEach((rule) => {
27
+ if (rule.pattern.test(line)) {
28
+ issues.push(`[${rule.severity}] ${rule.message} in ${path.relative(targetDir, f)}:${i + 1}`);
29
+ }
30
+ });
31
+ });
32
+ });
33
+ if (issues.length === 0) {
34
+ console.warn("✅ No security issues detected.");
35
+ } else {
36
+ issues.forEach((issue) => console.warn(`⚠️ ${issue}`));
37
+ }
38
+ }
@@ -0,0 +1,59 @@
1
+ import fs from "fs";
2
+
3
+ import { getMemoryPath, getFrameworkDir } from "../utils/memory.js";
4
+
5
+ /**
6
+ * Print the current framework status.
7
+ */
8
+ export function statusCommand() {
9
+ const memoryPath = getMemoryPath();
10
+ const frameworkDir = getFrameworkDir();
11
+ if (!fs.existsSync(memoryPath)) {
12
+ console.error(`❌ Error: ${frameworkDir}/PROJECT_MEMORY.md not found. Please run 'init' first.`);
13
+ return;
14
+ }
15
+
16
+ const content = fs.readFileSync(memoryPath, "utf8");
17
+
18
+ // Format 1: Table Style (Original)
19
+ const tableMatch = content.match(
20
+ /\| Active Phase \| Profile \| Last Update \| Active Trace ID \| Blockers \|\n\| :----------- \| :------ \| :---------- \| :-------------- \| :------- \|\n\| (.*?) \| (.*?) \| (.*?) \| (.*?) \| (.*?) \|/,
21
+ );
22
+
23
+ // Format 2: List Style (New)
24
+ const phaseMatch = content.match(/- Phase: (.*)/);
25
+ const traceIdMatch = content.match(/- Trace ID: (.*)/);
26
+ const profileMatch = content.match(/- Profile: (.*)/);
27
+ const updateMatch = content.match(/- Last Update: (.*)/);
28
+ const blockersMatch = content.match(/- Blockers: (.*)/);
29
+
30
+ console.warn("\n📊 --- PROJECT STATUS ---");
31
+
32
+ if (tableMatch) {
33
+ console.warn(`🔹 Phase: ${tableMatch[1].trim()}`);
34
+ console.warn(`🧭 Profile: ${tableMatch[2].trim()}`);
35
+ console.warn(`📅 Update: ${tableMatch[3].trim()}`);
36
+ console.warn(`🆔 Trace ID: ${tableMatch[4].trim()}`);
37
+ console.warn(`⛔ Blockers: ${tableMatch[5].trim()}`);
38
+ } else if (phaseMatch || traceIdMatch) {
39
+ if (phaseMatch) console.warn(`🔹 Phase: ${phaseMatch[1].trim()}`);
40
+ if (profileMatch) console.warn(`🧭 Profile: ${profileMatch[1].trim()}`);
41
+ if (updateMatch) console.warn(`📅 Update: ${updateMatch[1].trim()}`);
42
+ if (traceIdMatch) console.warn(`🆔 Trace ID: ${traceIdMatch[1].trim()}`);
43
+ if (blockersMatch) console.warn(`⛔ Blockers: ${blockersMatch[1].trim()}`);
44
+
45
+ // Check for manager state in list style
46
+ const managerState = content.match(/- @manager state: (.*)/);
47
+ if (managerState) console.warn(`🤖 Manager: ${managerState[1].trim()}`);
48
+ } else {
49
+ console.warn("⚠️ Status data could not be parsed in standard formats.");
50
+ }
51
+
52
+ const tasksSection = content.match(/## ACTIVE TASKS\n\n([\s\S]*?)(?=\n##|$)/);
53
+ if (tasksSection) {
54
+ console.warn("\n📋 Active Tasks:");
55
+ console.warn(tasksSection[1].trim());
56
+ }
57
+
58
+ console.warn("\n-----------------------\n");
59
+ }
@@ -0,0 +1,46 @@
1
+ import fs from "fs";
2
+
3
+ import { getMemoryPath, acquireMemoryLock, releaseMemoryLock } from "../utils/memory.js";
4
+ import { generateULID } from "../utils/time.js";
5
+ import { sanitizeTableCell, normalizeAgentName, normalizePriority, insertTaskRow } from "../utils/string.js";
6
+
7
+ /**
8
+ * Generate a new Trace ID and add it to project memory.
9
+ */
10
+ export function traceNewCommand(description: string, agent = "manager", priority = "P2"): string | void {
11
+ const memoryPath = getMemoryPath();
12
+ if (!fs.existsSync(memoryPath)) {
13
+ console.error("❌ Error: PROJECT_MEMORY.md not found.");
14
+ return;
15
+ }
16
+
17
+ const traceId = generateULID();
18
+ const safeDescription = sanitizeTableCell(description);
19
+ const safeAgent = normalizeAgentName(agent);
20
+ const safePriority = normalizePriority(priority);
21
+ const newTask = `| ${traceId} | ${safeDescription} | @${safeAgent} | ${safePriority} | IN_PROGRESS |`;
22
+ const lockPath = `${memoryPath}.lock`;
23
+
24
+ if (!acquireMemoryLock(lockPath)) {
25
+ console.error("❌ Error: Memory lock timeout (5 retries).");
26
+ return;
27
+ }
28
+
29
+ try {
30
+ const content = fs.readFileSync(memoryPath, "utf8");
31
+ const updated = insertTaskRow(content, newTask);
32
+ if (!updated) {
33
+ console.error("❌ Error: ACTIVE TASKS table not found, task could not be added.");
34
+ return;
35
+ }
36
+
37
+ fs.writeFileSync(memoryPath, updated);
38
+ console.warn(`
39
+ ✅ New Trace ID created: ${traceId}`);
40
+ console.warn(`📝 Added to task list: ${description}
41
+ `);
42
+ return traceId;
43
+ } finally {
44
+ releaseMemoryLock(lockPath);
45
+ }
46
+ }
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { getPackageVersion } from "./utils/pkg.js";
4
+ import { initCommand } from "./commands/init.js";
5
+ import { checkCommand } from "./commands/check.js";
6
+ import { statusCommand } from "./commands/status.js";
7
+ import { traceNewCommand } from "./commands/trace.js";
8
+ import { updateProjectMemoryCommand } from "./commands/memory.js";
9
+ import { createAppCommand } from "./commands/app.js";
10
+ import { verifyApiContractCommand } from "./commands/contract.js";
11
+ import { orchestrateCommand } from "./commands/orchestrate.js";
12
+
13
+ /**
14
+ * Main CLI entry point.
15
+ */
16
+ async function main() {
17
+ const args = process.argv.slice(2);
18
+ const command = args[0];
19
+
20
+ switch (command) {
21
+ case "init":
22
+ await initCommand(args[1]);
23
+ break;
24
+
25
+ case "check":
26
+ checkCommand();
27
+ break;
28
+
29
+ case "status":
30
+ statusCommand();
31
+ break;
32
+
33
+ case "trace:new": {
34
+ const description = args[1] || "Default task";
35
+ const agent = args[2] || "manager";
36
+ const priority = args[3] || "P1";
37
+ traceNewCommand(description, agent, priority);
38
+ break;
39
+ }
40
+
41
+ case "update_project_memory": {
42
+ const section = args[1];
43
+ const content = args[2];
44
+ if (!section || !content) {
45
+ console.error("❌ Error: section and content are required.");
46
+ process.exit(64);
47
+ }
48
+ updateProjectMemoryCommand(section, content);
49
+ break;
50
+ }
51
+
52
+ case "create-app":
53
+ await createAppCommand(args.slice(1));
54
+ break;
55
+
56
+ case "orchestrate":
57
+ case "loop":
58
+ orchestrateCommand();
59
+ break;
60
+
61
+ case "verify-contract":
62
+ verifyApiContractCommand();
63
+ break;
64
+
65
+ case "version":
66
+ case "-v":
67
+ case "--version":
68
+ console.log(`v${getPackageVersion()}`);
69
+ break;
70
+
71
+ case "help":
72
+ case "-h":
73
+ case "--help":
74
+ default:
75
+ console.log(`
76
+ 🤖 Agent Enderun CLI — Enterprise AI Orchestration
77
+
78
+ Usage:
79
+ agent-enderun <command> [options]
80
+
81
+ Commands:
82
+ init [adapter] Initialize Agent Enderun framework (gemini, claude, grok, etc.)
83
+ check Perform an enterprise-grade system health check
84
+ status Show active phase, trace ID, and agent statuses
85
+ trace:new <desc> Start a new task chain with a unique Trace ID
86
+ create-app <idea> Generate a new full-stack app from natural language
87
+ orchestrate Start the dynamic Hermes agent orchestration loop
88
+ verify-contract Validate type alignment between backend and frontend
89
+ version Show version information
90
+
91
+ Supported adapters (one init per IDE — separate folder each):
92
+ - gemini → .enderun/ (SSOT) + gemini.md
93
+ - claude → .enderun/ (SSOT) + claude.md
94
+ - grok → .enderun/ (SSOT) + grok.md
95
+ - antigravity → .enderun/ (SSOT) + agent.md
96
+
97
+ Example:
98
+ agent-enderun init gemini
99
+ agent-enderun check
100
+ agent-enderun status
101
+ agent-enderun trace:new "Auth module design" backend P1
102
+ `);
103
+ break;
104
+ }
105
+ }
106
+
107
+ main().catch(console.error);