agent-enderun 1.10.4 ā 1.11.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.
- package/README.md +34 -45
- package/dist/framework-mcp/tests/tools/quality/check_lint.test.js +1 -1
- package/dist/framework-mcp/tests/tools/quality/check_lint.test.js.map +1 -1
- package/dist/src/cli/adapters/core.d.ts +1 -1
- package/dist/src/cli/adapters/core.js +0 -1
- package/dist/src/cli/adapters/core.js.map +1 -1
- package/dist/src/cli/adapters/index.d.ts +1 -0
- package/dist/src/cli/adapters/index.js +1 -0
- package/dist/src/cli/adapters/index.js.map +1 -1
- package/dist/src/cli/adapters/scaffold.d.ts +1 -1
- package/dist/src/cli/adapters/scaffold.js +13 -7
- package/dist/src/cli/adapters/scaffold.js.map +1 -1
- package/dist/src/cli/commands/init/scaffold-core.d.ts +5 -2
- package/dist/src/cli/commands/init/scaffold-core.js +28 -6
- package/dist/src/cli/commands/init/scaffold-core.js.map +1 -1
- package/dist/src/cli/commands/init.js +31 -4
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/orchestrate.d.ts +9 -7
- package/dist/src/cli/commands/orchestrate.js +40 -4
- package/dist/src/cli/commands/orchestrate.js.map +1 -1
- package/dist/src/cli/commands/plan.d.ts +3 -1
- package/dist/src/cli/commands/plan.js +79 -22
- package/dist/src/cli/commands/plan.js.map +1 -1
- package/dist/src/cli/index.js +11 -15
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/utils/compliance.js +0 -1
- package/dist/src/cli/utils/compliance.js.map +1 -1
- package/dist/src/cli/utils/config-schema.d.ts +7 -7
- package/dist/src/cli/utils/pkg.d.ts +19 -0
- package/dist/src/cli/utils/pkg.js +29 -5
- package/dist/src/cli/utils/pkg.js.map +1 -1
- package/dist/src/modules/adapters/definitions.js +1 -1
- package/dist/src/modules/adapters/definitions.js.map +1 -1
- package/dist/src/modules/adapters/shared.js +7 -4
- package/dist/src/modules/adapters/shared.js.map +1 -1
- package/dist/src/modules/agents/definitions.d.ts +1 -1
- package/dist/src/modules/agents/definitions.js +129 -69
- package/dist/src/modules/agents/definitions.js.map +1 -1
- package/dist/src/modules/agents/registry/analyst.js +5 -1
- package/dist/src/modules/agents/registry/analyst.js.map +1 -1
- package/dist/src/modules/agents/registry/backend.js +5 -4
- package/dist/src/modules/agents/registry/backend.js.map +1 -1
- package/dist/src/modules/agents/registry/database.js +2 -1
- package/dist/src/modules/agents/registry/database.js.map +1 -1
- package/dist/src/modules/agents/registry/devops.js +2 -0
- package/dist/src/modules/agents/registry/devops.js.map +1 -1
- package/dist/src/modules/agents/registry/explorer.js +1 -0
- package/dist/src/modules/agents/registry/explorer.js.map +1 -1
- package/dist/src/modules/agents/registry/git.js +3 -1
- package/dist/src/modules/agents/registry/git.js.map +1 -1
- package/dist/src/modules/agents/registry/manager.js +8 -2
- package/dist/src/modules/agents/registry/manager.js.map +1 -1
- package/dist/src/modules/agents/registry/native.js +5 -1
- package/dist/src/modules/agents/registry/native.js.map +1 -1
- package/dist/src/modules/agents/registry/security.js +1 -0
- package/dist/src/modules/agents/registry/security.js.map +1 -1
- package/dist/src/shared/constants.d.ts +1 -1
- package/dist/src/shared/constants.js +10 -9
- package/dist/src/shared/constants.js.map +1 -1
- package/dist/tests/approve.test.js +4 -9
- package/dist/tests/approve.test.js.map +1 -1
- package/dist/tests/integration/agent_flow.test.js +2 -2
- package/dist/tests/integration/agent_flow.test.js.map +1 -1
- package/dist/tests/orchestrate.test.js +2 -7
- package/dist/tests/orchestrate.test.js.map +1 -1
- package/framework-mcp/dist/constants.js +64 -0
- package/framework-mcp/dist/index.js +109 -0
- package/framework-mcp/dist/tools/control_plane/locking.js +64 -0
- package/framework-mcp/dist/tools/control_plane/registry.js +34 -0
- package/framework-mcp/dist/tools/dashboard/start_dashboard.js +29 -0
- package/framework-mcp/dist/tools/definitions.js +300 -0
- package/framework-mcp/dist/tools/file_system/batch_surgical_edit.js +59 -0
- package/framework-mcp/dist/tools/file_system/patch_file.js +25 -0
- package/framework-mcp/dist/tools/file_system/read_file.js +51 -0
- package/framework-mcp/dist/tools/file_system/replace_text.js +43 -0
- package/framework-mcp/dist/tools/file_system/write_file.js +38 -0
- package/framework-mcp/dist/tools/framework/audit_deps.js +41 -0
- package/framework-mcp/dist/tools/framework/get_status.js +5 -0
- package/framework-mcp/dist/tools/framework/orchestrate.js +5 -0
- package/framework-mcp/dist/tools/framework/run_tests.js +25 -0
- package/framework-mcp/dist/tools/framework/update_contract_hash.js +5 -0
- package/framework-mcp/dist/tools/framework/update_memory.js +8 -0
- package/framework-mcp/dist/tools/index.js +62 -0
- package/framework-mcp/dist/tools/memory/get_insights.js +34 -0
- package/framework-mcp/dist/tools/memory/read_memory.js +28 -0
- package/framework-mcp/dist/tools/messaging/log_action.js +22 -0
- package/framework-mcp/dist/tools/messaging/send_message.js +87 -0
- package/framework-mcp/dist/tools/observability/check_ports.js +26 -0
- package/framework-mcp/dist/tools/observability/get_health.js +19 -0
- package/framework-mcp/dist/tools/quality/check_lint.js +28 -0
- package/framework-mcp/dist/tools/search/get_gaps.js +48 -0
- package/framework-mcp/dist/tools/search/get_map.js +43 -0
- package/framework-mcp/dist/tools/search/grep_search.js +76 -0
- package/framework-mcp/dist/tools/search/list_dir.js +28 -0
- package/framework-mcp/dist/tools/shell/run_command.js +46 -0
- package/framework-mcp/dist/tools/types.js +1 -0
- package/framework-mcp/dist/utils/cli.js +20 -0
- package/framework-mcp/dist/utils/compliance.js +29 -0
- package/framework-mcp/dist/utils/fs.js +44 -0
- package/framework-mcp/dist/utils/metrics.js +56 -0
- package/framework-mcp/dist/utils/security.js +60 -0
- package/framework-mcp/package.json +19 -0
- package/framework-mcp/src/constants.ts +78 -0
- package/framework-mcp/src/declarations.d.ts +17 -0
- package/framework-mcp/src/index.ts +132 -0
- package/framework-mcp/src/tools/control_plane/locking.ts +71 -0
- package/framework-mcp/src/tools/control_plane/registry.ts +38 -0
- package/framework-mcp/src/tools/dashboard/start_dashboard.ts +33 -0
- package/framework-mcp/src/tools/definitions.ts +302 -0
- package/framework-mcp/src/tools/file_system/batch_surgical_edit.ts +79 -0
- package/framework-mcp/src/tools/file_system/patch_file.ts +33 -0
- package/framework-mcp/src/tools/file_system/read_file.ts +58 -0
- package/framework-mcp/src/tools/file_system/replace_text.ts +52 -0
- package/framework-mcp/src/tools/file_system/write_file.ts +45 -0
- package/framework-mcp/src/tools/framework/audit_deps.ts +49 -0
- package/framework-mcp/src/tools/framework/get_status.ts +7 -0
- package/framework-mcp/src/tools/framework/orchestrate.ts +7 -0
- package/framework-mcp/src/tools/framework/run_tests.ts +28 -0
- package/framework-mcp/src/tools/framework/update_contract_hash.ts +7 -0
- package/framework-mcp/src/tools/framework/update_memory.ts +10 -0
- package/framework-mcp/src/tools/index.ts +66 -0
- package/framework-mcp/src/tools/memory/get_insights.ts +41 -0
- package/framework-mcp/src/tools/memory/read_memory.ts +31 -0
- package/framework-mcp/src/tools/messaging/log_action.ts +28 -0
- package/framework-mcp/src/tools/messaging/send_message.ts +89 -0
- package/framework-mcp/src/tools/observability/check_ports.ts +30 -0
- package/framework-mcp/src/tools/observability/get_health.ts +24 -0
- package/framework-mcp/src/tools/quality/check_lint.ts +33 -0
- package/framework-mcp/src/tools/search/get_gaps.ts +54 -0
- package/framework-mcp/src/tools/search/get_map.ts +48 -0
- package/framework-mcp/src/tools/search/grep_search.ts +76 -0
- package/framework-mcp/src/tools/search/list_dir.ts +34 -0
- package/framework-mcp/src/tools/shell/run_command.ts +56 -0
- package/framework-mcp/src/tools/types.ts +89 -0
- package/framework-mcp/src/utils/cli.ts +20 -0
- package/framework-mcp/src/utils/compliance.ts +37 -0
- package/framework-mcp/src/utils/fs.ts +45 -0
- package/framework-mcp/src/utils/metrics.ts +73 -0
- package/framework-mcp/src/utils/security.ts +66 -0
- package/framework-mcp/tests/tools/file_system/file_system_tools.test.ts +212 -0
- package/framework-mcp/tests/tools/messaging/send_message.test.ts +136 -0
- package/framework-mcp/tests/tools/quality/check_lint.test.ts +46 -0
- package/framework-mcp/tests/tools/shell/run_command.test.ts +55 -0
- package/framework-mcp/tsconfig.json +14 -0
- package/package.json +5 -3
- package/src/cli/adapters/core.ts +2 -3
- package/src/cli/adapters/index.ts +1 -0
- package/src/cli/adapters/scaffold.ts +20 -7
- package/src/cli/commands/init/scaffold-core.ts +45 -6
- package/src/cli/commands/init.ts +31 -2
- package/src/cli/commands/orchestrate.ts +41 -4
- package/src/cli/commands/plan.ts +89 -23
- package/src/cli/index.ts +14 -19
- package/src/cli/utils/compliance.ts +8 -9
- package/src/cli/utils/pkg.ts +42 -13
- package/src/modules/adapters/definitions.ts +1 -1
- package/src/modules/adapters/shared.ts +7 -4
- package/src/modules/agents/definitions.ts +140 -73
- package/src/modules/agents/registry/analyst.ts +5 -1
- package/src/modules/agents/registry/backend.ts +5 -4
- package/src/modules/agents/registry/database.ts +2 -1
- package/src/modules/agents/registry/devops.ts +2 -0
- package/src/modules/agents/registry/explorer.ts +1 -0
- package/src/modules/agents/registry/git.ts +3 -1
- package/src/modules/agents/registry/manager.ts +8 -2
- package/src/modules/agents/registry/native.ts +5 -1
- package/src/modules/agents/registry/security.ts +1 -0
- package/src/shared/constants.ts +14 -13
- package/templates/prompts/bug-fix-recipe.md +20 -0
- package/templates/prompts/contract-design-recipe.md +21 -0
- package/templates/prompts/db-management-recipe.md +25 -0
- package/templates/prompts/deployment-recipe.md +23 -0
- package/templates/prompts/new-feature-recipe.md +19 -0
- package/templates/prompts/performance-optimization-recipe.md +23 -0
- package/templates/prompts/pull-request-template.md +21 -0
- package/templates/prompts/refactoring-recipe.md +21 -0
- package/templates/prompts/security-audit-recipe.md +20 -0
- package/templates/standards/architecture-standards.md +23 -0
- package/templates/standards/auth-standards.md +125 -0
- package/templates/standards/crud-governance.md +21 -0
- package/templates/standards/deployment-standards.md +21 -0
- package/templates/standards/frontend-standards.md +37 -0
- package/templates/standards/github-actions-standards.md +43 -0
- package/templates/standards/i18n-standards.md +17 -0
- package/templates/standards/kysely-standards.md +47 -0
- package/templates/standards/llm-governance.md +15 -0
- package/templates/standards/logging-and-secrets.md +34 -0
- package/templates/standards/mobile-standards.md +23 -0
- package/templates/standards/observability-standards.md +15 -0
- package/templates/standards/performance-standards.md +15 -0
- package/templates/standards/pino-standards.md +46 -0
- package/templates/standards/playwright-standards.md +54 -0
- package/templates/standards/quality-standards.md +31 -0
- package/templates/standards/react-query-standards.md +72 -0
- package/templates/standards/react-router-standards.md +62 -0
- package/templates/standards/security-audit-standards.md +16 -0
- package/templates/standards/security-standards.md +21 -0
- package/templates/standards/swagger-standards.md +50 -0
- package/templates/standards/tailwind-standards.md +20 -0
- package/templates/standards/testing-standards.md +31 -0
- package/templates/standards/typeorm-standards.md +49 -0
- package/templates/standards/vitest-standards.md +110 -0
- package/src/cli/commands/app.ts +0 -56
- package/src/cli/utils/app-backend.ts +0 -257
- package/src/cli/utils/app-docs.ts +0 -83
- package/src/cli/utils/app-frontend.ts +0 -263
- package/src/cli/utils/app-inferrer.ts +0 -63
- package/src/cli/utils/app-mobile.ts +0 -113
- package/src/cli/utils/app-types.ts +0 -248
- package/src/cli/utils/app.ts +0 -6
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
2
|
+
import { handleCheckLint } from "../../../src/tools/quality/check_lint.js";
|
|
3
|
+
import { exec } from "child_process";
|
|
4
|
+
|
|
5
|
+
vi.mock("child_process");
|
|
6
|
+
|
|
7
|
+
describe("handleCheckLint", () => {
|
|
8
|
+
const projectRoot = "/fake/project";
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
vi.clearAllMocks();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("should execute the lint command and return output on success", async () => {
|
|
15
|
+
const args = {};
|
|
16
|
+
|
|
17
|
+
vi.mocked(exec).mockImplementation((_cmd, _opts, callback) => {
|
|
18
|
+
// @ts-expect-error: Mock implementation callback type is complex
|
|
19
|
+
callback(null, "All good!", "");
|
|
20
|
+
return {} as any;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const result = await handleCheckLint(projectRoot, args);
|
|
24
|
+
|
|
25
|
+
expect(exec).toHaveBeenCalledWith("npm run lint", { cwd: projectRoot, timeout: 60000 }, expect.any(Function));
|
|
26
|
+
expect(result.isError).toBeUndefined();
|
|
27
|
+
expect(result.content[0].text).toContain("All good!");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should execute the lint command and return output on failure (lint issues found)", async () => {
|
|
31
|
+
const args = {};
|
|
32
|
+
const lintErrorOutput = "Error: 2 problems (2 errors, 0 warnings)";
|
|
33
|
+
|
|
34
|
+
vi.mocked(exec).mockImplementation((_cmd, _opts, callback) => {
|
|
35
|
+
// @ts-expect-error: Mock implementation callback type is complex
|
|
36
|
+
callback({ code: 1, message: "Lint errors found" }, lintErrorOutput, "");
|
|
37
|
+
return {} as any;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const result = await handleCheckLint(projectRoot, args);
|
|
41
|
+
|
|
42
|
+
expect(exec).toHaveBeenCalledWith("npm run lint", { cwd: projectRoot, timeout: 60000 }, expect.any(Function));
|
|
43
|
+
expect(result.isError).toBe(true); // Implementation returns isError: true on failure
|
|
44
|
+
expect(result.content[0].text).toContain(lintErrorOutput);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
2
|
+
import { handleRunCommand } from "../../../src/tools/shell/run_command.js";
|
|
3
|
+
import { exec } from "child_process";
|
|
4
|
+
|
|
5
|
+
vi.mock("child_process");
|
|
6
|
+
|
|
7
|
+
describe("handleRunCommand", () => {
|
|
8
|
+
const projectRoot = "/fake/project";
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
vi.clearAllMocks();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("should execute an allowed command", async () => {
|
|
15
|
+
const args = { command: "git status" };
|
|
16
|
+
|
|
17
|
+
vi.mocked(exec).mockImplementation((_cmd, _opts, callback) => {
|
|
18
|
+
// @ts-expect-error: Mock implementation callback type is complex
|
|
19
|
+
callback(null, "On branch main", "");
|
|
20
|
+
return {} as any;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const result = await handleRunCommand(projectRoot, args);
|
|
24
|
+
|
|
25
|
+
expect(exec).toHaveBeenCalledWith("git status", { cwd: projectRoot, timeout: 30000 }, expect.any(Function));
|
|
26
|
+
expect(result.isError).toBeUndefined();
|
|
27
|
+
expect(result.content[0].text).toContain("On branch main");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should reject a disallowed command", async () => {
|
|
31
|
+
const args = { command: "rm -rf /" };
|
|
32
|
+
const result = await handleRunCommand(projectRoot, args);
|
|
33
|
+
|
|
34
|
+
expect(exec).not.toHaveBeenCalled();
|
|
35
|
+
expect(result.isError).toBe(true);
|
|
36
|
+
expect(result.content[0].text).toContain("Command not allowed");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should handle command failure", async () => {
|
|
40
|
+
const args = { command: "npm run build" };
|
|
41
|
+
|
|
42
|
+
vi.mocked(exec).mockImplementation((_cmd, _opts, callback) => {
|
|
43
|
+
// @ts-expect-error: Mock implementation callback type is complex
|
|
44
|
+
callback({ code: 1, message: "Build failed" }, "", "Error details");
|
|
45
|
+
return {} as any;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const result = await handleRunCommand(projectRoot, args);
|
|
49
|
+
|
|
50
|
+
expect(exec).toHaveBeenCalledWith("npm run build", { cwd: projectRoot, timeout: 30000 }, expect.any(Function));
|
|
51
|
+
expect(result.isError).toBe(true);
|
|
52
|
+
expect(result.content[0].text).toContain("Command failed with exit code 1");
|
|
53
|
+
expect(result.content[0].text).toContain("Error details");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"rootDir": "src",
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"types": ["node"]
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*.ts"]
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-enderun",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.1",
|
|
4
4
|
"description": "The Supreme AI Governance & Autonomous Orchestration Framework for Enterprise Development. Acts as a Corporate AI Management Assistant.",
|
|
5
5
|
"author": "Yusuf BEKAR",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
"bin",
|
|
34
34
|
"dist",
|
|
35
35
|
"src",
|
|
36
|
+
"templates",
|
|
37
|
+
"framework-mcp",
|
|
36
38
|
"README.md",
|
|
37
39
|
"LICENSE"
|
|
38
40
|
],
|
|
@@ -58,7 +60,7 @@
|
|
|
58
60
|
},
|
|
59
61
|
"devDependencies": {
|
|
60
62
|
"@eslint/js": "^10.0.1",
|
|
61
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
63
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
62
64
|
"@pandacss/dev": "^1.11.1",
|
|
63
65
|
"@types/node": "^25.9.1",
|
|
64
66
|
"eslint": "^10.4.0",
|
|
@@ -69,7 +71,7 @@
|
|
|
69
71
|
"vitest": "^3.0.0"
|
|
70
72
|
},
|
|
71
73
|
"enderun": {
|
|
72
|
-
"version": "1.
|
|
74
|
+
"version": "1.11.1",
|
|
73
75
|
"initializedAt": "2026-06-04T18:51:28.970Z",
|
|
74
76
|
"frameworkDir": ".enderun"
|
|
75
77
|
},
|
package/src/cli/adapters/core.ts
CHANGED
|
@@ -3,8 +3,8 @@ import path from "path";
|
|
|
3
3
|
import { writeJsonFile } from "../utils/fs.js";
|
|
4
4
|
import { getPackageRoot } from "../utils/pkg.js";
|
|
5
5
|
|
|
6
|
-
import type { AdapterConfig, AdapterId } from "../../modules/adapters/types.js";
|
|
7
6
|
import { ADAPTER_CONFIGS, POST_INIT_HANDLERS } from "../../modules/adapters/definitions.js";
|
|
7
|
+
import type { AdapterConfig, AdapterId } from "../../modules/adapters/types.js";
|
|
8
8
|
|
|
9
9
|
export const ADAPTERS: Record<AdapterId, AdapterConfig> = ADAPTER_CONFIGS;
|
|
10
10
|
|
|
@@ -16,7 +16,6 @@ export const FRAMEWORK_DIR_CANDIDATES = [
|
|
|
16
16
|
".claude",
|
|
17
17
|
".github",
|
|
18
18
|
".grok",
|
|
19
|
-
".windsurf",
|
|
20
19
|
".antigravity",
|
|
21
20
|
".agent",
|
|
22
21
|
".gemini/antigravity-cli",
|
|
@@ -28,7 +27,7 @@ export const FRAMEWORK_DIR_CANDIDATES = [
|
|
|
28
27
|
export function buildMcpServerEntry(projectRoot: string) {
|
|
29
28
|
const packageRoot = getPackageRoot();
|
|
30
29
|
const mcpServerPath = path.join(packageRoot, "framework-mcp/dist/index.js");
|
|
31
|
-
|
|
30
|
+
|
|
32
31
|
if (!fs.existsSync(mcpServerPath)) {
|
|
33
32
|
console.warn(`ā ļø MCP Server not found at ${mcpServerPath}. Did you run 'npm run build'?`);
|
|
34
33
|
}
|
|
@@ -2,3 +2,4 @@ export { ADAPTER_IDS, type AdapterConfig, type AdapterId, type AdapterRole } fro
|
|
|
2
2
|
export { ADAPTERS, FRAMEWORK_DIR_CANDIDATES, runAdapterPostInit, buildMcpServerEntry } from "./core.js";
|
|
3
3
|
export { resolveAdapter, isAdapterShimFile, remapFrameworkContent } from "./utils.js";
|
|
4
4
|
export { scaffoldAgents } from "./scaffold.js";
|
|
5
|
+
export { resolveAgentsDir, mirrorUnifiedAgentsToNative } from "./paths.js";
|
|
@@ -14,12 +14,22 @@ import {
|
|
|
14
14
|
import type { AdapterId } from "../../modules/adapters/types.js";
|
|
15
15
|
import { ADAPTERS } from "./core.js";
|
|
16
16
|
|
|
17
|
-
export function scaffoldAgents(
|
|
17
|
+
export function scaffoldAgents(
|
|
18
|
+
projectRoot: string,
|
|
19
|
+
adapterId: AdapterId,
|
|
20
|
+
dryRun: boolean,
|
|
21
|
+
agentsToScaffold?: string[],
|
|
22
|
+
explicitDestDir?: string,
|
|
23
|
+
explicitExt?: string
|
|
24
|
+
): void {
|
|
18
25
|
const adapter = ADAPTERS[adapterId];
|
|
19
|
-
if (!adapter
|
|
26
|
+
if (!adapter) return;
|
|
20
27
|
|
|
21
28
|
const allowedAgents = agentsToScaffold ? new Set(agentsToScaffold) : undefined;
|
|
22
|
-
const destAgentsDir = path.join(projectRoot, adapter.agentsDir);
|
|
29
|
+
const destAgentsDir = explicitDestDir ? path.join(projectRoot, explicitDestDir) : (adapter.agentsDir ? path.join(projectRoot, adapter.agentsDir) : null);
|
|
30
|
+
const extension = explicitExt || adapter.agentsExt || ".md";
|
|
31
|
+
|
|
32
|
+
if (!destAgentsDir) return;
|
|
23
33
|
|
|
24
34
|
const baseKnowledgeDir = path.join(getPackageRoot(), "templates/standards");
|
|
25
35
|
|
|
@@ -30,7 +40,7 @@ export function scaffoldAgents(projectRoot: string, adapterId: AdapterId, dryRun
|
|
|
30
40
|
if (allowedAgents && !allowedAgents.has(agent.name)) continue;
|
|
31
41
|
|
|
32
42
|
let content = "";
|
|
33
|
-
let fileName = `${agent.name}${
|
|
43
|
+
let fileName = `${agent.name}${extension}`;
|
|
34
44
|
let secondaryContent: string | null = null;
|
|
35
45
|
let secondaryFileName: string | null = null;
|
|
36
46
|
|
|
@@ -38,6 +48,10 @@ export function scaffoldAgents(projectRoot: string, adapterId: AdapterId, dryRun
|
|
|
38
48
|
case "gemini":
|
|
39
49
|
content = toGeminiCliMd(agent, baseKnowledgeDir);
|
|
40
50
|
break;
|
|
51
|
+
case "grok":
|
|
52
|
+
// Grok uses same Gemini-compatible YAML format
|
|
53
|
+
content = toGeminiCliMd(agent, baseKnowledgeDir);
|
|
54
|
+
break;
|
|
41
55
|
case "claude":
|
|
42
56
|
content = toClaudeCodeMd(agent, baseKnowledgeDir);
|
|
43
57
|
break;
|
|
@@ -52,7 +66,7 @@ export function scaffoldAgents(projectRoot: string, adapterId: AdapterId, dryRun
|
|
|
52
66
|
const agentDir = path.join(destAgentsDir, agent.name);
|
|
53
67
|
if (!dryRun) fs.mkdirSync(agentDir, { recursive: true });
|
|
54
68
|
|
|
55
|
-
content = toAntigravityJson(agent);
|
|
69
|
+
content = toAntigravityJson(agent, baseKnowledgeDir);
|
|
56
70
|
fileName = path.join(agent.name, "agent.json");
|
|
57
71
|
|
|
58
72
|
secondaryContent = `# šļø Agent Enderun ā @${agent.name}\n\n${agent.instructions.identity}\n\n${agent.instructions.mission}`;
|
|
@@ -72,8 +86,7 @@ export function scaffoldAgents(projectRoot: string, adapterId: AdapterId, dryRun
|
|
|
72
86
|
}
|
|
73
87
|
}
|
|
74
88
|
}
|
|
75
|
-
console.warn(`ā
Generated ${allowedAgents ? allowedAgents.size : ALL_AGENTS.length} Agent/Rule definitions under ${path.relative(projectRoot, destAgentsDir)}/`);
|
|
76
89
|
} catch (e) {
|
|
77
|
-
console.warn(`ā ļø Failed to scaffold agents: ${e}`);
|
|
90
|
+
console.warn(`ā ļø Failed to scaffold agents for ${adapterId}: ${e}`);
|
|
78
91
|
}
|
|
79
92
|
}
|
|
@@ -3,7 +3,8 @@ import path from "path";
|
|
|
3
3
|
import {
|
|
4
4
|
remapFrameworkContent,
|
|
5
5
|
type AdapterConfig,
|
|
6
|
-
type AdapterId
|
|
6
|
+
type AdapterId,
|
|
7
|
+
ADAPTERS
|
|
7
8
|
} from "../../adapters/index.js";
|
|
8
9
|
import { SHIM_TEMPLATES } from "../../shims.js";
|
|
9
10
|
import { writeJsonFile, writeTextFile } from "../../utils/fs.js";
|
|
@@ -38,7 +39,14 @@ export function scaffoldConstitution(targetDir: string, frameworkDir: string, ad
|
|
|
38
39
|
console.warn(`ā
Constitution file created inside: ${frameworkDir}/ENDERUN.md${readSuccess ? "" : " (default template)"}`);
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
export function scaffoldFrameworkConfigs(
|
|
42
|
+
export function scaffoldFrameworkConfigs(
|
|
43
|
+
targetDir: string,
|
|
44
|
+
fDir: string,
|
|
45
|
+
adapter: AdapterConfig,
|
|
46
|
+
dryRun: boolean,
|
|
47
|
+
selectedPalette: string,
|
|
48
|
+
options?: { unified?: boolean; adapters?: string[] }
|
|
49
|
+
) {
|
|
42
50
|
if (dryRun) return;
|
|
43
51
|
const frameworkDir = path.join(targetDir, fDir);
|
|
44
52
|
const palette = COLOR_PALETTES[selectedPalette as keyof typeof COLOR_PALETTES] || COLOR_PALETTES["Modern Blue"];
|
|
@@ -46,12 +54,28 @@ export function scaffoldFrameworkConfigs(targetDir: string, fDir: string, adapte
|
|
|
46
54
|
const config = {
|
|
47
55
|
name: FRAMEWORK_NAME,
|
|
48
56
|
version: getPackageVersion(),
|
|
57
|
+
unified: options?.unified || false,
|
|
58
|
+
adapters: options?.adapters || [adapter.id],
|
|
49
59
|
theme: {
|
|
50
60
|
palette: selectedPalette,
|
|
51
61
|
colors: palette
|
|
52
62
|
}
|
|
53
63
|
};
|
|
54
64
|
writeJsonFile(path.join(frameworkDir, "config.json"), config, dryRun);
|
|
65
|
+
|
|
66
|
+
// Scaffold shared-facts.json in memory-graph
|
|
67
|
+
const graphDir = path.join(frameworkDir, "memory-graph");
|
|
68
|
+
if (!fs.existsSync(graphDir)) fs.mkdirSync(graphDir, { recursive: true });
|
|
69
|
+
const sharedFactsPath = path.join(graphDir, "shared-facts.json");
|
|
70
|
+
if (!fs.existsSync(sharedFactsPath)) {
|
|
71
|
+
writeJsonFile(sharedFactsPath, {
|
|
72
|
+
project: FRAMEWORK_NAME,
|
|
73
|
+
initializedAt: new Date().toISOString(),
|
|
74
|
+
stack: [],
|
|
75
|
+
policies: []
|
|
76
|
+
}, dryRun);
|
|
77
|
+
}
|
|
78
|
+
|
|
55
79
|
let statusContent = "# šļø Status\n\n| Agent | State | Active Task | Last Updated | Notes | Extra | Backup |\n|---|---|---|---|---|---|---|\n";
|
|
56
80
|
for (const ag of ALL_AGENTS) {
|
|
57
81
|
statusContent += "| @" + ag.name + " | READY | Idle | - | - | - | - |\n";
|
|
@@ -59,13 +83,28 @@ export function scaffoldFrameworkConfigs(targetDir: string, fDir: string, adapte
|
|
|
59
83
|
writeTextFile(path.join(frameworkDir, "STATUS.md"), statusContent);
|
|
60
84
|
}
|
|
61
85
|
|
|
62
|
-
export function scaffoldShims(
|
|
86
|
+
export function scaffoldShims(
|
|
87
|
+
projectRoot: string,
|
|
88
|
+
coreDir: string,
|
|
89
|
+
adapterId: AdapterId,
|
|
90
|
+
adapter: AdapterConfig,
|
|
91
|
+
dryRun: boolean,
|
|
92
|
+
unified: boolean = false
|
|
93
|
+
) {
|
|
63
94
|
for (const [name, content] of Object.entries(SHIM_TEMPLATES)) {
|
|
64
|
-
|
|
95
|
+
const isSelectedAdapter = name.toLowerCase() === adapterId.split("-")[0] || name === adapterId;
|
|
96
|
+
|
|
97
|
+
if (unified || isSelectedAdapter) {
|
|
65
98
|
const shimContent = remapFrameworkContent(content, coreDir, adapterId);
|
|
66
|
-
const
|
|
99
|
+
const shimAdapter = ADAPTERS[name as AdapterId] || adapter;
|
|
100
|
+
const shimFileName = (unified && !isSelectedAdapter) ? (shimAdapter.shimFile || `${name.toUpperCase()}.md`) : (adapter.shimFile || `${name.toUpperCase()}.md`);
|
|
101
|
+
|
|
67
102
|
if (!dryRun) writeTextFile(path.join(projectRoot, shimFileName), shimContent);
|
|
68
|
-
|
|
103
|
+
if (isSelectedAdapter) {
|
|
104
|
+
console.warn(`ā
Platform shim created: ${shimFileName}`);
|
|
105
|
+
} else if (unified) {
|
|
106
|
+
console.warn(`ā
Unified platform shim added: ${shimFileName}`);
|
|
107
|
+
}
|
|
69
108
|
}
|
|
70
109
|
}
|
|
71
110
|
}
|
package/src/cli/commands/init.ts
CHANGED
|
@@ -5,6 +5,9 @@ import {
|
|
|
5
5
|
resolveAdapter,
|
|
6
6
|
runAdapterPostInit,
|
|
7
7
|
scaffoldAgents,
|
|
8
|
+
resolveAgentsDir,
|
|
9
|
+
mirrorUnifiedAgentsToNative,
|
|
10
|
+
ADAPTER_IDS,
|
|
8
11
|
type AdapterId,
|
|
9
12
|
} from "../adapters/index.js";
|
|
10
13
|
import { ensureDir } from "../utils/fs.js";
|
|
@@ -112,15 +115,41 @@ export async function initCommand(adapterName: string, options: { unified?: bool
|
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
scaffoldConstitution(projectRoot, coreDir, adapterId, dryRun);
|
|
118
|
+
scaffoldFrameworkConfigs(projectRoot, coreDir, adapter, dryRun, selectedPalette, {
|
|
119
|
+
unified: isUnified,
|
|
120
|
+
adapters: isUnified ? [...ADAPTER_IDS] : [adapterId]
|
|
121
|
+
});
|
|
115
122
|
|
|
116
123
|
scaffoldStandards(path.join(projectRoot, coreDir), dryRun);
|
|
117
|
-
|
|
124
|
+
|
|
125
|
+
if (isUnified) {
|
|
126
|
+
// Scaffold ALL agents for ALL adapters under unified hub
|
|
127
|
+
for (const id of ADAPTER_IDS) {
|
|
128
|
+
const dest = resolveAgentsDir(id, true, aiToolDir);
|
|
129
|
+
scaffoldAgents(projectRoot, id, dryRun, selectedAgents, dest.agentsDir, dest.agentsExt);
|
|
130
|
+
if (!dryRun) mirrorUnifiedAgentsToNative(projectRoot, id);
|
|
131
|
+
}
|
|
132
|
+
UI.success(`ā
Scaffolding complete for all adapters under ${aiToolDir}/ with native mirrors.`);
|
|
133
|
+
} else {
|
|
134
|
+
// Standard single-adapter scaffold
|
|
135
|
+
const dest = resolveAgentsDir(adapterId, false);
|
|
136
|
+
scaffoldAgents(projectRoot, adapterId, dryRun, selectedAgents, dest.agentsDir, dest.agentsExt);
|
|
137
|
+
UI.success(`ā
Generated agent definitions under ${dest.agentsDir}/`);
|
|
138
|
+
}
|
|
118
139
|
|
|
119
140
|
const skillsBaseDir = path.join(projectRoot, aiToolDir, "skills");
|
|
120
141
|
scaffoldSkills(skillsBaseDir, dryRun);
|
|
121
142
|
scaffoldOps(path.join(projectRoot, coreDir), dryRun);
|
|
122
|
-
scaffoldShims(projectRoot, coreDir, adapterId, adapter, dryRun);
|
|
143
|
+
scaffoldShims(projectRoot, coreDir, adapterId, adapter, dryRun, isUnified);
|
|
144
|
+
|
|
145
|
+
// Initialize runtime directories
|
|
146
|
+
if (!dryRun) {
|
|
147
|
+
ensureDir(path.join(projectRoot, coreDir, "messages"));
|
|
148
|
+
ensureDir(path.join(projectRoot, coreDir, "logs"));
|
|
149
|
+
ensureDir(path.join(projectRoot, coreDir, "memory-graph"));
|
|
150
|
+
}
|
|
123
151
|
|
|
152
|
+
initializeMemory(path.join(projectRoot, coreDir), dryRun);
|
|
124
153
|
runAdapterPostInit(adapter, projectRoot);
|
|
125
154
|
|
|
126
155
|
UI.success(`\nš ${FRAMEWORK_NAME} (v${getPackageVersion()}) initialized successfully!`);
|
|
@@ -28,11 +28,16 @@ export type HermesMessage = z.infer<typeof HermesMessageSchema>;
|
|
|
28
28
|
let agentStatusCache: Record<string, { state: string; task: string; lastUpdated?: string }> = {};
|
|
29
29
|
let isLooping = false;
|
|
30
30
|
|
|
31
|
-
export async function orchestrateCommand() {
|
|
31
|
+
export async function orchestrateCommand(options?: { maxIterations?: number }) {
|
|
32
32
|
UI.intent("Hermes Message Broker", "Starting the live agent orchestration loop...");
|
|
33
33
|
|
|
34
34
|
const frameworkDir = getFrameworkDir();
|
|
35
35
|
const messagesDir = path.join(frameworkDir, "messages");
|
|
36
|
+
const maxIterations = options?.maxIterations;
|
|
37
|
+
let iterationCount = 0;
|
|
38
|
+
|
|
39
|
+
// Reset in-memory cache so each invocation starts fresh (important for test isolation)
|
|
40
|
+
agentStatusCache = {};
|
|
36
41
|
|
|
37
42
|
// Graceful Shutdown Handling
|
|
38
43
|
const shutdown = async () => {
|
|
@@ -93,16 +98,36 @@ export async function orchestrateCommand() {
|
|
|
93
98
|
const parsed = JSON.parse(line);
|
|
94
99
|
const msg = HermesMessageSchema.parse(parsed);
|
|
95
100
|
|
|
96
|
-
// Contract Validation
|
|
101
|
+
// Contract Validation for structured task messages
|
|
102
|
+
// ACTION & DELEGATION must be valid TaskRequest payloads
|
|
103
|
+
// SUBTASK must have a parentId and valid task payload
|
|
104
|
+
// ALERT must have a content string (free-form, no schema required)
|
|
97
105
|
if (msg.category === "ACTION" || msg.category === "DELEGATION") {
|
|
98
106
|
try {
|
|
99
107
|
const payload = JSON.parse(msg.content);
|
|
100
108
|
TaskRequestSchema.parse(payload);
|
|
101
109
|
} catch (e) {
|
|
102
|
-
UI.error(`Invalid task contract payload: ${(e as Error).message}`);
|
|
110
|
+
UI.error(`Invalid task contract payload in ${msg.category} from @${msg.from}: ${(e as Error).message}`);
|
|
103
111
|
return; // Skip invalid message
|
|
104
112
|
}
|
|
105
113
|
}
|
|
114
|
+
if (msg.category === "SUBTASK") {
|
|
115
|
+
if (!msg.parentId) {
|
|
116
|
+
UI.error(`SUBTASK from @${msg.from} is missing required parentId ā skipping.`);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const payload = JSON.parse(msg.content);
|
|
121
|
+
TaskRequestSchema.parse(payload);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
UI.error(`Invalid SUBTASK payload from @${msg.from}: ${(e as Error).message}`);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (msg.category === "ALERT" && !msg.content.trim()) {
|
|
128
|
+
UI.error(`ALERT from @${msg.from} has empty content ā skipping.`);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
106
131
|
|
|
107
132
|
// A message is actionable if it's pending, or if it's been approved.
|
|
108
133
|
if (msg.status === "PENDING" || msg.status === "APPROVED") {
|
|
@@ -227,6 +252,13 @@ export async function orchestrateCommand() {
|
|
|
227
252
|
logger.debug("Hermes global loop failure", globalLoopErr);
|
|
228
253
|
}
|
|
229
254
|
|
|
255
|
+
iterationCount++;
|
|
256
|
+
// If maxIterations is set (e.g. in tests), stop after N iterations without sleeping
|
|
257
|
+
if (maxIterations !== undefined && iterationCount >= maxIterations) {
|
|
258
|
+
isLooping = false;
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
|
|
230
262
|
// Prevent 100% CPU and provide breathing room for I/O
|
|
231
263
|
await sleep(2000);
|
|
232
264
|
}
|
|
@@ -295,7 +327,12 @@ export async function sendMessage(args: {
|
|
|
295
327
|
|
|
296
328
|
try {
|
|
297
329
|
const defaultPriority = (args.category === "ALERT" || args.category === "ACTION") ? "HIGH" : "NORMAL";
|
|
298
|
-
|
|
330
|
+
// Only ALERT requires manager approval by default.
|
|
331
|
+
// ACTION messages flow freely unless the caller explicitly sets requiresApproval=true.
|
|
332
|
+
// This prevents workflow blockage on normal agent-to-agent task delegation.
|
|
333
|
+
const requiresApproval = args.requiresApproval !== undefined
|
|
334
|
+
? args.requiresApproval
|
|
335
|
+
: args.category === "ALERT";
|
|
299
336
|
|
|
300
337
|
const message: HermesMessage = {
|
|
301
338
|
timestamp: new Date().toISOString(),
|
package/src/cli/commands/plan.ts
CHANGED
|
@@ -1,47 +1,113 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { updateDocumentStore } from "../utils/memory.js";
|
|
4
3
|
import { generateULID } from "../utils/time.js";
|
|
5
4
|
import { UI } from "../utils/ui.js";
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
|
-
*
|
|
7
|
+
* Reads ALL markdown files from the docs/ directory and creates
|
|
8
|
+
* planning tasks from them. Agents will use this to understand
|
|
9
|
+
* project requirements and generate code accordingly.
|
|
9
10
|
*/
|
|
10
11
|
export async function planCommand() {
|
|
11
12
|
const projectRoot = process.cwd();
|
|
12
|
-
const
|
|
13
|
+
const docsDir = path.join(projectRoot, "docs");
|
|
13
14
|
|
|
14
|
-
if (!fs.existsSync(
|
|
15
|
-
UI.error("
|
|
15
|
+
if (!fs.existsSync(docsDir)) {
|
|
16
|
+
UI.error("Docs directory not found at docs/");
|
|
17
|
+
console.warn("š” Create a docs/ folder with your project requirements in .md files.");
|
|
16
18
|
return;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
let match;
|
|
22
|
-
let count = 0;
|
|
21
|
+
const entries = fs.readdirSync(docsDir, { withFileTypes: true });
|
|
22
|
+
const mdFiles = entries.filter(e => e.isFile() && e.name.endsWith(".md"));
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
if (mdFiles.length === 0) {
|
|
25
|
+
UI.warning("No markdown files found in docs/ directory.");
|
|
26
|
+
console.warn("š” Add .md files to docs/ with your project requirements.");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
UI.intent("Planning Engine", `Reading ${mdFiles.length} document(s) from docs/...`);
|
|
31
|
+
|
|
32
|
+
// Discover available template standards
|
|
33
|
+
const templatesDir = path.join(projectRoot, "templates");
|
|
34
|
+
const standards: string[] = [];
|
|
35
|
+
if (fs.existsSync(templatesDir)) {
|
|
36
|
+
const templateFiles = fs.readdirSync(templatesDir);
|
|
37
|
+
standards.push(...templateFiles.filter(f => f.endsWith("-standards.md")).map(f => `templates/${f}`));
|
|
38
|
+
if (standards.length > 0) {
|
|
39
|
+
UI.success(`Found ${standards.length} standard templates available for code generation.`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let totalTasks = 0;
|
|
44
|
+
|
|
45
|
+
for (const file of mdFiles) {
|
|
46
|
+
const filePath = path.join(docsDir, file.name);
|
|
47
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
48
|
+
const lines = content.split("\n");
|
|
30
49
|
const traceId = generateULID();
|
|
31
|
-
|
|
50
|
+
|
|
51
|
+
UI.success(`š docs/${file.name} (${lines.length} lines) ā Trace: ${traceId}`);
|
|
52
|
+
|
|
53
|
+
console.warn(` Content preview: ${content.substring(0, 200).replace(/\n/g, " ")}...`);
|
|
54
|
+
|
|
55
|
+
// Extract headings as task descriptions
|
|
56
|
+
const headingRegex = /^#{2,4}\s+(.+)$/gm;
|
|
57
|
+
let headingMatch;
|
|
58
|
+
let headingCount = 0;
|
|
59
|
+
while ((headingMatch = headingRegex.exec(content)) !== null) {
|
|
60
|
+
headingCount++;
|
|
61
|
+
totalTasks++;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Extract checklist items
|
|
65
|
+
const taskRegex = /- \[ \]\s+(.+)/g;
|
|
66
|
+
let taskMatch;
|
|
67
|
+
let taskCount = 0;
|
|
68
|
+
while ((taskMatch = taskRegex.exec(content)) !== null) {
|
|
69
|
+
if (taskMatch[1].trim().length >= 3) {
|
|
70
|
+
taskCount++;
|
|
71
|
+
totalTasks++;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
console.warn(` š ${headingCount} sections, ${taskCount} actionable tasks detected`);
|
|
76
|
+
|
|
77
|
+
// Store in project memory-compatible format
|
|
78
|
+
const memoryDir = path.join(projectRoot, ".enderun", "memory", "tasks");
|
|
79
|
+
if (!fs.existsSync(memoryDir)) {
|
|
80
|
+
fs.mkdirSync(memoryDir, { recursive: true });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const taskFile = path.join(memoryDir, `${traceId}.json`);
|
|
32
84
|
const taskData = {
|
|
33
85
|
traceId,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
agent: agent.trim().replace("@", ""),
|
|
86
|
+
source: `docs/${file.name}`,
|
|
87
|
+
description: `Process requirements from docs/${file.name}`,
|
|
37
88
|
status: "PENDING",
|
|
38
|
-
createdAt: new Date().toISOString()
|
|
89
|
+
createdAt: new Date().toISOString(),
|
|
90
|
+
standards,
|
|
91
|
+
headings: headingCount,
|
|
92
|
+
tasks: taskCount,
|
|
93
|
+
preview: content.substring(0, 500),
|
|
39
94
|
};
|
|
95
|
+
fs.writeFileSync(taskFile, JSON.stringify(taskData, null, 2));
|
|
96
|
+
}
|
|
40
97
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
98
|
+
// Log available standards
|
|
99
|
+
if (standards.length > 0) {
|
|
100
|
+
console.warn("");
|
|
101
|
+
UI.divider();
|
|
102
|
+
console.warn("š Available Enterprise Standards:");
|
|
103
|
+
standards.forEach(s => console.warn(` - ${s}`));
|
|
104
|
+
UI.divider();
|
|
44
105
|
}
|
|
45
106
|
|
|
46
|
-
UI.success(
|
|
107
|
+
UI.success(`\nā
Planning complete: ${totalTasks} tasks identified from ${mdFiles.length} document(s).`);
|
|
108
|
+
console.warn("\nš Next steps:");
|
|
109
|
+
console.warn(" 1. Run 'agent-enderun status' to see project state");
|
|
110
|
+
console.warn(" 2. AI agents (Claude, Gemini, Grok, etc.) will read docs/ and templates/");
|
|
111
|
+
console.warn(" 3. Agents generate enterprise-standard code based on requirements");
|
|
112
|
+
console.warn(" 4. Use @agent delegation for specific tasks: agent-enderun @backend \"...\"");
|
|
47
113
|
}
|