@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.
Files changed (144) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/README.md +21 -13
  3. package/assets/.agents/ACE/agent-qa/instructions.md +11 -0
  4. package/assets/agent-state/EVIDENCE_LOG.md +1 -1
  5. package/assets/agent-state/MODULES/roles/capability-framework.json +41 -0
  6. package/assets/agent-state/MODULES/roles/capability-git.json +33 -0
  7. package/assets/agent-state/MODULES/roles/capability-safety.json +37 -0
  8. package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +21 -0
  9. package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +43 -0
  10. package/assets/agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json +43 -0
  11. package/assets/agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json +11 -0
  12. package/assets/agent-state/STATUS.md +2 -2
  13. package/assets/agent-state/runtime-tool-specs.json +70 -2
  14. package/assets/instructions/ACE_Coder.instructions.md +13 -0
  15. package/assets/instructions/ACE_UI.instructions.md +11 -0
  16. package/assets/scripts/ace-hook-dispatch.mjs +70 -6
  17. package/assets/scripts/render-mcp-configs.sh +19 -5
  18. package/dist/ace-context.js +91 -11
  19. package/dist/ace-internal-tools.d.ts +3 -1
  20. package/dist/ace-internal-tools.js +10 -2
  21. package/dist/ace-server-instructions.js +3 -3
  22. package/dist/ace-state-resolver.js +5 -3
  23. package/dist/agent-runtime/role-adapters.d.ts +18 -1
  24. package/dist/agent-runtime/role-adapters.js +49 -5
  25. package/dist/astgrep-index.d.ts +57 -1
  26. package/dist/astgrep-index.js +140 -4
  27. package/dist/cli.js +232 -35
  28. package/dist/discovery-runtime-wrappers.d.ts +108 -0
  29. package/dist/discovery-runtime-wrappers.js +615 -0
  30. package/dist/handoff-registry.js +5 -5
  31. package/dist/helpers/artifacts.d.ts +19 -0
  32. package/dist/helpers/artifacts.js +152 -0
  33. package/dist/helpers/bootstrap.d.ts +24 -0
  34. package/dist/helpers/bootstrap.js +894 -0
  35. package/dist/helpers/constants.d.ts +53 -0
  36. package/dist/helpers/constants.js +295 -0
  37. package/dist/helpers/drift.d.ts +13 -0
  38. package/dist/helpers/drift.js +45 -0
  39. package/dist/helpers/path-utils.d.ts +24 -0
  40. package/dist/helpers/path-utils.js +123 -0
  41. package/dist/helpers/store-resolution.d.ts +19 -0
  42. package/dist/helpers/store-resolution.js +305 -0
  43. package/dist/helpers/workspace-root.d.ts +3 -0
  44. package/dist/helpers/workspace-root.js +80 -0
  45. package/dist/helpers.d.ts +8 -125
  46. package/dist/helpers.js +8 -1768
  47. package/dist/job-scheduler.js +33 -7
  48. package/dist/json-sanitizer.d.ts +16 -0
  49. package/dist/json-sanitizer.js +26 -0
  50. package/dist/local-model-policy.d.ts +27 -0
  51. package/dist/local-model-policy.js +84 -0
  52. package/dist/local-model-runtime.d.ts +6 -0
  53. package/dist/local-model-runtime.js +33 -21
  54. package/dist/model-bridge.d.ts +13 -1
  55. package/dist/model-bridge.js +410 -23
  56. package/dist/orchestrator-supervisor.d.ts +56 -0
  57. package/dist/orchestrator-supervisor.js +179 -1
  58. package/dist/plan-proposal.d.ts +115 -0
  59. package/dist/plan-proposal.js +1073 -0
  60. package/dist/run-ledger.js +3 -3
  61. package/dist/runtime-command.d.ts +8 -0
  62. package/dist/runtime-command.js +38 -6
  63. package/dist/runtime-executor.d.ts +20 -1
  64. package/dist/runtime-executor.js +737 -172
  65. package/dist/runtime-profile.d.ts +32 -0
  66. package/dist/runtime-profile.js +89 -13
  67. package/dist/runtime-tool-specs.d.ts +39 -0
  68. package/dist/runtime-tool-specs.js +144 -28
  69. package/dist/safe-edit.d.ts +7 -0
  70. package/dist/safe-edit.js +163 -37
  71. package/dist/schemas.js +48 -1
  72. package/dist/server.js +51 -0
  73. package/dist/shared.d.ts +3 -2
  74. package/dist/shared.js +2 -0
  75. package/dist/status-events.js +9 -6
  76. package/dist/store/ace-packed-store.d.ts +3 -2
  77. package/dist/store/ace-packed-store.js +188 -110
  78. package/dist/store/bootstrap-store.d.ts +2 -1
  79. package/dist/store/bootstrap-store.js +102 -83
  80. package/dist/store/cache-workspace.js +11 -5
  81. package/dist/store/materializers/context-snapshot-materializer.js +6 -2
  82. package/dist/store/materializers/hook-context-materializer.d.ts +6 -9
  83. package/dist/store/materializers/hook-context-materializer.js +11 -21
  84. package/dist/store/materializers/host-file-materializer.js +6 -0
  85. package/dist/store/materializers/projection-manager.d.ts +0 -1
  86. package/dist/store/materializers/projection-manager.js +5 -13
  87. package/dist/store/materializers/scheduler-projection-materializer.js +1 -1
  88. package/dist/store/materializers/vericify-projector.d.ts +7 -7
  89. package/dist/store/materializers/vericify-projector.js +11 -11
  90. package/dist/store/repositories/local-model-runtime-repository.d.ts +120 -3
  91. package/dist/store/repositories/local-model-runtime-repository.js +242 -6
  92. package/dist/store/repositories/vericify-repository.d.ts +1 -1
  93. package/dist/store/skills-install.d.ts +4 -0
  94. package/dist/store/skills-install.js +21 -12
  95. package/dist/store/state-reader.d.ts +2 -0
  96. package/dist/store/state-reader.js +20 -0
  97. package/dist/store/store-artifacts.d.ts +7 -0
  98. package/dist/store/store-artifacts.js +27 -1
  99. package/dist/store/store-authority-audit.d.ts +18 -1
  100. package/dist/store/store-authority-audit.js +115 -5
  101. package/dist/store/store-snapshot.d.ts +3 -0
  102. package/dist/store/store-snapshot.js +22 -2
  103. package/dist/store/workspace-store-paths.d.ts +39 -0
  104. package/dist/store/workspace-store-paths.js +94 -0
  105. package/dist/store/write-coordinator.d.ts +65 -0
  106. package/dist/store/write-coordinator.js +386 -0
  107. package/dist/todo-state.js +5 -5
  108. package/dist/tools-agent.d.ts +20 -0
  109. package/dist/tools-agent.js +789 -25
  110. package/dist/tools-discovery.js +136 -1
  111. package/dist/tools-files.d.ts +7 -0
  112. package/dist/tools-files.js +1002 -11
  113. package/dist/tools-framework.js +105 -66
  114. package/dist/tools-handoff.js +2 -2
  115. package/dist/tools-lifecycle.js +4 -4
  116. package/dist/tools-memory.js +6 -6
  117. package/dist/tools-todo.js +2 -2
  118. package/dist/tracker-adapters.d.ts +1 -1
  119. package/dist/tracker-adapters.js +13 -18
  120. package/dist/tracker-sync.js +5 -3
  121. package/dist/tui/agent-runner.js +3 -1
  122. package/dist/tui/chat.js +103 -7
  123. package/dist/tui/dashboard.d.ts +1 -0
  124. package/dist/tui/dashboard.js +43 -0
  125. package/dist/tui/index.js +10 -1
  126. package/dist/tui/layout.d.ts +20 -0
  127. package/dist/tui/layout.js +31 -1
  128. package/dist/tui/local-model-contract.d.ts +6 -2
  129. package/dist/tui/local-model-contract.js +16 -3
  130. package/dist/tui/ollama.d.ts +8 -1
  131. package/dist/tui/ollama.js +53 -12
  132. package/dist/tui/openai-compatible.d.ts +13 -0
  133. package/dist/tui/openai-compatible.js +305 -5
  134. package/dist/tui/provider-discovery.d.ts +1 -0
  135. package/dist/tui/provider-discovery.js +35 -11
  136. package/dist/vericify-bridge.d.ts +6 -1
  137. package/dist/vericify-bridge.js +27 -3
  138. package/dist/workspace-manager.d.ts +30 -3
  139. package/dist/workspace-manager.js +257 -27
  140. package/package.json +1 -2
  141. package/dist/internal-tool-runtime.d.ts +0 -21
  142. package/dist/internal-tool-runtime.js +0 -136
  143. package/dist/store/workspace-snapshot.d.ts +0 -26
  144. package/dist/store/workspace-snapshot.js +0 -107
