@voybio/ace-swarm 0.2.4 → 2.4.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/CHANGELOG.md +11 -1
- package/README.md +20 -13
- package/assets/.agents/skills/eval-harness/SKILL.md +14 -0
- package/assets/.agents/skills/handoff-lint/SKILL.md +14 -0
- package/assets/.agents/skills/incident-commander/SKILL.md +14 -0
- package/assets/.agents/skills/memory-curator/SKILL.md +14 -0
- package/assets/.agents/skills/release-sentry/SKILL.md +14 -0
- package/assets/.agents/skills/risk-quant/SKILL.md +14 -0
- package/assets/.agents/skills/schema-forge/SKILL.md +14 -0
- package/assets/.agents/skills/state-auditor/SKILL.md +14 -0
- package/assets/agent-state/EVIDENCE_LOG.md +1 -1
- package/assets/agent-state/MODULES/gates/gate-correctness.json +1 -1
- package/assets/agent-state/MODULES/roles/capability-framework.json +41 -0
- package/assets/agent-state/MODULES/roles/capability-git.json +33 -0
- package/assets/agent-state/MODULES/roles/capability-safety.json +37 -0
- package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +21 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +43 -0
- package/assets/agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json +11 -0
- package/assets/agent-state/STATUS.md +2 -2
- package/assets/scripts/ace-hook-dispatch.mjs +70 -6
- package/assets/scripts/render-mcp-configs.sh +19 -5
- package/dist/ace-context.js +22 -1
- package/dist/ace-server-instructions.js +3 -3
- package/dist/ace-state-resolver.js +5 -3
- package/dist/astgrep-index.d.ts +9 -1
- package/dist/astgrep-index.js +14 -3
- package/dist/cli.js +52 -20
- package/dist/handoff-registry.js +5 -5
- package/dist/helpers/artifacts.d.ts +19 -0
- package/dist/helpers/artifacts.js +152 -0
- package/dist/helpers/bootstrap.d.ts +24 -0
- package/dist/helpers/bootstrap.js +894 -0
- package/dist/helpers/constants.d.ts +53 -0
- package/dist/helpers/constants.js +288 -0
- package/dist/helpers/drift.d.ts +13 -0
- package/dist/helpers/drift.js +45 -0
- package/dist/helpers/path-utils.d.ts +17 -0
- package/dist/helpers/path-utils.js +104 -0
- package/dist/helpers/store-resolution.d.ts +19 -0
- package/dist/helpers/store-resolution.js +301 -0
- package/dist/helpers/workspace-root.d.ts +3 -0
- package/dist/helpers/workspace-root.js +80 -0
- package/dist/helpers.d.ts +8 -123
- package/dist/helpers.js +8 -1747
- package/dist/job-scheduler.js +3 -3
- package/dist/local-model-runtime.js +12 -1
- package/dist/model-bridge.d.ts +7 -0
- package/dist/model-bridge.js +75 -5
- package/dist/orchestrator-supervisor.d.ts +14 -0
- package/dist/orchestrator-supervisor.js +72 -1
- package/dist/run-ledger.js +3 -3
- package/dist/runtime-command.d.ts +8 -0
- package/dist/runtime-command.js +38 -6
- package/dist/runtime-executor.d.ts +14 -0
- package/dist/runtime-executor.js +669 -171
- package/dist/runtime-profile.d.ts +32 -0
- package/dist/runtime-profile.js +89 -13
- package/dist/runtime-tool-specs.d.ts +21 -0
- package/dist/runtime-tool-specs.js +78 -3
- package/dist/safe-edit.d.ts +7 -0
- package/dist/safe-edit.js +163 -37
- package/dist/schemas.js +19 -0
- package/dist/shared.d.ts +2 -2
- package/dist/status-events.js +9 -6
- package/dist/store/ace-packed-store.d.ts +3 -2
- package/dist/store/ace-packed-store.js +188 -110
- package/dist/store/bootstrap-store.d.ts +1 -1
- package/dist/store/bootstrap-store.js +94 -81
- package/dist/store/cache-workspace.d.ts +22 -0
- package/dist/store/cache-workspace.js +149 -0
- package/dist/store/materializers/context-snapshot-materializer.js +6 -7
- package/dist/store/materializers/hook-context-materializer.d.ts +6 -9
- package/dist/store/materializers/hook-context-materializer.js +11 -21
- package/dist/store/materializers/host-file-materializer.js +6 -0
- package/dist/store/materializers/projection-manager.d.ts +0 -1
- package/dist/store/materializers/projection-manager.js +5 -13
- package/dist/store/materializers/scheduler-projection-materializer.js +1 -1
- package/dist/store/materializers/vericify-projector.d.ts +7 -7
- package/dist/store/materializers/vericify-projector.js +11 -11
- package/dist/store/repositories/local-model-runtime-repository.d.ts +120 -3
- package/dist/store/repositories/local-model-runtime-repository.js +242 -6
- package/dist/store/skills-install.d.ts +4 -0
- package/dist/store/skills-install.js +21 -12
- package/dist/store/state-reader.d.ts +2 -0
- package/dist/store/state-reader.js +20 -0
- package/dist/store/store-artifacts.d.ts +7 -0
- package/dist/store/store-artifacts.js +27 -1
- package/dist/store/store-authority-audit.d.ts +18 -1
- package/dist/store/store-authority-audit.js +115 -5
- package/dist/store/store-snapshot.d.ts +3 -0
- package/dist/store/store-snapshot.js +22 -2
- package/dist/store/workspace-store-paths.d.ts +39 -0
- package/dist/store/workspace-store-paths.js +94 -0
- package/dist/store/write-coordinator.d.ts +65 -0
- package/dist/store/write-coordinator.js +386 -0
- package/dist/todo-state.js +5 -5
- package/dist/tools-agent.js +319 -34
- package/dist/tools-discovery.js +1 -1
- package/dist/tools-files.d.ts +7 -0
- package/dist/tools-files.js +299 -10
- package/dist/tools-framework.js +107 -27
- package/dist/tools-handoff.js +2 -2
- package/dist/tools-lifecycle.js +4 -4
- package/dist/tools-memory.js +6 -6
- package/dist/tools-todo.js +2 -2
- package/dist/tracker-adapters.d.ts +1 -1
- package/dist/tracker-adapters.js +13 -18
- package/dist/tracker-sync.js +5 -3
- package/dist/tui/agent-runner.js +3 -1
- package/dist/tui/chat.js +103 -7
- package/dist/tui/dashboard.d.ts +1 -0
- package/dist/tui/dashboard.js +43 -0
- package/dist/tui/layout.d.ts +20 -0
- package/dist/tui/layout.js +31 -1
- package/dist/tui/local-model-contract.d.ts +6 -2
- package/dist/tui/local-model-contract.js +16 -3
- package/dist/vericify-bridge.d.ts +5 -0
- package/dist/vericify-bridge.js +27 -3
- package/dist/workspace-manager.d.ts +30 -3
- package/dist/workspace-manager.js +257 -27
- package/package.json +1 -2
- package/dist/internal-tool-runtime.d.ts +0 -21
- package/dist/internal-tool-runtime.js +0 -136
- package/dist/store/workspace-snapshot.d.ts +0 -26
- package/dist/store/workspace-snapshot.js +0 -107
package/dist/helpers.js
CHANGED
|
@@ -1,1750 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
* Shared helpers – path resolution, file I/O, artifact discovery, bootstrap.
|
|
3
|
-
*/
|
|
4
|
-
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
|
|
5
|
-
import { homedir } from "node:os";
|
|
6
|
-
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { buildHostInstructionText } from "./ace-server-instructions.js";
|
|
9
|
-
import { isInside, normalizeRelPath } from "./shared.js";
|
|
10
|
-
import { getWorkspaceStorePath, listStoreKeysSync, parseVirtualStorePath, readStoreBlobSync, readVirtualStorePathSync, toVirtualStorePath, } from "./store/store-snapshot.js";
|
|
11
|
-
import { isOperationalArtifactPath, operationalArtifactKey, writeStoreBlobSync, writeOperationalArtifactSync, } from "./store/store-artifacts.js";
|
|
12
|
-
import { buildProviderDoctorCommands, buildOpenAiCompatibleBaseUrl, defaultModelForProvider, normalizeLocalBaseUrl, normalizeProvider, } from "./tui/provider-discovery.js";
|
|
1
|
+
import { resolveWorkspaceRoot } from "./helpers/workspace-root.js";
|
|
13
2
|
export { isInside, isReadError, normalizeRelPath, looksLikeSwarmHandoffPath } from "./shared.js";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export const SERVER_ROOT = resolve(__dirname, "..");
|
|
17
|
-
export const PACKAGE_ROOT = SERVER_ROOT;
|
|
18
|
-
function normalizeWorkspaceRootCandidate(candidate) {
|
|
19
|
-
const trimmed = candidate?.trim();
|
|
20
|
-
if (!trimmed)
|
|
21
|
-
return undefined;
|
|
22
|
-
return resolve(trimmed);
|
|
23
|
-
}
|
|
24
|
-
function isFilesystemRoot(path) {
|
|
25
|
-
return dirname(path) === path;
|
|
26
|
-
}
|
|
27
|
-
function normalizeWorkspaceRootLikePath(candidate) {
|
|
28
|
-
const resolvedCandidate = resolve(candidate);
|
|
29
|
-
if (resolvedCandidate.endsWith(join(".agents", "ACE", "ace-state.ace"))) {
|
|
30
|
-
return dirname(dirname(dirname(resolvedCandidate)));
|
|
31
|
-
}
|
|
32
|
-
if (resolvedCandidate.endsWith(join(".agents", "ACE"))) {
|
|
33
|
-
return dirname(dirname(resolvedCandidate));
|
|
34
|
-
}
|
|
35
|
-
if (resolvedCandidate.endsWith(join(".agents"))) {
|
|
36
|
-
return dirname(resolvedCandidate);
|
|
37
|
-
}
|
|
38
|
-
return resolvedCandidate;
|
|
39
|
-
}
|
|
40
|
-
function hasInitiatedAceWorkspace(root) {
|
|
41
|
-
return (existsSync(resolve(root, ".agents", "ACE", "ace-state.ace")) ||
|
|
42
|
-
existsSync(resolve(root, ".agents", "ACE")) ||
|
|
43
|
-
existsSync(resolve(root, "agent-state", "TASK.md")) ||
|
|
44
|
-
existsSync(resolve(root, "agent-state", "STATUS.md")));
|
|
45
|
-
}
|
|
46
|
-
function findNearestInitiatedWorkspaceRoot(candidate) {
|
|
47
|
-
let cursor = normalizeWorkspaceRootLikePath(candidate);
|
|
48
|
-
while (true) {
|
|
49
|
-
if (existsSync(cursor) && hasInitiatedAceWorkspace(cursor)) {
|
|
50
|
-
return cursor;
|
|
51
|
-
}
|
|
52
|
-
const parent = dirname(cursor);
|
|
53
|
-
if (parent === cursor)
|
|
54
|
-
break;
|
|
55
|
-
cursor = parent;
|
|
56
|
-
}
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
function pinWorkspaceRoot(root) {
|
|
60
|
-
const normalized = normalizeWorkspaceRootLikePath(root);
|
|
61
|
-
process.env.ACE_WORKSPACE_ROOT = normalized;
|
|
62
|
-
return normalized;
|
|
63
|
-
}
|
|
64
|
-
export function resolveWorkspaceRoot() {
|
|
65
|
-
const explicit = normalizeWorkspaceRootCandidate(process.env.ACE_WORKSPACE_ROOT);
|
|
66
|
-
if (explicit)
|
|
67
|
-
return pinWorkspaceRoot(findNearestInitiatedWorkspaceRoot(explicit) ?? explicit);
|
|
68
|
-
const ordered = [
|
|
69
|
-
process.env.ACE_TUI_WORKSPACE_ROOT,
|
|
70
|
-
process.env.INIT_CWD,
|
|
71
|
-
process.env.PWD,
|
|
72
|
-
process.cwd(),
|
|
73
|
-
]
|
|
74
|
-
.map(normalizeWorkspaceRootCandidate)
|
|
75
|
-
.filter((candidate) => Boolean(candidate));
|
|
76
|
-
const candidates = [...new Set(ordered)];
|
|
77
|
-
for (const candidate of candidates) {
|
|
78
|
-
const initiated = findNearestInitiatedWorkspaceRoot(candidate);
|
|
79
|
-
if (initiated)
|
|
80
|
-
return pinWorkspaceRoot(initiated);
|
|
81
|
-
}
|
|
82
|
-
const firstExistingNonRoot = candidates.find((candidate) => existsSync(candidate) && !isFilesystemRoot(candidate));
|
|
83
|
-
if (firstExistingNonRoot)
|
|
84
|
-
return pinWorkspaceRoot(firstExistingNonRoot);
|
|
85
|
-
const firstExisting = candidates.find((candidate) => existsSync(candidate));
|
|
86
|
-
if (firstExisting)
|
|
87
|
-
return pinWorkspaceRoot(firstExisting);
|
|
88
|
-
return pinWorkspaceRoot(candidates[0] ?? resolve(process.cwd()));
|
|
89
|
-
}
|
|
3
|
+
export * from "./helpers/constants.js";
|
|
4
|
+
export { resolveWorkspaceRoot };
|
|
90
5
|
export const WORKSPACE_ROOT = resolveWorkspaceRoot();
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
export
|
|
95
|
-
|
|
96
|
-
const DEFAULTS_TASKS_ROOT = resolve(DEFAULTS_ROOT, "tasks");
|
|
97
|
-
const DEFAULTS_SKILLS_ROOT = resolve(DEFAULTS_ROOT, ".agents", "skills");
|
|
98
|
-
const DEFAULTS_AGENT_STATE_ROOT = resolve(DEFAULTS_ROOT, "agent-state");
|
|
99
|
-
const DEFAULTS_SCRIPTS_ROOT = resolve(DEFAULTS_ROOT, "scripts");
|
|
100
|
-
const DEFAULTS_GITHUB_ROOT = resolve(DEFAULTS_ROOT, ".github");
|
|
101
|
-
export const ACE_ROOT_REL = ".agents/ACE";
|
|
102
|
-
export const ACE_SKILLS_ROOT_REL = `${ACE_ROOT_REL}/skills`;
|
|
103
|
-
export const ACE_TASKS_ROOT_REL = `${ACE_ROOT_REL}/tasks`;
|
|
104
|
-
export const ACE_SCRIPTS_ROOT_REL = `${ACE_ROOT_REL}/scripts/ace`;
|
|
105
|
-
export const ACE_BUNDLE_ROOT_REL = ".mcp-config";
|
|
106
|
-
export const ACE_LLM_ROOT_REL = `${ACE_ROOT_REL}/.ace`;
|
|
107
|
-
export const ACE_VSCODE_ROOT_REL = ".vscode";
|
|
108
|
-
export const ACE_CURSOR_ROOT_REL = ".cursor";
|
|
109
|
-
export const ACE_CLAUDE_ROOT_REL = ".claude";
|
|
110
|
-
export const ACE_GITHUB_ROOT_REL = ".github";
|
|
111
|
-
export const ACE_HOST_AGENTS_REL = "AGENTS.md";
|
|
112
|
-
export const ACE_HOST_CLAUDE_REL = "CLAUDE.md";
|
|
113
|
-
export const ACE_HOST_CURSOR_RULES_REL = ".cursorrules";
|
|
114
|
-
const ACE_MANAGED_PREFIXES = [
|
|
115
|
-
"agent-state",
|
|
116
|
-
"global-state",
|
|
117
|
-
"venture-state",
|
|
118
|
-
"brand-state",
|
|
119
|
-
"business-state",
|
|
120
|
-
"engineering-state",
|
|
121
|
-
".ace",
|
|
122
|
-
".mcp-config",
|
|
123
|
-
];
|
|
124
|
-
export const ALL_MCP_CLIENTS = [
|
|
125
|
-
"codex",
|
|
126
|
-
"vscode",
|
|
127
|
-
"claude",
|
|
128
|
-
"cursor",
|
|
129
|
-
"antigravity",
|
|
130
|
-
];
|
|
131
|
-
export const ALL_LLM_PROVIDERS = [
|
|
132
|
-
"ollama",
|
|
133
|
-
"llama.cpp",
|
|
134
|
-
"codex",
|
|
135
|
-
"claude",
|
|
136
|
-
"gemini",
|
|
137
|
-
"copilot",
|
|
138
|
-
];
|
|
139
|
-
export const ALL_AGENTS = [
|
|
140
|
-
"orchestrator",
|
|
141
|
-
"vos",
|
|
142
|
-
"ui",
|
|
143
|
-
"coders",
|
|
144
|
-
"astgrep",
|
|
145
|
-
"skeptic",
|
|
146
|
-
"ops",
|
|
147
|
-
"research",
|
|
148
|
-
"spec",
|
|
149
|
-
"builder",
|
|
150
|
-
"qa",
|
|
151
|
-
"docs",
|
|
152
|
-
"memory",
|
|
153
|
-
"security",
|
|
154
|
-
"observability",
|
|
155
|
-
"eval",
|
|
156
|
-
"release",
|
|
157
|
-
];
|
|
158
|
-
export const SWARM_AGENTS = ["orchestrator", "vos", "ui", "coders"];
|
|
159
|
-
export const COMPOSABLE_AGENTS = [
|
|
160
|
-
"astgrep",
|
|
161
|
-
"skeptic",
|
|
162
|
-
"ops",
|
|
163
|
-
"research",
|
|
164
|
-
"spec",
|
|
165
|
-
"builder",
|
|
166
|
-
"qa",
|
|
167
|
-
"docs",
|
|
168
|
-
"memory",
|
|
169
|
-
"security",
|
|
170
|
-
"observability",
|
|
171
|
-
"eval",
|
|
172
|
-
"release",
|
|
173
|
-
];
|
|
174
|
-
export const SWARM_SUBAGENT_MAP = {
|
|
175
|
-
orchestrator: COMPOSABLE_AGENTS,
|
|
176
|
-
vos: COMPOSABLE_AGENTS,
|
|
177
|
-
ui: COMPOSABLE_AGENTS,
|
|
178
|
-
coders: COMPOSABLE_AGENTS,
|
|
179
|
-
};
|
|
180
|
-
// Workspace-first agent instruction candidates.
|
|
181
|
-
export const AGENT_FILES = {
|
|
182
|
-
orchestrator: [
|
|
183
|
-
".agents/ACE/orchestrator/instructions.md",
|
|
184
|
-
".agents/ACE/orchestrator/AGENTS.md",
|
|
185
|
-
"ACE.instructions.md",
|
|
186
|
-
// Legacy fallback (pre split where ACE-Init carried orchestrator behavior)
|
|
187
|
-
".agents/ACE/ACE-Init/instructions.md",
|
|
188
|
-
".agents/ACE/ACE-Init/AGENTS.md",
|
|
189
|
-
],
|
|
190
|
-
vos: [
|
|
191
|
-
".agents/ACE/VOS/instructions.md",
|
|
192
|
-
".agents/ACE/VOS/AGENTS.md",
|
|
193
|
-
"ACE_VOS.instructions.md",
|
|
194
|
-
],
|
|
195
|
-
ui: [
|
|
196
|
-
".agents/ACE/UI/instructions.md",
|
|
197
|
-
".agents/ACE/UI/AGENTS.md",
|
|
198
|
-
"ACE_UI.instructions.md",
|
|
199
|
-
],
|
|
200
|
-
coders: [
|
|
201
|
-
".agents/ACE/ACE_coders/INSTRUCTIONS.md",
|
|
202
|
-
".agents/ACE/ACE_coders/AGENTS.md",
|
|
203
|
-
"ACE_Coder.instructions.md",
|
|
204
|
-
],
|
|
205
|
-
astgrep: [".agents/ACE/agent-astgrep/instructions.md", ".agents/ACE/agent-astgrep/AGENTS.md"],
|
|
206
|
-
skeptic: [".agents/ACE/agent-skeptic/instructions.md", ".agents/ACE/agent-skeptic/AGENTS.md"],
|
|
207
|
-
ops: [".agents/ACE/agent-ops/instructions.md", ".agents/ACE/agent-ops/AGENTS.md"],
|
|
208
|
-
research: [
|
|
209
|
-
".agents/ACE/agent-research/instructions.md",
|
|
210
|
-
".agents/ACE/agent-research/AGENTS.md",
|
|
211
|
-
],
|
|
212
|
-
spec: [".agents/ACE/agent-spec/instructions.md", ".agents/ACE/agent-spec/AGENTS.md"],
|
|
213
|
-
builder: [
|
|
214
|
-
".agents/ACE/agent-builder/instructions.md",
|
|
215
|
-
".agents/ACE/agent-builder/AGENTS.md",
|
|
216
|
-
],
|
|
217
|
-
qa: [".agents/ACE/agent-qa/instructions.md", ".agents/ACE/agent-qa/AGENTS.md"],
|
|
218
|
-
docs: [".agents/ACE/agent-docs/instructions.md", ".agents/ACE/agent-docs/AGENTS.md"],
|
|
219
|
-
memory: [
|
|
220
|
-
".agents/ACE/agent-memory/instructions.md",
|
|
221
|
-
".agents/ACE/agent-memory/AGENTS.md",
|
|
222
|
-
],
|
|
223
|
-
security: [
|
|
224
|
-
".agents/ACE/agent-security/instructions.md",
|
|
225
|
-
".agents/ACE/agent-security/AGENTS.md",
|
|
226
|
-
],
|
|
227
|
-
observability: [
|
|
228
|
-
".agents/ACE/agent-observability/instructions.md",
|
|
229
|
-
".agents/ACE/agent-observability/AGENTS.md",
|
|
230
|
-
],
|
|
231
|
-
eval: [".agents/ACE/agent-eval/instructions.md", ".agents/ACE/agent-eval/AGENTS.md"],
|
|
232
|
-
release: [".agents/ACE/agent-release/instructions.md", ".agents/ACE/agent-release/AGENTS.md"],
|
|
233
|
-
};
|
|
234
|
-
// Workspace-first agent manifest candidates.
|
|
235
|
-
export const AGENT_MANIFEST_FILES = {
|
|
236
|
-
orchestrator: [
|
|
237
|
-
".agents/ACE/orchestrator/AGENTS.md",
|
|
238
|
-
// Legacy fallback (pre split where ACE-Init carried orchestrator behavior)
|
|
239
|
-
".agents/ACE/ACE-Init/AGENTS.md",
|
|
240
|
-
],
|
|
241
|
-
vos: [".agents/ACE/VOS/AGENTS.md"],
|
|
242
|
-
ui: [".agents/ACE/UI/AGENTS.md"],
|
|
243
|
-
coders: [".agents/ACE/ACE_coders/AGENTS.md"],
|
|
244
|
-
astgrep: [".agents/ACE/agent-astgrep/AGENTS.md"],
|
|
245
|
-
skeptic: [".agents/ACE/agent-skeptic/AGENTS.md"],
|
|
246
|
-
ops: [".agents/ACE/agent-ops/AGENTS.md"],
|
|
247
|
-
research: [".agents/ACE/agent-research/AGENTS.md"],
|
|
248
|
-
spec: [".agents/ACE/agent-spec/AGENTS.md"],
|
|
249
|
-
builder: [".agents/ACE/agent-builder/AGENTS.md"],
|
|
250
|
-
qa: [".agents/ACE/agent-qa/AGENTS.md"],
|
|
251
|
-
docs: [".agents/ACE/agent-docs/AGENTS.md"],
|
|
252
|
-
memory: [".agents/ACE/agent-memory/AGENTS.md"],
|
|
253
|
-
security: [".agents/ACE/agent-security/AGENTS.md"],
|
|
254
|
-
observability: [".agents/ACE/agent-observability/AGENTS.md"],
|
|
255
|
-
eval: [".agents/ACE/agent-eval/AGENTS.md"],
|
|
256
|
-
release: [".agents/ACE/agent-release/AGENTS.md"],
|
|
257
|
-
};
|
|
258
|
-
export const TASK_FILES = {
|
|
259
|
-
todo: [`${ACE_TASKS_ROOT_REL}/todo.md`],
|
|
260
|
-
role_tasks: [`${ACE_TASKS_ROOT_REL}/role_tasks.md`],
|
|
261
|
-
cli_work_split: [`${ACE_TASKS_ROOT_REL}/cli_work_split.md`],
|
|
262
|
-
lessons: [`${ACE_TASKS_ROOT_REL}/lessons.md`],
|
|
263
|
-
readme: [`${ACE_TASKS_ROOT_REL}/README.md`],
|
|
264
|
-
handoff_template: [`${ACE_TASKS_ROOT_REL}/SWARM_HANDOFF.template.json`],
|
|
265
|
-
handoff_example: [`${ACE_TASKS_ROOT_REL}/SWARM_HANDOFF.example.json`],
|
|
266
|
-
handoff_example_vos_ui: [`${ACE_TASKS_ROOT_REL}/SWARM_HANDOFF.example_vos_to_ui.json`],
|
|
267
|
-
handoff_example_ui_coders: [`${ACE_TASKS_ROOT_REL}/SWARM_HANDOFF.example_ui_to_coders.json`],
|
|
268
|
-
};
|
|
269
|
-
export const KERNEL_FILES = {
|
|
270
|
-
directive_kernel: [
|
|
271
|
-
".agents/ACE/DIRECTIVE_KERNEL.md",
|
|
272
|
-
"agent-state/ACE_MACHINE_KERNEL_DIRECTIVES.md",
|
|
273
|
-
],
|
|
274
|
-
agent_registry: [
|
|
275
|
-
".agents/ACE/AGENT_REGISTRY.md",
|
|
276
|
-
".agents/ACE/AGENT_REGISTRY_7.md",
|
|
277
|
-
"agent-state/ACE_7_AGENT_SYSTEM_SPEC.md",
|
|
278
|
-
],
|
|
279
|
-
};
|
|
280
|
-
const DEFAULT_AGENT_INSTRUCTION_FILES = {
|
|
281
|
-
orchestrator: resolve(DEFAULTS_INSTRUCTIONS_ROOT, "ACE.instructions.md"),
|
|
282
|
-
vos: resolve(DEFAULTS_INSTRUCTIONS_ROOT, "ACE_VOS.instructions.md"),
|
|
283
|
-
ui: resolve(DEFAULTS_INSTRUCTIONS_ROOT, "ACE_UI.instructions.md"),
|
|
284
|
-
coders: resolve(DEFAULTS_INSTRUCTIONS_ROOT, "ACE_Coder.instructions.md"),
|
|
285
|
-
astgrep: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-astgrep", "instructions.md"),
|
|
286
|
-
skeptic: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-skeptic", "instructions.md"),
|
|
287
|
-
ops: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-ops", "instructions.md"),
|
|
288
|
-
research: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-research", "instructions.md"),
|
|
289
|
-
spec: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-spec", "instructions.md"),
|
|
290
|
-
builder: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-builder", "instructions.md"),
|
|
291
|
-
qa: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-qa", "instructions.md"),
|
|
292
|
-
docs: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-docs", "instructions.md"),
|
|
293
|
-
memory: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-memory", "instructions.md"),
|
|
294
|
-
security: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-security", "instructions.md"),
|
|
295
|
-
observability: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-observability", "instructions.md"),
|
|
296
|
-
eval: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-eval", "instructions.md"),
|
|
297
|
-
release: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-release", "instructions.md"),
|
|
298
|
-
};
|
|
299
|
-
const DEFAULT_AGENT_MANIFEST_FILES = {
|
|
300
|
-
orchestrator: resolve(DEFAULTS_ROOT, ".agents", "ACE", "orchestrator", "AGENTS.md"),
|
|
301
|
-
vos: resolve(DEFAULTS_ROOT, ".agents", "ACE", "VOS", "AGENTS.md"),
|
|
302
|
-
ui: resolve(DEFAULTS_ROOT, ".agents", "ACE", "UI", "AGENTS.md"),
|
|
303
|
-
coders: resolve(DEFAULTS_ROOT, ".agents", "ACE", "ACE_coders", "AGENTS.md"),
|
|
304
|
-
astgrep: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-astgrep", "AGENTS.md"),
|
|
305
|
-
skeptic: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-skeptic", "AGENTS.md"),
|
|
306
|
-
ops: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-ops", "AGENTS.md"),
|
|
307
|
-
research: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-research", "AGENTS.md"),
|
|
308
|
-
spec: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-spec", "AGENTS.md"),
|
|
309
|
-
builder: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-builder", "AGENTS.md"),
|
|
310
|
-
qa: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-qa", "AGENTS.md"),
|
|
311
|
-
docs: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-docs", "AGENTS.md"),
|
|
312
|
-
memory: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-memory", "AGENTS.md"),
|
|
313
|
-
security: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-security", "AGENTS.md"),
|
|
314
|
-
observability: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-observability", "AGENTS.md"),
|
|
315
|
-
eval: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-eval", "AGENTS.md"),
|
|
316
|
-
release: resolve(DEFAULTS_ROOT, ".agents", "ACE", "agent-release", "AGENTS.md"),
|
|
317
|
-
};
|
|
318
|
-
const DEFAULT_TASK_FILES = {
|
|
319
|
-
todo: resolve(DEFAULTS_TASKS_ROOT, "todo.md"),
|
|
320
|
-
role_tasks: resolve(DEFAULTS_TASKS_ROOT, "role_tasks.md"),
|
|
321
|
-
cli_work_split: resolve(DEFAULTS_TASKS_ROOT, "cli_work_split.md"),
|
|
322
|
-
lessons: resolve(DEFAULTS_TASKS_ROOT, "lessons.md"),
|
|
323
|
-
readme: resolve(DEFAULTS_TASKS_ROOT, "README.md"),
|
|
324
|
-
handoff_template: resolve(DEFAULTS_TASKS_ROOT, "SWARM_HANDOFF.template.json"),
|
|
325
|
-
handoff_example: resolve(DEFAULTS_TASKS_ROOT, "SWARM_HANDOFF.example.json"),
|
|
326
|
-
handoff_example_vos_ui: resolve(DEFAULTS_TASKS_ROOT, "SWARM_HANDOFF.example_vos_to_ui.json"),
|
|
327
|
-
handoff_example_ui_coders: resolve(DEFAULTS_TASKS_ROOT, "SWARM_HANDOFF.example_ui_to_coders.json"),
|
|
328
|
-
};
|
|
329
|
-
const DEFAULT_KERNEL_FILES = {
|
|
330
|
-
directive_kernel: resolve(DEFAULTS_ROOT, ".agents", "ACE", "DIRECTIVE_KERNEL.md"),
|
|
331
|
-
agent_registry: resolve(DEFAULTS_ROOT, ".agents", "ACE", "AGENT_REGISTRY.md"),
|
|
332
|
-
};
|
|
333
|
-
const STORE_AGENT_FILES = {
|
|
334
|
-
orchestrator: {
|
|
335
|
-
agent: "ace-orchestrator",
|
|
336
|
-
instructions: ["instructions.md", "AGENTS.md"],
|
|
337
|
-
manifests: ["AGENTS.md"],
|
|
338
|
-
},
|
|
339
|
-
vos: { agent: "ace-vos", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
340
|
-
ui: { agent: "ace-ui", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
341
|
-
coders: { agent: "ace-coders", instructions: ["INSTRUCTIONS.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
342
|
-
astgrep: { agent: "astgrep", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
343
|
-
skeptic: { agent: "skeptic", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
344
|
-
ops: { agent: "ops", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
345
|
-
research: { agent: "research", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
346
|
-
spec: { agent: "spec", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
347
|
-
builder: { agent: "builder", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
348
|
-
qa: { agent: "qa", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
349
|
-
docs: { agent: "docs", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
350
|
-
memory: { agent: "memory", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
351
|
-
security: { agent: "security", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
352
|
-
observability: {
|
|
353
|
-
agent: "observability",
|
|
354
|
-
instructions: ["instructions.md", "AGENTS.md"],
|
|
355
|
-
manifests: ["AGENTS.md"],
|
|
356
|
-
},
|
|
357
|
-
eval: { agent: "eval", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
358
|
-
release: { agent: "release", instructions: ["instructions.md", "AGENTS.md"], manifests: ["AGENTS.md"] },
|
|
359
|
-
};
|
|
360
|
-
const STORE_TASK_FILES = {
|
|
361
|
-
todo: "knowledge/tasks/todo.md",
|
|
362
|
-
role_tasks: "knowledge/tasks/role_tasks.md",
|
|
363
|
-
cli_work_split: "knowledge/tasks/cli_work_split.md",
|
|
364
|
-
lessons: "knowledge/tasks/lessons.md",
|
|
365
|
-
readme: "knowledge/tasks/README.md",
|
|
366
|
-
handoff_template: "knowledge/tasks/SWARM_HANDOFF.template.json",
|
|
367
|
-
handoff_example: "knowledge/tasks/SWARM_HANDOFF.example.json",
|
|
368
|
-
handoff_example_vos_ui: "knowledge/tasks/SWARM_HANDOFF.example_vos_to_ui.json",
|
|
369
|
-
handoff_example_ui_coders: "knowledge/tasks/SWARM_HANDOFF.example_ui_to_coders.json",
|
|
370
|
-
};
|
|
371
|
-
const STORE_KERNEL_FILES = {
|
|
372
|
-
directive_kernel: ["knowledge/kernel/DIRECTIVE_KERNEL.md"],
|
|
373
|
-
agent_registry: ["knowledge/kernel/AGENT_REGISTRY.md", "knowledge/kernel/AGENT_REGISTRY_7.md"],
|
|
374
|
-
};
|
|
375
|
-
export function mapAceWorkspaceRelativePath(path) {
|
|
376
|
-
const normalized = normalizeRelPath(path);
|
|
377
|
-
if (!normalized || normalized === ".")
|
|
378
|
-
return normalized;
|
|
379
|
-
if (normalized === ACE_ROOT_REL || normalized.startsWith(`${ACE_ROOT_REL}/`)) {
|
|
380
|
-
return normalized;
|
|
381
|
-
}
|
|
382
|
-
for (const prefix of ACE_MANAGED_PREFIXES) {
|
|
383
|
-
if (normalized === prefix || normalized.startsWith(`${prefix}/`)) {
|
|
384
|
-
return `${ACE_ROOT_REL}/${normalized}`;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
return normalized;
|
|
388
|
-
}
|
|
389
|
-
export function acePath(...segments) {
|
|
390
|
-
return resolve(currentWorkspaceRoot(), ACE_ROOT_REL, ...segments);
|
|
391
|
-
}
|
|
392
|
-
export function wsPath(...segments) {
|
|
393
|
-
const relativePath = normalizeRelPath(segments.join("/"));
|
|
394
|
-
return resolve(currentWorkspaceRoot(), mapAceWorkspaceRelativePath(relativePath));
|
|
395
|
-
}
|
|
396
|
-
/** Normalize a path for validation: workspace-relative, forward slashes. */
|
|
397
|
-
export function normalizePathForValidation(path) {
|
|
398
|
-
const root = currentWorkspaceRoot();
|
|
399
|
-
const relPath = isAbsolute(path) ? relative(root, path) : path;
|
|
400
|
-
return normalizeRelPath(relPath);
|
|
401
|
-
}
|
|
402
|
-
/** Check if a role is a swarm agent (vs composable). */
|
|
403
|
-
export function isSwarmRole(role) {
|
|
404
|
-
return SWARM_AGENTS.includes(role);
|
|
405
|
-
}
|
|
406
|
-
/** Atomically write a file via tmp + rename to prevent partial writes. */
|
|
407
|
-
export function atomicWrite(filePath, content) {
|
|
408
|
-
const abs = isAbsolute(filePath) ? filePath : resolveWorkspaceWritePath(filePath);
|
|
409
|
-
mkdirSync(dirname(abs), { recursive: true });
|
|
410
|
-
const tmpPath = `${abs}.${process.pid}.tmp`;
|
|
411
|
-
writeFileSync(tmpPath, content, "utf-8");
|
|
412
|
-
renameSync(tmpPath, abs);
|
|
413
|
-
return abs;
|
|
414
|
-
}
|
|
415
|
-
/** Check if a file exists. Relative paths are workspace-relative. */
|
|
416
|
-
export function fileExists(filePath) {
|
|
417
|
-
const abs = isAbsolute(filePath) ? filePath : resolveWorkspaceReadPath(filePath);
|
|
418
|
-
return existsSync(abs);
|
|
419
|
-
}
|
|
420
|
-
export function resolveWorkspaceWritePath(filePath) {
|
|
421
|
-
const root = currentWorkspaceRoot();
|
|
422
|
-
if (isFilesystemRoot(root)) {
|
|
423
|
-
throw new Error("Workspace root resolved to filesystem root. Set ACE_WORKSPACE_ROOT or run ACE from the target workspace.");
|
|
424
|
-
}
|
|
425
|
-
const abs = isAbsolute(filePath)
|
|
426
|
-
? filePath
|
|
427
|
-
: resolve(root, mapAceWorkspaceRelativePath(filePath));
|
|
428
|
-
if (!isInside(root, abs)) {
|
|
429
|
-
throw new Error(`Path escapes workspace root: ${filePath}`);
|
|
430
|
-
}
|
|
431
|
-
return abs;
|
|
432
|
-
}
|
|
433
|
-
export function resolveWorkspaceReadPath(filePath) {
|
|
434
|
-
const root = currentWorkspaceRoot();
|
|
435
|
-
if (isAbsolute(filePath)) {
|
|
436
|
-
if (!isInside(root, filePath)) {
|
|
437
|
-
throw new Error(`Path escapes workspace root: ${filePath}`);
|
|
438
|
-
}
|
|
439
|
-
return filePath;
|
|
440
|
-
}
|
|
441
|
-
const normalized = normalizeRelPath(filePath);
|
|
442
|
-
const canonicalRel = mapAceWorkspaceRelativePath(normalized);
|
|
443
|
-
const canonicalAbs = resolve(root, canonicalRel);
|
|
444
|
-
if (canonicalRel !== normalized) {
|
|
445
|
-
const legacyAbs = resolve(root, normalized);
|
|
446
|
-
if (!existsSync(canonicalAbs) && existsSync(legacyAbs)) {
|
|
447
|
-
return legacyAbs;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
if (!isInside(root, canonicalAbs)) {
|
|
451
|
-
throw new Error(`Path escapes workspace root: ${filePath}`);
|
|
452
|
-
}
|
|
453
|
-
return canonicalAbs;
|
|
454
|
-
}
|
|
455
|
-
export function resolveWorkspaceArtifactPath(filePath, mode = "write") {
|
|
456
|
-
return mode === "read" ? resolveWorkspaceReadPath(filePath) : resolveWorkspaceWritePath(filePath);
|
|
457
|
-
}
|
|
458
|
-
function toAbsoluteWorkspaceCandidates(candidates) {
|
|
459
|
-
return candidates.map((candidate) => isAbsolute(candidate) ? candidate : resolveWorkspaceReadPath(candidate));
|
|
460
|
-
}
|
|
461
|
-
function firstExistingPath(paths) {
|
|
462
|
-
return paths.find((candidate) => existsSync(candidate));
|
|
463
|
-
}
|
|
464
|
-
function readText(absPath) {
|
|
465
|
-
return readFileSync(absPath, "utf-8");
|
|
466
|
-
}
|
|
467
|
-
function resolveStoreFallbackKeys(filePath) {
|
|
468
|
-
const normalized = normalizeRelPath(filePath);
|
|
469
|
-
if (!normalized)
|
|
470
|
-
return [];
|
|
471
|
-
const canonical = mapAceWorkspaceRelativePath(normalized);
|
|
472
|
-
const keys = new Set();
|
|
473
|
-
if (canonical.startsWith(`${ACE_ROOT_REL}/agent-state/`)) {
|
|
474
|
-
const rel = canonical.slice(`${ACE_ROOT_REL}/`.length);
|
|
475
|
-
if (isOperationalArtifactPath(rel)) {
|
|
476
|
-
keys.add(operationalArtifactKey(rel));
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
if (normalized === "agent-state/ACE_WORKFLOW.md" || canonical === `${ACE_ROOT_REL}/agent-state/ACE_WORKFLOW.md`) {
|
|
480
|
-
keys.add("knowledge/runtime/ACE_WORKFLOW.md");
|
|
481
|
-
}
|
|
482
|
-
const gatePrefix = `${ACE_ROOT_REL}/agent-state/MODULES/gates/`;
|
|
483
|
-
if (canonical.startsWith(gatePrefix)) {
|
|
484
|
-
const file = canonical.slice(gatePrefix.length);
|
|
485
|
-
if (file)
|
|
486
|
-
keys.add(`knowledge/gates/${file}`);
|
|
487
|
-
}
|
|
488
|
-
const rolePrefix = `${ACE_ROOT_REL}/agent-state/MODULES/roles/`;
|
|
489
|
-
if (canonical.startsWith(rolePrefix)) {
|
|
490
|
-
const file = canonical.slice(rolePrefix.length);
|
|
491
|
-
if (file)
|
|
492
|
-
keys.add(`knowledge/roles/${file}`);
|
|
493
|
-
}
|
|
494
|
-
const schemaPrefix = `${ACE_ROOT_REL}/agent-state/MODULES/schemas/`;
|
|
495
|
-
if (canonical.startsWith(schemaPrefix)) {
|
|
496
|
-
const file = canonical.slice(schemaPrefix.length);
|
|
497
|
-
if (file)
|
|
498
|
-
keys.add(`knowledge/schemas/${file}`);
|
|
499
|
-
}
|
|
500
|
-
const staticAgentState = new Set([
|
|
501
|
-
"ACE_WORKFLOW.md",
|
|
502
|
-
"ARTIFACT_MANIFEST.json",
|
|
503
|
-
"AST_GREP_COMMANDS.md",
|
|
504
|
-
"AST_GREP_INDEX.json",
|
|
505
|
-
"AST_GREP_INDEX.md",
|
|
506
|
-
"DECISIONS.md",
|
|
507
|
-
"EVIDENCE_LOG.md",
|
|
508
|
-
"HANDOFF.json",
|
|
509
|
-
"INTERFACE_REGISTRY.md",
|
|
510
|
-
"PROVENANCE_LOG.md",
|
|
511
|
-
"QUALITY_GATES.md",
|
|
512
|
-
"RISKS.md",
|
|
513
|
-
"SCOPE.md",
|
|
514
|
-
"SKILL_CATALOG.md",
|
|
515
|
-
"STATUS.md",
|
|
516
|
-
"STATUS_EVENTS.ndjson",
|
|
517
|
-
"TASK.md",
|
|
518
|
-
"TEAL_CONFIG.md",
|
|
519
|
-
"MODULES/registry.json",
|
|
520
|
-
"handoff-registry.json",
|
|
521
|
-
"index-fingerprints.json",
|
|
522
|
-
"index.json",
|
|
523
|
-
"run-ledger.json",
|
|
524
|
-
"runtime-executor-sessions.json",
|
|
525
|
-
"runtime-tool-specs.json",
|
|
526
|
-
"runtime-workspaces.json",
|
|
527
|
-
"todo-state.json",
|
|
528
|
-
"tracker-snapshot.json",
|
|
529
|
-
"vericify/ace-bridge.json",
|
|
530
|
-
"vericify/process-posts.json",
|
|
531
|
-
]);
|
|
532
|
-
const statePrefix = `${ACE_ROOT_REL}/agent-state/`;
|
|
533
|
-
if (canonical.startsWith(statePrefix)) {
|
|
534
|
-
const rel = canonical.slice(statePrefix.length);
|
|
535
|
-
const runtimeProjectionKey = {
|
|
536
|
-
"job-queue.json": "state/artifacts/agent-state/job-queue.json",
|
|
537
|
-
"job-locks.json": "state/artifacts/agent-state/job-locks.json",
|
|
538
|
-
"scheduler-lease.json": "state/artifacts/agent-state/scheduler-lease.json",
|
|
539
|
-
}[rel];
|
|
540
|
-
if (runtimeProjectionKey)
|
|
541
|
-
keys.add(runtimeProjectionKey);
|
|
542
|
-
if (staticAgentState.has(rel)) {
|
|
543
|
-
keys.add(`knowledge/agent-state/${rel}`);
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
const contextSnapshotPrefix = `${ACE_ROOT_REL}/agent-state/context-snapshots/`;
|
|
547
|
-
if (canonical.startsWith(contextSnapshotPrefix)) {
|
|
548
|
-
const rel = canonical.slice(contextSnapshotPrefix.length);
|
|
549
|
-
if (rel)
|
|
550
|
-
keys.add(`state/memory/context_snapshots/${rel}`);
|
|
551
|
-
}
|
|
552
|
-
const tasksPrefix = `${ACE_TASKS_ROOT_REL}/`;
|
|
553
|
-
if (canonical.startsWith(tasksPrefix)) {
|
|
554
|
-
keys.add(`knowledge/tasks/${canonical.slice(tasksPrefix.length)}`);
|
|
555
|
-
}
|
|
556
|
-
const scriptsPrefix = `${ACE_SCRIPTS_ROOT_REL}/`;
|
|
557
|
-
if (canonical.startsWith(scriptsPrefix)) {
|
|
558
|
-
keys.add(`knowledge/scripts/${canonical.slice(scriptsPrefix.length)}`);
|
|
559
|
-
}
|
|
560
|
-
for (const [key, candidates] of Object.entries(TASK_FILES)) {
|
|
561
|
-
if (candidates.includes(canonical)) {
|
|
562
|
-
keys.add(STORE_TASK_FILES[key]);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
for (const [key, candidates] of Object.entries(KERNEL_FILES)) {
|
|
566
|
-
if (candidates.includes(canonical)) {
|
|
567
|
-
for (const storeKey of STORE_KERNEL_FILES[key])
|
|
568
|
-
keys.add(storeKey);
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
for (const [role, candidates] of Object.entries(AGENT_FILES)) {
|
|
572
|
-
if (candidates.includes(canonical)) {
|
|
573
|
-
for (const file of STORE_AGENT_FILES[role].instructions) {
|
|
574
|
-
keys.add(`knowledge/agents/${STORE_AGENT_FILES[role].agent}/${file}`);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
for (const [role, candidates] of Object.entries(AGENT_MANIFEST_FILES)) {
|
|
579
|
-
if (candidates.includes(canonical)) {
|
|
580
|
-
for (const file of STORE_AGENT_FILES[role].manifests) {
|
|
581
|
-
keys.add(`knowledge/agents/${STORE_AGENT_FILES[role].agent}/${file}`);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
return [...keys];
|
|
586
|
-
}
|
|
587
|
-
function readFirstAvailable(paths) {
|
|
588
|
-
const found = firstExistingPath(paths);
|
|
589
|
-
if (!found) {
|
|
590
|
-
return {
|
|
591
|
-
text: `[FILE NOT FOUND]\nTried:\n${paths.map((p) => `- ${p}`).join("\n")}`,
|
|
592
|
-
path: undefined,
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
return { text: readText(found), path: found };
|
|
596
|
-
}
|
|
597
|
-
export function classifyPathSource(path) {
|
|
598
|
-
if (!path)
|
|
599
|
-
return "missing";
|
|
600
|
-
const root = currentWorkspaceRoot();
|
|
601
|
-
if (path.includes(".ace#"))
|
|
602
|
-
return "store";
|
|
603
|
-
if (isInside(root, path))
|
|
604
|
-
return "workspace";
|
|
605
|
-
if (isInside(DEFAULTS_ROOT, path))
|
|
606
|
-
return "package-defaults";
|
|
607
|
-
return "missing";
|
|
608
|
-
}
|
|
609
|
-
/** Safely read a workspace file, returning either text or a not-found/access message. */
|
|
610
|
-
export function safeRead(filePath) {
|
|
611
|
-
try {
|
|
612
|
-
if (parseVirtualStorePath(filePath)) {
|
|
613
|
-
const direct = readVirtualStorePathSync(filePath);
|
|
614
|
-
return typeof direct === "string" ? direct : `[FILE NOT FOUND] ${filePath}`;
|
|
615
|
-
}
|
|
616
|
-
const abs = resolveWorkspaceReadPath(filePath);
|
|
617
|
-
if (!existsSync(abs)) {
|
|
618
|
-
const store = readStoreText(resolveStoreFallbackKeys(filePath));
|
|
619
|
-
if (store)
|
|
620
|
-
return store.text;
|
|
621
|
-
return `[FILE NOT FOUND] ${abs}`;
|
|
622
|
-
}
|
|
623
|
-
return readText(abs);
|
|
624
|
-
}
|
|
625
|
-
catch (err) {
|
|
626
|
-
return `[ACCESS DENIED] ${String(err)}`;
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
/** Safely write a workspace file atomically (tmp + rename), creating directories if needed. */
|
|
630
|
-
export function safeWrite(filePath, content) {
|
|
631
|
-
const normalized = normalizeRelPath(filePath);
|
|
632
|
-
const canonical = mapAceWorkspaceRelativePath(normalized);
|
|
633
|
-
const root = currentWorkspaceRoot();
|
|
634
|
-
if (canonical.startsWith(`${ACE_ROOT_REL}/agent-state/`)) {
|
|
635
|
-
const rel = canonical.slice(`${ACE_ROOT_REL}/`.length);
|
|
636
|
-
if (isOperationalArtifactPath(rel) && existsSync(getWorkspaceStorePath(root))) {
|
|
637
|
-
return writeOperationalArtifactSync(root, rel, content);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
const storeKeys = resolveStoreFallbackKeys(filePath);
|
|
641
|
-
if (storeKeys.length > 0 && existsSync(getWorkspaceStorePath(root))) {
|
|
642
|
-
writeStoreBlobSync(root, storeKeys[0], content);
|
|
643
|
-
}
|
|
644
|
-
const abs = resolveWorkspaceWritePath(filePath);
|
|
645
|
-
mkdirSync(dirname(abs), { recursive: true });
|
|
646
|
-
const tmpPath = `${abs}.${process.pid}.${Date.now()}.tmp`;
|
|
647
|
-
writeFileSync(tmpPath, content, "utf-8");
|
|
648
|
-
renameSync(tmpPath, abs);
|
|
649
|
-
return abs;
|
|
650
|
-
}
|
|
651
|
-
// ────────────────────────────────────────────────────────────────────
|
|
652
|
-
// File locks for read-modify-write concurrency safety
|
|
653
|
-
// ────────────────────────────────────────────────────────────────────
|
|
654
|
-
const _fileLocks = new Map();
|
|
655
|
-
/**
|
|
656
|
-
* Execute `fn` while holding a per-path serialization lock.
|
|
657
|
-
* Prevents concurrent read-modify-write cycles on the same file
|
|
658
|
-
* within a single process. Cross-process safety relies on atomic rename.
|
|
659
|
-
*/
|
|
660
|
-
export async function withFileLock(path, fn) {
|
|
661
|
-
const key = resolveWorkspaceWritePath(path);
|
|
662
|
-
const prev = _fileLocks.get(key) ?? Promise.resolve();
|
|
663
|
-
let releaseLock;
|
|
664
|
-
const next = new Promise((r) => { releaseLock = r; });
|
|
665
|
-
_fileLocks.set(key, next);
|
|
666
|
-
await prev;
|
|
667
|
-
try {
|
|
668
|
-
return await fn();
|
|
669
|
-
}
|
|
670
|
-
finally {
|
|
671
|
-
releaseLock();
|
|
672
|
-
if (_fileLocks.get(key) === next)
|
|
673
|
-
_fileLocks.delete(key);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
function formatStorePath(key) {
|
|
677
|
-
return toVirtualStorePath(getWorkspaceStorePath(currentWorkspaceRoot()), key);
|
|
678
|
-
}
|
|
679
|
-
function readStoreText(keys) {
|
|
680
|
-
const root = currentWorkspaceRoot();
|
|
681
|
-
for (const key of keys) {
|
|
682
|
-
const text = readStoreBlobSync(root, key);
|
|
683
|
-
if (typeof text === "string") {
|
|
684
|
-
return { key, path: formatStorePath(key), text };
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
return undefined;
|
|
688
|
-
}
|
|
689
|
-
function listStoreSkillReferences() {
|
|
690
|
-
const root = currentWorkspaceRoot();
|
|
691
|
-
const names = new Set();
|
|
692
|
-
for (const key of listStoreKeysSync(root, "knowledge/skills/")) {
|
|
693
|
-
const parts = key.split("/");
|
|
694
|
-
if (parts[2])
|
|
695
|
-
names.add(parts[2]);
|
|
696
|
-
}
|
|
697
|
-
return [...names]
|
|
698
|
-
.sort((a, b) => a.localeCompare(b))
|
|
699
|
-
.map((name) => ({
|
|
700
|
-
name,
|
|
701
|
-
path: formatStorePath(`knowledge/skills/${name}/SKILL.md`),
|
|
702
|
-
source: "store",
|
|
703
|
-
}));
|
|
704
|
-
}
|
|
705
|
-
function shouldPreferWorkspaceTaskFile(key) {
|
|
706
|
-
return key === "todo" || key === "lessons";
|
|
707
|
-
}
|
|
708
|
-
export function getAgentInstructionPath(role) {
|
|
709
|
-
const store = readStoreText(STORE_AGENT_FILES[role].instructions.map((file) => `knowledge/agents/${STORE_AGENT_FILES[role].agent}/${file}`));
|
|
710
|
-
if (store)
|
|
711
|
-
return store.path;
|
|
712
|
-
const workspaceCandidates = toAbsoluteWorkspaceCandidates(AGENT_FILES[role]);
|
|
713
|
-
return firstExistingPath([...workspaceCandidates, DEFAULT_AGENT_INSTRUCTION_FILES[role]]);
|
|
714
|
-
}
|
|
715
|
-
export function getAgentManifestPath(role) {
|
|
716
|
-
const store = readStoreText(STORE_AGENT_FILES[role].manifests.map((file) => `knowledge/agents/${STORE_AGENT_FILES[role].agent}/${file}`));
|
|
717
|
-
if (store)
|
|
718
|
-
return store.path;
|
|
719
|
-
const workspaceCandidates = toAbsoluteWorkspaceCandidates(AGENT_MANIFEST_FILES[role]);
|
|
720
|
-
return firstExistingPath([...workspaceCandidates, DEFAULT_AGENT_MANIFEST_FILES[role]]);
|
|
721
|
-
}
|
|
722
|
-
export function readAgentInstructions(role) {
|
|
723
|
-
const store = readStoreText(STORE_AGENT_FILES[role].instructions.map((file) => `knowledge/agents/${STORE_AGENT_FILES[role].agent}/${file}`));
|
|
724
|
-
if (store)
|
|
725
|
-
return store.text;
|
|
726
|
-
const workspaceCandidates = toAbsoluteWorkspaceCandidates(AGENT_FILES[role]);
|
|
727
|
-
return readFirstAvailable([...workspaceCandidates, DEFAULT_AGENT_INSTRUCTION_FILES[role]]).text;
|
|
728
|
-
}
|
|
729
|
-
export function readAgentManifest(role) {
|
|
730
|
-
const store = readStoreText(STORE_AGENT_FILES[role].manifests.map((file) => `knowledge/agents/${STORE_AGENT_FILES[role].agent}/${file}`));
|
|
731
|
-
if (store)
|
|
732
|
-
return store.text;
|
|
733
|
-
const workspaceCandidates = toAbsoluteWorkspaceCandidates(AGENT_MANIFEST_FILES[role]);
|
|
734
|
-
return readFirstAvailable([...workspaceCandidates, DEFAULT_AGENT_MANIFEST_FILES[role]]).text;
|
|
735
|
-
}
|
|
736
|
-
export function getTaskArtifactPath(key) {
|
|
737
|
-
const workspaceCandidates = toAbsoluteWorkspaceCandidates(TASK_FILES[key]);
|
|
738
|
-
const workspaceFirst = shouldPreferWorkspaceTaskFile(key);
|
|
739
|
-
if (workspaceFirst) {
|
|
740
|
-
const workspace = firstExistingPath(workspaceCandidates);
|
|
741
|
-
if (workspace)
|
|
742
|
-
return workspace;
|
|
743
|
-
}
|
|
744
|
-
const store = readStoreText([STORE_TASK_FILES[key]]);
|
|
745
|
-
if (store)
|
|
746
|
-
return store.path;
|
|
747
|
-
return firstExistingPath([
|
|
748
|
-
...workspaceCandidates,
|
|
749
|
-
DEFAULT_TASK_FILES[key],
|
|
750
|
-
]);
|
|
751
|
-
}
|
|
752
|
-
export function readTaskArtifact(key) {
|
|
753
|
-
if (shouldPreferWorkspaceTaskFile(key)) {
|
|
754
|
-
const workspaceCandidates = toAbsoluteWorkspaceCandidates(TASK_FILES[key]);
|
|
755
|
-
const workspacePath = firstExistingPath(workspaceCandidates);
|
|
756
|
-
if (workspacePath)
|
|
757
|
-
return readText(workspacePath);
|
|
758
|
-
}
|
|
759
|
-
const store = readStoreText([STORE_TASK_FILES[key]]);
|
|
760
|
-
if (store)
|
|
761
|
-
return store.text;
|
|
762
|
-
const workspaceCandidates = toAbsoluteWorkspaceCandidates(TASK_FILES[key]);
|
|
763
|
-
return readFirstAvailable([...workspaceCandidates, DEFAULT_TASK_FILES[key]]).text;
|
|
764
|
-
}
|
|
765
|
-
export function getKernelArtifactPath(key) {
|
|
766
|
-
const store = readStoreText(STORE_KERNEL_FILES[key]);
|
|
767
|
-
if (store)
|
|
768
|
-
return store.path;
|
|
769
|
-
const workspaceCandidates = toAbsoluteWorkspaceCandidates(KERNEL_FILES[key]);
|
|
770
|
-
return firstExistingPath([...workspaceCandidates, DEFAULT_KERNEL_FILES[key]]);
|
|
771
|
-
}
|
|
772
|
-
export function readKernelArtifact(key) {
|
|
773
|
-
const store = readStoreText(STORE_KERNEL_FILES[key]);
|
|
774
|
-
if (store)
|
|
775
|
-
return store.text;
|
|
776
|
-
const workspaceCandidates = toAbsoluteWorkspaceCandidates(KERNEL_FILES[key]);
|
|
777
|
-
return readFirstAvailable([...workspaceCandidates, DEFAULT_KERNEL_FILES[key]]).text;
|
|
778
|
-
}
|
|
779
|
-
export function resolveWritableTaskPath(key) {
|
|
780
|
-
const workspaceCandidates = toAbsoluteWorkspaceCandidates(TASK_FILES[key]);
|
|
781
|
-
const existingWorkspacePath = workspaceCandidates.find((candidate) => existsSync(candidate));
|
|
782
|
-
if (existingWorkspacePath)
|
|
783
|
-
return existingWorkspacePath;
|
|
784
|
-
// Write to canonical workspace target when not yet present.
|
|
785
|
-
return resolveWorkspaceWritePath(TASK_FILES[key][0]);
|
|
786
|
-
}
|
|
787
|
-
function listSkillDirs() {
|
|
788
|
-
const root = currentWorkspaceRoot();
|
|
789
|
-
return [
|
|
790
|
-
{ root: acePath("skills"), source: "workspace" },
|
|
791
|
-
{ root: resolve(root, ".agents", "skills"), source: "workspace" },
|
|
792
|
-
{ root: DEFAULTS_SKILLS_ROOT, source: "package-defaults" },
|
|
793
|
-
];
|
|
794
|
-
}
|
|
795
|
-
export function listAvailableSkills() {
|
|
796
|
-
const dedup = new Map();
|
|
797
|
-
for (const skill of listStoreSkillReferences()) {
|
|
798
|
-
dedup.set(skill.name, skill);
|
|
799
|
-
}
|
|
800
|
-
for (const { root, source } of listSkillDirs()) {
|
|
801
|
-
if (!existsSync(root))
|
|
802
|
-
continue;
|
|
803
|
-
const entries = readdirSync(root, { withFileTypes: true });
|
|
804
|
-
for (const entry of entries) {
|
|
805
|
-
if (!entry.isDirectory())
|
|
806
|
-
continue;
|
|
807
|
-
const skillName = entry.name;
|
|
808
|
-
const skillPath = resolve(root, skillName, "SKILL.md");
|
|
809
|
-
if (!existsSync(skillPath))
|
|
810
|
-
continue;
|
|
811
|
-
if (source === "package-defaults" && dedup.has(skillName)) {
|
|
812
|
-
continue;
|
|
813
|
-
}
|
|
814
|
-
dedup.set(skillName, {
|
|
815
|
-
name: skillName,
|
|
816
|
-
path: skillPath,
|
|
817
|
-
source,
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
return [...dedup.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
822
|
-
}
|
|
823
|
-
export function getSkillPath(name) {
|
|
824
|
-
const target = name.trim().toLowerCase();
|
|
825
|
-
const skills = listAvailableSkills();
|
|
826
|
-
const exact = skills.find((skill) => skill.name.toLowerCase() === target);
|
|
827
|
-
return exact?.path;
|
|
828
|
-
}
|
|
829
|
-
export function readSkillInstructions(name) {
|
|
830
|
-
const target = name.trim().toLowerCase();
|
|
831
|
-
const match = listAvailableSkills().find((skill) => skill.name.toLowerCase() === target);
|
|
832
|
-
if (!match) {
|
|
833
|
-
return `Skill not found: ${name}\nAvailable: ${listAvailableSkills()
|
|
834
|
-
.map((s) => s.name)
|
|
835
|
-
.join(", ")}`;
|
|
836
|
-
}
|
|
837
|
-
if (match.source === "store") {
|
|
838
|
-
return readStoreBlobSync(currentWorkspaceRoot(), `knowledge/skills/${match.name}/SKILL.md`) ?? "";
|
|
839
|
-
}
|
|
840
|
-
return readText(match.path);
|
|
841
|
-
}
|
|
842
|
-
function ensureDir(dirPath, result) {
|
|
843
|
-
if (existsSync(dirPath))
|
|
844
|
-
return;
|
|
845
|
-
mkdirSync(dirPath, { recursive: true });
|
|
846
|
-
result.created.push(dirPath);
|
|
847
|
-
}
|
|
848
|
-
function copyTree(srcRoot, destRoot, result, force = false) {
|
|
849
|
-
if (!existsSync(srcRoot))
|
|
850
|
-
return;
|
|
851
|
-
const entries = readdirSync(srcRoot, { withFileTypes: true });
|
|
852
|
-
for (const entry of entries) {
|
|
853
|
-
const src = resolve(srcRoot, entry.name);
|
|
854
|
-
const dest = resolve(destRoot, entry.name);
|
|
855
|
-
if (entry.isDirectory()) {
|
|
856
|
-
ensureDir(dest, result);
|
|
857
|
-
copyTree(src, dest, result, force);
|
|
858
|
-
continue;
|
|
859
|
-
}
|
|
860
|
-
if (!existsSync(dest)) {
|
|
861
|
-
mkdirSync(dirname(dest), { recursive: true });
|
|
862
|
-
copyFileSync(src, dest);
|
|
863
|
-
result.created.push(dest);
|
|
864
|
-
continue;
|
|
865
|
-
}
|
|
866
|
-
if (force) {
|
|
867
|
-
copyFileSync(src, dest);
|
|
868
|
-
result.updated.push(dest);
|
|
869
|
-
}
|
|
870
|
-
else {
|
|
871
|
-
result.skipped.push(dest);
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
function writeIfMissingOrForced(path, content, result, force = false) {
|
|
876
|
-
if (!existsSync(path)) {
|
|
877
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
878
|
-
writeFileSync(path, content, "utf-8");
|
|
879
|
-
result.created.push(path);
|
|
880
|
-
return;
|
|
881
|
-
}
|
|
882
|
-
if (force) {
|
|
883
|
-
writeFileSync(path, content, "utf-8");
|
|
884
|
-
result.updated.push(path);
|
|
885
|
-
}
|
|
886
|
-
else {
|
|
887
|
-
result.skipped.push(path);
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
function quotePosixShell(value) {
|
|
891
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
892
|
-
}
|
|
893
|
-
function quoteCmdExe(value) {
|
|
894
|
-
return `"${value.replace(/"/g, '""')}"`;
|
|
895
|
-
}
|
|
896
|
-
function buildPosixMcpLaunchCommand(workspaceRoot) {
|
|
897
|
-
const quotedWorkspaceRoot = quotePosixShell(workspaceRoot);
|
|
898
|
-
return `cd ${quotedWorkspaceRoot} && ACE_WORKSPACE_ROOT=${quotedWorkspaceRoot} npx -y ace-swarm mcp`;
|
|
899
|
-
}
|
|
900
|
-
function buildWindowsMcpLaunchCommand(workspaceRoot) {
|
|
901
|
-
return [
|
|
902
|
-
`cd /d ${quoteCmdExe(workspaceRoot)}`,
|
|
903
|
-
`set "ACE_WORKSPACE_ROOT=${workspaceRoot.replace(/"/g, '""')}"`,
|
|
904
|
-
"npx -y ace-swarm mcp",
|
|
905
|
-
].join(" && ");
|
|
906
|
-
}
|
|
907
|
-
function getMcpCommandSpec(workspaceRoot = WORKSPACE_ROOT) {
|
|
908
|
-
// On macOS/Linux, VS Code may not inherit the user's shell PATH (nvm, fnm,
|
|
909
|
-
// volta, etc.), so `npx` resolves to ENOENT. Wrap via a login-shell so the
|
|
910
|
-
// user's profile is sourced and node tooling is on PATH.
|
|
911
|
-
if (process.platform !== "win32") {
|
|
912
|
-
const shell = process.env.SHELL || "/bin/zsh";
|
|
913
|
-
return {
|
|
914
|
-
command: shell,
|
|
915
|
-
args: ["-lc", buildPosixMcpLaunchCommand(workspaceRoot)],
|
|
916
|
-
};
|
|
917
|
-
}
|
|
918
|
-
return {
|
|
919
|
-
command: "cmd.exe",
|
|
920
|
-
args: ["/d", "/s", "/c", buildWindowsMcpLaunchCommand(workspaceRoot)],
|
|
921
|
-
};
|
|
922
|
-
}
|
|
923
|
-
const ACE_HOOK_EVENTS = [
|
|
924
|
-
"SessionStart",
|
|
925
|
-
"UserPromptSubmit",
|
|
926
|
-
"PreToolUse",
|
|
927
|
-
"PostToolUse",
|
|
928
|
-
"PreCompact",
|
|
929
|
-
"SubagentStart",
|
|
930
|
-
"SubagentStop",
|
|
931
|
-
"Stop",
|
|
932
|
-
];
|
|
933
|
-
const ACE_HOOK_DISPATCH_REL = `${ACE_SCRIPTS_ROOT_REL}/ace-hook-dispatch.mjs`;
|
|
934
|
-
const ACE_HOOK_DISPATCH_COMMAND = `node ./${ACE_HOOK_DISPATCH_REL}`;
|
|
935
|
-
function buildCopilotHookSettings() {
|
|
936
|
-
const hook = {
|
|
937
|
-
type: "command",
|
|
938
|
-
command: ACE_HOOK_DISPATCH_COMMAND,
|
|
939
|
-
windows: "node .\\\\.agents\\\\ACE\\\\scripts\\\\ace\\\\ace-hook-dispatch.mjs",
|
|
940
|
-
timeout: 10,
|
|
941
|
-
};
|
|
942
|
-
const hooks = Object.fromEntries(ACE_HOOK_EVENTS.map((event) => [event, [hook]]));
|
|
943
|
-
return JSON.stringify({ hooks }, null, 2);
|
|
944
|
-
}
|
|
945
|
-
function buildClaudeHookSettings() {
|
|
946
|
-
const hook = {
|
|
947
|
-
type: "command",
|
|
948
|
-
command: ACE_HOOK_DISPATCH_COMMAND,
|
|
949
|
-
};
|
|
950
|
-
return JSON.stringify({
|
|
951
|
-
hooks: {
|
|
952
|
-
SessionStart: [{ matcher: "", hooks: [hook] }],
|
|
953
|
-
UserPromptSubmit: [{ matcher: "", hooks: [hook] }],
|
|
954
|
-
PreToolUse: [{ matcher: "", hooks: [hook] }],
|
|
955
|
-
PostToolUse: [{ matcher: "", hooks: [hook] }],
|
|
956
|
-
PreCompact: [{ matcher: "", hooks: [hook] }],
|
|
957
|
-
SubagentStart: [{ matcher: "", hooks: [hook] }],
|
|
958
|
-
SubagentStop: [{ matcher: "", hooks: [hook] }],
|
|
959
|
-
Stop: [{ matcher: "", hooks: [hook] }],
|
|
960
|
-
},
|
|
961
|
-
}, null, 2);
|
|
962
|
-
}
|
|
963
|
-
function buildCursorHookSettings() {
|
|
964
|
-
return buildCopilotHookSettings();
|
|
965
|
-
}
|
|
966
|
-
function buildVsCodeHookSettings() {
|
|
967
|
-
return buildCopilotHookSettings();
|
|
968
|
-
}
|
|
969
|
-
function buildGeminiHookSettings() {
|
|
970
|
-
return buildCopilotHookSettings();
|
|
971
|
-
}
|
|
972
|
-
function buildAntigravityHookSettings() {
|
|
973
|
-
return buildCopilotHookSettings();
|
|
974
|
-
}
|
|
975
|
-
function buildCodexHookSettings() {
|
|
976
|
-
return [
|
|
977
|
-
"# ACE lifecycle hook scaffold for Codex-compatible runtimes.",
|
|
978
|
-
"# Merge or source these entries in the host hook config that supports SessionStart/SubagentStart hooks.",
|
|
979
|
-
"",
|
|
980
|
-
...ACE_HOOK_EVENTS.flatMap((event) => [
|
|
981
|
-
"[[hooks]]",
|
|
982
|
-
`event = "${event}"`,
|
|
983
|
-
`command = "${ACE_HOOK_DISPATCH_COMMAND}"`,
|
|
984
|
-
"",
|
|
985
|
-
]),
|
|
986
|
-
].join("\n");
|
|
987
|
-
}
|
|
988
|
-
function buildWorkspaceStateSeedFiles(projectName, generatedAt) {
|
|
989
|
-
const swarmHandoffTemplate = readText(DEFAULT_TASK_FILES.handoff_template);
|
|
990
|
-
return [
|
|
991
|
-
{
|
|
992
|
-
path: wsPath("global-state", "GLOBAL_RISKS.md"),
|
|
993
|
-
content: [
|
|
994
|
-
"# GLOBAL_RISKS",
|
|
995
|
-
"",
|
|
996
|
-
`Generated: ${generatedAt}`,
|
|
997
|
-
"",
|
|
998
|
-
"## Systemic Risks",
|
|
999
|
-
"- None logged yet. Record cross-swarm blockers, runway constraints, and release risks here.",
|
|
1000
|
-
"",
|
|
1001
|
-
"## Update Rule",
|
|
1002
|
-
"- Keep local implementation risks in the owning swarm folder or `agent-state/RISKS.md`.",
|
|
1003
|
-
].join("\n"),
|
|
1004
|
-
},
|
|
1005
|
-
{
|
|
1006
|
-
path: wsPath("global-state", "DECISION_LOG.md"),
|
|
1007
|
-
content: [
|
|
1008
|
-
"# DECISION_LOG",
|
|
1009
|
-
"",
|
|
1010
|
-
`Generated: ${generatedAt}`,
|
|
1011
|
-
"",
|
|
1012
|
-
"Append-only record for orchestrator-level tradeoffs that affect multiple swarms.",
|
|
1013
|
-
"",
|
|
1014
|
-
"## Entry Template",
|
|
1015
|
-
`- ${generatedAt} — Decision: <what changed>`,
|
|
1016
|
-
" - Reason: <why>",
|
|
1017
|
-
" - Impact: <which swarm/state folders are affected>",
|
|
1018
|
-
].join("\n"),
|
|
1019
|
-
},
|
|
1020
|
-
{
|
|
1021
|
-
path: wsPath("global-state", "ENGINEERING_SNAPSHOT.md"),
|
|
1022
|
-
content: [
|
|
1023
|
-
"# ENGINEERING_SNAPSHOT.md",
|
|
1024
|
-
"",
|
|
1025
|
-
`Generated: ${generatedAt}`,
|
|
1026
|
-
"",
|
|
1027
|
-
"## Profile",
|
|
1028
|
-
"- Status: pending initial orchestrator discovery scan",
|
|
1029
|
-
"- Project: " + projectName,
|
|
1030
|
-
`- Durable location: \`${ACE_ROOT_REL}/global-state/ENGINEERING_SNAPSHOT.md\``,
|
|
1031
|
-
"",
|
|
1032
|
-
"## Quality Signals",
|
|
1033
|
-
"- Tests: pending scan",
|
|
1034
|
-
"- Public surface: pending scan",
|
|
1035
|
-
"- Delivery risk: pending scan",
|
|
1036
|
-
"",
|
|
1037
|
-
"## Routing Recommendation",
|
|
1038
|
-
"- Run the orchestrator discovery pass before first coder handoff.",
|
|
1039
|
-
].join("\n"),
|
|
1040
|
-
},
|
|
1041
|
-
{
|
|
1042
|
-
path: wsPath("global-state", "SWARM_HANDOFF.json"),
|
|
1043
|
-
content: swarmHandoffTemplate,
|
|
1044
|
-
},
|
|
1045
|
-
{
|
|
1046
|
-
path: wsPath("venture-state", "STATUS.md"),
|
|
1047
|
-
content: [
|
|
1048
|
-
"# VENTURE STATUS",
|
|
1049
|
-
"",
|
|
1050
|
-
"- Mode: bootstrap",
|
|
1051
|
-
"- Focus: clarify thesis and MVP",
|
|
1052
|
-
"- Current phase: discovery",
|
|
1053
|
-
"- Next handoff: ACE-VOS -> ACE-Orchestrator",
|
|
1054
|
-
`- Last update: ${generatedAt}`,
|
|
1055
|
-
].join("\n"),
|
|
1056
|
-
},
|
|
1057
|
-
{
|
|
1058
|
-
path: wsPath("venture-state", "TEAL_CONFIG.md"),
|
|
1059
|
-
content: [
|
|
1060
|
-
"# TEAL_CONFIG",
|
|
1061
|
-
"",
|
|
1062
|
-
"## Venture Pipeline",
|
|
1063
|
-
"- discovery -> thesis -> blueprint -> MVP spec -> handoff",
|
|
1064
|
-
"",
|
|
1065
|
-
"## Durable Outputs",
|
|
1066
|
-
`- \`${ACE_ROOT_REL}/venture-state/THESIS.md\``,
|
|
1067
|
-
`- \`${ACE_ROOT_REL}/venture-state/BLUEPRINT.md\``,
|
|
1068
|
-
`- \`${ACE_ROOT_REL}/venture-state/GROWTH_LOOPS.md\``,
|
|
1069
|
-
`- \`${ACE_ROOT_REL}/venture-state/RISKS.md\``,
|
|
1070
|
-
`- \`${ACE_ROOT_REL}/venture-state/PROTOTYPE/MVP_SPEC.md\``,
|
|
1071
|
-
].join("\n"),
|
|
1072
|
-
},
|
|
1073
|
-
{
|
|
1074
|
-
path: wsPath("venture-state", "THESIS.md"),
|
|
1075
|
-
content: [
|
|
1076
|
-
"# THESIS",
|
|
1077
|
-
"",
|
|
1078
|
-
"## Problem",
|
|
1079
|
-
"- TBD",
|
|
1080
|
-
"",
|
|
1081
|
-
"## Users",
|
|
1082
|
-
"- TBD",
|
|
1083
|
-
"",
|
|
1084
|
-
"## Why Now",
|
|
1085
|
-
"- TBD",
|
|
1086
|
-
"",
|
|
1087
|
-
"## Wedge",
|
|
1088
|
-
"- TBD",
|
|
1089
|
-
].join("\n"),
|
|
1090
|
-
},
|
|
1091
|
-
{
|
|
1092
|
-
path: wsPath("venture-state", "INTERROGATION.log"),
|
|
1093
|
-
content: [
|
|
1094
|
-
"# INTERROGATION LOG",
|
|
1095
|
-
"",
|
|
1096
|
-
`- ${generatedAt} bootstrap: venture interrogation started.`,
|
|
1097
|
-
].join("\n"),
|
|
1098
|
-
},
|
|
1099
|
-
{
|
|
1100
|
-
path: wsPath("venture-state", "BLUEPRINT.md"),
|
|
1101
|
-
content: [
|
|
1102
|
-
"# BLUEPRINT",
|
|
1103
|
-
"",
|
|
1104
|
-
"## System Outline",
|
|
1105
|
-
"- TBD",
|
|
1106
|
-
"",
|
|
1107
|
-
"## Critical Flows",
|
|
1108
|
-
"- TBD",
|
|
1109
|
-
].join("\n"),
|
|
1110
|
-
},
|
|
1111
|
-
{
|
|
1112
|
-
path: wsPath("venture-state", "GROWTH_LOOPS.md"),
|
|
1113
|
-
content: [
|
|
1114
|
-
"# GROWTH_LOOPS",
|
|
1115
|
-
"",
|
|
1116
|
-
"## Acquisition",
|
|
1117
|
-
"- TBD",
|
|
1118
|
-
"",
|
|
1119
|
-
"## Retention",
|
|
1120
|
-
"- TBD",
|
|
1121
|
-
"",
|
|
1122
|
-
"## Monetization",
|
|
1123
|
-
"- TBD",
|
|
1124
|
-
].join("\n"),
|
|
1125
|
-
},
|
|
1126
|
-
{
|
|
1127
|
-
path: wsPath("venture-state", "RISKS.md"),
|
|
1128
|
-
content: [
|
|
1129
|
-
"# VENTURE RISKS",
|
|
1130
|
-
"",
|
|
1131
|
-
"## Active Risks",
|
|
1132
|
-
"- None logged yet.",
|
|
1133
|
-
].join("\n"),
|
|
1134
|
-
},
|
|
1135
|
-
{
|
|
1136
|
-
path: wsPath("venture-state", "PROTOTYPE", "MVP_SPEC.md"),
|
|
1137
|
-
content: [
|
|
1138
|
-
"# MVP_SPEC",
|
|
1139
|
-
"",
|
|
1140
|
-
"## Objective",
|
|
1141
|
-
"- TBD",
|
|
1142
|
-
"",
|
|
1143
|
-
"## Must-Have Behaviors",
|
|
1144
|
-
"- TBD",
|
|
1145
|
-
"",
|
|
1146
|
-
"## Proof Requirement",
|
|
1147
|
-
"- Define the smallest working slice that demonstrates value.",
|
|
1148
|
-
].join("\n"),
|
|
1149
|
-
},
|
|
1150
|
-
{
|
|
1151
|
-
path: wsPath("venture-state", "PROTOTYPE", "src", "README.md"),
|
|
1152
|
-
content: [
|
|
1153
|
-
"# Venture Prototype Source",
|
|
1154
|
-
"",
|
|
1155
|
-
`Use this directory when the venture swarm needs a lightweight proof-of-concept separate from \`${ACE_ROOT_REL}/engineering-state/src/\`.`,
|
|
1156
|
-
].join("\n"),
|
|
1157
|
-
},
|
|
1158
|
-
{
|
|
1159
|
-
path: wsPath("brand-state", "BRAND_VOICE.md"),
|
|
1160
|
-
content: [
|
|
1161
|
-
"# BRAND_VOICE",
|
|
1162
|
-
"",
|
|
1163
|
-
"## Positioning",
|
|
1164
|
-
"- TBD",
|
|
1165
|
-
"",
|
|
1166
|
-
"## Tone",
|
|
1167
|
-
"- Clear",
|
|
1168
|
-
"- Specific",
|
|
1169
|
-
"- Trust-building",
|
|
1170
|
-
"",
|
|
1171
|
-
"## Messaging Guardrails",
|
|
1172
|
-
"- Avoid generic claims.",
|
|
1173
|
-
"- Tie every headline to a concrete user outcome.",
|
|
1174
|
-
].join("\n"),
|
|
1175
|
-
},
|
|
1176
|
-
{
|
|
1177
|
-
path: wsPath("brand-state", "AUDIT_LOG.md"),
|
|
1178
|
-
content: [
|
|
1179
|
-
"# AUDIT_LOG",
|
|
1180
|
-
"",
|
|
1181
|
-
`- ${generatedAt} bootstrap: brand audit log initialized.`,
|
|
1182
|
-
].join("\n"),
|
|
1183
|
-
},
|
|
1184
|
-
{
|
|
1185
|
-
path: wsPath("brand-state", "COPY_DECK.md"),
|
|
1186
|
-
content: [
|
|
1187
|
-
"# COPY_DECK",
|
|
1188
|
-
"",
|
|
1189
|
-
"## Primary Headline",
|
|
1190
|
-
"- TBD",
|
|
1191
|
-
"",
|
|
1192
|
-
"## Supporting Copy",
|
|
1193
|
-
"- TBD",
|
|
1194
|
-
"",
|
|
1195
|
-
"## CTA",
|
|
1196
|
-
"- TBD",
|
|
1197
|
-
].join("\n"),
|
|
1198
|
-
},
|
|
1199
|
-
{
|
|
1200
|
-
path: wsPath("brand-state", "ASSETS", "strings.json"),
|
|
1201
|
-
content: JSON.stringify({
|
|
1202
|
-
app_name: projectName,
|
|
1203
|
-
headline: "",
|
|
1204
|
-
subheadline: "",
|
|
1205
|
-
primary_cta: "",
|
|
1206
|
-
}, null, 2),
|
|
1207
|
-
},
|
|
1208
|
-
{
|
|
1209
|
-
path: wsPath("engineering-state", "BUILD_STATUS.md"),
|
|
1210
|
-
content: [
|
|
1211
|
-
"# BUILD_STATUS",
|
|
1212
|
-
"",
|
|
1213
|
-
"- Status: not started",
|
|
1214
|
-
"- Active owner: ACE-Coders",
|
|
1215
|
-
"- Blockers: none recorded",
|
|
1216
|
-
`- Last update: ${generatedAt}`,
|
|
1217
|
-
].join("\n"),
|
|
1218
|
-
},
|
|
1219
|
-
{
|
|
1220
|
-
path: wsPath("engineering-state", "SPEC_CONTRACT.json"),
|
|
1221
|
-
content: JSON.stringify({
|
|
1222
|
-
version: "0.1.0",
|
|
1223
|
-
project: projectName,
|
|
1224
|
-
status: "draft",
|
|
1225
|
-
requirements: [],
|
|
1226
|
-
acceptance_tests: [],
|
|
1227
|
-
deliverables: [],
|
|
1228
|
-
}, null, 2),
|
|
1229
|
-
},
|
|
1230
|
-
{
|
|
1231
|
-
path: wsPath("engineering-state", "ARCHITECTURE.md"),
|
|
1232
|
-
content: [
|
|
1233
|
-
"# ARCHITECTURE",
|
|
1234
|
-
"",
|
|
1235
|
-
"## Stack",
|
|
1236
|
-
"- TBD",
|
|
1237
|
-
"",
|
|
1238
|
-
"## Interfaces",
|
|
1239
|
-
"- TBD",
|
|
1240
|
-
"",
|
|
1241
|
-
"## Constraints",
|
|
1242
|
-
"- TBD",
|
|
1243
|
-
].join("\n"),
|
|
1244
|
-
},
|
|
1245
|
-
{
|
|
1246
|
-
path: wsPath("engineering-state", "TEST_LOG.md"),
|
|
1247
|
-
content: [
|
|
1248
|
-
"# TEST_LOG",
|
|
1249
|
-
"",
|
|
1250
|
-
`- ${generatedAt} bootstrap: no tests executed yet.`,
|
|
1251
|
-
].join("\n"),
|
|
1252
|
-
},
|
|
1253
|
-
{
|
|
1254
|
-
path: wsPath("engineering-state", "src", "README.md"),
|
|
1255
|
-
content: [
|
|
1256
|
-
"# Engineering Source",
|
|
1257
|
-
"",
|
|
1258
|
-
`Place the main implementation here. Keep test evidence in \`${ACE_ROOT_REL}/engineering-state/TEST_LOG.md\`.`,
|
|
1259
|
-
].join("\n"),
|
|
1260
|
-
},
|
|
1261
|
-
];
|
|
1262
|
-
}
|
|
1263
|
-
export function getMcpClientBundlePath(client) {
|
|
1264
|
-
if (client === "codex")
|
|
1265
|
-
return wsPath(".mcp-config", "codex.config.toml");
|
|
1266
|
-
if (client === "vscode")
|
|
1267
|
-
return wsPath(".mcp-config", "vscode.mcp.json");
|
|
1268
|
-
if (client === "claude")
|
|
1269
|
-
return wsPath(".mcp-config", "claude_desktop_config.json");
|
|
1270
|
-
if (client === "cursor")
|
|
1271
|
-
return wsPath(".mcp-config", "cursor.mcp.json");
|
|
1272
|
-
return wsPath(".mcp-config", "antigravity.mcp.json");
|
|
1273
|
-
}
|
|
1274
|
-
export function getMcpClientInstallHint(client) {
|
|
1275
|
-
if (client === "codex") {
|
|
1276
|
-
const codexHome = resolve(process.env.CODEX_HOME ?? resolve(homedir(), ".codex"));
|
|
1277
|
-
return `${resolve(codexHome, "config.toml")} (append output from \`ace mcp-config --client codex\`)`;
|
|
1278
|
-
}
|
|
1279
|
-
if (client === "vscode") {
|
|
1280
|
-
return `${wsPath(".vscode", "mcp.json")} (workspace) or merge output from \`ace mcp-config --client vscode\``;
|
|
1281
|
-
}
|
|
1282
|
-
if (client === "claude") {
|
|
1283
|
-
return [
|
|
1284
|
-
`${resolve(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json")} (macOS, merge output from \`ace mcp-config --client claude\`)`,
|
|
1285
|
-
`${resolve(homedir(), ".config", "Claude", "claude_desktop_config.json")} (Linux, merge output from \`ace mcp-config --client claude\`)`,
|
|
1286
|
-
].join(" | ");
|
|
1287
|
-
}
|
|
1288
|
-
if (client === "cursor") {
|
|
1289
|
-
return `${resolve(homedir(), ".cursor", "mcp.json")} (merge output from \`ace mcp-config --client cursor\`)`;
|
|
1290
|
-
}
|
|
1291
|
-
return "Use Antigravity MCP UI import with output from `ace mcp-config --client antigravity`";
|
|
1292
|
-
}
|
|
1293
|
-
export function getMcpServerConfigSnippet(client = "vscode") {
|
|
1294
|
-
const stdio = getMcpCommandSpec();
|
|
1295
|
-
if (client === "codex") {
|
|
1296
|
-
return [
|
|
1297
|
-
`# ACE instructions are scaffolded into ${ACE_HOST_AGENTS_REL} during bootstrap.`,
|
|
1298
|
-
`[mcp_servers.ace-swarm]`,
|
|
1299
|
-
`command = "${stdio.command}"`,
|
|
1300
|
-
`args = ["${stdio.args.join('", "')}"]`,
|
|
1301
|
-
"",
|
|
1302
|
-
].join("\n");
|
|
1303
|
-
}
|
|
1304
|
-
const mcpServers = {
|
|
1305
|
-
"ace-swarm": {
|
|
1306
|
-
...stdio,
|
|
1307
|
-
},
|
|
1308
|
-
};
|
|
1309
|
-
if (client === "vscode") {
|
|
1310
|
-
return JSON.stringify({
|
|
1311
|
-
servers: {
|
|
1312
|
-
"ace-swarm": {
|
|
1313
|
-
type: "stdio",
|
|
1314
|
-
...stdio,
|
|
1315
|
-
},
|
|
1316
|
-
},
|
|
1317
|
-
}, null, 2);
|
|
1318
|
-
}
|
|
1319
|
-
return JSON.stringify({ mcpServers }, null, 2);
|
|
1320
|
-
}
|
|
1321
|
-
export function getAllMcpServerConfigSnippets() {
|
|
1322
|
-
return {
|
|
1323
|
-
codex: getMcpServerConfigSnippet("codex"),
|
|
1324
|
-
vscode: getMcpServerConfigSnippet("vscode"),
|
|
1325
|
-
claude: getMcpServerConfigSnippet("claude"),
|
|
1326
|
-
cursor: getMcpServerConfigSnippet("cursor"),
|
|
1327
|
-
antigravity: getMcpServerConfigSnippet("antigravity"),
|
|
1328
|
-
};
|
|
1329
|
-
}
|
|
1330
|
-
export function bootstrapAceWorkspace(options = {}) {
|
|
1331
|
-
const force = options.force ?? false;
|
|
1332
|
-
const projectName = options.projectName?.trim() || "ACE Project";
|
|
1333
|
-
const includeMcpConfig = options.includeMcpConfig ?? true;
|
|
1334
|
-
const includeClientConfigBundle = options.includeClientConfigBundle ?? true;
|
|
1335
|
-
const normalizedProvider = normalizeProvider(options.llmProvider);
|
|
1336
|
-
const llmProvider = normalizedProvider;
|
|
1337
|
-
const llmModel = options.llmModel?.trim() ||
|
|
1338
|
-
options.ollamaModel?.trim() ||
|
|
1339
|
-
defaultModelForProvider(llmProvider);
|
|
1340
|
-
const llmBaseUrl = normalizeLocalBaseUrl(options.llmBaseUrl ?? options.ollamaBaseUrl);
|
|
1341
|
-
if (llmProvider && !ALL_LLM_PROVIDERS.includes(llmProvider)) {
|
|
1342
|
-
throw new Error(`Unsupported llmProvider: ${llmProvider}`);
|
|
1343
|
-
}
|
|
1344
|
-
const result = { created: [], updated: [], skipped: [] };
|
|
1345
|
-
const generatedAt = new Date().toISOString();
|
|
1346
|
-
const dirSeeds = [
|
|
1347
|
-
acePath(),
|
|
1348
|
-
wsPath("global-state"),
|
|
1349
|
-
wsPath("venture-state"),
|
|
1350
|
-
wsPath("brand-state"),
|
|
1351
|
-
wsPath("brand-state", "ASSETS"),
|
|
1352
|
-
wsPath("engineering-state"),
|
|
1353
|
-
wsPath("engineering-state", "src"),
|
|
1354
|
-
wsPath("agent-state"),
|
|
1355
|
-
wsPath("agent-state", "MODULES"),
|
|
1356
|
-
wsPath("agent-state", "MODULES", "roles"),
|
|
1357
|
-
wsPath("agent-state", "MODULES", "gates"),
|
|
1358
|
-
acePath("tasks"),
|
|
1359
|
-
acePath(".github"),
|
|
1360
|
-
acePath(".github", "hooks"),
|
|
1361
|
-
acePath(".claude"),
|
|
1362
|
-
acePath(".cursor"),
|
|
1363
|
-
acePath(".vscode"),
|
|
1364
|
-
acePath(".mcp-config"),
|
|
1365
|
-
acePath("scripts"),
|
|
1366
|
-
acePath("scripts", "ace"),
|
|
1367
|
-
acePath("skills"),
|
|
1368
|
-
];
|
|
1369
|
-
if (llmProvider) {
|
|
1370
|
-
dirSeeds.push(acePath(".ace"));
|
|
1371
|
-
}
|
|
1372
|
-
for (const dir of dirSeeds)
|
|
1373
|
-
ensureDir(dir, result);
|
|
1374
|
-
// Copy packaged defaults. When the store bootstrap has already run,
|
|
1375
|
-
// skip the trees it now owns so we don't overwrite its materialized output.
|
|
1376
|
-
const skipStoreManaged = options.skipStoreManaged ?? false;
|
|
1377
|
-
if (!skipStoreManaged) {
|
|
1378
|
-
copyTree(DEFAULTS_TASKS_ROOT, acePath("tasks"), result, force);
|
|
1379
|
-
copyTree(DEFAULTS_AGENT_STATE_ROOT, wsPath("agent-state"), result, force);
|
|
1380
|
-
copyTree(resolve(DEFAULTS_ROOT, ".agents", "ACE"), acePath(), result, force);
|
|
1381
|
-
copyTree(DEFAULTS_SKILLS_ROOT, acePath("skills"), result, force);
|
|
1382
|
-
}
|
|
1383
|
-
copyTree(DEFAULTS_GITHUB_ROOT, acePath(".github"), result, force);
|
|
1384
|
-
copyTree(DEFAULTS_SCRIPTS_ROOT, acePath("scripts", "ace"), result, force);
|
|
1385
|
-
// Global ACE orchestrator state files.
|
|
1386
|
-
const masterPlanPath = wsPath("global-state", "MASTER_PLAN.md");
|
|
1387
|
-
writeIfMissingOrForced(masterPlanPath, [
|
|
1388
|
-
`# ${projectName} — Master Plan`,
|
|
1389
|
-
"",
|
|
1390
|
-
`Created: ${generatedAt}`,
|
|
1391
|
-
"",
|
|
1392
|
-
"## Status",
|
|
1393
|
-
"",
|
|
1394
|
-
"- Phase: Bootstrap",
|
|
1395
|
-
"- Next: Route first handoff",
|
|
1396
|
-
"",
|
|
1397
|
-
"## Roadmap",
|
|
1398
|
-
"",
|
|
1399
|
-
"1. [ ] Validate venture thesis (ACE-VOS)",
|
|
1400
|
-
"2. [ ] Define UX copy/flow package (ACE-UI)",
|
|
1401
|
-
"3. [ ] Ship tested implementation (ACE-Coders)",
|
|
1402
|
-
"",
|
|
1403
|
-
"## Active Swarm",
|
|
1404
|
-
"",
|
|
1405
|
-
"| Agent | Status | Last Update |",
|
|
1406
|
-
"|---|---|---|",
|
|
1407
|
-
"| ACE-Orchestrator | active | bootstrap |",
|
|
1408
|
-
"| ACE-VOS | idle | — |",
|
|
1409
|
-
"| ACE-UI | idle | — |",
|
|
1410
|
-
"| ACE-Coders | idle | — |",
|
|
1411
|
-
].join("\n"), result, force);
|
|
1412
|
-
for (const file of buildWorkspaceStateSeedFiles(projectName, generatedAt)) {
|
|
1413
|
-
writeIfMissingOrForced(file.path, file.content, result, force);
|
|
1414
|
-
}
|
|
1415
|
-
// SWARM_REGISTRY is a derived artifact from code topology — always refresh.
|
|
1416
|
-
const registryPath = wsPath("global-state", "SWARM_REGISTRY.json");
|
|
1417
|
-
const swarmSubagents = [...COMPOSABLE_AGENTS];
|
|
1418
|
-
const parentSwarms = [...SWARM_AGENTS].map((role) => `ace-${role}`);
|
|
1419
|
-
writeIfMissingOrForced(registryPath, JSON.stringify({
|
|
1420
|
-
swarms: {
|
|
1421
|
-
"ace-orchestrator": {
|
|
1422
|
-
group: "swarm",
|
|
1423
|
-
state_dir: `./${ACE_ROOT_REL}/global-state/`,
|
|
1424
|
-
status: "active",
|
|
1425
|
-
instructions: ".agents/ACE/orchestrator/instructions.md",
|
|
1426
|
-
subagents: swarmSubagents,
|
|
1427
|
-
},
|
|
1428
|
-
"ace-vos": {
|
|
1429
|
-
group: "swarm",
|
|
1430
|
-
state_dir: `./${ACE_ROOT_REL}/venture-state/`,
|
|
1431
|
-
status: "idle",
|
|
1432
|
-
instructions: ".agents/ACE/VOS/instructions.md",
|
|
1433
|
-
subagents: swarmSubagents,
|
|
1434
|
-
},
|
|
1435
|
-
"ace-ui": {
|
|
1436
|
-
group: "swarm",
|
|
1437
|
-
state_dir: `./${ACE_ROOT_REL}/brand-state/`,
|
|
1438
|
-
status: "idle",
|
|
1439
|
-
instructions: ".agents/ACE/UI/instructions.md",
|
|
1440
|
-
subagents: swarmSubagents,
|
|
1441
|
-
},
|
|
1442
|
-
"ace-coders": {
|
|
1443
|
-
group: "swarm",
|
|
1444
|
-
state_dir: `./${ACE_ROOT_REL}/engineering-state/`,
|
|
1445
|
-
status: "idle",
|
|
1446
|
-
instructions: ".agents/ACE/ACE_coders/INSTRUCTIONS.md",
|
|
1447
|
-
subagents: swarmSubagents,
|
|
1448
|
-
},
|
|
1449
|
-
"agent-astgrep": {
|
|
1450
|
-
group: "composable",
|
|
1451
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1452
|
-
status: "idle",
|
|
1453
|
-
instructions: ".agents/ACE/agent-astgrep/instructions.md",
|
|
1454
|
-
parent_swarms: parentSwarms,
|
|
1455
|
-
},
|
|
1456
|
-
"agent-skeptic": {
|
|
1457
|
-
group: "composable",
|
|
1458
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1459
|
-
status: "idle",
|
|
1460
|
-
instructions: ".agents/ACE/agent-skeptic/instructions.md",
|
|
1461
|
-
parent_swarms: parentSwarms,
|
|
1462
|
-
},
|
|
1463
|
-
"agent-ops": {
|
|
1464
|
-
group: "composable",
|
|
1465
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1466
|
-
status: "idle",
|
|
1467
|
-
instructions: ".agents/ACE/agent-ops/instructions.md",
|
|
1468
|
-
parent_swarms: parentSwarms,
|
|
1469
|
-
},
|
|
1470
|
-
"agent-research": {
|
|
1471
|
-
group: "composable",
|
|
1472
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1473
|
-
status: "idle",
|
|
1474
|
-
instructions: ".agents/ACE/agent-research/instructions.md",
|
|
1475
|
-
parent_swarms: parentSwarms,
|
|
1476
|
-
},
|
|
1477
|
-
"agent-spec": {
|
|
1478
|
-
group: "composable",
|
|
1479
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1480
|
-
status: "idle",
|
|
1481
|
-
instructions: ".agents/ACE/agent-spec/instructions.md",
|
|
1482
|
-
parent_swarms: parentSwarms,
|
|
1483
|
-
},
|
|
1484
|
-
"agent-builder": {
|
|
1485
|
-
group: "composable",
|
|
1486
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1487
|
-
status: "idle",
|
|
1488
|
-
instructions: ".agents/ACE/agent-builder/instructions.md",
|
|
1489
|
-
parent_swarms: parentSwarms,
|
|
1490
|
-
},
|
|
1491
|
-
"agent-qa": {
|
|
1492
|
-
group: "composable",
|
|
1493
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1494
|
-
status: "idle",
|
|
1495
|
-
instructions: ".agents/ACE/agent-qa/instructions.md",
|
|
1496
|
-
parent_swarms: parentSwarms,
|
|
1497
|
-
},
|
|
1498
|
-
"agent-docs": {
|
|
1499
|
-
group: "composable",
|
|
1500
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1501
|
-
status: "idle",
|
|
1502
|
-
instructions: ".agents/ACE/agent-docs/instructions.md",
|
|
1503
|
-
parent_swarms: parentSwarms,
|
|
1504
|
-
},
|
|
1505
|
-
"agent-memory": {
|
|
1506
|
-
group: "composable",
|
|
1507
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1508
|
-
status: "idle",
|
|
1509
|
-
instructions: ".agents/ACE/agent-memory/instructions.md",
|
|
1510
|
-
parent_swarms: parentSwarms,
|
|
1511
|
-
},
|
|
1512
|
-
"agent-security": {
|
|
1513
|
-
group: "composable",
|
|
1514
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1515
|
-
status: "idle",
|
|
1516
|
-
instructions: ".agents/ACE/agent-security/instructions.md",
|
|
1517
|
-
parent_swarms: parentSwarms,
|
|
1518
|
-
},
|
|
1519
|
-
"agent-observability": {
|
|
1520
|
-
group: "composable",
|
|
1521
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1522
|
-
status: "idle",
|
|
1523
|
-
instructions: ".agents/ACE/agent-observability/instructions.md",
|
|
1524
|
-
parent_swarms: parentSwarms,
|
|
1525
|
-
},
|
|
1526
|
-
"agent-eval": {
|
|
1527
|
-
group: "composable",
|
|
1528
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1529
|
-
status: "idle",
|
|
1530
|
-
instructions: ".agents/ACE/agent-eval/instructions.md",
|
|
1531
|
-
parent_swarms: parentSwarms,
|
|
1532
|
-
},
|
|
1533
|
-
"agent-release": {
|
|
1534
|
-
group: "composable",
|
|
1535
|
-
state_dir: `./${ACE_ROOT_REL}/agent-state/`,
|
|
1536
|
-
status: "idle",
|
|
1537
|
-
instructions: ".agents/ACE/agent-release/instructions.md",
|
|
1538
|
-
parent_swarms: parentSwarms,
|
|
1539
|
-
},
|
|
1540
|
-
},
|
|
1541
|
-
}, null, 2), result, true // Always force SWARM_REGISTRY refresh — derived from code topology
|
|
1542
|
-
);
|
|
1543
|
-
writeIfMissingOrForced(wsPath("agent-state", "run-ledger.json"), JSON.stringify({
|
|
1544
|
-
version: 1,
|
|
1545
|
-
updated_at: new Date().toISOString(),
|
|
1546
|
-
entries: [],
|
|
1547
|
-
}, null, 2), result, force);
|
|
1548
|
-
writeIfMissingOrForced(wsPath("agent-state", "handoff-registry.json"), JSON.stringify({
|
|
1549
|
-
version: 1,
|
|
1550
|
-
updated_at: new Date().toISOString(),
|
|
1551
|
-
handoffs: {},
|
|
1552
|
-
}, null, 2), result, force);
|
|
1553
|
-
writeIfMissingOrForced(wsPath("agent-state", "index.json"), JSON.stringify({
|
|
1554
|
-
version: 1,
|
|
1555
|
-
root: ".",
|
|
1556
|
-
generated_at: "",
|
|
1557
|
-
discovery: {
|
|
1558
|
-
mode: "ast_grep_commands",
|
|
1559
|
-
command_pack: "agent-state/AST_GREP_COMMANDS.md",
|
|
1560
|
-
subagent: "astgrep",
|
|
1561
|
-
skill: "astgrep-index",
|
|
1562
|
-
fingerprint_store: "agent-state/index-fingerprints.json",
|
|
1563
|
-
},
|
|
1564
|
-
options: {
|
|
1565
|
-
depth: 6,
|
|
1566
|
-
max_files: 10000,
|
|
1567
|
-
include_hidden: false,
|
|
1568
|
-
exclude: [
|
|
1569
|
-
".git",
|
|
1570
|
-
"node_modules",
|
|
1571
|
-
"dist",
|
|
1572
|
-
"target",
|
|
1573
|
-
".venv",
|
|
1574
|
-
"__pycache__",
|
|
1575
|
-
".DS_Store",
|
|
1576
|
-
],
|
|
1577
|
-
file_entry_cap: 0,
|
|
1578
|
-
},
|
|
1579
|
-
file_count: 0,
|
|
1580
|
-
stored_file_count: 0,
|
|
1581
|
-
directories: {},
|
|
1582
|
-
extensions: {},
|
|
1583
|
-
files: {},
|
|
1584
|
-
}, null, 2), result, force);
|
|
1585
|
-
writeIfMissingOrForced(wsPath("agent-state", "index-fingerprints.json"), JSON.stringify({
|
|
1586
|
-
version: 1,
|
|
1587
|
-
root: ".",
|
|
1588
|
-
generated_at: "",
|
|
1589
|
-
file_count: 0,
|
|
1590
|
-
fingerprints: {},
|
|
1591
|
-
}, null, 2), result, force);
|
|
1592
|
-
writeIfMissingOrForced(wsPath("agent-state", "todo-state.json"), JSON.stringify({
|
|
1593
|
-
version: 1,
|
|
1594
|
-
updated_at: new Date().toISOString(),
|
|
1595
|
-
source_todo_path: `${ACE_TASKS_ROOT_REL}/todo.md`,
|
|
1596
|
-
order: [],
|
|
1597
|
-
nodes: {},
|
|
1598
|
-
}, null, 2), result, force);
|
|
1599
|
-
writeIfMissingOrForced(wsPath("agent-state", "job-queue.json"), JSON.stringify({
|
|
1600
|
-
version: 1,
|
|
1601
|
-
updated_at: new Date().toISOString(),
|
|
1602
|
-
jobs: [],
|
|
1603
|
-
}, null, 2), result, force);
|
|
1604
|
-
writeIfMissingOrForced(wsPath("agent-state", "job-locks.json"), JSON.stringify({
|
|
1605
|
-
version: 1,
|
|
1606
|
-
updated_at: new Date().toISOString(),
|
|
1607
|
-
locks: [],
|
|
1608
|
-
}, null, 2), result, force);
|
|
1609
|
-
writeIfMissingOrForced(wsPath("agent-state", "scheduler-lease.json"), JSON.stringify({
|
|
1610
|
-
version: 1,
|
|
1611
|
-
lease_id: "LEASE-UNASSIGNED",
|
|
1612
|
-
owner: "unassigned",
|
|
1613
|
-
acquired_at: new Date().toISOString(),
|
|
1614
|
-
heartbeat_at: new Date().toISOString(),
|
|
1615
|
-
expires_at: new Date().toISOString(),
|
|
1616
|
-
}, null, 2), result, force);
|
|
1617
|
-
if (includeMcpConfig) {
|
|
1618
|
-
writeIfMissingOrForced(acePath(".vscode", "mcp.json"), getMcpServerConfigSnippet("vscode"), result, force);
|
|
1619
|
-
}
|
|
1620
|
-
if (includeClientConfigBundle) {
|
|
1621
|
-
const snippets = getAllMcpServerConfigSnippets();
|
|
1622
|
-
for (const client of ALL_MCP_CLIENTS) {
|
|
1623
|
-
writeIfMissingOrForced(getMcpClientBundlePath(client), snippets[client], result, force);
|
|
1624
|
-
}
|
|
1625
|
-
writeIfMissingOrForced(acePath("CLAUDE.md"), buildHostInstructionText("claude", WORKSPACE_ROOT), result, force);
|
|
1626
|
-
writeIfMissingOrForced(acePath(".github", "copilot-instructions.md"), buildHostInstructionText("copilot", WORKSPACE_ROOT), result, force);
|
|
1627
|
-
writeIfMissingOrForced(acePath(".cursorrules"), buildHostInstructionText("cursor", WORKSPACE_ROOT), result, force);
|
|
1628
|
-
writeIfMissingOrForced(acePath("AGENTS.md"), buildHostInstructionText("codex", WORKSPACE_ROOT), result, force);
|
|
1629
|
-
writeIfMissingOrForced(acePath(".claude", "settings.json"), buildClaudeHookSettings(), result, force);
|
|
1630
|
-
writeIfMissingOrForced(acePath(".github", "hooks", "ace-copilot.json"), buildCopilotHookSettings(), result, force);
|
|
1631
|
-
writeIfMissingOrForced(acePath(".vscode", "ace-hooks.json"), buildVsCodeHookSettings(), result, force);
|
|
1632
|
-
writeIfMissingOrForced(acePath(".cursor", "hooks.json"), buildCursorHookSettings(), result, force);
|
|
1633
|
-
writeIfMissingOrForced(wsPath(".mcp-config", "codex.hooks.toml"), buildCodexHookSettings(), result, force);
|
|
1634
|
-
writeIfMissingOrForced(wsPath(".mcp-config", "gemini.hooks.json"), buildGeminiHookSettings(), result, force);
|
|
1635
|
-
writeIfMissingOrForced(wsPath(".mcp-config", "antigravity.hooks.json"), buildAntigravityHookSettings(), result, force);
|
|
1636
|
-
writeIfMissingOrForced(wsPath(".mcp-config", "README.md"), [
|
|
1637
|
-
"# ACE MCP Client Config Bundle",
|
|
1638
|
-
"",
|
|
1639
|
-
"Generated by `ace init` so this workspace is turnkey across MCP clients.",
|
|
1640
|
-
"",
|
|
1641
|
-
"## Files",
|
|
1642
|
-
"- `codex.config.toml`",
|
|
1643
|
-
"- `vscode.mcp.json`",
|
|
1644
|
-
"- `claude_desktop_config.json`",
|
|
1645
|
-
"- `cursor.mcp.json`",
|
|
1646
|
-
"- `antigravity.mcp.json`",
|
|
1647
|
-
"",
|
|
1648
|
-
"## Instruction + Hook Files",
|
|
1649
|
-
`- \`${ACE_HOST_CLAUDE_REL}\``,
|
|
1650
|
-
`- \`${ACE_GITHUB_ROOT_REL}/copilot-instructions.md\``,
|
|
1651
|
-
`- \`${ACE_HOST_CURSOR_RULES_REL}\``,
|
|
1652
|
-
`- \`${ACE_HOST_AGENTS_REL}\``,
|
|
1653
|
-
`- \`${ACE_CLAUDE_ROOT_REL}/settings.json\``,
|
|
1654
|
-
`- \`${ACE_VSCODE_ROOT_REL}/ace-hooks.json\``,
|
|
1655
|
-
`- \`${ACE_CURSOR_ROOT_REL}/hooks.json\``,
|
|
1656
|
-
`- \`${ACE_BUNDLE_ROOT_REL}/codex.hooks.toml\``,
|
|
1657
|
-
`- \`${ACE_BUNDLE_ROOT_REL}/gemini.hooks.json\``,
|
|
1658
|
-
`- \`${ACE_BUNDLE_ROOT_REL}/antigravity.hooks.json\``,
|
|
1659
|
-
"",
|
|
1660
|
-
"## Install Hints",
|
|
1661
|
-
...ALL_MCP_CLIENTS.map((client) => `- ${client}: ${getMcpClientInstallHint(client)}`),
|
|
1662
|
-
...(llmProvider
|
|
1663
|
-
? [
|
|
1664
|
-
"",
|
|
1665
|
-
"## LLM Runtime Profile",
|
|
1666
|
-
`- \`${ACE_LLM_ROOT_REL}/llm-profile.json\` (generated for ${llmProvider})`,
|
|
1667
|
-
`- \`${ACE_LLM_ROOT_REL}/doctor-checks.md\` (commands to verify provider runtime)`,
|
|
1668
|
-
llmBaseUrl
|
|
1669
|
-
? `- Run \`ace doctor --llm ${llmProvider} --model ${llmModel} --base-url ${llmBaseUrl}\``
|
|
1670
|
-
: llmProvider === "ollama" || llmProvider === "llama.cpp"
|
|
1671
|
-
? `- Run \`ace doctor --llm ${llmProvider} --model ${llmModel} --scan\` to discover a local endpoint`
|
|
1672
|
-
: `- Run \`ace doctor --llm ${llmProvider} --model ${llmModel}\` after exporting the provider credentials`,
|
|
1673
|
-
]
|
|
1674
|
-
: []),
|
|
1675
|
-
].join("\n"), result, force);
|
|
1676
|
-
}
|
|
1677
|
-
if (llmProvider) {
|
|
1678
|
-
const profilePayload = {
|
|
1679
|
-
provider: llmProvider,
|
|
1680
|
-
model: llmModel,
|
|
1681
|
-
generated_at: new Date().toISOString(),
|
|
1682
|
-
};
|
|
1683
|
-
if (llmBaseUrl) {
|
|
1684
|
-
profilePayload.base_url = llmBaseUrl;
|
|
1685
|
-
if (llmProvider === "ollama") {
|
|
1686
|
-
profilePayload.api_compat_base_url = buildOpenAiCompatibleBaseUrl(llmBaseUrl);
|
|
1687
|
-
profilePayload.default_api_key = "ollama";
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
|
-
writeIfMissingOrForced(wsPath(".ace", "llm-profile.json"), JSON.stringify(profilePayload, null, 2), result, force);
|
|
1691
|
-
const doctorCommands = buildProviderDoctorCommands(llmProvider, llmModel, llmBaseUrl);
|
|
1692
|
-
writeIfMissingOrForced(wsPath(".ace", "doctor-checks.md"), [
|
|
1693
|
-
`# ACE + ${llmProvider} Runtime Checks`,
|
|
1694
|
-
"",
|
|
1695
|
-
"Run these commands to verify ACE runtime readiness:",
|
|
1696
|
-
"",
|
|
1697
|
-
"```bash",
|
|
1698
|
-
...doctorCommands,
|
|
1699
|
-
"```",
|
|
1700
|
-
"",
|
|
1701
|
-
`MCP is still configured separately via \`${ACE_VSCODE_ROOT_REL}/mcp.json\` or \`${ACE_BUNDLE_ROOT_REL}/*\`.`,
|
|
1702
|
-
].join("\n"), result, force);
|
|
1703
|
-
}
|
|
1704
|
-
return result;
|
|
1705
|
-
}
|
|
1706
|
-
/**
|
|
1707
|
-
* Compare packaged assets against runtime workspace copies.
|
|
1708
|
-
* Detects silent divergence between authoritative defaults and live state.
|
|
1709
|
-
*/
|
|
1710
|
-
export function detectAssetDrift() {
|
|
1711
|
-
const entries = [];
|
|
1712
|
-
const assetDirs = [
|
|
1713
|
-
{ assetRoot: DEFAULTS_AGENT_STATE_ROOT, workspaceRoot: wsPath("agent-state") },
|
|
1714
|
-
{ assetRoot: DEFAULTS_TASKS_ROOT, workspaceRoot: acePath("tasks") },
|
|
1715
|
-
];
|
|
1716
|
-
function walkAndCompare(assetDir, runtimeDir) {
|
|
1717
|
-
if (!existsSync(assetDir))
|
|
1718
|
-
return;
|
|
1719
|
-
const items = readdirSync(assetDir, { withFileTypes: true });
|
|
1720
|
-
for (const item of items) {
|
|
1721
|
-
const assetPath = resolve(assetDir, item.name);
|
|
1722
|
-
const runtimePath = resolve(runtimeDir, item.name);
|
|
1723
|
-
if (item.isDirectory()) {
|
|
1724
|
-
walkAndCompare(assetPath, runtimePath);
|
|
1725
|
-
continue;
|
|
1726
|
-
}
|
|
1727
|
-
if (!existsSync(runtimePath)) {
|
|
1728
|
-
entries.push({ asset_path: assetPath, runtime_path: runtimePath, status: "missing-runtime" });
|
|
1729
|
-
continue;
|
|
1730
|
-
}
|
|
1731
|
-
const assetContent = readText(assetPath);
|
|
1732
|
-
const runtimeContent = readText(runtimePath);
|
|
1733
|
-
entries.push({
|
|
1734
|
-
asset_path: assetPath,
|
|
1735
|
-
runtime_path: runtimePath,
|
|
1736
|
-
status: assetContent === runtimeContent ? "match" : "drift",
|
|
1737
|
-
});
|
|
1738
|
-
}
|
|
1739
|
-
}
|
|
1740
|
-
for (const { assetRoot, workspaceRoot } of assetDirs) {
|
|
1741
|
-
walkAndCompare(assetRoot, workspaceRoot);
|
|
1742
|
-
}
|
|
1743
|
-
return {
|
|
1744
|
-
checked: entries.length,
|
|
1745
|
-
drifted: entries.filter((e) => e.status === "drift").length,
|
|
1746
|
-
missing_runtime: entries.filter((e) => e.status === "missing-runtime").length,
|
|
1747
|
-
entries,
|
|
1748
|
-
};
|
|
1749
|
-
}
|
|
6
|
+
export * from "./helpers/path-utils.js";
|
|
7
|
+
export * from "./helpers/store-resolution.js";
|
|
8
|
+
export * from "./helpers/artifacts.js";
|
|
9
|
+
export * from "./helpers/bootstrap.js";
|
|
10
|
+
export * from "./helpers/drift.js";
|
|
1750
11
|
//# sourceMappingURL=helpers.js.map
|