@voybio/ace-swarm 0.2.5 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -1
- package/README.md +21 -13
- package/assets/.agents/ACE/agent-qa/instructions.md +11 -0
- package/assets/agent-state/EVIDENCE_LOG.md +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/RUNTIME_TOOL_SPEC_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/agent-state/runtime-tool-specs.json +70 -2
- package/assets/instructions/ACE_Coder.instructions.md +13 -0
- package/assets/instructions/ACE_UI.instructions.md +11 -0
- package/assets/scripts/ace-hook-dispatch.mjs +70 -6
- package/assets/scripts/render-mcp-configs.sh +19 -5
- package/dist/ace-context.js +91 -11
- package/dist/ace-internal-tools.d.ts +3 -1
- package/dist/ace-internal-tools.js +10 -2
- package/dist/ace-server-instructions.js +3 -3
- package/dist/ace-state-resolver.js +5 -3
- package/dist/agent-runtime/role-adapters.d.ts +18 -1
- package/dist/agent-runtime/role-adapters.js +49 -5
- package/dist/astgrep-index.d.ts +57 -1
- package/dist/astgrep-index.js +140 -4
- package/dist/cli.js +232 -35
- package/dist/discovery-runtime-wrappers.d.ts +108 -0
- package/dist/discovery-runtime-wrappers.js +615 -0
- 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 +295 -0
- package/dist/helpers/drift.d.ts +13 -0
- package/dist/helpers/drift.js +45 -0
- package/dist/helpers/path-utils.d.ts +24 -0
- package/dist/helpers/path-utils.js +123 -0
- package/dist/helpers/store-resolution.d.ts +19 -0
- package/dist/helpers/store-resolution.js +305 -0
- package/dist/helpers/workspace-root.d.ts +3 -0
- package/dist/helpers/workspace-root.js +80 -0
- package/dist/helpers.d.ts +8 -125
- package/dist/helpers.js +8 -1768
- package/dist/job-scheduler.js +33 -7
- package/dist/json-sanitizer.d.ts +16 -0
- package/dist/json-sanitizer.js +26 -0
- package/dist/local-model-policy.d.ts +27 -0
- package/dist/local-model-policy.js +84 -0
- package/dist/local-model-runtime.d.ts +6 -0
- package/dist/local-model-runtime.js +33 -21
- package/dist/model-bridge.d.ts +13 -1
- package/dist/model-bridge.js +410 -23
- package/dist/orchestrator-supervisor.d.ts +56 -0
- package/dist/orchestrator-supervisor.js +179 -1
- package/dist/plan-proposal.d.ts +115 -0
- package/dist/plan-proposal.js +1073 -0
- 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 +20 -1
- package/dist/runtime-executor.js +737 -172
- package/dist/runtime-profile.d.ts +32 -0
- package/dist/runtime-profile.js +89 -13
- package/dist/runtime-tool-specs.d.ts +39 -0
- package/dist/runtime-tool-specs.js +144 -28
- package/dist/safe-edit.d.ts +7 -0
- package/dist/safe-edit.js +163 -37
- package/dist/schemas.js +48 -1
- package/dist/server.js +51 -0
- package/dist/shared.d.ts +3 -2
- package/dist/shared.js +2 -0
- 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 +2 -1
- package/dist/store/bootstrap-store.js +102 -83
- package/dist/store/cache-workspace.js +11 -5
- package/dist/store/materializers/context-snapshot-materializer.js +6 -2
- 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/repositories/vericify-repository.d.ts +1 -1
- 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.d.ts +20 -0
- package/dist/tools-agent.js +789 -25
- package/dist/tools-discovery.js +136 -1
- package/dist/tools-files.d.ts +7 -0
- package/dist/tools-files.js +1002 -11
- package/dist/tools-framework.js +105 -66
- 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/index.js +10 -1
- 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/tui/ollama.d.ts +8 -1
- package/dist/tui/ollama.js +53 -12
- package/dist/tui/openai-compatible.d.ts +13 -0
- package/dist/tui/openai-compatible.js +305 -5
- package/dist/tui/provider-discovery.d.ts +1 -0
- package/dist/tui/provider-discovery.js +35 -11
- package/dist/vericify-bridge.d.ts +6 -1
- 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
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Replaces the old copyTree()-based bootstrap with:
|
|
7
7
|
* 1. Create minimal directories
|
|
8
|
-
* 2. Initialize AcePackedStore at
|
|
8
|
+
* 2. Initialize AcePackedStore at agent-state/ace-state.ace
|
|
9
9
|
* 3. Bake core knowledge (agents, modules, kernel)
|
|
10
10
|
* 4. Write topology records
|
|
11
11
|
* 5. Write initial runtime state seeds
|
|
@@ -26,6 +26,8 @@ import { HostFileMaterializer } from "./materializers/host-file-materializer.js"
|
|
|
26
26
|
import { ProjectionManager } from "./materializers/projection-manager.js";
|
|
27
27
|
import { TodoSyncer } from "./materializers/todo-syncer.js";
|
|
28
28
|
import { OPERATIONAL_ARTIFACT_REL_PATHS, operationalArtifactKey, } from "./store-artifacts.js";
|
|
29
|
+
import { ensureCanonicalWorkspaceStore } from "./workspace-store-paths.js";
|
|
30
|
+
import { withStoreWriteCoordinator } from "./write-coordinator.js";
|
|
29
31
|
import { STORE_VERSION } from "./types.js";
|
|
30
32
|
import { buildProviderDoctorCommands, defaultModelForProvider, normalizeLocalBaseUrl, normalizeProvider, } from "../tui/provider-discovery.js";
|
|
31
33
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -41,13 +43,19 @@ async function applyLlmRuntimeConfig(store, opts) {
|
|
|
41
43
|
if (!opts.llm)
|
|
42
44
|
return;
|
|
43
45
|
const provider = normalizeProvider(opts.llm) ?? opts.llm;
|
|
44
|
-
const configuredModel = opts.model
|
|
46
|
+
const configuredModel = opts.model?.trim() ||
|
|
47
|
+
(provider === "ollama" ? defaultModelForProvider(provider) : undefined);
|
|
45
48
|
const configuredBaseUrl = normalizeLocalBaseUrl(opts.baseUrl ?? opts.ollamaUrl);
|
|
46
49
|
const profilePayload = {
|
|
47
50
|
provider,
|
|
48
|
-
model: configuredModel,
|
|
49
51
|
generated_at: new Date().toISOString(),
|
|
50
52
|
};
|
|
53
|
+
if (configuredModel) {
|
|
54
|
+
profilePayload.model = configuredModel;
|
|
55
|
+
}
|
|
56
|
+
if (opts.launcherCommand) {
|
|
57
|
+
profilePayload.launch_command = opts.launcherCommand;
|
|
58
|
+
}
|
|
51
59
|
if (configuredBaseUrl) {
|
|
52
60
|
profilePayload.base_url = configuredBaseUrl;
|
|
53
61
|
if (provider === "ollama") {
|
|
@@ -91,12 +99,7 @@ async function materializeStoreSurfaces(store, workspaceRoot, opts) {
|
|
|
91
99
|
await store.commit();
|
|
92
100
|
const projections = new ProjectionManager(store, workspaceRoot);
|
|
93
101
|
await projections.projectAfterCommit(["hook_context", "todo_state", "scheduler", "context_snapshots"]);
|
|
94
|
-
materialized.push(join(workspaceRoot, ".agents", "ACE", "ace-hook-context.json"));
|
|
95
102
|
materialized.push(join(workspaceRoot, ".agents", "ACE", "tasks", "todo.md"));
|
|
96
|
-
materialized.push(join(workspaceRoot, ".agents", "ACE", "agent-state", "job-queue.json"));
|
|
97
|
-
materialized.push(join(workspaceRoot, ".agents", "ACE", "agent-state", "job-locks.json"));
|
|
98
|
-
materialized.push(join(workspaceRoot, ".agents", "ACE", "agent-state", "scheduler-lease.json"));
|
|
99
|
-
materialized.push(join(workspaceRoot, ".agents", "ACE", "agent-state", "context-snapshots", "index.json"));
|
|
100
103
|
return [...new Set(materialized)];
|
|
101
104
|
}
|
|
102
105
|
// Artifacts that receive live timestamp substitution on first seed.
|
|
@@ -116,88 +119,101 @@ async function seedOperationalArtifacts(store) {
|
|
|
116
119
|
}
|
|
117
120
|
export async function bootstrapStoreWorkspace(opts) {
|
|
118
121
|
const { workspaceRoot, force = false } = opts;
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
const resolved = await ensureCanonicalWorkspaceStore(workspaceRoot, {
|
|
123
|
+
operationLabel: "bootstrapStoreWorkspace",
|
|
124
|
+
});
|
|
125
|
+
const storePath = resolved.storePath;
|
|
126
|
+
return withStoreWriteCoordinator(storePath, async () => {
|
|
127
|
+
const warnings = [...resolved.warnings];
|
|
128
|
+
const materialized = [];
|
|
129
|
+
if (resolved.mode === "dual_store_conflict" && !force) {
|
|
130
|
+
warnings.push("Both canonical and legacy stores exist and differ. Resolve with 'ace repair' before reinitializing.");
|
|
125
131
|
return { storePath, agents: 0, modules: { gates: 0, roles: 0, schemas: 0 }, materialized, warnings };
|
|
126
132
|
}
|
|
127
|
-
|
|
133
|
+
if (existsSync(storePath) && !force) {
|
|
134
|
+
if (!(opts.includeMcpConfig ?? false) && !(opts.includeClientConfigBundle ?? false) && !opts.llm) {
|
|
135
|
+
warnings.push(`Store already exists at ${storePath}. Use --force to reinitialize, or run 'ace migrate' to import existing state.`);
|
|
136
|
+
return { storePath, agents: 0, modules: { gates: 0, roles: 0, schemas: 0 }, materialized, warnings };
|
|
137
|
+
}
|
|
138
|
+
const existingStore = await openStore(storePath);
|
|
139
|
+
try {
|
|
140
|
+
await seedOperationalArtifacts(existingStore);
|
|
141
|
+
materialized.push(...(await materializeStoreSurfaces(existingStore, workspaceRoot, opts)));
|
|
142
|
+
const agents = (await existingStore.listAgents()).length;
|
|
143
|
+
warnings.push(`Reused existing store at ${storePath} and refreshed host materializations.`);
|
|
144
|
+
return { storePath, agents, modules: { gates: 0, roles: 0, schemas: 0 }, materialized, warnings };
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
await existingStore.close();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
for (const dir of [
|
|
151
|
+
join(workspaceRoot, "agent-state"),
|
|
152
|
+
join(workspaceRoot, ".agents", "ACE"),
|
|
153
|
+
join(workspaceRoot, ".agents", "ACE", "tasks"),
|
|
154
|
+
]) {
|
|
155
|
+
mkdirSync(dir, { recursive: true });
|
|
156
|
+
}
|
|
157
|
+
const store = await openStore(storePath);
|
|
128
158
|
try {
|
|
129
|
-
await
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
159
|
+
await store.setJSON("meta/schema_version", STORE_VERSION);
|
|
160
|
+
await store.setJSON("meta/created_at", Date.now());
|
|
161
|
+
await store.setJSON("meta/project_name", opts.projectName ?? "ACE Workspace");
|
|
162
|
+
await store.setJSON("meta/host_materialization", {
|
|
163
|
+
include_mcp_config: opts.includeMcpConfig ?? false,
|
|
164
|
+
include_client_config_bundle: opts.includeClientConfigBundle ?? false,
|
|
165
|
+
});
|
|
166
|
+
const assetsRoot = getAssetsRoot();
|
|
167
|
+
const knowledge = await bakeAllCoreKnowledge(store, assetsRoot);
|
|
168
|
+
await bakeTopology(store, assetsRoot);
|
|
169
|
+
await store.setJSON("state/handoffs/__index", []);
|
|
170
|
+
await store.setJSON("state/todo/index", []);
|
|
171
|
+
await store.setJSON("state/ledger/seq", 0);
|
|
172
|
+
await store.setJSON("state/scheduler/queue", []);
|
|
173
|
+
await store.setJSON("state/scheduler/locks", []);
|
|
174
|
+
await store.setJSON("state/scheduler/lease", null);
|
|
175
|
+
await store.setJSON("state/memory/context_snapshots/index.json", { snapshots: [] });
|
|
176
|
+
await store.setJSON("state/runtime/sessions/index", []);
|
|
177
|
+
await store.setJSON("state/discovery/index", []);
|
|
178
|
+
await store.setJSON("state/vericify/posts/index", []);
|
|
179
|
+
await applyLlmRuntimeConfig(store, opts);
|
|
180
|
+
await seedOperationalArtifacts(store);
|
|
181
|
+
await buildCatalog(store);
|
|
182
|
+
await store.commit();
|
|
183
|
+
await store.compact();
|
|
184
|
+
materialized.push(...(await materializeStoreSurfaces(store, workspaceRoot, opts)));
|
|
185
|
+
const agents = (await store.listAgents()).length;
|
|
186
|
+
return {
|
|
187
|
+
storePath,
|
|
188
|
+
agents,
|
|
189
|
+
modules: knowledge.modules,
|
|
190
|
+
materialized,
|
|
191
|
+
warnings,
|
|
192
|
+
};
|
|
134
193
|
}
|
|
135
194
|
finally {
|
|
136
|
-
await
|
|
195
|
+
await store.close();
|
|
137
196
|
}
|
|
138
|
-
}
|
|
139
|
-
// 1. Create minimal directories under .agents/ACE/ (canonical ACE namespace)
|
|
140
|
-
for (const dir of [
|
|
141
|
-
join(workspaceRoot, ".agents", "ACE"),
|
|
142
|
-
join(workspaceRoot, ".agents", "ACE", "tasks"),
|
|
143
|
-
]) {
|
|
144
|
-
mkdirSync(dir, { recursive: true });
|
|
145
|
-
}
|
|
146
|
-
// 2. Initialize store
|
|
147
|
-
const store = await openStore(storePath);
|
|
148
|
-
try {
|
|
149
|
-
// 3. Write meta
|
|
150
|
-
await store.setJSON("meta/schema_version", STORE_VERSION);
|
|
151
|
-
await store.setJSON("meta/created_at", Date.now());
|
|
152
|
-
await store.setJSON("meta/project_name", opts.projectName ?? "ACE Workspace");
|
|
153
|
-
await store.setJSON("meta/host_materialization", {
|
|
154
|
-
include_mcp_config: opts.includeMcpConfig ?? false,
|
|
155
|
-
include_client_config_bundle: opts.includeClientConfigBundle ?? false,
|
|
156
|
-
});
|
|
157
|
-
// 4. Bake core knowledge
|
|
158
|
-
const assetsRoot = getAssetsRoot();
|
|
159
|
-
const knowledge = await bakeAllCoreKnowledge(store, assetsRoot);
|
|
160
|
-
// 5. Write topology
|
|
161
|
-
await bakeTopology(store, assetsRoot);
|
|
162
|
-
// 6. Write initial empty runtime seeds
|
|
163
|
-
await store.setJSON("state/handoffs/__index", []);
|
|
164
|
-
await store.setJSON("state/todo/index", []);
|
|
165
|
-
await store.setJSON("state/ledger/seq", 0);
|
|
166
|
-
await store.setJSON("state/scheduler/queue", []);
|
|
167
|
-
await store.setJSON("state/scheduler/locks", []);
|
|
168
|
-
await store.setJSON("state/scheduler/lease", null);
|
|
169
|
-
await store.setJSON("state/memory/context_snapshots/index.json", { snapshots: [] });
|
|
170
|
-
await store.setJSON("state/runtime/sessions/index", []);
|
|
171
|
-
await store.setJSON("state/discovery/index", []);
|
|
172
|
-
await store.setJSON("state/vericify/posts/index", []);
|
|
173
|
-
await applyLlmRuntimeConfig(store, opts);
|
|
174
|
-
await seedOperationalArtifacts(store);
|
|
175
|
-
// 7. Build catalog
|
|
176
|
-
await buildCatalog(store);
|
|
177
|
-
// 8. Commit + compact
|
|
178
|
-
await store.commit();
|
|
179
|
-
await store.compact();
|
|
180
|
-
materialized.push(...(await materializeStoreSurfaces(store, workspaceRoot, opts)));
|
|
181
|
-
const agents = (await store.listAgents()).length;
|
|
182
|
-
return {
|
|
183
|
-
storePath,
|
|
184
|
-
agents,
|
|
185
|
-
modules: knowledge.modules,
|
|
186
|
-
materialized,
|
|
187
|
-
warnings,
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
finally {
|
|
191
|
-
await store.close();
|
|
192
|
-
}
|
|
197
|
+
}, { operation_label: "bootstrapStoreWorkspace" });
|
|
193
198
|
}
|
|
194
199
|
// ── ace repair ────────────────────────────────────────────────────────────────
|
|
195
200
|
export async function repairWorkspace(workspaceRoot) {
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
201
|
+
const resolved = await ensureCanonicalWorkspaceStore(workspaceRoot, {
|
|
202
|
+
operationLabel: "repairWorkspace",
|
|
203
|
+
});
|
|
204
|
+
if (resolved.mode === "missing") {
|
|
205
|
+
return [
|
|
206
|
+
`No store found at ${resolved.canonicalPath} or ${resolved.legacyPath}. Run 'ace init' first.`,
|
|
207
|
+
];
|
|
199
208
|
}
|
|
200
|
-
|
|
209
|
+
if (resolved.mode === "dual_store_conflict") {
|
|
210
|
+
return [
|
|
211
|
+
...resolved.warnings,
|
|
212
|
+
"Resolve dual ACE stores before repair can safely materialize host files.",
|
|
213
|
+
];
|
|
214
|
+
}
|
|
215
|
+
const { storePath } = resolved;
|
|
216
|
+
const warnings = [...resolved.warnings];
|
|
201
217
|
const store = await openStore(storePath);
|
|
202
218
|
try {
|
|
203
219
|
const hostPolicy = (await store.getJSON("meta/host_materialization")) ?? {};
|
|
@@ -221,10 +237,13 @@ export async function repairWorkspace(workspaceRoot) {
|
|
|
221
237
|
}
|
|
222
238
|
// ── ace compact ───────────────────────────────────────────────────────────────
|
|
223
239
|
export async function compactWorkspace(workspaceRoot) {
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
240
|
+
const resolved = await ensureCanonicalWorkspaceStore(workspaceRoot, {
|
|
241
|
+
operationLabel: "compactWorkspace",
|
|
242
|
+
});
|
|
243
|
+
if (resolved.mode === "missing") {
|
|
244
|
+
throw new Error(`No store found at ${resolved.canonicalPath} or ${resolved.legacyPath}. Run 'ace init' first.`);
|
|
227
245
|
}
|
|
246
|
+
const { storePath } = resolved;
|
|
228
247
|
const { statSync } = await import("fs");
|
|
229
248
|
const before = statSync(storePath).size;
|
|
230
249
|
const store = await openStore(storePath);
|
|
@@ -2,7 +2,8 @@ import { existsSync, readdirSync, readFileSync, rmSync } from "node:fs";
|
|
|
2
2
|
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
3
3
|
import { ACE_ROOT_REL, isProjectedAceWorkspacePath, mapAceWorkspaceRelativePath, resolveStoreFallbackKeysForPath, } from "../helpers.js";
|
|
4
4
|
import { normalizeRelPath } from "../shared.js";
|
|
5
|
-
import {
|
|
5
|
+
import { getWorkspaceStorePath } from "./store-snapshot.js";
|
|
6
|
+
import { writeStoreBlobsQueued } from "./store-artifacts.js";
|
|
6
7
|
const SCAN_ROOTS_REL = [
|
|
7
8
|
"agent-state",
|
|
8
9
|
".agents/ACE/agent-state",
|
|
@@ -48,10 +49,15 @@ function isTextBuffer(input) {
|
|
|
48
49
|
function selectScanRoots(workspaceRoot) {
|
|
49
50
|
return SCAN_ROOTS_REL.map((relPath) => join(workspaceRoot, relPath)).filter((abs) => existsSync(abs));
|
|
50
51
|
}
|
|
52
|
+
function isCacheableAcePath(path) {
|
|
53
|
+
return path === "agent-state"
|
|
54
|
+
|| path.startsWith("agent-state/")
|
|
55
|
+
|| path.startsWith(`${ACE_ROOT_REL}/`);
|
|
56
|
+
}
|
|
51
57
|
export async function cacheWorkspaceArtifacts(workspaceRoot, options = {}) {
|
|
52
58
|
const dryRun = options.dryRun ?? false;
|
|
53
59
|
const clean = options.clean ?? true;
|
|
54
|
-
const storePath =
|
|
60
|
+
const storePath = getWorkspaceStorePath(workspaceRoot);
|
|
55
61
|
if (!existsSync(storePath)) {
|
|
56
62
|
throw new Error(`No store found at ${storePath}. Run 'ace init' first.`);
|
|
57
63
|
}
|
|
@@ -66,7 +72,7 @@ export async function cacheWorkspaceArtifacts(workspaceRoot, options = {}) {
|
|
|
66
72
|
scanned += 1;
|
|
67
73
|
const relPath = normalizeRelPath(relative(workspaceRoot, absPath));
|
|
68
74
|
const canonicalPath = mapAceWorkspaceRelativePath(relPath);
|
|
69
|
-
if (!canonicalPath
|
|
75
|
+
if (!isCacheableAcePath(canonicalPath)) {
|
|
70
76
|
skipped += 1;
|
|
71
77
|
continue;
|
|
72
78
|
}
|
|
@@ -105,10 +111,10 @@ export async function cacheWorkspaceArtifacts(workspaceRoot, options = {}) {
|
|
|
105
111
|
}
|
|
106
112
|
const uniqueForWrite = [...dedupByKey.values()];
|
|
107
113
|
if (!dryRun && uniqueForWrite.length > 0) {
|
|
108
|
-
|
|
114
|
+
await writeStoreBlobsQueued(workspaceRoot, uniqueForWrite.map((candidate) => ({
|
|
109
115
|
key: candidate.key,
|
|
110
116
|
content: candidate.content,
|
|
111
|
-
})));
|
|
117
|
+
})), { operation_label: "cacheWorkspace" });
|
|
112
118
|
}
|
|
113
119
|
let removed = 0;
|
|
114
120
|
if (!dryRun && clean && candidates.length > 0) {
|
|
@@ -19,13 +19,14 @@ export class ContextSnapshotMaterializer {
|
|
|
19
19
|
this.repo = new ContextSnapshotRepository(store);
|
|
20
20
|
}
|
|
21
21
|
directoryPath() {
|
|
22
|
-
return join(this.workspaceRoot, "
|
|
22
|
+
return join(this.workspaceRoot, "agent-state", "context-snapshots");
|
|
23
23
|
}
|
|
24
24
|
async materializeAll() {
|
|
25
25
|
const dir = this.directoryPath();
|
|
26
26
|
if (!existsSync(dir))
|
|
27
27
|
mkdirSync(dir, { recursive: true });
|
|
28
28
|
const snapshots = await this.repo.listSnapshots();
|
|
29
|
+
const expectedFiles = new Set(["index.json", ...snapshots.map(({ file }) => file)]);
|
|
29
30
|
writeText(join(dir, "index.json"), `${JSON.stringify({
|
|
30
31
|
snapshots: snapshots.map(({ name, file, timestamp, summary }) => ({
|
|
31
32
|
name,
|
|
@@ -34,10 +35,13 @@ export class ContextSnapshotMaterializer {
|
|
|
34
35
|
summary,
|
|
35
36
|
})),
|
|
36
37
|
}, null, 2)}\n`);
|
|
38
|
+
for (const { file, record } of snapshots) {
|
|
39
|
+
writeText(join(dir, file), `${JSON.stringify(record, null, 2)}\n`);
|
|
40
|
+
}
|
|
37
41
|
for (const file of readdirSync(dir)) {
|
|
38
42
|
if (!file.endsWith(".json"))
|
|
39
43
|
continue;
|
|
40
|
-
if (file
|
|
44
|
+
if (expectedFiles.has(file))
|
|
41
45
|
continue;
|
|
42
46
|
rmSync(join(dir, file), { force: true });
|
|
43
47
|
}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HookContextMaterializer
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* The hook dispatcher (ace-hook-dispatch.mjs) reads ONLY this file.
|
|
8
|
-
* It never touches the .ace store directly.
|
|
4
|
+
* Stages the compact hook snapshot into ace-state.ace so hook clients can
|
|
5
|
+
* read a single runtime payload without extra workspace projections.
|
|
9
6
|
*/
|
|
10
7
|
import { AcePackedStore } from "../ace-packed-store.js";
|
|
11
8
|
export declare class HookContextMaterializer {
|
|
12
9
|
private store;
|
|
13
|
-
|
|
10
|
+
static readonly STORE_KEY = "state/runtime/hook_context";
|
|
14
11
|
private kv;
|
|
15
|
-
constructor(store: AcePackedStore
|
|
16
|
-
private
|
|
17
|
-
|
|
12
|
+
constructor(store: AcePackedStore);
|
|
13
|
+
private buildSnapshot;
|
|
14
|
+
stageStoreProjection(): Promise<void>;
|
|
18
15
|
private _readContent;
|
|
19
16
|
private _readKernelWorkflow;
|
|
20
17
|
private _getEnabledAgents;
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HookContextMaterializer
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* The hook dispatcher (ace-hook-dispatch.mjs) reads ONLY this file.
|
|
8
|
-
* It never touches the .ace store directly.
|
|
4
|
+
* Stages the compact hook snapshot into ace-state.ace so hook clients can
|
|
5
|
+
* read a single runtime payload without extra workspace projections.
|
|
9
6
|
*/
|
|
10
|
-
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
11
|
-
import { join, dirname } from "path";
|
|
12
7
|
import { RuntimeKVRepository } from "../repositories/runtime-kv-repository.js";
|
|
13
8
|
function fnv1a(s) {
|
|
14
9
|
let h = 2166136261;
|
|
@@ -20,17 +15,13 @@ function fnv1a(s) {
|
|
|
20
15
|
}
|
|
21
16
|
export class HookContextMaterializer {
|
|
22
17
|
store;
|
|
23
|
-
|
|
18
|
+
static STORE_KEY = "state/runtime/hook_context";
|
|
24
19
|
kv;
|
|
25
|
-
constructor(store
|
|
20
|
+
constructor(store) {
|
|
26
21
|
this.store = store;
|
|
27
|
-
this.workspaceRoot = workspaceRoot;
|
|
28
22
|
this.kv = new RuntimeKVRepository(store);
|
|
29
23
|
}
|
|
30
|
-
|
|
31
|
-
return join(this.workspaceRoot, ".agents", "ACE", "ace-hook-context.json");
|
|
32
|
-
}
|
|
33
|
-
async materialize() {
|
|
24
|
+
async buildSnapshot() {
|
|
34
25
|
const task = await this._readContent("task");
|
|
35
26
|
const status = await this._readContent("status");
|
|
36
27
|
const scope = await this._readContent("scope");
|
|
@@ -38,7 +29,7 @@ export class HookContextMaterializer {
|
|
|
38
29
|
const workflow = await this._readKernelWorkflow();
|
|
39
30
|
const enabledAgents = await this._getEnabledAgents();
|
|
40
31
|
const gatedTools = await this._buildGateMap();
|
|
41
|
-
|
|
32
|
+
return {
|
|
42
33
|
schema_version: 1,
|
|
43
34
|
generated_at: new Date().toISOString(),
|
|
44
35
|
task: { content: task, hash: fnv1a(task) },
|
|
@@ -49,11 +40,9 @@ export class HookContextMaterializer {
|
|
|
49
40
|
active_agents: enabledAgents,
|
|
50
41
|
gated_tools: gatedTools,
|
|
51
42
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
mkdirSync(dir, { recursive: true });
|
|
56
|
-
writeFileSync(contextPath, JSON.stringify(snapshot, null, 2), "utf8");
|
|
43
|
+
}
|
|
44
|
+
async stageStoreProjection() {
|
|
45
|
+
await this.store.setJSON(HookContextMaterializer.STORE_KEY, await this.buildSnapshot());
|
|
57
46
|
}
|
|
58
47
|
async _readContent(kind) {
|
|
59
48
|
// Try KV first (runtime overrides), then store blobs, then empty
|
|
@@ -94,7 +83,8 @@ export class HookContextMaterializer {
|
|
|
94
83
|
/** Update a runtime content field (task, status, scope, etc.) */
|
|
95
84
|
async setContent(kind, content) {
|
|
96
85
|
await this.kv.setString(`context/${kind}`, content);
|
|
97
|
-
await this.
|
|
86
|
+
await this.stageStoreProjection();
|
|
87
|
+
await this.store.commit();
|
|
98
88
|
}
|
|
99
89
|
}
|
|
100
90
|
//# sourceMappingURL=hook-context-materializer.js.map
|
|
@@ -198,6 +198,7 @@ export class HostFileMaterializer {
|
|
|
198
198
|
const fileNames = {
|
|
199
199
|
codex: "codex.config.toml",
|
|
200
200
|
vscode: "vscode.mcp.json",
|
|
201
|
+
copilot: ".mcp.json",
|
|
201
202
|
claude: "claude_desktop_config.json",
|
|
202
203
|
cursor: "cursor.mcp.json",
|
|
203
204
|
antigravity: "antigravity.mcp.json",
|
|
@@ -272,6 +273,11 @@ export class HostFileMaterializer {
|
|
|
272
273
|
}
|
|
273
274
|
if (includeMcpConfig) {
|
|
274
275
|
paths.push(await this.materializeEntry(this.buildVsCodeMcpEntry()));
|
|
276
|
+
paths.push(await this.materializeEntry({
|
|
277
|
+
absPath: this.root(".mcp.json"),
|
|
278
|
+
keyParts: [".mcp.json"],
|
|
279
|
+
fallbackContent: getMcpServerConfigSnippet("copilot"),
|
|
280
|
+
}));
|
|
275
281
|
}
|
|
276
282
|
if (includeClientConfigBundle) {
|
|
277
283
|
for (const entry of this.buildInstructionShimEntries()) {
|
|
@@ -6,7 +6,6 @@ export declare class ProjectionManager {
|
|
|
6
6
|
private vericify;
|
|
7
7
|
private todoSyncer;
|
|
8
8
|
private hookContext;
|
|
9
|
-
private contextSnapshots;
|
|
10
9
|
private scheduler;
|
|
11
10
|
constructor(store: AcePackedStore, workspaceRoot: string);
|
|
12
11
|
projectAfterCommit(targets: readonly RuntimeProjectionTarget[]): Promise<void>;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ContextSnapshotMaterializer } from "./context-snapshot-materializer.js";
|
|
2
1
|
import { HookContextMaterializer } from "./hook-context-materializer.js";
|
|
3
2
|
import { SchedulerProjectionMaterializer } from "./scheduler-projection-materializer.js";
|
|
4
3
|
import { TodoSyncer } from "./todo-syncer.js";
|
|
@@ -9,15 +8,13 @@ export class ProjectionManager {
|
|
|
9
8
|
vericify;
|
|
10
9
|
todoSyncer;
|
|
11
10
|
hookContext;
|
|
12
|
-
contextSnapshots;
|
|
13
11
|
scheduler;
|
|
14
12
|
constructor(store, workspaceRoot) {
|
|
15
13
|
this.store = store;
|
|
16
14
|
this.workspaceRoot = workspaceRoot;
|
|
17
15
|
this.vericify = new VericifyProjector(store, workspaceRoot);
|
|
18
16
|
this.todoSyncer = new TodoSyncer(store, workspaceRoot);
|
|
19
|
-
this.hookContext = new HookContextMaterializer(store
|
|
20
|
-
this.contextSnapshots = new ContextSnapshotMaterializer(store, workspaceRoot);
|
|
17
|
+
this.hookContext = new HookContextMaterializer(store);
|
|
21
18
|
this.scheduler = new SchedulerProjectionMaterializer(store, workspaceRoot);
|
|
22
19
|
}
|
|
23
20
|
async projectAfterCommit(targets) {
|
|
@@ -45,6 +42,10 @@ export class ProjectionManager {
|
|
|
45
42
|
await this.vericify.projectVericifyPosts();
|
|
46
43
|
stagedStoreWrites = true;
|
|
47
44
|
}
|
|
45
|
+
else if (target === "hook_context") {
|
|
46
|
+
await this.hookContext.stageStoreProjection();
|
|
47
|
+
stagedStoreWrites = true;
|
|
48
|
+
}
|
|
48
49
|
else if (target === "scheduler") {
|
|
49
50
|
renderedScheduler = await this.scheduler.render();
|
|
50
51
|
await this.scheduler.stageStoreProjections(renderedScheduler);
|
|
@@ -58,15 +59,6 @@ export class ProjectionManager {
|
|
|
58
59
|
if (target === "todo_state") {
|
|
59
60
|
await this.todoSyncer.writeToFile();
|
|
60
61
|
}
|
|
61
|
-
else if (target === "hook_context") {
|
|
62
|
-
await this.hookContext.materialize();
|
|
63
|
-
}
|
|
64
|
-
else if (target === "context_snapshots") {
|
|
65
|
-
await this.contextSnapshots.materializeAll();
|
|
66
|
-
}
|
|
67
|
-
else if (target === "scheduler") {
|
|
68
|
-
await this.scheduler.materializeFiles(renderedScheduler);
|
|
69
|
-
}
|
|
70
62
|
}
|
|
71
63
|
}
|
|
72
64
|
}
|
|
@@ -20,7 +20,7 @@ export class SchedulerProjectionMaterializer {
|
|
|
20
20
|
this.repo = new SchedulerRepository(store);
|
|
21
21
|
}
|
|
22
22
|
filePath(file) {
|
|
23
|
-
return join(this.workspaceRoot, "
|
|
23
|
+
return join(this.workspaceRoot, "agent-state", file);
|
|
24
24
|
}
|
|
25
25
|
async render() {
|
|
26
26
|
const queue = await this.repo.readQueue();
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
* Writes 5 Vericify-facing files from store state on every relevant mutation.
|
|
5
5
|
* These are MIRRORS only — the store is source of truth.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Runtime-facing state projections now live under top-level agent-state/.
|
|
8
|
+
* Host/task scaffolding remains under .agents/ACE/ where required.
|
|
9
9
|
*
|
|
10
10
|
* Files projected:
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* agent-state/handoff-registry.json
|
|
12
|
+
* agent-state/todo-state.json ← schema: { version, updated_at, order[], nodes{} }
|
|
13
|
+
* agent-state/run-ledger.json ← schema: { version, updated_at, entries[] }
|
|
14
|
+
* agent-state/STATUS_EVENTS.ndjson ← schema: StatusEventRecord per line
|
|
15
|
+
* agent-state/vericify/process-posts.json
|
|
16
16
|
*/
|
|
17
17
|
import { AcePackedStore } from "../ace-packed-store.js";
|
|
18
18
|
export declare class VericifyProjector {
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
* Writes 5 Vericify-facing files from store state on every relevant mutation.
|
|
5
5
|
* These are MIRRORS only — the store is source of truth.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Runtime-facing state projections now live under top-level agent-state/.
|
|
8
|
+
* Host/task scaffolding remains under .agents/ACE/ where required.
|
|
9
9
|
*
|
|
10
10
|
* Files projected:
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* agent-state/handoff-registry.json
|
|
12
|
+
* agent-state/todo-state.json ← schema: { version, updated_at, order[], nodes{} }
|
|
13
|
+
* agent-state/run-ledger.json ← schema: { version, updated_at, entries[] }
|
|
14
|
+
* agent-state/STATUS_EVENTS.ndjson ← schema: StatusEventRecord per line
|
|
15
|
+
* agent-state/vericify/process-posts.json
|
|
16
16
|
*/
|
|
17
17
|
import { createHash, randomUUID } from "crypto";
|
|
18
18
|
import { HandoffRepository } from "../repositories/handoff-repository.js";
|
|
@@ -21,9 +21,9 @@ import { LedgerRepository } from "../repositories/ledger-repository.js";
|
|
|
21
21
|
import { TrackerRepository } from "../repositories/tracker-repository.js";
|
|
22
22
|
import { VericifyRepository } from "../repositories/vericify-repository.js";
|
|
23
23
|
import { operationalArtifactKey } from "../store-artifacts.js";
|
|
24
|
-
//
|
|
25
|
-
const
|
|
26
|
-
const
|
|
24
|
+
// Runtime-facing state now lives in top-level agent-state/.
|
|
25
|
+
const ACE_STATE_ROOT = "agent-state";
|
|
26
|
+
const ACE_TASKS_ROOT = ".agents/ACE/tasks";
|
|
27
27
|
const CHECKSUMS_KEY = "host/materializations/checksums";
|
|
28
28
|
function sha256(content) {
|
|
29
29
|
return createHash("sha256").update(content, "utf8").digest("hex");
|
|
@@ -101,7 +101,7 @@ export class VericifyProjector {
|
|
|
101
101
|
const content = JSON.stringify({
|
|
102
102
|
version: 1,
|
|
103
103
|
updated_at: new Date().toISOString(),
|
|
104
|
-
source_todo_path: `${
|
|
104
|
+
source_todo_path: `${ACE_TASKS_ROOT}/todo.md`,
|
|
105
105
|
order,
|
|
106
106
|
nodes,
|
|
107
107
|
}, null, 2);
|