@@ -0,0 +1,386 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { hostname } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ import { getWorkspaceStorePath } from "./store-snapshot.js";
6
+ import { withStoreWriteQueue } from "./write-queue.js";
7
+ const DEFAULT_WAIT_MS = 15_000;
8
+ const DEFAULT_POLL_INTERVAL_MS = 100;
9
+ const DEFAULT_LEASE_TTL_MS = 30_000;
10
+ const DEFAULT_STALE_GRACE_MS = 1_000;
11
+ export class StoreWriteLeaseBusyError extends Error {
12
+ storePath;
13
+ lockPath;
14
+ waitedMs;
15
+ currentHolder;
16
+ constructor(input) {
17
+ super(input.currentHolder
18
+ ? `Store write lease busy at ${input.storePath}; held by pid=${input.currentHolder.pid} hostname=${input.currentHolder.hostname}`
19
+ : `Store write lease busy at ${input.storePath}; no lease metadata available`);
20
+ this.name = "StoreWriteLeaseBusyError";
21
+ this.storePath = input.storePath;
22
+ this.lockPath = input.lockPath;
23
+ this.waitedMs = input.waitedMs;
24
+ this.currentHolder = input.currentHolder;
25
+ }
26
+ }
27
+ export class StoreSyncWriteBlockedByAsyncLeaseError extends Error {
28
+ code = "STORE_SYNC_WRITE_BLOCKED_BY_ASYNC_LEASE";
29
+ storePath;
30
+ currentAsyncOperationLabels;
31
+ constructor(input) {
32
+ super(`Sync store write blocked for ${input.storePath}; async ownership is already active in this process. Use safeWriteAsync() / appendStatusEventSafe() / createWorkspaceSessionAsync() instead.`);
33
+ this.name = "StoreSyncWriteBlockedByAsyncLeaseError";
34
+ this.storePath = input.storePath;
35
+ this.currentAsyncOperationLabels = input.currentAsyncOperationLabels;
36
+ }
37
+ }
38
+ const asyncStoreOwnerships = new Map();
39
+ function leaseDirPath(storePath) {
40
+ return `${storePath}.write.lock`;
41
+ }
42
+ function leaseMetadataPath(lockPath) {
43
+ return join(lockPath, "lease.json");
44
+ }
45
+ function getOperationLabel(options) {
46
+ return options.operation_label?.trim() || undefined;
47
+ }
48
+ function emitLifecycleEvent(options, event) {
49
+ if (options.emit_lifecycle_events === false)
50
+ return;
51
+ const sink = options.lifecycle_sink;
52
+ if (!sink)
53
+ return;
54
+ try {
55
+ sink({
56
+ ...event,
57
+ hostname: hostname(),
58
+ pid: process.pid,
59
+ timestamp: new Date().toISOString(),
60
+ });
61
+ }
62
+ catch {
63
+ // Lifecycle sinks are observability only; they must not affect lease behavior.
64
+ }
65
+ }
66
+ function registerAsyncStoreOwnership(storePath, operationLabel) {
67
+ const current = asyncStoreOwnerships.get(storePath);
68
+ if (!current) {
69
+ asyncStoreOwnerships.set(storePath, {
70
+ count: 1,
71
+ operationLabels: operationLabel ? [operationLabel] : [],
72
+ });
73
+ return;
74
+ }
75
+ current.count += 1;
76
+ if (operationLabel) {
77
+ current.operationLabels.push(operationLabel);
78
+ }
79
+ }
80
+ function releaseAsyncStoreOwnership(storePath, operationLabel) {
81
+ const current = asyncStoreOwnerships.get(storePath);
82
+ if (!current)
83
+ return;
84
+ current.count = Math.max(0, current.count - 1);
85
+ if (operationLabel) {
86
+ const index = current.operationLabels.lastIndexOf(operationLabel);
87
+ if (index >= 0) {
88
+ current.operationLabels.splice(index, 1);
89
+ }
90
+ }
91
+ if (current.count === 0) {
92
+ asyncStoreOwnerships.delete(storePath);
93
+ }
94
+ }
95
+ function getAsyncStoreOwnership(storePath) {
96
+ const current = asyncStoreOwnerships.get(storePath);
97
+ if (!current)
98
+ return undefined;
99
+ return {
100
+ count: current.count,
101
+ operationLabels: [...current.operationLabels],
102
+ };
103
+ }
104
+ function sleepSync(ms) {
105
+ if (ms <= 0)
106
+ return;
107
+ const shared = new SharedArrayBuffer(4);
108
+ const view = new Int32Array(shared);
109
+ Atomics.wait(view, 0, 0, ms);
110
+ }
111
+ function sleepAsync(ms) {
112
+ return new Promise((resolve) => setTimeout(resolve, ms));
113
+ }
114
+ function normalizeLeaseRecord(record) {
115
+ if (!record)
116
+ return undefined;
117
+ if (typeof record.token !== "string" ||
118
+ typeof record.storePath !== "string" ||
119
+ typeof record.lockPath !== "string" ||
120
+ typeof record.metadataPath !== "string" ||
121
+ typeof record.pid !== "number" ||
122
+ typeof record.hostname !== "string" ||
123
+ typeof record.acquiredAt !== "string" ||
124
+ typeof record.expiresAt !== "string" ||
125
+ typeof record.ttlMs !== "number" ||
126
+ typeof record.waitedMs !== "number") {
127
+ return undefined;
128
+ }
129
+ return {
130
+ token: record.token,
131
+ storePath: record.storePath,
132
+ lockPath: record.lockPath,
133
+ metadataPath: record.metadataPath,
134
+ pid: record.pid,
135
+ hostname: record.hostname,
136
+ agentId: typeof record.agentId === "string" ? record.agentId : undefined,
137
+ operationLabel: typeof record.operationLabel === "string" ? record.operationLabel : undefined,
138
+ acquiredAt: record.acquiredAt,
139
+ expiresAt: record.expiresAt,
140
+ ttlMs: record.ttlMs,
141
+ waitedMs: record.waitedMs,
142
+ };
143
+ }
144
+ function readLeaseRecord(lockPath) {
145
+ const metadataPath = leaseMetadataPath(lockPath);
146
+ if (!existsSync(metadataPath))
147
+ return undefined;
148
+ try {
149
+ const parsed = JSON.parse(readFileSync(metadataPath, "utf-8"));
150
+ return normalizeLeaseRecord(parsed);
151
+ }
152
+ catch {
153
+ return undefined;
154
+ }
155
+ }
156
+ function leaseIsStale(lease, staleGraceMs) {
157
+ const expiresAt = Date.parse(lease.expiresAt);
158
+ if (!Number.isFinite(expiresAt))
159
+ return true;
160
+ return Date.now() > expiresAt + staleGraceMs;
161
+ }
162
+ function canRecoverStaleLease(lease, staleGraceMs) {
163
+ if (!leaseIsStale(lease, staleGraceMs))
164
+ return false;
165
+ if (lease.hostname !== hostname())
166
+ return false;
167
+ try {
168
+ process.kill(lease.pid, 0);
169
+ return false;
170
+ }
171
+ catch (error) {
172
+ return error instanceof Error && "code" in error && error.code === "ESRCH";
173
+ }
174
+ }
175
+ function createLeaseRecord(storePath, lockPath, options, waitedMs) {
176
+ const ttlMs = options.lease_ttl_ms ?? DEFAULT_LEASE_TTL_MS;
177
+ const acquiredAtMs = Date.now();
178
+ const acquiredAt = new Date(acquiredAtMs).toISOString();
179
+ return {
180
+ token: randomUUID(),
181
+ storePath,
182
+ lockPath,
183
+ metadataPath: leaseMetadataPath(lockPath),
184
+ pid: process.pid,
185
+ hostname: hostname(),
186
+ agentId: options.agent_id,
187
+ operationLabel: options.operation_label,
188
+ acquiredAt,
189
+ expiresAt: new Date(acquiredAtMs + ttlMs).toISOString(),
190
+ ttlMs,
191
+ waitedMs,
192
+ };
193
+ }
194
+ function tryAcquireLeaseSync(storePath, lockPath, options, waitedMs) {
195
+ mkdirSync(dirname(lockPath), { recursive: true });
196
+ mkdirSync(lockPath, { recursive: false });
197
+ const lease = createLeaseRecord(storePath, lockPath, options, waitedMs);
198
+ writeFileSync(lease.metadataPath, JSON.stringify({ kind: "store_write_lease", ...lease }, null, 2), "utf-8");
199
+ return lease;
200
+ }
201
+ async function tryAcquireLeaseAsync(storePath, lockPath, options, waitedMs) {
202
+ mkdirSync(dirname(lockPath), { recursive: true });
203
+ mkdirSync(lockPath, { recursive: false });
204
+ const lease = createLeaseRecord(storePath, lockPath, options, waitedMs);
205
+ writeFileSync(lease.metadataPath, JSON.stringify({ kind: "store_write_lease", ...lease }, null, 2), "utf-8");
206
+ return lease;
207
+ }
208
+ function releaseLease(lease) {
209
+ const current = readLeaseRecord(lease.lockPath);
210
+ if (!current) {
211
+ rmSync(lease.lockPath, { recursive: true, force: true });
212
+ return;
213
+ }
214
+ if (current.token !== lease.token) {
215
+ throw new Error(`Store write lease token mismatch while releasing ${lease.storePath}; refusing to remove a different holder's lock`);
216
+ }
217
+ rmSync(lease.lockPath, { recursive: true, force: true });
218
+ }
219
+ async function acquireLeaseAsync(storePath, options) {
220
+ const lockPath = leaseDirPath(storePath);
221
+ const waitMs = options.wait_ms ?? DEFAULT_WAIT_MS;
222
+ const pollIntervalMs = options.poll_interval_ms ?? DEFAULT_POLL_INTERVAL_MS;
223
+ const staleGraceMs = options.stale_grace_ms ?? DEFAULT_STALE_GRACE_MS;
224
+ const startedAt = Date.now();
225
+ while (Date.now() - startedAt <= waitMs) {
226
+ try {
227
+ return await tryAcquireLeaseAsync(storePath, lockPath, options, Date.now() - startedAt);
228
+ }
229
+ catch (error) {
230
+ const isBusy = error instanceof Error &&
231
+ "code" in error &&
232
+ error.code === "EEXIST";
233
+ if (!isBusy)
234
+ throw error;
235
+ const current = readLeaseRecord(lockPath);
236
+ if (current && canRecoverStaleLease(current, staleGraceMs)) {
237
+ rmSync(lockPath, { recursive: true, force: true });
238
+ continue;
239
+ }
240
+ await sleepAsync(Math.min(pollIntervalMs, waitMs));
241
+ }
242
+ }
243
+ const currentHolder = readLeaseRecord(lockPath);
244
+ emitLifecycleEvent(options, {
245
+ event: "store-write-blocked",
246
+ storePath,
247
+ operationLabel: getOperationLabel(options),
248
+ waitedMs: Date.now() - startedAt,
249
+ currentHolder,
250
+ asyncOwnership: getAsyncStoreOwnership(storePath),
251
+ });
252
+ throw new StoreWriteLeaseBusyError({
253
+ storePath,
254
+ lockPath,
255
+ waitedMs: Date.now() - startedAt,
256
+ currentHolder,
257
+ });
258
+ }
259
+ function acquireLeaseSync(storePath, options) {
260
+ const lockPath = leaseDirPath(storePath);
261
+ const waitMs = options.wait_ms ?? DEFAULT_WAIT_MS;
262
+ const pollIntervalMs = options.poll_interval_ms ?? DEFAULT_POLL_INTERVAL_MS;
263
+ const staleGraceMs = options.stale_grace_ms ?? DEFAULT_STALE_GRACE_MS;
264
+ const startedAt = Date.now();
265
+ while (Date.now() - startedAt <= waitMs) {
266
+ try {
267
+ return tryAcquireLeaseSync(storePath, lockPath, options, Date.now() - startedAt);
268
+ }
269
+ catch (error) {
270
+ const isBusy = error instanceof Error &&
271
+ "code" in error &&
272
+ error.code === "EEXIST";
273
+ if (!isBusy)
274
+ throw error;
275
+ const current = readLeaseRecord(lockPath);
276
+ if (current && canRecoverStaleLease(current, staleGraceMs)) {
277
+ rmSync(lockPath, { recursive: true, force: true });
278
+ continue;
279
+ }
280
+ sleepSync(Math.min(pollIntervalMs, waitMs));
281
+ }
282
+ }
283
+ const currentHolder = readLeaseRecord(lockPath);
284
+ emitLifecycleEvent(options, {
285
+ event: "store-write-blocked",
286
+ storePath,
287
+ operationLabel: getOperationLabel(options),
288
+ waitedMs: Date.now() - startedAt,
289
+ currentHolder,
290
+ asyncOwnership: getAsyncStoreOwnership(storePath),
291
+ });
292
+ throw new StoreWriteLeaseBusyError({
293
+ storePath,
294
+ lockPath,
295
+ waitedMs: Date.now() - startedAt,
296
+ currentHolder,
297
+ });
298
+ }
299
+ export async function withStoreWriteCoordinator(storePath, fn, options = {}) {
300
+ const operationLabel = getOperationLabel(options);
301
+ registerAsyncStoreOwnership(storePath, operationLabel);
302
+ emitLifecycleEvent(options, {
303
+ event: "store-write-requested",
304
+ storePath,
305
+ operationLabel,
306
+ asyncOwnership: getAsyncStoreOwnership(storePath),
307
+ });
308
+ try {
309
+ return await withStoreWriteQueue(storePath, async () => {
310
+ emitLifecycleEvent(options, {
311
+ event: "store-write-accepted",
312
+ storePath,
313
+ operationLabel,
314
+ asyncOwnership: getAsyncStoreOwnership(storePath),
315
+ });
316
+ const lease = await acquireLeaseAsync(storePath, options);
317
+ emitLifecycleEvent(options, {
318
+ event: "store-write-started",
319
+ storePath,
320
+ operationLabel,
321
+ waitedMs: lease.waitedMs,
322
+ currentHolder: lease,
323
+ asyncOwnership: getAsyncStoreOwnership(storePath),
324
+ });
325
+ try {
326
+ const result = await fn();
327
+ emitLifecycleEvent(options, {
328
+ event: "store-write-committed",
329
+ storePath,
330
+ operationLabel,
331
+ waitedMs: lease.waitedMs,
332
+ currentHolder: lease,
333
+ asyncOwnership: getAsyncStoreOwnership(storePath),
334
+ });
335
+ return result;
336
+ }
337
+ catch (error) {
338
+ emitLifecycleEvent(options, {
339
+ event: "store-write-failed",
340
+ storePath,
341
+ operationLabel,
342
+ waitedMs: lease.waitedMs,
343
+ currentHolder: lease,
344
+ error: error instanceof Error ? error.message : String(error),
345
+ asyncOwnership: getAsyncStoreOwnership(storePath),
346
+ });
347
+ throw error;
348
+ }
349
+ finally {
350
+ releaseLease(lease);
351
+ }
352
+ });
353
+ }
354
+ finally {
355
+ releaseAsyncStoreOwnership(storePath, operationLabel);
356
+ }
357
+ }
358
+ export function withStoreWriteCoordinatorSync(storePath, fn, options = {}) {
359
+ const operationLabel = getOperationLabel(options);
360
+ const asyncOwnership = getAsyncStoreOwnership(storePath);
361
+ if (asyncOwnership && asyncOwnership.count > 0) {
362
+ emitLifecycleEvent(options, {
363
+ event: "store-write-blocked",
364
+ storePath,
365
+ operationLabel,
366
+ asyncOwnership,
367
+ });
368
+ throw new StoreSyncWriteBlockedByAsyncLeaseError({
369
+ storePath,
370
+ currentAsyncOperationLabels: asyncOwnership.operationLabels.length > 0
371
+ ? asyncOwnership.operationLabels
372
+ : ["unknown async store writer"],
373
+ });
374
+ }
375
+ const lease = acquireLeaseSync(storePath, options);
376
+ try {
377
+ return fn();
378
+ }
379
+ finally {
380
+ releaseLease(lease);
381
+ }
382
+ }
383
+ export function resolveStoreWriteLeasePath(workspaceRoot) {
384
+ return `${getWorkspaceStorePath(workspaceRoot)}.write.lock`;
385
+ }
386
+ //# sourceMappingURL=write-coordinator.js.map
@@ -5,7 +5,7 @@ import { ProjectionManager } from "./store/materializers/projection-manager.js";
5
5
  import { TodoRepository } from "./store/repositories/todo-repository.js";
