@voybio/ace-swarm 2.4.9 → 2.4.10
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 +52 -14
- package/README.md +14 -10
- package/assets/.agents/ACE/ACE_coders/AGENTS.md +23 -30
- package/assets/.agents/ACE/ACE_coders/INSTRUCTIONS.md +21 -30
- package/assets/.agents/skills/landing-review-watcher/SKILL.md +1 -1
- package/assets/.agents/skills/learn-from-work/SKILL.md +41 -0
- package/assets/agent-state/ACE_WORKFLOW.md +25 -2
- package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +143 -2
- package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +2 -2
- package/assets/agent-state/MODULES/schemas/SWARM_HANDOFF.schema.json +10 -0
- package/assets/eval-battery/battery.json +1 -1
- package/assets/instructions/ACE_Coder.instructions.md +9 -13
- package/assets/scripts/ace-hook-dispatch.mjs +16 -411
- package/assets/tasks/SWARM_HANDOFF.example_ui_to_coders.json +1 -2
- package/assets/vendor/README.md +9 -0
- package/assets/vendor/vericify-reader.mjs +272 -0
- package/assets/vendor/vericify-reader.provenance.json +10 -0
- package/dist/ace-autonomy.d.ts +58 -0
- package/dist/ace-autonomy.js +211 -6
- package/dist/ace-internal-tools.d.ts +1 -0
- package/dist/ace-internal-tools.js +3 -3
- package/dist/ace-server-instructions.d.ts +3 -3
- package/dist/ace-server-instructions.js +46 -192
- package/dist/cli.js +44 -6
- package/dist/experience-reflector.d.ts +7 -0
- package/dist/experience-reflector.js +39 -0
- package/dist/goal-engine.d.ts +64 -7
- package/dist/goal-engine.js +197 -41
- package/dist/handoff-registry.d.ts +10 -0
- package/dist/handoff-registry.js +59 -0
- package/dist/helpers/artifacts.d.ts +6 -2
- package/dist/helpers/artifacts.js +8 -6
- package/dist/helpers/bootstrap.js +13 -20
- package/dist/helpers/path-utils.js +2 -0
- package/dist/helpers/store-resolution.js +18 -3
- package/dist/helpers/workspace-root.d.ts +2 -0
- package/dist/helpers/workspace-root.js +9 -0
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +1 -0
- package/dist/hermes/bridge-protocol.d.ts +1 -1
- package/dist/hermes/session-manager.d.ts +17 -0
- package/dist/hermes/session-manager.js +67 -14
- package/dist/host-goal-engine.d.ts +138 -0
- package/dist/host-goal-engine.js +793 -0
- package/dist/host-goal-status.d.ts +113 -0
- package/dist/host-goal-status.js +175 -0
- package/dist/host-learning.d.ts +68 -0
- package/dist/host-learning.js +115 -0
- package/dist/host-observation.d.ts +12 -0
- package/dist/host-observation.js +91 -0
- package/dist/host-plan-revision.d.ts +14 -0
- package/dist/host-plan-revision.js +101 -0
- package/dist/host-verification-job.d.ts +12 -0
- package/dist/host-verification-job.js +183 -0
- package/dist/host-work-context.d.ts +12 -0
- package/dist/host-work-context.js +8 -0
- package/dist/job-scheduler.d.ts +48 -14
- package/dist/job-scheduler.js +169 -23
- package/dist/job-worker.d.ts +3 -1
- package/dist/job-worker.js +10 -3
- package/dist/kanban.d.ts +4 -1
- package/dist/kanban.js +44 -16
- package/dist/learned-artifacts.d.ts +64 -0
- package/dist/learned-artifacts.js +321 -0
- package/dist/learning-controls.d.ts +142 -0
- package/dist/learning-controls.js +135 -0
- package/dist/learning-input-context.d.ts +9 -0
- package/dist/learning-input-context.js +62 -0
- package/dist/learning-lifecycle.d.ts +10 -0
- package/dist/learning-lifecycle.js +11 -0
- package/dist/learning-overlays.d.ts +3 -0
- package/dist/learning-overlays.js +17 -0
- package/dist/learning-policy.d.ts +40 -0
- package/dist/learning-policy.js +38 -0
- package/dist/learning-records.d.ts +35 -0
- package/dist/learning-records.js +17 -0
- package/dist/learning-scorecard.d.ts +82 -0
- package/dist/learning-scorecard.js +86 -0
- package/dist/learning-serving.d.ts +29 -0
- package/dist/learning-serving.js +134 -0
- package/dist/linked-work.d.ts +9 -0
- package/dist/linked-work.js +28 -0
- package/dist/local-model-runtime.js +1 -1
- package/dist/mcp-command-progress.d.ts +16 -0
- package/dist/mcp-command-progress.js +70 -0
- package/dist/model-bridge.d.ts +14 -13
- package/dist/model-bridge.js +73 -41
- package/dist/orchestrator-supervisor.d.ts +108 -6
- package/dist/orchestrator-supervisor.js +4 -32
- package/dist/plan-proposal.js +3 -3
- package/dist/playbook-curator.d.ts +1 -0
- package/dist/playbook-curator.js +11 -9
- package/dist/process-identity.d.ts +8 -0
- package/dist/process-identity.js +38 -0
- package/dist/progress-command.d.ts +34 -0
- package/dist/progress-command.js +153 -0
- package/dist/prompts.js +15 -15
- package/dist/resources.js +2 -2
- package/dist/runtime-command.d.ts +8 -1
- package/dist/runtime-command.js +48 -7
- package/dist/runtime-executor.js +33 -11
- package/dist/runtime-profile-syntax.d.ts +6 -0
- package/dist/runtime-profile-syntax.js +121 -0
- package/dist/runtime-profile.d.ts +37 -5
- package/dist/runtime-profile.js +36 -129
- package/dist/runtime-tool-specs.js +1 -1
- package/dist/safe-edit.d.ts +7 -3
- package/dist/safe-edit.js +40 -47
- package/dist/schemas.js +4 -2
- package/dist/server.d.ts +2 -16
- package/dist/server.js +14 -20
- package/dist/shared.d.ts +2 -0
- package/dist/shared.js +2 -0
- package/dist/skill-auditor.d.ts +19 -0
- package/dist/skill-auditor.js +32 -2
- package/dist/skill-catalog.d.ts +4 -1
- package/dist/skill-catalog.js +6 -5
- package/dist/store/ace-packed-store.d.ts +5 -1
- package/dist/store/ace-packed-store.js +33 -1
- package/dist/store/bootstrap-store.js +19 -12
- package/dist/store/cache-workspace.d.ts +8 -0
- package/dist/store/cache-workspace.js +94 -27
- package/dist/store/importer.js +11 -20
- package/dist/store/knowledge-bake.d.ts +3 -1
- package/dist/store/knowledge-bake.js +10 -1
- package/dist/store/legacy-vericify-posts.d.ts +8 -0
- package/dist/store/legacy-vericify-posts.js +76 -0
- package/dist/store/materializers/hook-context-materializer.d.ts +2 -1
- package/dist/store/materializers/hook-context-materializer.js +6 -2
- package/dist/store/materializers/host-file-materializer.js +2 -2
- package/dist/store/materializers/projection-manager.d.ts +4 -1
- package/dist/store/materializers/projection-manager.js +10 -3
- package/dist/store/materializers/todo-syncer.d.ts +39 -20
- package/dist/store/materializers/todo-syncer.js +208 -110
- package/dist/store/materializers/vericify-projector.js +15 -26
- package/dist/store/repositories/goal-repository.d.ts +51 -2
- package/dist/store/repositories/goal-repository.js +114 -48
- package/dist/store/repositories/playbook-repository.d.ts +41 -3
- package/dist/store/repositories/playbook-repository.js +61 -5
- package/dist/store/repositories/todo-repository.d.ts +8 -2
- package/dist/store/repositories/todo-repository.js +1 -1
- package/dist/store/repositories/vericify-repository.d.ts +4 -0
- package/dist/store/repositories/vericify-repository.js +46 -0
- package/dist/store/skills-install.d.ts +1 -0
- package/dist/store/skills-install.js +20 -16
- package/dist/store/source-preservation.d.ts +24 -0
- package/dist/store/source-preservation.js +79 -0
- package/dist/store/store-artifacts.js +8 -1
- package/dist/store/test-write-boundary.d.ts +16 -0
- package/dist/store/test-write-boundary.js +175 -0
- package/dist/store/types.d.ts +5 -1
- package/dist/store/write-coordinator.js +16 -0
- package/dist/task-plan-context.d.ts +11 -0
- package/dist/task-plan-context.js +59 -0
- package/dist/todo-state.d.ts +19 -9
- package/dist/todo-state.js +204 -321
- package/dist/tools-agent.d.ts +1 -1
- package/dist/tools-agent.js +38 -62
- package/dist/tools-files.d.ts +0 -3
- package/dist/tools-files.js +21 -11
- package/dist/tools-framework.js +16 -25
- package/dist/tools-goal.d.ts +2 -4
- package/dist/tools-goal.js +119 -16
- package/dist/tools-handoff.js +28 -4
- package/dist/tools-lifecycle.js +1 -1
- package/dist/tools-memory.d.ts +0 -3
- package/dist/tools-memory.js +51 -6
- package/dist/tools-scheduler.js +19 -17
- package/dist/tools-todo.js +160 -148
- package/dist/vericify-bridge.d.ts +8 -0
- package/dist/vericify-bridge.js +18 -0
- package/dist/vericify-context.d.ts +4 -0
- package/dist/vericify-context.js +26 -5
- package/dist/vericify-native.d.ts +101 -0
- package/dist/vericify-native.js +221 -0
- package/dist/verification-worker.d.ts +2 -0
- package/dist/verification-worker.js +31 -0
- package/docs/mcp-tool-reference.md +44 -9
- package/package.json +19 -6
- package/scripts/dev/run-tests-isolated.mjs +165 -0
- package/scripts/dev/run_hermes_crispr_live.mjs +1 -0
- package/scripts/dev/test-isolation-guard.mjs +20 -0
- package/scripts/dev/test-preload.mjs +153 -0
- package/scripts/dev/test-source-inventory.mjs +31 -0
- package/docs/development.md +0 -46
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { CommandProgress } from "./progress-command.js";
|
|
3
|
+
/** MCP liveness messages keep opted-in requests alive without claiming output progress. */
|
|
4
|
+
export declare function withMcpCommandProgress<T>(extra: {
|
|
5
|
+
_meta?: {
|
|
6
|
+
progressToken?: string | number;
|
|
7
|
+
};
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
sendNotification?: (notification: any) => Promise<unknown>;
|
|
10
|
+
} | undefined, label: string, work: (onProgress: (progress: CommandProgress) => void, signal: AbortSignal) => Promise<T>, connectionIsOpen?: () => boolean): Promise<T>;
|
|
11
|
+
export declare const commandPolicySchema: z.ZodObject<{
|
|
12
|
+
stall_min: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
kill_min: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
deadline_min: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
//# sourceMappingURL=mcp-command-progress.d.ts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** MCP liveness messages keep opted-in requests alive without claiming output progress. */
|
|
3
|
+
export async function withMcpCommandProgress(extra, label, work, connectionIsOpen) {
|
|
4
|
+
// The SDK cancels a request when its client stops waiting. That cancellation
|
|
5
|
+
// owns the response channel, not the command's lifetime. Explicit operator
|
|
6
|
+
// cancellation and ACE's explicitly configured tool deadlines still propagate.
|
|
7
|
+
const sourceSignal = extra?.signal;
|
|
8
|
+
const workController = new AbortController();
|
|
9
|
+
const beganConnected = connectionIsOpen?.() ?? false;
|
|
10
|
+
const forwardCancellation = () => {
|
|
11
|
+
const reason = sourceSignal?.reason;
|
|
12
|
+
const text = String(reason ?? "");
|
|
13
|
+
const code = reason && typeof reason === "object" && "code" in reason ? reason.code : undefined;
|
|
14
|
+
const clientWaitExpired = code === -32001 || /(?:McpError|MCP error).*Request timed out/i.test(text);
|
|
15
|
+
const transportClosed = /(?:connection|transport|stream)(?: was)? closed|\bdisconnected\b|ECONNRESET|EPIPE/i.test(text);
|
|
16
|
+
if (clientWaitExpired || transportClosed)
|
|
17
|
+
return;
|
|
18
|
+
const genericAbort = (reason instanceof Error && reason.name === "AbortError") || /^AbortError:/i.test(text);
|
|
19
|
+
if (genericAbort && beganConnected) {
|
|
20
|
+
// SDK _onclose aborts handlers before clearing its transport. Check after
|
|
21
|
+
// that synchronous close sequence; an operator abort leaves transport open.
|
|
22
|
+
queueMicrotask(() => {
|
|
23
|
+
if (connectionIsOpen?.() === false)
|
|
24
|
+
return;
|
|
25
|
+
workController.abort(reason);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
else
|
|
29
|
+
workController.abort(reason);
|
|
30
|
+
};
|
|
31
|
+
if (sourceSignal?.aborted) {
|
|
32
|
+
forwardCancellation();
|
|
33
|
+
await Promise.resolve();
|
|
34
|
+
}
|
|
35
|
+
else
|
|
36
|
+
sourceSignal?.addEventListener("abort", forwardCancellation, { once: true });
|
|
37
|
+
const token = extra?._meta?.progressToken;
|
|
38
|
+
let sequence = 0;
|
|
39
|
+
let latest = "running";
|
|
40
|
+
const notify = () => {
|
|
41
|
+
if (token === undefined || !extra?.sendNotification)
|
|
42
|
+
return;
|
|
43
|
+
try {
|
|
44
|
+
void Promise.resolve(extra.sendNotification({
|
|
45
|
+
method: "notifications/progress",
|
|
46
|
+
params: { progressToken: token, progress: ++sequence, message: `${label}: ${latest}` },
|
|
47
|
+
})).catch(() => undefined);
|
|
48
|
+
}
|
|
49
|
+
catch { /* A closed notification channel must not change command outcomes. */ }
|
|
50
|
+
};
|
|
51
|
+
notify();
|
|
52
|
+
const heartbeat = setInterval(notify, 15_000);
|
|
53
|
+
heartbeat.unref?.();
|
|
54
|
+
try {
|
|
55
|
+
return await work((progress) => {
|
|
56
|
+
latest = `${progress.status}; running ${Math.floor(progress.elapsed_ms / 1000)}s, last output ${Math.floor(progress.silence_ms / 1000)}s ago`;
|
|
57
|
+
notify();
|
|
58
|
+
}, workController.signal);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
clearInterval(heartbeat);
|
|
62
|
+
sourceSignal?.removeEventListener("abort", forwardCancellation);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export const commandPolicySchema = z.object({
|
|
66
|
+
stall_min: z.number().nonnegative().finite().optional().describe("Silence before suspected stall; default 10 minutes, 0 disables stall detection"),
|
|
67
|
+
kill_min: z.number().nonnegative().finite().optional().describe("Total silence before terminating stalled process group; default 60 minutes"),
|
|
68
|
+
deadline_min: z.number().positive().finite().optional().describe("Explicit overall deadline in minutes; omitted means no overall deadline"),
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=mcp-command-progress.js.map
|
package/dist/model-bridge.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface BridgeToolResult {
|
|
|
10
10
|
ok: boolean;
|
|
11
11
|
summary: string;
|
|
12
12
|
isError: boolean;
|
|
13
|
-
/**
|
|
13
|
+
/** Classified failure or nonterminal state (for example "still_running"). */
|
|
14
14
|
reason_code?: string;
|
|
15
15
|
}
|
|
16
16
|
export interface BridgeUsageTotals {
|
|
@@ -83,20 +83,20 @@ export declare function verifyCompletionArtifacts(result: BridgeResult, context:
|
|
|
83
83
|
requiredEvidenceRefs?: string[];
|
|
84
84
|
forceCompletionVerification?: boolean;
|
|
85
85
|
}): Promise<BridgeResult>;
|
|
86
|
-
|
|
87
|
-
* Per-tool-call deadline (E12). A hung validation/test subprocess must never
|
|
88
|
-
* wedge a turn indefinitely — and under Promise.all one stuck call also holds
|
|
89
|
-
* every parallel sibling's feedback hostage. On timeout we resolve a classified
|
|
90
|
-
* `tool_timeout` failure that then feeds the WS-C doom-loop brake.
|
|
91
|
-
*/
|
|
92
|
-
export declare function executeToolWithDeadline(tool: string, args: Record<string, unknown>, sessionId: string, opts: {
|
|
93
|
-
workspace_path: string;
|
|
94
|
-
}, deadlineMs: number, exec?: (tool: string, args: Record<string, unknown>, sessionId: string, opts: {
|
|
86
|
+
type InternalToolOptions = {
|
|
95
87
|
workspace_path: string;
|
|
96
|
-
|
|
88
|
+
signal?: AbortSignal;
|
|
89
|
+
};
|
|
90
|
+
type ToolDeadlineOutcome = {
|
|
97
91
|
rawToolResult: unknown;
|
|
98
|
-
timedOut:
|
|
99
|
-
|
|
92
|
+
timedOut: false;
|
|
93
|
+
stillRunning?: boolean;
|
|
94
|
+
operationId?: string;
|
|
95
|
+
};
|
|
96
|
+
/** No implicit cutoff. An explicit deadline requests cancellation; unconfirmed
|
|
97
|
+
* cancellation is reported as still running. Identical retries collect the same
|
|
98
|
+
* operation instead of launching a duplicate side effect. */
|
|
99
|
+
export declare function executeToolWithDeadline(tool: string, args: Record<string, unknown>, sessionId: string, opts: InternalToolOptions, deadlineMs?: number, exec?: (tool: string, args: Record<string, unknown>, sessionId: string, opts: InternalToolOptions) => Promise<unknown>): Promise<ToolDeadlineOutcome>;
|
|
100
100
|
export declare class ModelBridge {
|
|
101
101
|
private clients;
|
|
102
102
|
private activeProviderClient;
|
|
@@ -108,4 +108,5 @@ export declare class ModelBridge {
|
|
|
108
108
|
private selectToolScope;
|
|
109
109
|
run(options: ModelBridgeRunOptions): Promise<BridgeResult>;
|
|
110
110
|
}
|
|
111
|
+
export {};
|
|
111
112
|
//# sourceMappingURL=model-bridge.d.ts.map
|
package/dist/model-bridge.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { appendFileSync, existsSync, mkdirSync, writeFileSync, realpathSync } from "node:fs";
|
|
3
3
|
import { dirname, isAbsolute, resolve, sep } from "node:path";
|
|
4
4
|
import { executeAceInternalTool, listAceInternalToolCatalog, } from "./ace-internal-tools.js";
|
|
5
|
-
import {
|
|
5
|
+
import { appendAutomaticVericifyProcessPostSafe, deriveWorkspaceVericifyRunRef, } from "./vericify-bridge.js";
|
|
6
6
|
import { buildToolPlan, renderAceContext } from "./ace-context.js";
|
|
7
7
|
import { appendRunLedgerEntrySafe } from "./run-ledger.js";
|
|
8
8
|
import { appendStatusEventSafe } from "./status-events.js";
|
|
@@ -479,7 +479,7 @@ function isRetryableProviderError(error) {
|
|
|
479
479
|
function formatToolFeedback(results) {
|
|
480
480
|
return [
|
|
481
481
|
"Tool execution results:",
|
|
482
|
-
...results.map((result) => `- ${result.tool}: ${result.ok ? "ok" : "error"} — ${result.summary}`),
|
|
482
|
+
...results.map((result) => `- ${result.tool}: ${result.reason_code === "still_running" ? "still_running" : result.ok ? "ok" : "error"} — ${result.summary}`),
|
|
483
483
|
"Continue with another JSON response.",
|
|
484
484
|
].join("\n");
|
|
485
485
|
}
|
|
@@ -527,31 +527,67 @@ function withUsageTotals(result, usageTotals) {
|
|
|
527
527
|
function contextOverflowSuspected(usage, numCtx) {
|
|
528
528
|
return Boolean(usage && usage.prompt_tokens >= Math.floor(numCtx * 0.98));
|
|
529
529
|
}
|
|
530
|
-
const DEFAULT_TOOL_DEADLINE_MS = 120_000;
|
|
531
530
|
function toolDeadlineMs() {
|
|
532
531
|
const raw = Number(process.env.ACE_TOOL_DEADLINE_MS);
|
|
533
|
-
return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) :
|
|
532
|
+
return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : undefined;
|
|
534
533
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
534
|
+
const pendingToolOperations = new Map();
|
|
535
|
+
function canonicalToolInput(value) {
|
|
536
|
+
if (Array.isArray(value))
|
|
537
|
+
return value.map(canonicalToolInput);
|
|
538
|
+
if (value && typeof value === "object")
|
|
539
|
+
return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, entry]) => [key, canonicalToolInput(entry)]));
|
|
540
|
+
return value;
|
|
541
|
+
}
|
|
542
|
+
/** No implicit cutoff. An explicit deadline requests cancellation; unconfirmed
|
|
543
|
+
* cancellation is reported as still running. Identical retries collect the same
|
|
544
|
+
* operation instead of launching a duplicate side effect. */
|
|
541
545
|
export async function executeToolWithDeadline(tool, args, sessionId, opts, deadlineMs, exec = executeAceInternalTool) {
|
|
546
|
+
const key = JSON.stringify([sessionId, opts.workspace_path, tool, canonicalToolInput(args)]);
|
|
547
|
+
let operation = pendingToolOperations.get(key);
|
|
548
|
+
const collecting = Boolean(operation);
|
|
549
|
+
if (!operation) {
|
|
550
|
+
const controller = new AbortController();
|
|
551
|
+
const forwardAbort = () => controller.abort(opts.signal?.reason);
|
|
552
|
+
if (opts.signal?.aborted)
|
|
553
|
+
forwardAbort();
|
|
554
|
+
else
|
|
555
|
+
opts.signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
556
|
+
const created = { id: randomUUID(), controller, state: "running", promise: Promise.resolve() };
|
|
557
|
+
created.promise = Promise.resolve().then(() => exec(tool, args, sessionId, { ...opts, signal: controller.signal })).then((value) => { created.state = "done"; return value; }, (error) => { created.state = "failed"; throw error; }).finally(() => opts.signal?.removeEventListener("abort", forwardAbort));
|
|
558
|
+
// Keep eventual failures observed while an explicit caller has stopped waiting.
|
|
559
|
+
void created.promise.catch(() => undefined);
|
|
560
|
+
operation = created;
|
|
561
|
+
pendingToolOperations.set(key, operation);
|
|
562
|
+
}
|
|
542
563
|
let timer;
|
|
543
|
-
const
|
|
544
|
-
timer = setTimeout(() => resolve({ rawToolResult: undefined, timedOut: true }), deadlineMs);
|
|
545
|
-
timer.unref?.();
|
|
546
|
-
});
|
|
564
|
+
const pending = Symbol("still-running");
|
|
547
565
|
try {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
566
|
+
const value = deadlineMs === undefined || deadlineMs <= 0
|
|
567
|
+
? await operation.promise
|
|
568
|
+
: await Promise.race([
|
|
569
|
+
operation.promise,
|
|
570
|
+
new Promise((resolve) => { timer = setTimeout(() => resolve(pending), deadlineMs); timer.unref?.(); }),
|
|
571
|
+
]);
|
|
572
|
+
if (value === pending) {
|
|
573
|
+
operation.controller.abort(new Error(`Explicit tool deadline elapsed after ${deadlineMs}ms`));
|
|
574
|
+
return {
|
|
551
575
|
timedOut: false,
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
576
|
+
stillRunning: true,
|
|
577
|
+
operationId: operation.id,
|
|
578
|
+
rawToolResult: {
|
|
579
|
+
isError: false,
|
|
580
|
+
structuredContent: { status: "still_running", operation_id: operation.id, cancellation_requested: true },
|
|
581
|
+
content: [{ type: "text", text: `Operation ${operation.id} is still running after its explicit deadline; cancellation was requested but is not yet confirmed. Repeat this same tool call to collect its result without starting duplicate work.` }],
|
|
582
|
+
},
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
pendingToolOperations.delete(key);
|
|
586
|
+
return { rawToolResult: value, timedOut: false, operationId: collecting ? operation.id : undefined };
|
|
587
|
+
}
|
|
588
|
+
catch (error) {
|
|
589
|
+
pendingToolOperations.delete(key);
|
|
590
|
+
throw error;
|
|
555
591
|
}
|
|
556
592
|
finally {
|
|
557
593
|
if (timer)
|
|
@@ -727,7 +763,7 @@ export class ModelBridge {
|
|
|
727
763
|
session_id: this.bridgeId,
|
|
728
764
|
role: options.role,
|
|
729
765
|
});
|
|
730
|
-
await
|
|
766
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
731
767
|
run_id: refs.run_id,
|
|
732
768
|
branch_id: refs.branch_id,
|
|
733
769
|
lane_id: refs.lane_id,
|
|
@@ -871,7 +907,7 @@ export class ModelBridge {
|
|
|
871
907
|
// intra-turn runaway is bounded separately by the num_predict output cap.
|
|
872
908
|
const textLoopCounts = new Map();
|
|
873
909
|
try {
|
|
874
|
-
await
|
|
910
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
875
911
|
run_id: refs.run_id,
|
|
876
912
|
branch_id: refs.branch_id,
|
|
877
913
|
lane_id: refs.lane_id,
|
|
@@ -881,7 +917,7 @@ export class ModelBridge {
|
|
|
881
917
|
tool_refs: aceContext.tools.map((tool) => tool.name),
|
|
882
918
|
});
|
|
883
919
|
noteProgress("process_post", { kind: "intent" });
|
|
884
|
-
for (let turn = 1; turn <= options.maxTurns; turn += 1) {
|
|
920
|
+
for (let turn = 1; options.maxTurns === 0 || turn <= options.maxTurns; turn += 1) {
|
|
885
921
|
const compressed = compressConversationHistory(messages, numCtx);
|
|
886
922
|
if (compressed.compressed) {
|
|
887
923
|
messages.splice(0, messages.length, ...compressed.messages);
|
|
@@ -936,7 +972,7 @@ export class ModelBridge {
|
|
|
936
972
|
}
|
|
937
973
|
if (textLoopCount >= 4) {
|
|
938
974
|
const summary = "Bridge blocked after repeating an identical response four times without progress.";
|
|
939
|
-
await
|
|
975
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
940
976
|
run_id: refs.run_id,
|
|
941
977
|
branch_id: refs.branch_id,
|
|
942
978
|
lane_id: refs.lane_id,
|
|
@@ -1020,7 +1056,7 @@ export class ModelBridge {
|
|
|
1020
1056
|
const summary = rawResponse.trim() || "Bridge completed.";
|
|
1021
1057
|
options.onOutput?.(summary);
|
|
1022
1058
|
noteProgress("output", { status: "complete", fallback: "plain_text" });
|
|
1023
|
-
await
|
|
1059
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
1024
1060
|
run_id: refs.run_id,
|
|
1025
1061
|
branch_id: refs.branch_id,
|
|
1026
1062
|
lane_id: refs.lane_id,
|
|
@@ -1077,7 +1113,7 @@ export class ModelBridge {
|
|
|
1077
1113
|
status: "parse_error",
|
|
1078
1114
|
role_contract_violation: isContractViolation,
|
|
1079
1115
|
});
|
|
1080
|
-
await
|
|
1116
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
1081
1117
|
run_id: refs.run_id,
|
|
1082
1118
|
branch_id: refs.branch_id,
|
|
1083
1119
|
lane_id: refs.lane_id,
|
|
@@ -1146,14 +1182,8 @@ export class ModelBridge {
|
|
|
1146
1182
|
noteProgress("tool_start", { tool: toolCall.tool });
|
|
1147
1183
|
const deadlineMs = toolDeadlineMs();
|
|
1148
1184
|
const outcome = await executeToolWithDeadline(toolCall.tool, args, sessionId, { workspace_path: options.workspace }, deadlineMs);
|
|
1149
|
-
const result = outcome.
|
|
1150
|
-
? {
|
|
1151
|
-
tool: toolCall.tool,
|
|
1152
|
-
ok: false,
|
|
1153
|
-
isError: true,
|
|
1154
|
-
summary: `tool_timeout: ${toolCall.tool} exceeded ${deadlineMs}ms deadline`,
|
|
1155
|
-
reason_code: "tool_timeout",
|
|
1156
|
-
}
|
|
1185
|
+
const result = outcome.stillRunning
|
|
1186
|
+
? { tool: toolCall.tool, ok: false, isError: false, summary: summarizeToolText(outcome.rawToolResult), reason_code: "still_running" }
|
|
1157
1187
|
: truncateToolResult({
|
|
1158
1188
|
tool: toolCall.tool,
|
|
1159
1189
|
ok: !Boolean(outcome.rawToolResult?.isError),
|
|
@@ -1161,7 +1191,7 @@ export class ModelBridge {
|
|
|
1161
1191
|
summary: summarizeToolText(outcome.rawToolResult),
|
|
1162
1192
|
}, options.workspace);
|
|
1163
1193
|
options.onToolResult?.(toolCall.tool, result);
|
|
1164
|
-
noteProgress("tool_finish", { tool: toolCall.tool, ok: result.ok });
|
|
1194
|
+
noteProgress(result.reason_code === "still_running" ? "thinking" : "tool_finish", { tool: toolCall.tool, ok: result.ok });
|
|
1165
1195
|
toolResults.push(result);
|
|
1166
1196
|
if (result.ok) {
|
|
1167
1197
|
const pathArg = typeof args.path === "string"
|
|
@@ -1187,6 +1217,8 @@ export class ModelBridge {
|
|
|
1187
1217
|
toolCalls: executed,
|
|
1188
1218
|
});
|
|
1189
1219
|
for (const { toolCall, result } of executedPairs) {
|
|
1220
|
+
if (result.reason_code === "still_running")
|
|
1221
|
+
continue;
|
|
1190
1222
|
const loopKey = toolDoomLoopKey(toolCall, result);
|
|
1191
1223
|
const count = (toolDoomLoopCounts.get(loopKey) ?? 0) + 1;
|
|
1192
1224
|
toolDoomLoopCounts.set(loopKey, count);
|
|
@@ -1205,7 +1237,7 @@ export class ModelBridge {
|
|
|
1205
1237
|
}
|
|
1206
1238
|
if (count >= 4) {
|
|
1207
1239
|
const summary = `Bridge blocked after repeated identical tool result for ${toolCall.tool}.`;
|
|
1208
|
-
await
|
|
1240
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
1209
1241
|
run_id: refs.run_id,
|
|
1210
1242
|
branch_id: refs.branch_id,
|
|
1211
1243
|
lane_id: refs.lane_id,
|
|
@@ -1251,7 +1283,7 @@ export class ModelBridge {
|
|
|
1251
1283
|
const message = readEnvelopeText(envelope.message) || rawResponse.trim();
|
|
1252
1284
|
options.onOutput?.(message);
|
|
1253
1285
|
noteProgress("output", { status: "message" });
|
|
1254
|
-
await
|
|
1286
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
1255
1287
|
run_id: refs.run_id,
|
|
1256
1288
|
branch_id: refs.branch_id,
|
|
1257
1289
|
lane_id: refs.lane_id,
|
|
@@ -1293,7 +1325,7 @@ export class ModelBridge {
|
|
|
1293
1325
|
const message = readEnvelopeText(envelope.message) || "Additional operator input required.";
|
|
1294
1326
|
options.onOutput?.(message);
|
|
1295
1327
|
noteProgress("output", { status: "need_input" });
|
|
1296
|
-
await
|
|
1328
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
1297
1329
|
run_id: refs.run_id,
|
|
1298
1330
|
branch_id: refs.branch_id,
|
|
1299
1331
|
lane_id: refs.lane_id,
|
|
@@ -1348,7 +1380,7 @@ export class ModelBridge {
|
|
|
1348
1380
|
const driftSummary = `[output_drift_violation] ${role}: ${driftViolation}`;
|
|
1349
1381
|
options.onOutput?.(driftSummary);
|
|
1350
1382
|
noteProgress("output", { status: "output_drift_violation" });
|
|
1351
|
-
await
|
|
1383
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
1352
1384
|
run_id: refs.run_id,
|
|
1353
1385
|
branch_id: refs.branch_id,
|
|
1354
1386
|
lane_id: refs.lane_id,
|
|
@@ -1372,7 +1404,7 @@ export class ModelBridge {
|
|
|
1372
1404
|
// Clean output — accept the completion.
|
|
1373
1405
|
options.onOutput?.(summary);
|
|
1374
1406
|
noteProgress("output", { status: "complete" });
|
|
1375
|
-
await
|
|
1407
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
1376
1408
|
run_id: refs.run_id,
|
|
1377
1409
|
branch_id: refs.branch_id,
|
|
1378
1410
|
lane_id: refs.lane_id,
|
|
@@ -1402,7 +1434,7 @@ export class ModelBridge {
|
|
|
1402
1434
|
}
|
|
1403
1435
|
}
|
|
1404
1436
|
const summary = "Bridge stopped after reaching max turns.";
|
|
1405
|
-
await
|
|
1437
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
1406
1438
|
run_id: refs.run_id,
|
|
1407
1439
|
branch_id: refs.branch_id,
|
|
1408
1440
|
lane_id: refs.lane_id,
|
|
@@ -1,8 +1,48 @@
|
|
|
1
|
+
export { getReadyTaskSteps, collectUpstreamOutputs } from "./task-plan-context.js";
|
|
1
2
|
import { type DispatchJobsResult } from "./job-scheduler.js";
|
|
2
3
|
import type { BridgeResult } from "./model-bridge.js";
|
|
3
4
|
import type { LocalModelRuntimeRepository } from "./store/repositories/local-model-runtime-repository.js";
|
|
4
5
|
export type TaskStepStatus = "planned" | "running" | "done" | "failed" | "skipped" | "blocked";
|
|
5
6
|
export type TaskPlanStatus = "planning" | "executing" | "reviewing" | "blocked" | "done" | "failed";
|
|
7
|
+
export interface ObservedRun {
|
|
8
|
+
record_id: string;
|
|
9
|
+
attribution: "Linked" | "Inferred" | "Ambiguous" | "Unknown";
|
|
10
|
+
command: string;
|
|
11
|
+
cwd?: string;
|
|
12
|
+
exit_code: number | null;
|
|
13
|
+
outcome: "ok" | "failed" | "unknown";
|
|
14
|
+
at: string;
|
|
15
|
+
output_tail?: string;
|
|
16
|
+
command_norm: string;
|
|
17
|
+
paths?: string[];
|
|
18
|
+
tool_use_id?: string;
|
|
19
|
+
session_id?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface StepAttempt {
|
|
22
|
+
attempt: number;
|
|
23
|
+
status: "done" | "blocked" | "failed";
|
|
24
|
+
at: string;
|
|
25
|
+
summary: string;
|
|
26
|
+
checks?: Array<{
|
|
27
|
+
command: string;
|
|
28
|
+
cwd: string;
|
|
29
|
+
ok: boolean;
|
|
30
|
+
}>;
|
|
31
|
+
failure_signature?: string;
|
|
32
|
+
failure_excerpt?: string;
|
|
33
|
+
scope_snapshot?: {
|
|
34
|
+
role: string;
|
|
35
|
+
paths: string[];
|
|
36
|
+
task_tags: string[];
|
|
37
|
+
};
|
|
38
|
+
served_context?: {
|
|
39
|
+
items: Array<Pick<import('./learning-serving.js').ServedLearningItem, 'id' | 'kind' | 'scope'>>;
|
|
40
|
+
rendered_bytes: number;
|
|
41
|
+
};
|
|
42
|
+
evidence_refs: string[];
|
|
43
|
+
served?: string[];
|
|
44
|
+
observed_runs?: ObservedRun[];
|
|
45
|
+
}
|
|
6
46
|
export interface TaskStep {
|
|
7
47
|
step_id: string;
|
|
8
48
|
role: string;
|
|
@@ -25,6 +65,8 @@ export interface TaskStep {
|
|
|
25
65
|
expected_artifacts?: Array<{
|
|
26
66
|
path: string;
|
|
27
67
|
required?: boolean;
|
|
68
|
+
/** Required when this step completes, but not a final deliverable. */
|
|
69
|
+
transient?: boolean;
|
|
28
70
|
evidence_ref_kind?: "artifact" | "diff" | "hash" | "test" | "gate";
|
|
29
71
|
}>;
|
|
30
72
|
allowed_tools?: string[];
|
|
@@ -35,6 +77,72 @@ export interface TaskStep {
|
|
|
35
77
|
reason: string;
|
|
36
78
|
evidence_ref: string;
|
|
37
79
|
};
|
|
80
|
+
assignee?: string;
|
|
81
|
+
attempt?: number;
|
|
82
|
+
started_at?: string;
|
|
83
|
+
last_ace_call_at?: string;
|
|
84
|
+
waiting_on?: string;
|
|
85
|
+
result_digest?: string;
|
|
86
|
+
result_response?: unknown;
|
|
87
|
+
attempts_log?: StepAttempt[];
|
|
88
|
+
served_learning?: import('./learning-serving.js').ServedLearning;
|
|
89
|
+
learning_feedback?: Array<{
|
|
90
|
+
id: string;
|
|
91
|
+
helpful: boolean;
|
|
92
|
+
}>;
|
|
93
|
+
loaded_learning?: Array<{
|
|
94
|
+
id: string;
|
|
95
|
+
at: string;
|
|
96
|
+
}>;
|
|
97
|
+
learning_kind?: "meta" | "graduation";
|
|
98
|
+
learning_source?: string;
|
|
99
|
+
learning_trigger?: string;
|
|
100
|
+
learning_inputs?: import('./learning-input-context.js').LearningInputRefs;
|
|
101
|
+
learning_scope?: string;
|
|
102
|
+
learning_opened_at?: string;
|
|
103
|
+
learning_payload?: import('./learned-artifacts.js').LearnedPayload;
|
|
104
|
+
learning_result?: import('./learned-artifacts.js').LearningAcceptance;
|
|
105
|
+
attempt_history?: Array<Pick<TaskStep, 'attempt' | 'assignee' | 'status' | 'result_summary' | 'evidence' | 'artifacts' | 'result_digest' | 'result_response'>>;
|
|
106
|
+
evidence?: Array<{
|
|
107
|
+
ref: string;
|
|
108
|
+
kind: "command" | "artifact" | "diff" | "note";
|
|
109
|
+
provenance: "host" | "ace";
|
|
110
|
+
detail?: string;
|
|
111
|
+
ok?: boolean;
|
|
112
|
+
}>;
|
|
113
|
+
artifacts?: string[];
|
|
114
|
+
todo_id?: string;
|
|
115
|
+
required_observation?: "action" | "command_pass";
|
|
116
|
+
observation?: "available" | "pending" | "unavailable";
|
|
117
|
+
observation_window?: {
|
|
118
|
+
workspace_id: string;
|
|
119
|
+
session_id?: string;
|
|
120
|
+
started_at: string;
|
|
121
|
+
ended_at?: string;
|
|
122
|
+
};
|
|
123
|
+
observation_refs?: Array<{
|
|
124
|
+
id: string;
|
|
125
|
+
attribution: "Linked" | "Inferred" | "Ambiguous" | "Unknown";
|
|
126
|
+
kind: string;
|
|
127
|
+
result?: string;
|
|
128
|
+
run?: ObservedRun;
|
|
129
|
+
}>;
|
|
130
|
+
/** Additive acceptance metadata; saved result_response and original window remain immutable. */
|
|
131
|
+
observation_check?: {
|
|
132
|
+
attempt: number;
|
|
133
|
+
status: "pending" | "passed" | "unmet" | "unsupported";
|
|
134
|
+
deadline_at: string;
|
|
135
|
+
wait_ms: number;
|
|
136
|
+
poll_ms: number;
|
|
137
|
+
reason_code?: string;
|
|
138
|
+
};
|
|
139
|
+
observation_query?: Record<string, unknown>;
|
|
140
|
+
observation_coverage?: Record<string, unknown>;
|
|
141
|
+
verification_failure?: {
|
|
142
|
+
command: string;
|
|
143
|
+
output: string;
|
|
144
|
+
ref: string;
|
|
145
|
+
};
|
|
38
146
|
}
|
|
39
147
|
export interface TaskPlan {
|
|
40
148
|
plan_id: string;
|
|
@@ -138,15 +246,9 @@ export declare function createTaskPlan(input: {
|
|
|
138
246
|
execution_mode?: TaskPlan["execution_mode"];
|
|
139
247
|
vcx_cursor?: string;
|
|
140
248
|
}): TaskPlan;
|
|
141
|
-
export declare function getReadyTaskSteps(plan: TaskPlan): TaskStep[];
|
|
142
249
|
export declare function markTaskStepStatus(plan: TaskPlan, stepId: string, status: TaskStepStatus, patch?: Partial<Omit<TaskStep, "step_id" | "status">>): TaskPlan;
|
|
143
250
|
export declare function applyBridgeResultToStep(plan: TaskPlan, stepId: string, result: BridgeResult): TaskPlan;
|
|
144
251
|
export declare function amendTaskPlan(plan: TaskPlan, amendment: TaskPlanAmendment): TaskPlan;
|
|
145
|
-
export declare function collectUpstreamOutputs(plan: TaskPlan, step: TaskStep): {
|
|
146
|
-
step_id: string;
|
|
147
|
-
result_summary: string;
|
|
148
|
-
evidence_refs: string[];
|
|
149
|
-
}[];
|
|
150
252
|
export declare function applyBridgeResultToStepWithTransition(plan: TaskPlan, stepId: string, result: BridgeResult, repo?: LocalModelRuntimeRepository): Promise<TaskPlan>;
|
|
151
253
|
export declare function amendTaskPlanWithTransition(plan: TaskPlan, amendment: TaskPlanAmendment, repo?: LocalModelRuntimeRepository, reason?: string, reason_code?: string): Promise<TaskPlan>;
|
|
152
254
|
export declare function promoteParallelGroupToScheduler(plan: TaskPlan, parallelGroup: string, owner?: string): Promise<{
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { getReadyTaskSteps, collectUpstreamOutputs } from "./task-plan-context.js";
|
|
2
|
+
export { getReadyTaskSteps, collectUpstreamOutputs } from "./task-plan-context.js";
|
|
1
3
|
import { existsSync } from "node:fs";
|
|
2
4
|
import { dirname } from "node:path";
|
|
3
5
|
import { randomUUID } from "node:crypto";
|
|
4
6
|
import { dispatchJobs, enqueueJob, getJobQueuePath } from "./job-scheduler.js";
|
|
5
|
-
import {
|
|
7
|
+
import { appendAutomaticVericifyProcessPostSafe, deriveWorkspaceVericifyRunRef, } from "./vericify-bridge.js";
|
|
6
8
|
function parseNumericStepId(stepId) {
|
|
7
9
|
const numeric = Number(stepId.replace(/^step-/, ""));
|
|
8
10
|
return Number.isFinite(numeric) && numeric > 0 ? numeric : 0;
|
|
@@ -90,17 +92,6 @@ export function createTaskPlan(input) {
|
|
|
90
92
|
vcx_cursor: input.vcx_cursor,
|
|
91
93
|
});
|
|
92
94
|
}
|
|
93
|
-
export function getReadyTaskSteps(plan) {
|
|
94
|
-
const completed = new Set(plan.steps
|
|
95
|
-
.filter((step) => step.status === "done" || step.status === "skipped")
|
|
96
|
-
.map((step) => step.step_id));
|
|
97
|
-
return plan.steps.filter((step) => {
|
|
98
|
-
if (step.status !== "planned")
|
|
99
|
-
return false;
|
|
100
|
-
const dependencies = step.depends_on ?? [];
|
|
101
|
-
return dependencies.every((dependency) => completed.has(dependency));
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
95
|
export function markTaskStepStatus(plan, stepId, status, patch = {}) {
|
|
105
96
|
return withDerivedStatus({
|
|
106
97
|
...plan,
|
|
@@ -212,25 +203,6 @@ export function amendTaskPlan(plan, amendment) {
|
|
|
212
203
|
vcx_cursor: amendment.vcx_cursor ?? plan.vcx_cursor,
|
|
213
204
|
});
|
|
214
205
|
}
|
|
215
|
-
export function collectUpstreamOutputs(plan, step) {
|
|
216
|
-
const dependencyOutputs = (step.depends_on ?? [])
|
|
217
|
-
.map((depId) => plan.steps.find((s) => s.step_id === depId))
|
|
218
|
-
.filter((dep) => dep?.status === "done")
|
|
219
|
-
.map((dep) => ({
|
|
220
|
-
step_id: dep.step_id,
|
|
221
|
-
result_summary: dep.result_summary ?? "",
|
|
222
|
-
evidence_refs: dep.evidence_refs ?? [],
|
|
223
|
-
}));
|
|
224
|
-
const carriedOutputs = (step.upstream_outputs ?? []).filter((output) => Boolean(output) &&
|
|
225
|
-
typeof output.step_id === "string" &&
|
|
226
|
-
typeof output.result_summary === "string" &&
|
|
227
|
-
Array.isArray(output.evidence_refs));
|
|
228
|
-
const merged = new Map();
|
|
229
|
-
for (const output of [...dependencyOutputs, ...carriedOutputs]) {
|
|
230
|
-
merged.set(output.step_id, output);
|
|
231
|
-
}
|
|
232
|
-
return [...merged.values()];
|
|
233
|
-
}
|
|
234
206
|
export async function applyBridgeResultToStepWithTransition(plan, stepId, result, repo) {
|
|
235
207
|
const updated = applyBridgeResultToStep(plan, stepId, result);
|
|
236
208
|
if (repo && plan.plan_id) {
|
|
@@ -351,7 +323,7 @@ export async function promoteParallelGroupToScheduler(plan, parallelGroup, owner
|
|
|
351
323
|
? dispatch.error ?? job?.error
|
|
352
324
|
: undefined;
|
|
353
325
|
}
|
|
354
|
-
await
|
|
326
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
355
327
|
run_id: refs.run_id,
|
|
356
328
|
branch_id: refs.branch_id,
|
|
357
329
|
lane_id: refs.lane_id,
|
package/dist/plan-proposal.js
CHANGED
|
@@ -8,7 +8,7 @@ import { listAceInternalToolCatalog } from "./ace-internal-tools.js";
|
|
|
8
8
|
import { runLocalModelTask } from "./local-model-runtime.js";
|
|
9
9
|
import { listRuntimeToolSpecs } from "./runtime-tool-specs.js";
|
|
10
10
|
import { resolveWorkspaceRoot, safeRead, safeWriteAsync } from "./helpers.js";
|
|
11
|
-
import {
|
|
11
|
+
import { appendAutomaticVericifyProcessPostSafe } from "./vericify-bridge.js";
|
|
12
12
|
import { withLocalModelRuntimeRepository } from "./store/repositories/local-model-runtime-repository.js";
|
|
13
13
|
// ── In-memory proposal cache (plan_id → ProposePlanResult) ────────────────
|
|
14
14
|
const _proposalCache = new Map();
|
|
@@ -1051,8 +1051,8 @@ export async function validatePlan(input) {
|
|
|
1051
1051
|
catch {
|
|
1052
1052
|
// Non-fatal
|
|
1053
1053
|
}
|
|
1054
|
-
//
|
|
1055
|
-
await
|
|
1054
|
+
// Optional legacy summary; native Vericify owns observation capture.
|
|
1055
|
+
await appendAutomaticVericifyProcessPostSafe({
|
|
1056
1056
|
run_id: "workspace:current",
|
|
1057
1057
|
agent_id: "ace-planner",
|
|
1058
1058
|
kind: "plan_quality_assessment",
|