@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
|
@@ -28,6 +28,9 @@ const ACE_CORE_FILES = [
|
|
|
28
28
|
"agent-state/SCOPE.md",
|
|
29
29
|
"agent-state/EVIDENCE_LOG.md",
|
|
30
30
|
];
|
|
31
|
+
const STORE_MAGIC = "ACEPACK1";
|
|
32
|
+
const STORE_HEADER_SIZE = 32;
|
|
33
|
+
const HOOK_CONTEXT_STORE_KEY = "state/runtime/hook_context";
|
|
31
34
|
|
|
32
35
|
const PROTECTED_PATH_FRAGMENTS = [
|
|
33
36
|
".github/hooks/",
|
|
@@ -114,9 +117,61 @@ function resolveAcePath(workspaceRoot, relativePath) {
|
|
|
114
117
|
return canonical;
|
|
115
118
|
}
|
|
116
119
|
|
|
120
|
+
function getWorkspaceStorePath(workspaceRoot) {
|
|
121
|
+
const canonical = resolve(workspaceRoot, "agent-state", "ace-state.ace");
|
|
122
|
+
if (existsSync(canonical)) return canonical;
|
|
123
|
+
return resolve(workspaceRoot, ACE_ROOT, "ace-state.ace");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function readStoreUint64(buffer, offset) {
|
|
127
|
+
return buffer.readUInt32BE(offset) * 2 ** 32 + buffer.readUInt32BE(offset + 4);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function readStoreBlob(workspaceRoot, key) {
|
|
131
|
+
const storePath = getWorkspaceStorePath(workspaceRoot);
|
|
132
|
+
if (!existsSync(storePath)) return undefined;
|
|
133
|
+
try {
|
|
134
|
+
const file = readFileSync(storePath);
|
|
135
|
+
if (file.length < STORE_HEADER_SIZE) return undefined;
|
|
136
|
+
if (file.subarray(0, 8).toString("utf8") !== STORE_MAGIC) return undefined;
|
|
137
|
+
const indexOffset = readStoreUint64(file, 16);
|
|
138
|
+
const indexLength = readStoreUint64(file, 24);
|
|
139
|
+
const index = JSON.parse(file.subarray(indexOffset, indexOffset + indexLength).toString("utf8"));
|
|
140
|
+
const entry = index?.[key];
|
|
141
|
+
if (!entry || typeof entry.offset !== "number" || typeof entry.length !== "number") {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
const start = entry.offset + 4;
|
|
145
|
+
const end = start + entry.length;
|
|
146
|
+
return file.subarray(start, end).toString("utf8");
|
|
147
|
+
} catch {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
117
152
|
function readIfPresent(workspaceRoot, relativePath) {
|
|
118
153
|
const absolute = resolveAcePath(workspaceRoot, relativePath);
|
|
119
|
-
if (!existsSync(absolute))
|
|
154
|
+
if (!existsSync(absolute)) {
|
|
155
|
+
const normalized = String(relativePath).replace(/\\/g, "/").replace(/^\.?\//, "");
|
|
156
|
+
const logicalPath = normalized.startsWith(`${ACE_ROOT}/`)
|
|
157
|
+
? normalized.slice(`${ACE_ROOT}/`.length)
|
|
158
|
+
: normalized;
|
|
159
|
+
const rel = logicalPath.startsWith("agent-state/") ? logicalPath.slice("agent-state/".length) : "";
|
|
160
|
+
const keys = [];
|
|
161
|
+
if (rel) {
|
|
162
|
+
keys.push(`state/artifacts/agent-state/${rel}`);
|
|
163
|
+
keys.push(`knowledge/agent-state/${rel}`);
|
|
164
|
+
if (rel === "ACE_WORKFLOW.md") {
|
|
165
|
+
keys.unshift("knowledge/runtime/ACE_WORKFLOW.md");
|
|
166
|
+
keys.push("knowledge/kernel/ACE_WORKFLOW.md");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
for (const key of keys) {
|
|
170
|
+
const blob = readStoreBlob(workspaceRoot, key);
|
|
171
|
+
if (typeof blob === "string") return blob;
|
|
172
|
+
}
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
120
175
|
try {
|
|
121
176
|
return readFileSync(absolute, "utf8");
|
|
122
177
|
} catch {
|
|
@@ -203,12 +258,19 @@ function buildRoleToolHint(role) {
|
|
|
203
258
|
}
|
|
204
259
|
|
|
205
260
|
/**
|
|
206
|
-
* Try to read the store-
|
|
261
|
+
* Try to read the store-backed hook context snapshot.
|
|
207
262
|
* Returns the parsed snapshot or undefined if not present / unreadable.
|
|
208
|
-
* When present this is the single authoritative source; the dispatcher
|
|
209
|
-
* never needs to open the .ace store directly.
|
|
210
263
|
*/
|
|
211
264
|
function tryReadHookContextSnapshot(workspaceRoot) {
|
|
265
|
+
const storeRaw = readStoreBlob(workspaceRoot, HOOK_CONTEXT_STORE_KEY);
|
|
266
|
+
if (typeof storeRaw === "string") {
|
|
267
|
+
try {
|
|
268
|
+
const parsed = JSON.parse(storeRaw);
|
|
269
|
+
if (parsed?.schema_version === 1) return parsed;
|
|
270
|
+
} catch {
|
|
271
|
+
// Fall through to legacy file compatibility.
|
|
272
|
+
}
|
|
273
|
+
}
|
|
212
274
|
const snapshotPath = resolve(workspaceRoot, ACE_ROOT, "ace-hook-context.json");
|
|
213
275
|
if (!existsSync(snapshotPath)) return undefined;
|
|
214
276
|
try {
|
|
@@ -222,7 +284,7 @@ function tryReadHookContextSnapshot(workspaceRoot) {
|
|
|
222
284
|
}
|
|
223
285
|
|
|
224
286
|
function aceContext(workspaceRoot) {
|
|
225
|
-
// ── Fast path: store-
|
|
287
|
+
// ── Fast path: store-backed snapshot ────────────────────────────────────
|
|
226
288
|
const snapshot = tryReadHookContextSnapshot(workspaceRoot);
|
|
227
289
|
if (snapshot) {
|
|
228
290
|
const taskObjective = snapshot.task?.content
|
|
@@ -233,7 +295,9 @@ function aceContext(workspaceRoot) {
|
|
|
233
295
|
const scopeReminder = scopeLines.length
|
|
234
296
|
? `ACE scope reminder: ${truncate(scopeLines.slice(0, 4).join(" "), 220)}`
|
|
235
297
|
: undefined;
|
|
236
|
-
const hasAgentState =
|
|
298
|
+
const hasAgentState =
|
|
299
|
+
existsSync(resolve(workspaceRoot, ACE_ROOT, "agent-state")) ||
|
|
300
|
+
existsSync(resolve(workspaceRoot, "agent-state", "ace-state.ace"));
|
|
237
301
|
const hasSkills = existsSync(resolve(workspaceRoot, ACE_ROOT, "skills")) ||
|
|
238
302
|
existsSync(resolve(workspaceRoot, ".agents", "skills"));
|
|
239
303
|
return {
|
|
@@ -12,6 +12,9 @@ CURSOR_DIR="${ACE_ROOT}/.cursor"
|
|
|
12
12
|
VSCODE_DIR="${ACE_ROOT}/.vscode"
|
|
13
13
|
HOOK_COMMAND="node ./.agents/ACE/scripts/ace/ace-hook-dispatch.mjs"
|
|
14
14
|
HOOK_COMMAND_WINDOWS="node .\\\\.agents\\\\ACE\\\\scripts\\\\ace\\\\ace-hook-dispatch.mjs"
|
|
15
|
+
NODE_BIN_DIR="$(dirname -- "$(command -v node)")"
|
|
16
|
+
CLI_ENTRY="${WORKSPACE_ROOT}/dist/cli.js"
|
|
17
|
+
MCP_LAUNCH="export PATH=\"${NODE_BIN_DIR}:\$PATH\" && if ! command -v node >/dev/null 2>&1; then [ -s \"\$HOME/.zprofile\" ] && . \"\$HOME/.zprofile\"; [ -s \"\$HOME/.zshrc\" ] && . \"\$HOME/.zshrc\"; fi && cd \"${WORKSPACE_ROOT}\" && ACE_WORKSPACE_ROOT=\"${WORKSPACE_ROOT}\" node \"${CLI_ENTRY}\" mcp"
|
|
15
18
|
|
|
16
19
|
mkdir -p "${MCP_CONFIG_DIR}"
|
|
17
20
|
mkdir -p "${GITHUB_DIR}/hooks"
|
|
@@ -25,7 +28,18 @@ cat > "${MCP_CONFIG_DIR}/vscode.mcp.json" <<JSON
|
|
|
25
28
|
"ace-swarm": {
|
|
26
29
|
"type": "stdio",
|
|
27
30
|
"command": "/bin/zsh",
|
|
28
|
-
"args": ["-lc", "
|
|
31
|
+
"args": ["-lc", "${MCP_LAUNCH}"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
JSON
|
|
36
|
+
|
|
37
|
+
cat > "${WORKSPACE_ROOT}/.mcp.json" <<JSON
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"ace-swarm": {
|
|
41
|
+
"command": "/bin/zsh",
|
|
42
|
+
"args": ["-lc", "${MCP_LAUNCH}"]
|
|
29
43
|
}
|
|
30
44
|
}
|
|
31
45
|
}
|
|
@@ -36,7 +50,7 @@ cat > "${MCP_CONFIG_DIR}/cursor.mcp.json" <<JSON
|
|
|
36
50
|
"mcpServers": {
|
|
37
51
|
"ace-swarm": {
|
|
38
52
|
"command": "/bin/zsh",
|
|
39
|
-
"args": ["-lc", "
|
|
53
|
+
"args": ["-lc", "${MCP_LAUNCH}"]
|
|
40
54
|
}
|
|
41
55
|
}
|
|
42
56
|
}
|
|
@@ -47,7 +61,7 @@ cat > "${MCP_CONFIG_DIR}/claude_desktop_config.json" <<JSON
|
|
|
47
61
|
"mcpServers": {
|
|
48
62
|
"ace-swarm": {
|
|
49
63
|
"command": "/bin/zsh",
|
|
50
|
-
"args": ["-lc", "
|
|
64
|
+
"args": ["-lc", "${MCP_LAUNCH}"]
|
|
51
65
|
}
|
|
52
66
|
}
|
|
53
67
|
}
|
|
@@ -58,7 +72,7 @@ cat > "${MCP_CONFIG_DIR}/antigravity.mcp.json" <<JSON
|
|
|
58
72
|
"mcpServers": {
|
|
59
73
|
"ace-swarm": {
|
|
60
74
|
"command": "/bin/zsh",
|
|
61
|
-
"args": ["-lc", "
|
|
75
|
+
"args": ["-lc", "${MCP_LAUNCH}"]
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
78
|
}
|
|
@@ -68,7 +82,7 @@ cat > "${MCP_CONFIG_DIR}/codex.config.toml" <<TOML
|
|
|
68
82
|
# ACE instructions are scaffolded into .agents/ACE/AGENTS.md during bootstrap.
|
|
69
83
|
[mcp_servers.ace-swarm]
|
|
70
84
|
command = "/bin/zsh"
|
|
71
|
-
args = ["-lc", "
|
|
85
|
+
args = ["-lc", "${MCP_LAUNCH}"]
|
|
72
86
|
TOML
|
|
73
87
|
|
|
74
88
|
cat > "${ACE_ROOT}/CLAUDE.md" <<MD
|
package/dist/ace-context.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { buildAceContinuityPacket, buildAceRecallContext, formatAceContinuityPacketMarkdown, formatAceRecallMarkdown, normalizeAutonomyPolicy, normalizeContinuityPolicy, } from "./ace-autonomy.js";
|
|
2
2
|
import { listAceInternalToolCatalog, } from "./ace-internal-tools.js";
|
|
3
|
-
import { ALL_AGENTS, readAgentInstructions } from "./helpers.js";
|
|
3
|
+
import { ALL_AGENTS, listAvailableSkills, readAgentInstructions } from "./helpers.js";
|
|
4
4
|
import { readRuntimeProfileState, renderRuntimePrompt } from "./runtime-profile.js";
|
|
5
5
|
const ROLE_TOOL_DEFAULTS = {
|
|
6
6
|
orchestrator: [
|
|
@@ -156,6 +156,23 @@ function buildPlanningCatalog(role, task, tier) {
|
|
|
156
156
|
.slice(0, limit)
|
|
157
157
|
.map((entry) => entry.tool);
|
|
158
158
|
}
|
|
159
|
+
function inferRelevantSkills(task) {
|
|
160
|
+
const lowered = task.toLowerCase();
|
|
161
|
+
const skillSignals = [
|
|
162
|
+
{ name: "state-auditor", pattern: /\b(state|drift|authority|audit)\b/ },
|
|
163
|
+
{ name: "handoff-lint", pattern: /\b(handoff|transition|payload)\b/ },
|
|
164
|
+
{ name: "schema-forge", pattern: /\b(schema|contract|interface)\b/ },
|
|
165
|
+
{ name: "release-sentry", pattern: /\b(ship|release|promotion|rollback)\b/ },
|
|
166
|
+
{ name: "risk-quant", pattern: /\b(risk|blocker|severity)\b/ },
|
|
167
|
+
{ name: "eval-harness", pattern: /\b(eval|regression|verify|validation)\b/ },
|
|
168
|
+
{ name: "incident-commander", pattern: /\b(incident|outage|blocker storm)\b/ },
|
|
169
|
+
{ name: "problem-triage", pattern: /\b(triage|classify|scope)\b/ },
|
|
170
|
+
];
|
|
171
|
+
const available = new Set(listAvailableSkills().map((skill) => skill.name));
|
|
172
|
+
return skillSignals
|
|
173
|
+
.filter((signal) => signal.pattern.test(lowered) && available.has(signal.name))
|
|
174
|
+
.map((signal) => signal.name);
|
|
175
|
+
}
|
|
159
176
|
export function buildToolPlan(options) {
|
|
160
177
|
const tier = options.tier ?? "compressed";
|
|
161
178
|
const catalog = Array.isArray(options.tools) && options.tools.length > 0
|
|
@@ -211,6 +228,7 @@ export function renderAceContext(options) {
|
|
|
211
228
|
const roleInstructions = resolveRoleInstructions(options.role);
|
|
212
229
|
const toolCatalog = renderToolCatalogMarkdown(tools, tier);
|
|
213
230
|
const stateDigest = recall.task_contract.summary;
|
|
231
|
+
const relevantSkills = inferRelevantSkills(options.task);
|
|
214
232
|
const systemPrompt = [
|
|
215
233
|
runtimePrompt,
|
|
216
234
|
"",
|
|
@@ -223,6 +241,9 @@ export function renderAceContext(options) {
|
|
|
223
241
|
"## Tool Scope",
|
|
224
242
|
toolCatalog || "- No ACE tools available.",
|
|
225
243
|
"",
|
|
244
|
+
"## Relevant Skills",
|
|
245
|
+
relevantSkills.length > 0 ? `- ${relevantSkills.join(", ")}` : "- No task-specific skill hint matched.",
|
|
246
|
+
"",
|
|
226
247
|
"## Compact Guardrails",
|
|
227
248
|
"- Stop if you are about to claim tested, verified, or passed without evidence.",
|
|
228
249
|
"- If ACE state is thin or contradictory, call recall_context or validate_framework before improvising.",
|
|
@@ -229,10 +229,10 @@ export function buildHostInstructionText(host, workspaceRoot) {
|
|
|
229
229
|
"3. Prefer ACE prompts/resources (`ace-orchestrator`, `get_task_pack`, `get_skill_instructions`) over relying on this file.",
|
|
230
230
|
"",
|
|
231
231
|
"Ground truth:",
|
|
232
|
-
"- `agent-state/*` is the
|
|
233
|
-
"-
|
|
232
|
+
"- `agent-state/*` is the visible runtime state surface for this workspace.",
|
|
233
|
+
"- `agent-state/ace-state.ace` is the canonical store path; legacy nested store layouts are compatibility fallback only.",
|
|
234
234
|
"- `.agents/ACE/tasks/todo.md` is the human-facing todo surface.",
|
|
235
|
-
"-
|
|
235
|
+
"- Hook context is store-backed in `agent-state/ace-state.ace` and consumed without extra workspace projections.",
|
|
236
236
|
"",
|
|
237
237
|
`Workspace digest hint: ${buildAceDigest(workspaceRoot)}.`,
|
|
238
238
|
].join("\n");
|
|
@@ -95,9 +95,11 @@ export function resolveAceStateLayout(workspaceRoot) {
|
|
|
95
95
|
scopePath: resolveAceLogicalPath(workspaceRoot, "agent-state/SCOPE.md"),
|
|
96
96
|
evidencePath: resolveAceLogicalPath(workspaceRoot, "agent-state/EVIDENCE_LOG.md"),
|
|
97
97
|
storePath: storePresent ? storePath : undefined,
|
|
98
|
-
hookSnapshotPath:
|
|
99
|
-
?
|
|
100
|
-
:
|
|
98
|
+
hookSnapshotPath: readStoreBlobSync(workspaceRoot, "state/runtime/hook_context") != null
|
|
99
|
+
? toVirtualStorePath(storePath, "state/runtime/hook_context")
|
|
100
|
+
: existsSync(nestedAcePath(workspaceRoot, "ace-hook-context.json"))
|
|
101
|
+
? nestedAcePath(workspaceRoot, "ace-hook-context.json")
|
|
102
|
+
: undefined,
|
|
101
103
|
isAcePresent: physicalMode !== "missing" ||
|
|
102
104
|
CRITICAL_LOGICAL_PATHS.some((relativePath) => typeof readAceLogicalFile(workspaceRoot, relativePath) === "string"),
|
|
103
105
|
missingCriticalArtifacts,
|
package/dist/astgrep-index.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export interface AstgrepMatch {
|
|
2
|
+
file: string;
|
|
3
|
+
line: number;
|
|
4
|
+
column: number;
|
|
5
|
+
text: string;
|
|
6
|
+
context_lines?: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function runAstgrepQuery(pattern: string, lang: string, roots: string[], _contextLines?: number): AstgrepMatch[];
|
|
1
9
|
export interface RefreshAstgrepIndexInput {
|
|
2
10
|
scope?: string;
|
|
3
11
|
append_evidence?: boolean;
|
|
@@ -20,5 +28,5 @@ export interface RefreshAstgrepIndexResult {
|
|
|
20
28
|
todo_signals: number;
|
|
21
29
|
};
|
|
22
30
|
}
|
|
23
|
-
export declare function refreshAstgrepIndex(input?: RefreshAstgrepIndexInput): RefreshAstgrepIndexResult
|
|
31
|
+
export declare function refreshAstgrepIndex(input?: RefreshAstgrepIndexInput): Promise<RefreshAstgrepIndexResult>;
|
|
24
32
|
//# sourceMappingURL=astgrep-index.d.ts.map
|
package/dist/astgrep-index.js
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
|
-
import {
|
|
4
|
+
import { appendStatusEventSafe } from "./status-events.js";
|
|
5
5
|
import { safeRead, safeWrite, WORKSPACE_ROOT, wsPath } from "./helpers.js";
|
|
6
|
+
export function runAstgrepQuery(pattern, lang, roots, _contextLines) {
|
|
7
|
+
const cmd = detectAstgrepCommand();
|
|
8
|
+
const raw = runAstgrep(cmd, pattern, lang, roots);
|
|
9
|
+
return raw.slice(0, 200).map((m) => ({
|
|
10
|
+
file: m.file ?? "",
|
|
11
|
+
line: m.range?.start?.line ?? 0,
|
|
12
|
+
column: m.range?.start?.column ?? 0,
|
|
13
|
+
text: m.text ?? "",
|
|
14
|
+
context_lines: [],
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
6
17
|
const CODE_EXTENSIONS = new Set(["ts", "tsx", "js", "mjs", "cjs", "py", "rs", "go"]);
|
|
7
18
|
const EXCLUDE_DIRS = new Set([
|
|
8
19
|
".git",
|
|
@@ -180,7 +191,7 @@ function appendEvidenceLine(timestamp, astgrepCmd, stats) {
|
|
|
180
191
|
].join("\n");
|
|
181
192
|
safeWrite("agent-state/EVIDENCE_LOG.md", `${seed}${entry}\n`);
|
|
182
193
|
}
|
|
183
|
-
export function refreshAstgrepIndex(input = {}) {
|
|
194
|
+
export async function refreshAstgrepIndex(input = {}) {
|
|
184
195
|
const generatedAt = new Date().toISOString();
|
|
185
196
|
const scope = resolveScope(input.scope);
|
|
186
197
|
const appendEvidence = input.append_evidence ?? true;
|
|
@@ -440,7 +451,7 @@ export function refreshAstgrepIndex(input = {}) {
|
|
|
440
451
|
if (emitEvent) {
|
|
441
452
|
const status = astgrepCmd ? "pass" : "blocked";
|
|
442
453
|
const eventType = astgrepCmd ? "DISCOVERY_INDEX_READY" : "DISCOVERY_SCOPE_BLOCKED";
|
|
443
|
-
const event =
|
|
454
|
+
const event = await appendStatusEventSafe({
|
|
444
455
|
source_module: "capability-astgrep",
|
|
445
456
|
event_type: eventType,
|
|
446
457
|
status,
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { ACE_TASKS_ROOT_REL, ALL_MCP_CLIENTS, ALL_LLM_PROVIDERS, DEFAULTS_ROOT, PACKAGE_ROOT, WORKSPACE_ROOT, fileExists, getAllMcpServerConfigSnippets, getMcpClientInstallHint, getMcpServerConfigSnippet, wsPath, } from "./helpers.js";
|
|
3
3
|
import { refreshAstgrepIndex } from "./astgrep-index.js";
|
|
4
4
|
import { scanWorkspaceDelta } from "./index-store.js";
|
|
5
5
|
import { startStdioServer } from "./server.js";
|
|
@@ -8,9 +8,10 @@ import { waitForPendingStatusEventMirrors } from "./status-events.js";
|
|
|
8
8
|
import { bootstrapStoreWorkspace } from "./store/bootstrap-store.js";
|
|
9
9
|
import { HostFileMaterializer } from "./store/materializers/host-file-materializer.js";
|
|
10
10
|
import { openStore } from "./store/ace-packed-store.js";
|
|
11
|
-
import { withStoreWriteQueue } from "./store/write-queue.js";
|
|
12
11
|
import { DiscoveryRepository } from "./store/repositories/discovery-repository.js";
|
|
12
|
+
import { withStoreWriteCoordinator } from "./store/write-coordinator.js";
|
|
13
13
|
import { getWorkspaceStorePath, readStoreBlobSync, readStoreJsonSync, } from "./store/store-snapshot.js";
|
|
14
|
+
import { ensureCanonicalWorkspaceStore } from "./store/workspace-store-paths.js";
|
|
14
15
|
import { readFileSync } from "node:fs";
|
|
15
16
|
import { runTui } from "./tui/index.js";
|
|
16
17
|
import { buildOpenAiCompatibleBaseUrl, buildProviderDoctorCommands, defaultModelForProvider, discoverProviderContext, isLocalLlmProvider, normalizeLocalBaseUrl, normalizeProvider, scanLocalModelRuntimes, } from "./tui/provider-discovery.js";
|
|
@@ -25,6 +26,7 @@ Usage:
|
|
|
25
26
|
ace init [options] Bootstrap the ACE store into current workspace
|
|
26
27
|
ace turnkey [options] Project minimal workspace bootstrap stubs from the ACE store
|
|
27
28
|
ace doctor [options] Validate ACE runtime + MCP readiness
|
|
29
|
+
ace cache [options] Cache ACE artifacts into ace-state.ace and optionally clean projections
|
|
28
30
|
ace mcp-config [options] Print global/client MCP config snippet(s) from store
|
|
29
31
|
ace preconfig Write .mcp-config/ bundle for all supported clients to workspace root
|
|
30
32
|
ace paths Show resolved package/workspace paths
|
|
@@ -37,7 +39,7 @@ Options for tui:
|
|
|
37
39
|
--ollama-url <url> Legacy alias for --base-url
|
|
38
40
|
|
|
39
41
|
Options for init:
|
|
40
|
-
--project <name> Project name stored in
|
|
42
|
+
--project <name> Project name stored in agent-state/ace-state.ace metadata
|
|
41
43
|
--force Overwrite scaffolded files if they already exist
|
|
42
44
|
--mcp-config Also write .vscode/mcp.json workspace bridge
|
|
43
45
|
--client-config-bundle Also write minimal workspace host stubs (AGENTS.md, CLAUDE.md, .cursorrules, .github/copilot-instructions.md)
|
|
@@ -47,18 +49,23 @@ Options for init:
|
|
|
47
49
|
--ollama-url <url> Legacy alias for --base-url
|
|
48
50
|
|
|
49
51
|
Options for doctor:
|
|
50
|
-
--llm <provider> ollama|llama.cpp|codex|claude|gemini|copilot|... (default: auto from
|
|
52
|
+
--llm <provider> ollama|llama.cpp|codex|claude|gemini|copilot|... (default: auto from agent-state/ace-state.ace)
|
|
51
53
|
--model <name> Model name override
|
|
52
54
|
--base-url <url> Runtime base URL override
|
|
53
55
|
--ollama-url <url> Legacy alias for --base-url
|
|
54
56
|
--scan Probe common local Ollama + llama.cpp endpoints when URL is unset
|
|
55
57
|
|
|
58
|
+
Options for cache:
|
|
59
|
+
--dry-run Preview what would be cached and cleaned (no writes/deletes)
|
|
60
|
+
--no-clean Keep workspace ACE artifacts after caching them into ace-state.ace
|
|
61
|
+
|
|
56
62
|
Options for mcp-config:
|
|
57
|
-
--client <name> codex|vscode|claude|cursor|antigravity
|
|
63
|
+
--client <name> codex|vscode|copilot|claude|cursor|antigravity
|
|
58
64
|
--all Print all client snippets for optional global install
|
|
59
65
|
|
|
60
66
|
preconfig writes .mcp-config/ at the workspace root with ready-to-use config files for every
|
|
61
|
-
supported MCP client
|
|
67
|
+
supported MCP client plus a root .mcp.json for GitHub Copilot CLI. Run once after ace init.
|
|
68
|
+
Each file includes the install hint for its client.
|
|
62
69
|
`);
|
|
63
70
|
}
|
|
64
71
|
function readFlagValue(args, flag) {
|
|
@@ -111,7 +118,7 @@ function parseLlmOptions(args) {
|
|
|
111
118
|
}
|
|
112
119
|
async function writeLlmProfile(profile) {
|
|
113
120
|
const storePath = getWorkspaceStorePath(WORKSPACE_ROOT);
|
|
114
|
-
await
|
|
121
|
+
await withStoreWriteCoordinator(storePath, async () => {
|
|
115
122
|
const payload = {
|
|
116
123
|
provider: profile.provider,
|
|
117
124
|
model: profile.model,
|
|
@@ -143,12 +150,12 @@ async function writeLlmProfile(profile) {
|
|
|
143
150
|
finally {
|
|
144
151
|
await store.close();
|
|
145
152
|
}
|
|
146
|
-
});
|
|
153
|
+
}, { operation_label: "writeLlmProfile" });
|
|
147
154
|
return `${storePath}#state/runtime/llm_profile`;
|
|
148
155
|
}
|
|
149
156
|
async function recordDiscoveryProfile(input) {
|
|
150
157
|
const storePath = getWorkspaceStorePath(WORKSPACE_ROOT);
|
|
151
|
-
await
|
|
158
|
+
await withStoreWriteCoordinator(storePath, async () => {
|
|
152
159
|
const store = await openStore(storePath);
|
|
153
160
|
try {
|
|
154
161
|
const discovery = new DiscoveryRepository(store);
|
|
@@ -171,7 +178,7 @@ async function recordDiscoveryProfile(input) {
|
|
|
171
178
|
finally {
|
|
172
179
|
await store.close();
|
|
173
180
|
}
|
|
174
|
-
});
|
|
181
|
+
}, { operation_label: "recordDiscoveryProfile" });
|
|
175
182
|
}
|
|
176
183
|
async function runInit(args, mode = "init") {
|
|
177
184
|
const projectName = readFlagValue(args, "--project");
|
|
@@ -192,7 +199,7 @@ async function runInit(args, mode = "init") {
|
|
|
192
199
|
model: llm.llmModel ?? undefined,
|
|
193
200
|
baseUrl: llm.llmBaseUrl ?? undefined,
|
|
194
201
|
});
|
|
195
|
-
const astIndex = refreshAstgrepIndex({
|
|
202
|
+
const astIndex = await refreshAstgrepIndex({
|
|
196
203
|
scope: ".",
|
|
197
204
|
append_evidence: true,
|
|
198
205
|
emit_event: true,
|
|
@@ -248,7 +255,7 @@ async function runInit(args, mode = "init") {
|
|
|
248
255
|
message: `ace ${mode} completed: ${storeResult.materialized.length} bootstrap files materialized`,
|
|
249
256
|
artifacts: [
|
|
250
257
|
`${ACE_TASKS_ROOT_REL}/`,
|
|
251
|
-
|
|
258
|
+
storeResult.storePath,
|
|
252
259
|
delta.index_path,
|
|
253
260
|
astIndex.output_json_path,
|
|
254
261
|
],
|
|
@@ -335,7 +342,7 @@ async function runDoctor(args) {
|
|
|
335
342
|
ok: hasProfile,
|
|
336
343
|
detail: hasProfile
|
|
337
344
|
? profilePath
|
|
338
|
-
: `Missing
|
|
345
|
+
: `Missing agent-state/ace-state.ace#state/runtime/llm_profile. Run \`ace init --llm <provider>\` or \`ace doctor --scan\` for a local runtime.`,
|
|
339
346
|
});
|
|
340
347
|
let provider = llm.llmProvider;
|
|
341
348
|
let model = llm.llmModel;
|
|
@@ -378,7 +385,7 @@ async function runDoctor(args) {
|
|
|
378
385
|
}
|
|
379
386
|
}
|
|
380
387
|
if (!provider) {
|
|
381
|
-
throw new Error(`No runtime provider configured. Use --llm <provider>, bootstrap one into
|
|
388
|
+
throw new Error(`No runtime provider configured. Use --llm <provider>, bootstrap one into agent-state/ace-state.ace#state/runtime/llm_profile, or run \`ace doctor --scan\` for a local runtime.`);
|
|
382
389
|
}
|
|
383
390
|
if (!model) {
|
|
384
391
|
model = defaultModelForProvider(provider);
|
|
@@ -515,16 +522,21 @@ function parseClientFlag(args) {
|
|
|
515
522
|
return match;
|
|
516
523
|
}
|
|
517
524
|
async function runPreconfig() {
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
|
|
525
|
+
const resolved = await ensureCanonicalWorkspaceStore(WORKSPACE_ROOT, {
|
|
526
|
+
operationLabel: "runPreconfig",
|
|
527
|
+
});
|
|
528
|
+
if (resolved.mode === "missing") {
|
|
529
|
+
console.error(`No ACE store found. Expected canonical ${resolved.canonicalPath}; legacy fallback ${resolved.legacyPath} was also not found. Run 'ace init' first.`);
|
|
521
530
|
process.exit(1);
|
|
522
531
|
}
|
|
523
|
-
const
|
|
532
|
+
for (const w of resolved.warnings) {
|
|
533
|
+
console.warn(`[preconfig] ${w}`);
|
|
534
|
+
}
|
|
535
|
+
const store = await openStore(resolved.storePath);
|
|
524
536
|
try {
|
|
525
537
|
const mat = new HostFileMaterializer(store, WORKSPACE_ROOT);
|
|
526
538
|
const written = await mat.materializeMcpBundle();
|
|
527
|
-
console.log(`ACE preconfig complete — wrote ${written.length} files to .mcp-config
|
|
539
|
+
console.log(`ACE preconfig complete — wrote ${written.length} files to .mcp-config/ and root .mcp.json\n`);
|
|
528
540
|
for (const p of written) {
|
|
529
541
|
console.log(` ${p}`);
|
|
530
542
|
}
|
|
@@ -644,7 +656,7 @@ async function main() {
|
|
|
644
656
|
}
|
|
645
657
|
if (command === "migrate") {
|
|
646
658
|
const { importFromFileWorkspace } = await import("./store/importer.js");
|
|
647
|
-
const storePath = args[1] ??
|
|
659
|
+
const storePath = args[1] ?? getWorkspaceStorePath(WORKSPACE_ROOT);
|
|
648
660
|
console.log(`Migrating file workspace at ${WORKSPACE_ROOT} to store at ${storePath}...`);
|
|
649
661
|
const result = await importFromFileWorkspace(WORKSPACE_ROOT, storePath);
|
|
650
662
|
console.log(`Migration complete:`);
|
|
@@ -680,6 +692,26 @@ async function main() {
|
|
|
680
692
|
console.log(`Store compacted: ${result.before} → ${result.after} bytes (saved ${savedKb}KB)`);
|
|
681
693
|
return;
|
|
682
694
|
}
|
|
695
|
+
if (command === "cache") {
|
|
696
|
+
const { cacheWorkspaceArtifacts } = await import("./store/cache-workspace.js");
|
|
697
|
+
const dryRun = args.includes("--dry-run");
|
|
698
|
+
const clean = !args.includes("--no-clean");
|
|
699
|
+
const result = await cacheWorkspaceArtifacts(WORKSPACE_ROOT, { dryRun, clean });
|
|
700
|
+
console.log("ACE cache complete");
|
|
701
|
+
console.log(`Workspace: ${WORKSPACE_ROOT}`);
|
|
702
|
+
console.log(`Store: ${result.storePath}`);
|
|
703
|
+
console.log(`Scanned files: ${result.scanned_files}`);
|
|
704
|
+
console.log(`Cached files: ${result.cached_files}`);
|
|
705
|
+
console.log(`Kept projected files: ${result.kept_projected_files}`);
|
|
706
|
+
console.log(`Skipped files: ${result.skipped_files}`);
|
|
707
|
+
console.log(`Removed files: ${result.removed_files}`);
|
|
708
|
+
if (result.warnings.length > 0) {
|
|
709
|
+
console.warn(`Warnings (${result.warnings.length}):`);
|
|
710
|
+
for (const warning of result.warnings)
|
|
711
|
+
console.warn(` ! ${warning}`);
|
|
712
|
+
}
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
683
715
|
if (command === "help" || command === "--help" || command === "-h") {
|
|
684
716
|
printHelp();
|
|
685
717
|
return;
|
package/dist/handoff-registry.js
CHANGED
|
@@ -4,7 +4,7 @@ import { openStore } from "./store/ace-packed-store.js";
|
|
|
4
4
|
import { ProjectionManager } from "./store/materializers/projection-manager.js";
|
|
5
5
|
import { HandoffRepository } from "./store/repositories/handoff-repository.js";
|
|
6
6
|
import { getWorkspaceStorePath, listStoreKeysSync, readStoreJsonSync, storeExistsSync, } from "./store/store-snapshot.js";
|
|
7
|
-
import {
|
|
7
|
+
import { withStoreWriteCoordinator } from "./store/write-coordinator.js";
|
|
8
8
|
import { waitForPendingStatusEventMirrors } from "./status-events.js";
|
|
9
9
|
import { waitForTodoStoreMirror } from "./todo-state.js";
|
|
10
10
|
const HANDOFF_REGISTRY_REL = "agent-state/handoff-registry.json";
|
|
@@ -299,7 +299,7 @@ export async function registerHandoffSafe(input) {
|
|
|
299
299
|
return withFileLock(HANDOFF_REGISTRY_REL, () => registerHandoff(input));
|
|
300
300
|
}
|
|
301
301
|
return withFileLock(HANDOFF_REGISTRY_REL, async () => {
|
|
302
|
-
return
|
|
302
|
+
return withStoreWriteCoordinator(storePath, async () => {
|
|
303
303
|
const store = await openStore(storePath);
|
|
304
304
|
try {
|
|
305
305
|
const repo = new HandoffRepository(store);
|
|
@@ -346,7 +346,7 @@ export async function registerHandoffSafe(input) {
|
|
|
346
346
|
finally {
|
|
347
347
|
await store.close();
|
|
348
348
|
}
|
|
349
|
-
});
|
|
349
|
+
}, { operation_label: "registerHandoffSafe" });
|
|
350
350
|
});
|
|
351
351
|
}
|
|
352
352
|
/**
|
|
@@ -361,7 +361,7 @@ export async function acknowledgeHandoffSafe(input) {
|
|
|
361
361
|
return withFileLock(HANDOFF_REGISTRY_REL, () => acknowledgeHandoff(input));
|
|
362
362
|
}
|
|
363
363
|
return withFileLock(HANDOFF_REGISTRY_REL, async () => {
|
|
364
|
-
return
|
|
364
|
+
return withStoreWriteCoordinator(storePath, async () => {
|
|
365
365
|
const store = await openStore(storePath);
|
|
366
366
|
try {
|
|
367
367
|
const repo = new HandoffRepository(store);
|
|
@@ -420,7 +420,7 @@ export async function acknowledgeHandoffSafe(input) {
|
|
|
420
420
|
finally {
|
|
421
421
|
await store.close();
|
|
422
422
|
}
|
|
423
|
-
});
|
|
423
|
+
}, { operation_label: "acknowledgeHandoffSafe" });
|
|
424
424
|
});
|
|
425
425
|
}
|
|
426
426
|
//# sourceMappingURL=handoff-registry.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type AgentRole, type KernelKey, type TaskKey } from "./constants.js";
|
|
2
|
+
export interface SkillReference {
|
|
3
|
+
name: string;
|
|
4
|
+
path: string;
|
|
5
|
+
source: "workspace" | "package-defaults" | "store";
|
|
6
|
+
}
|
|
7
|
+
export declare function getAgentInstructionPath(role: AgentRole): string | undefined;
|
|
8
|
+
export declare function getAgentManifestPath(role: AgentRole): string | undefined;
|
|
9
|
+
export declare function readAgentInstructions(role: AgentRole): string;
|
|
10
|
+
export declare function readAgentManifest(role: AgentRole): string;
|
|
11
|
+
export declare function getTaskArtifactPath(key: TaskKey): string | undefined;
|
|
12
|
+
export declare function readTaskArtifact(key: TaskKey): string;
|
|
13
|
+
export declare function getKernelArtifactPath(key: KernelKey): string | undefined;
|
|
14
|
+
export declare function readKernelArtifact(key: KernelKey): string;
|
|
15
|
+
export declare function resolveWritableTaskPath(key: TaskKey): string;
|
|
16
|
+
export declare function listAvailableSkills(): SkillReference[];
|
|
17
|
+
export declare function getSkillPath(name: string): string | undefined;
|
|
18
|
+
export declare function readSkillInstructions(name: string): string;
|
|
19
|
+
//# sourceMappingURL=artifacts.d.ts.map
|