6
6
  import { getWorkspaceStorePath, readStoreJsonSync, storeExistsSync } from "./store/store-snapshot.js";
7
7
  import { operationalArtifactVirtualPath } from "./store/store-artifacts.js";
8
- import { withStoreWriteQueue } from "./store/write-queue.js";
8
+ import { withStoreWriteCoordinator } from "./store/write-coordinator.js";
9
9
  import { isReadError, slugify } from "./shared.js";
10
10
  const TODO_MARKDOWN_REL = `${ACE_TASKS_ROOT_REL}/todo.md`;
11
11
  const TODO_STATE_REL = "agent-state/todo-state.json";
@@ -263,7 +263,7 @@ async function mirrorTodoStateToStore(root, state) {
263
263
  const storePath = getWorkspaceStorePath(root);
264
264
  if (!existsSync(storePath))
265
265
  return;
266
- await withStoreWriteQueue(storePath, async () => {
266
+ await withStoreWriteCoordinator(storePath, async () => {
267
267
  const store = await openStore(storePath);
268
268
  try {
269
269
  const nextIds = state.order.filter((id) => Boolean(state.nodes[id]));
@@ -294,14 +294,14 @@ async function mirrorTodoStateToStore(root, state) {
294
294
  finally {
295
295
  await store.close();
296
296
  }
297
- });
297
+ }, { operation_label: "syncTodoStateSafe" });
298
298
  }
299
299
  async function writeStateStoreBacked(root, state) {
300
300
  const storePath = getWorkspaceStorePath(root);
301
301
  if (!existsSync(storePath)) {
302
302
  return writeState(state);
303
303
  }
304
- return withStoreWriteQueue(storePath, async () => {
304
+ return withStoreWriteCoordinator(storePath, async () => {
305
305
  const store = await openStore(storePath);
306
306
  try {
307
307
  const repo = new TodoRepository(store);
@@ -324,7 +324,7 @@ async function writeStateStoreBacked(root, state) {
324
324
  finally {
325
325
  await store.close();
326
326
  }
327
- });
327
+ }, { operation_label: "syncTodoStateSafe" });
328
328
  }
329
329
  function scheduleTodoMirror(root, state) {
330
330
  const snapshot = JSON.parse(JSON.stringify(state));
@@ -2,6 +2,26 @@
2
2
  * Agent, skill, kernel, and task-pack tool registrations.
3
3
  */
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { type BridgeResult } from "./model-bridge.js";
6
+ import { proposePlan as proposePlanImpl, validatePlan as validatePlanImpl, loadAcceptanceTraceContract as loadAcceptanceTraceContractImpl } from "./plan-proposal.js";
7
+ import { type TaskPlan, type TaskStep } from "./orchestrator-supervisor.js";
5
8
  export type { TaskPlan, TaskStep } from "./orchestrator-supervisor.js";
9
+ export declare function formatStepTaskForBridge(step: Pick<TaskStep, "task" | "upstream_outputs">): string;
10
+ type IntentVerificationOutcome = "ok" | "revisit_step" | "replan_required";
11
+ type IntentDriftReasonCode = "contract_missing" | "contract_invalid" | "bridge_output_malformed_json" | "role_drift_ui_off_topic" | "coder_artifact_stub" | "qa_rewrote_artifact" | "artifact_mismatch" | "forbidden_pattern" | "required_evidence_missing";
12
+ interface IntentVerificationResult {
13
+ outcome: IntentVerificationOutcome;
14
+ reason: string;
15
+ reason_code?: IntentDriftReasonCode;
16
+ uncovered_clauses?: string[];
17
+ }
18
+ export { loadAcceptanceTraceContractImpl as loadAcceptanceTraceContract };
19
+ export { proposePlanImpl as proposePlan, validatePlanImpl as validatePlan };
20
+ export declare function verifyIntentAgainstContract(input: {
21
+ plan: TaskPlan;
22
+ step: TaskStep;
23
+ result: BridgeResult;
24
+ intent_contract: unknown;
25
+ }): IntentVerificationResult;
6
26
  export declare function registerAgentTools(server: McpServer): void;
7
27
  //# sourceMappingURL=tools-agent.d.ts.map