@algosuite/vo-mcp 0.2.0-beta.57 → 0.2.0-beta.59

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.
@@ -3666,6 +3666,93 @@ var init_control_plane_knowledge_context = __esm({
3666
3666
  }
3667
3667
  });
3668
3668
 
3669
+ // ../../scripts/virtual-office/code-runner/control-plane-prepared-job.mjs
3670
+ function preparedJobQuery({ agent = "claude", env: env2 = {} } = {}) {
3671
+ const params = new URLSearchParams();
3672
+ params.set("agent", String(agent));
3673
+ const sent = [];
3674
+ const dropped = [];
3675
+ for (const key of PREPARED_JOB_ENV_QUERY_KEYS) {
3676
+ const raw = env2?.[key];
3677
+ if (typeof raw !== "string" || raw.length === 0) continue;
3678
+ if (raw.length > PREPARED_JOB_ENV_VALUE_MAX) {
3679
+ dropped.push(key);
3680
+ continue;
3681
+ }
3682
+ params.set(key, raw);
3683
+ sent.push(key);
3684
+ }
3685
+ return { query: params.toString(), sent, dropped };
3686
+ }
3687
+ async function refusalCode(res) {
3688
+ try {
3689
+ const body = await res.json();
3690
+ return typeof body?.error === "string" && body.error ? body.error : null;
3691
+ } catch {
3692
+ return null;
3693
+ }
3694
+ }
3695
+ async function getPreparedJobRequest(req, taskId, options = {}, invalidateToken = () => {
3696
+ }) {
3697
+ const { agent = "claude", env: env2 = {}, timeoutMs = 15e3 } = options;
3698
+ const { query, sent, dropped } = preparedJobQuery({ agent, env: env2 });
3699
+ const envMeta = { envSent: sent, envDropped: dropped };
3700
+ if (typeof taskId !== "string" || taskId.length === 0) {
3701
+ return { ok: false, reason: "missing_task_id", status: 0, ...envMeta };
3702
+ }
3703
+ const path22 = `/api/v1/code-task/${encodeURIComponent(taskId)}/prepared-job?${query}`;
3704
+ let res;
3705
+ try {
3706
+ res = await req("GET", path22, void 0, { timeoutMs });
3707
+ } catch (err) {
3708
+ return { ok: false, reason: `transport: ${err?.message || String(err)}`, status: 0, ...envMeta };
3709
+ }
3710
+ if (res?.status === 401) {
3711
+ try {
3712
+ invalidateToken();
3713
+ } catch {
3714
+ }
3715
+ return { ok: false, reason: "unauthorized", status: 401, ...envMeta };
3716
+ }
3717
+ if (!res?.ok) {
3718
+ const code = await refusalCode(res);
3719
+ return { ok: false, reason: code || `http_${res?.status ?? "unknown"}`, status: res?.status ?? 0, ...envMeta };
3720
+ }
3721
+ let body;
3722
+ try {
3723
+ body = await res.json();
3724
+ } catch (err) {
3725
+ return { ok: false, reason: `unreadable_body: ${err?.message || String(err)}`, status: res.status, ...envMeta };
3726
+ }
3727
+ const job = body?.prepared_job;
3728
+ if (!job || typeof job !== "object") {
3729
+ return { ok: false, reason: "no_prepared_job_in_body", status: res.status, ...envMeta };
3730
+ }
3731
+ return {
3732
+ ok: true,
3733
+ job,
3734
+ composition: body?.composition && typeof body.composition === "object" ? body.composition : {},
3735
+ ...envMeta
3736
+ };
3737
+ }
3738
+ var PREPARED_JOB_ENV_QUERY_KEYS, PREPARED_JOB_ENV_VALUE_MAX;
3739
+ var init_control_plane_prepared_job = __esm({
3740
+ "../../scripts/virtual-office/code-runner/control-plane-prepared-job.mjs"() {
3741
+ "use strict";
3742
+ PREPARED_JOB_ENV_QUERY_KEYS = [
3743
+ "VO_CODE_RUNNER_NO_WEB",
3744
+ "VO_CODE_RUNNER_NO_WORKFLOW",
3745
+ "VO_CODE_RUNNER_NO_CONSENSUS",
3746
+ "VO_CODE_RUNNER_PERMISSION_MODE",
3747
+ "VO_CODE_RUNNER_DEFAULT_BUDGET_USD",
3748
+ "VO_CODE_RUNNER_META_REASONING_EFFORT",
3749
+ "VO_CODE_RUNNER_ALLOW_MISSING_KNOWLEDGE_CONTEXT",
3750
+ "VO_ENABLE_CONTEXT7"
3751
+ ];
3752
+ PREPARED_JOB_ENV_VALUE_MAX = 64;
3753
+ }
3754
+ });
3755
+
3669
3756
  // src/runner/control-plane-auth-stub.mjs
3670
3757
  var control_plane_auth_stub_exports = {};
3671
3758
  __export(control_plane_auth_stub_exports, {
@@ -3902,6 +3989,10 @@ function createControlPlaneClient({
3902
3989
  log: (m) => console.warn(`[code-runner ${(/* @__PURE__ */ new Date()).toISOString()}] ${m}`)
3903
3990
  });
3904
3991
  },
3992
+ /** ADR-004 § 11.1b: the plane's prepared job, for SHADOW comparison. Never throws. */
3993
+ getPreparedJob: (taskId, options) => getPreparedJobRequest(req, taskId, options, () => {
3994
+ cachedFirebaseToken = null;
3995
+ }),
3905
3996
  /** Weekly Claude token usage report — see control-plane-weekly-tokens.mjs. */
3906
3997
  async postWeeklyTokens(report) {
3907
3998
  return postWeeklyTokensRequest(taskReq, report, () => {
@@ -3923,8 +4014,8 @@ function createControlPlaneClient({
3923
4014
  * authenticated operator so the web shows a TRUE "runner online" signal.
3924
4015
  * Best-effort caller; throws on 401/non-ok so the daemon can log + retry.
3925
4016
  */
3926
- async postHeartbeat({ runnerId: runnerId2, runnerInstanceId: runnerInstanceId2, operatorId, uptimeSec, activeTasks, maxConcurrency, effectiveConcurrency, measuredTaskSlots, measuredCpuSlots, measuredMemorySlots, version, daemonVersion, defaultAgent, supervisorInstanceId, supervisorVersion, supervisorCapabilities, servedRepos, servedOperators, availableAgents, accountUsage, availableLocalModels }) {
3927
- const body = { runner_id: runnerId2 };
4017
+ async postHeartbeat({ runnerId: runnerId2, runnerInstanceId: runnerInstanceId2, operatorId, uptimeSec, activeTasks, maxConcurrency, effectiveConcurrency, measuredTaskSlots, measuredCpuSlots, measuredMemorySlots, version, daemonVersion, defaultAgent, supervisorInstanceId, supervisorVersion, supervisorCapabilities, servedRepos, servedOperators, availableAgents, accountUsage, availableLocalModels, prepared_job_shadow: preparedJobShadow }) {
4018
+ const body = { runner_id: runnerId2, ...preparedJobShadow ? { prepared_job_shadow: preparedJobShadow } : {} };
3928
4019
  if (runnerInstanceId2) body.runner_instance_id = runnerInstanceId2;
3929
4020
  if (operatorId) body.operator_id = operatorId;
3930
4021
  if (typeof uptimeSec === "number") body.uptime_sec = uptimeSec;
@@ -4055,6 +4146,7 @@ var init_control_plane_client = __esm({
4055
4146
  init_control_plane_telemetry_relay();
4056
4147
  init_claim_gate_notice();
4057
4148
  init_control_plane_knowledge_context();
4149
+ init_control_plane_prepared_job();
4058
4150
  cachedFirebaseToken = null;
4059
4151
  ClaimAuthorityChangedError = class extends Error {
4060
4152
  constructor() {
@@ -7649,8 +7741,17 @@ function messageExcerpt(output) {
7649
7741
  const s = String(output ?? "");
7650
7742
  return s.length > 1200 ? `...${s.slice(-1200)}` : s;
7651
7743
  }
7652
- async function enforceCompletionGateOrFail({ client, id, task, worktreeDir, log: log2 = () => {
7653
- }, execFileImpl = execFile } = {}) {
7744
+ async function enforceCompletionGateOrFail({
7745
+ client,
7746
+ id,
7747
+ task,
7748
+ worktreeDir,
7749
+ run = null,
7750
+ truncated = false,
7751
+ log: log2 = () => {
7752
+ },
7753
+ execFileImpl = execFile
7754
+ } = {}) {
7654
7755
  const resolved = resolveCompletionGate(task);
7655
7756
  if (resolved === null) return false;
7656
7757
  if (resolved.invalid) {
@@ -7674,6 +7775,12 @@ ${messageExcerpt(cached2.output)}`, "completion_gate_failed");
7674
7775
  return false;
7675
7776
  }
7676
7777
  const kind = outcome.timedOut ? `timed out after ${COMPLETION_GATE_TIMEOUT_MS}ms` : `exited ${outcome.exitCode}`;
7778
+ if (truncated) {
7779
+ log2(`task ${id}: completion gate FAILED (${kind}) after a budget/turn-truncated run \u2014 salvaging as PARTIAL draft, not terminal-failing`);
7780
+ if (run) run.gateFailureNote = `completion gate '${task.completion_gate}' ${kind} (gate ran against a budget/turn-truncated run):
7781
+ ${messageExcerpt(outcome.output)}`;
7782
+ return false;
7783
+ }
7677
7784
  log2(`task ${id}: completion gate FAILED (${kind}) \u2014 not publishing`);
7678
7785
  await postFailed2(client, id, `completion gate '${task.completion_gate}' ${kind} \u2014 task may not claim completion:
7679
7786
  ${messageExcerpt(outcome.output)}`, "completion_gate_failed");
@@ -8769,13 +8876,13 @@ async function materializeTaskAttachments(client, task, { tempRoot = os2.tmpdir(
8769
8876
  const content = await client.downloadTaskAttachment(task.code_task_id, ref.attachment_id);
8770
8877
  if (!Buffer.isBuffer(content)) throw new Error(`attachment ${ref.attachment_id} did not return binary content`);
8771
8878
  if (content.byteLength !== ref.size_bytes) throw new Error(`attachment ${ref.attachment_id} size mismatch`);
8772
- const sha256 = createHash4("sha256").update(content).digest("hex");
8773
- if (sha256 !== ref.sha256) throw new Error(`attachment ${ref.attachment_id} sha256 mismatch`);
8879
+ const sha2562 = createHash4("sha256").update(content).digest("hex");
8880
+ if (sha2562 !== ref.sha256) throw new Error(`attachment ${ref.attachment_id} sha256 mismatch`);
8774
8881
  const name = sanitizeTaskAttachmentName(ref.name, index);
8775
8882
  const filePath = path16.join(state.directory, name);
8776
8883
  await writeFile(filePath, content, { flag: "wx", mode: 384 });
8777
8884
  await chmod(filePath, 384);
8778
- files.push({ attachmentId: ref.attachment_id, name, mime: ref.mime, sizeBytes: ref.size_bytes, sha256, path: path16.resolve(filePath) });
8885
+ files.push({ attachmentId: ref.attachment_id, name, mime: ref.mime, sizeBytes: ref.size_bytes, sha256: sha2562, path: path16.resolve(filePath) });
8779
8886
  }
8780
8887
  return { directory: state.directory, files, manifestMarkdown: buildManifest(files), cleanup: () => cleanupGeneratedDirectory(state) };
8781
8888
  } catch (error) {
@@ -9428,6 +9535,13 @@ function makeLoopTicks({
9428
9535
  applyRemoteConfig: () => false,
9429
9536
  heartbeatFields: () => ({})
9430
9537
  },
9538
+ // ADR-004 § 11.1b-2: plane-delivered prepared-job consumption mode + the
9539
+ // counts-only shadow tally (prepared-job-remote-config.mjs). Same no-op
9540
+ // default contract as above, so an absent controller changes nothing.
9541
+ preparedJobController = {
9542
+ applyRemoteConfig: () => false,
9543
+ heartbeatFields: () => ({})
9544
+ },
9431
9545
  // Host version awareness: reads `update_status` off the heartbeat ACK and logs
9432
9546
  // ONE line per drift change (daemon-update-status.mjs). No-op default keeps
9433
9547
  // old callers working; absent update_status reads as unknown, never current.
@@ -9476,6 +9590,7 @@ function makeLoopTicks({
9476
9590
  request.then((response) => {
9477
9591
  capacityController.applyCapacity(response?.capacity, nextPayload.operatorId);
9478
9592
  localModelController.applyRemoteConfig(response?.local_model, nextPayload.operatorId);
9593
+ preparedJobController.applyRemoteConfig(response?.prepared_job, nextPayload.operatorId);
9479
9594
  updateStatusTracker.applyHeartbeatResponse(response);
9480
9595
  }).catch((e) => log2(`heartbeat failed: ${e.message}`)).finally(() => {
9481
9596
  for (const done of waiters) done();
@@ -9520,6 +9635,7 @@ function makeLoopTicks({
9520
9635
  const supervisorCapabilities = String(env2.VO_RUNNER_SUPERVISOR_CAPABILITIES || "").split(",").map((value) => value.trim()).filter(Boolean).slice(0, 8);
9521
9636
  const capacityFields = capacityController.heartbeatFields();
9522
9637
  const localModelFields = localModelController.heartbeatFields();
9638
+ const preparedJobFields = preparedJobController.heartbeatFields();
9523
9639
  const baseHeartbeat = {
9524
9640
  runnerId: cfg.runnerId,
9525
9641
  ...runnerInstanceId ? { runnerInstanceId } : {},
@@ -9537,7 +9653,8 @@ function makeLoopTicks({
9537
9653
  activeTasks: getActive(),
9538
9654
  maxConcurrency: cfg.maxConcurrency,
9539
9655
  ...capacityFields,
9540
- ...localModelFields
9656
+ ...localModelFields,
9657
+ ...preparedJobFields
9541
9658
  };
9542
9659
  const operatorIds = servedOperators.length > 0 ? servedOperators : [void 0];
9543
9660
  for (const operatorId of operatorIds) {
@@ -9904,6 +10021,434 @@ var init_local_model_remote_config = __esm({
9904
10021
  }
9905
10022
  });
9906
10023
 
10024
+ // ../../scripts/virtual-office/code-runner/prepared-job-shadow.mjs
10025
+ import { appendFileSync, mkdirSync as mkdirSync8 } from "node:fs";
10026
+ import { createHash as createHash6 } from "node:crypto";
10027
+ import { homedir as homedir9 } from "node:os";
10028
+ import { dirname as dirname10, join as join14 } from "node:path";
10029
+ function setRemotePreparedJobMode(mode) {
10030
+ const value = typeof mode === "string" ? mode.trim().toLowerCase() : "";
10031
+ remotePreparedJobMode = value && PREPARED_JOB_MODES.includes(value) ? value : "";
10032
+ }
10033
+ function preparedJobConsumptionMode(env2 = process.env) {
10034
+ const raw = String(env2?.[PREPARED_JOB_MODE_ENV] ?? "").trim().toLowerCase();
10035
+ if (raw && PREPARED_JOB_MODES.includes(raw)) return raw;
10036
+ return remotePreparedJobMode || "off";
10037
+ }
10038
+ function shadowTimeoutMs(env2 = process.env) {
10039
+ const n = Number(env2?.[PREPARED_JOB_SHADOW_TIMEOUT_ENV]);
10040
+ return Number.isFinite(n) && n > 0 ? Math.min(n, 6e4) : DEFAULT_SHADOW_TIMEOUT_MS;
10041
+ }
10042
+ function firstDivergenceIndex(a, b) {
10043
+ const A = String(a ?? "");
10044
+ const B = String(b ?? "");
10045
+ const limit = Math.min(A.length, B.length);
10046
+ for (let i = 0; i < limit; i += 1) if (A[i] !== B[i]) return i;
10047
+ return A.length === B.length ? -1 : limit;
10048
+ }
10049
+ function localCompositionAsPreparedJob(local = {}, { agent = "claude", env: env2 = process.env } = {}) {
10050
+ const isClaude = String(agent || "").trim().toLowerCase() === "claude";
10051
+ return {
10052
+ prompt: local.prompt ?? "",
10053
+ argv: buildClaudeArgs({
10054
+ permissionMode: local.permissionMode,
10055
+ maxTurns: isClaude ? local.maxTurns : void 0,
10056
+ model: local.model,
10057
+ effort: local.effort,
10058
+ maxBudgetUsd: isClaude ? local.maxBudgetUsd : void 0,
10059
+ researchHarness: local.methodology?.shape === "research",
10060
+ env: env2
10061
+ }),
10062
+ permission_mode: local.permissionMode ?? null,
10063
+ dispatch_mode: local.dispatchMode ?? null,
10064
+ tier: local.tier ?? null,
10065
+ model: local.model ?? null,
10066
+ effort: local.effort ?? null,
10067
+ max_turns: local.maxTurns ?? null,
10068
+ max_budget_usd: local.maxBudgetUsd ?? null,
10069
+ methodology_shape: local.methodology?.shape ?? null,
10070
+ methodology_stakes: local.methodology?.stakes ?? null
10071
+ };
10072
+ }
10073
+ function planeJobAsComparable(job = {}) {
10074
+ return {
10075
+ prompt: job.prompt ?? "",
10076
+ argv: job.argv ?? null,
10077
+ permission_mode: job.permission_mode ?? null,
10078
+ dispatch_mode: job.dispatch_mode ?? null,
10079
+ tier: job.tier ?? null,
10080
+ model: job.model ?? null,
10081
+ effort: job.effort ?? null,
10082
+ max_turns: job.max_turns ?? null,
10083
+ max_budget_usd: job.max_budget_usd ?? null,
10084
+ methodology_shape: job.methodology?.shape ?? null,
10085
+ methodology_stakes: job.methodology?.stakes ?? null
10086
+ };
10087
+ }
10088
+ function classifyDivergence(field, ctx = {}) {
10089
+ const known = (reason) => ({ class: "known_remainder", reason });
10090
+ if (Array.isArray(ctx.envDropped) && ctx.envDropped.length > 0) {
10091
+ return known(`env_value_too_long:${ctx.envDropped.join("+")}`);
10092
+ }
10093
+ if ((field === "model" || field === "tier") && ctx.planeModelRegistryUnavailable) {
10094
+ return known("no_plane_model_registry");
10095
+ }
10096
+ if (field === "dispatch_mode" && ctx.taskDispatchModeAbsent) return known("plane_dispatch_mode_default");
10097
+ if (ctx.dispatchModeDiverged && DISPATCH_MODE_DEPENDENT.has(field)) {
10098
+ return known("downstream_of_dispatch_mode");
10099
+ }
10100
+ if (field === "prompt" && ctx.attachmentManifestPresent) return known("attachment_manifest_not_sent");
10101
+ if (field === "prompt" && ctx.planeSkillCatalogUnavailable) return known("skill_catalog_unavailable");
10102
+ return { class: "unexplained", reason: null };
10103
+ }
10104
+ function comparePreparedJob({ local, plane, context = {} }) {
10105
+ const L = local || {};
10106
+ const P = plane || {};
10107
+ const raw = COMPARED_FIELDS.filter((f) => !sameValue(L[f], P[f]));
10108
+ const ctx = { ...context, dispatchModeDiverged: raw.includes("dispatch_mode") };
10109
+ const divergences = raw.map((field) => {
10110
+ const { class: cls, reason } = classifyDivergence(field, ctx);
10111
+ const entry = { field, class: cls, reason };
10112
+ if (field !== "prompt") {
10113
+ entry.runner = L[field] ?? null;
10114
+ entry.plane = P[field] ?? null;
10115
+ }
10116
+ return entry;
10117
+ });
10118
+ const unexplainedFields = divergences.filter((d) => d.class === "unexplained").map((d) => d.field);
10119
+ return {
10120
+ verdict: divergences.length === 0 ? "parity_ok" : unexplainedFields.length > 0 ? "parity_diverged" : "parity_known_remainder",
10121
+ divergences,
10122
+ divergentFields: raw,
10123
+ unexplainedFields,
10124
+ prompt: {
10125
+ runner_len: String(L.prompt ?? "").length,
10126
+ plane_len: String(P.prompt ?? "").length,
10127
+ runner_sha256: sha256(L.prompt),
10128
+ plane_sha256: sha256(P.prompt),
10129
+ first_diff_index: firstDivergenceIndex(L.prompt, P.prompt)
10130
+ }
10131
+ };
10132
+ }
10133
+ function selectDispatchComposition({ mode, local, plane, comparison }) {
10134
+ if (mode === "prepared" && plane && comparison?.verdict !== "unavailable") {
10135
+ return { source: "plane", composition: plane };
10136
+ }
10137
+ return { source: "local", composition: local };
10138
+ }
10139
+ function buildShadowRecord({
10140
+ taskId,
10141
+ repo,
10142
+ agent,
10143
+ mode,
10144
+ comparison,
10145
+ fetched,
10146
+ ts
10147
+ }) {
10148
+ const base = {
10149
+ schema_version: 1,
10150
+ kind: "prepared_job_shadow",
10151
+ adr: "ADR-004 \xA7 11.1b",
10152
+ ts,
10153
+ code_task_id: taskId ?? null,
10154
+ repo: repo ?? null,
10155
+ agent: agent ?? null,
10156
+ mode,
10157
+ env_sent: fetched?.envSent ?? [],
10158
+ env_dropped: fetched?.envDropped ?? []
10159
+ };
10160
+ if (!comparison) {
10161
+ return {
10162
+ ...base,
10163
+ verdict: "unavailable",
10164
+ reason: fetched?.reason ?? "unknown",
10165
+ status: fetched?.status ?? 0,
10166
+ divergent_fields: [],
10167
+ unexplained_fields: [],
10168
+ divergences: []
10169
+ };
10170
+ }
10171
+ return {
10172
+ ...base,
10173
+ verdict: comparison.verdict,
10174
+ reason: null,
10175
+ divergent_fields: comparison.divergentFields,
10176
+ unexplained_fields: comparison.unexplainedFields,
10177
+ divergences: comparison.divergences,
10178
+ prompt: comparison.prompt,
10179
+ plane_composition: {
10180
+ model_registry: fetched?.composition?.model_registry ?? null,
10181
+ skill_catalog_available: fetched?.composition?.skill_catalog_available ?? null
10182
+ }
10183
+ };
10184
+ }
10185
+ function formatShadowLogLine(record) {
10186
+ const parts = [
10187
+ `task=${record.code_task_id}`,
10188
+ `mode=${record.mode}`,
10189
+ `verdict=${record.verdict}`
10190
+ ];
10191
+ if (record.verdict === "unavailable") parts.push(`reason=${record.reason}`, `status=${record.status}`);
10192
+ if (record.unexplained_fields?.length) parts.push(`UNEXPLAINED=${record.unexplained_fields.join(",")}`);
10193
+ const known = (record.divergences || []).filter((d) => d.class === "known_remainder");
10194
+ if (known.length) parts.push(`known=${known.map((d) => `${d.field}(${d.reason})`).join(",")}`);
10195
+ if (record.verdict === "parity_diverged" && typeof record.prompt?.first_diff_index === "number" && record.prompt.first_diff_index >= 0 && record.unexplained_fields?.includes("prompt")) {
10196
+ parts.push(`prompt_first_diff_index=${record.prompt.first_diff_index}`);
10197
+ }
10198
+ const loud = record.unexplained_fields?.length ? "!! " : "";
10199
+ return `${loud}[prepared-job-shadow] ${parts.join(" ")}`;
10200
+ }
10201
+ function appendShadowRecord(record, { path: path22 = PREPARED_JOB_SHADOW_SINK, append = appendFileSync, mkdir: mkdir5 = mkdirSync8 } = {}) {
10202
+ try {
10203
+ mkdir5(dirname10(path22), { recursive: true });
10204
+ append(path22, `${JSON.stringify(record)}
10205
+ `, "utf8");
10206
+ return true;
10207
+ } catch {
10208
+ return false;
10209
+ }
10210
+ }
10211
+ async function preparedJobShadowPass({
10212
+ client,
10213
+ task,
10214
+ agent = "claude",
10215
+ env: env2 = process.env,
10216
+ local,
10217
+ log: log2 = () => {
10218
+ },
10219
+ now = () => (/* @__PURE__ */ new Date()).toISOString(),
10220
+ sinkOptions
10221
+ } = {}) {
10222
+ const mode = preparedJobConsumptionMode(env2);
10223
+ if (mode === "off") return { mode: "off" };
10224
+ try {
10225
+ if (mode === "prepared") {
10226
+ log2("[prepared-job-shadow] prepared_mode_not_wired \u2014 comparing only; ADR-004 \xA7 11.1c owns the flip");
10227
+ }
10228
+ if (typeof client?.getPreparedJob !== "function") {
10229
+ return { mode, verdict: "unavailable", reason: "client_lacks_get_prepared_job" };
10230
+ }
10231
+ const fetched = await client.getPreparedJob(task?.code_task_id, {
10232
+ agent,
10233
+ env: env2,
10234
+ timeoutMs: shadowTimeoutMs(env2)
10235
+ });
10236
+ const localJob = localCompositionAsPreparedJob(local, { agent, env: env2 });
10237
+ const comparison = fetched?.ok ? comparePreparedJob({
10238
+ local: localJob,
10239
+ plane: planeJobAsComparable(fetched.job),
10240
+ context: {
10241
+ planeModelRegistryUnavailable: fetched.composition?.model_registry !== "injected",
10242
+ planeSkillCatalogUnavailable: fetched.composition?.skill_catalog_available === false,
10243
+ taskDispatchModeAbsent: !task?.dispatch_mode,
10244
+ attachmentManifestPresent: Boolean(local?.attachmentManifestMarkdown),
10245
+ envDropped: fetched.envDropped
10246
+ }
10247
+ }) : null;
10248
+ const record = buildShadowRecord({
10249
+ taskId: task?.code_task_id,
10250
+ repo: task?.repo,
10251
+ agent,
10252
+ mode,
10253
+ comparison,
10254
+ fetched,
10255
+ ts: now()
10256
+ });
10257
+ appendShadowRecord(record, sinkOptions);
10258
+ log2(formatShadowLogLine(record));
10259
+ return {
10260
+ mode,
10261
+ verdict: record.verdict,
10262
+ record,
10263
+ selection: selectDispatchComposition({
10264
+ mode,
10265
+ local: localJob,
10266
+ plane: fetched?.ok ? planeJobAsComparable(fetched.job) : null,
10267
+ comparison
10268
+ })
10269
+ };
10270
+ } catch (err) {
10271
+ try {
10272
+ log2(`[prepared-job-shadow] shadow pass failed (dispatch unaffected): ${err?.message || err}`);
10273
+ } catch {
10274
+ }
10275
+ return { mode, verdict: "unavailable", reason: `shadow_error: ${err?.message || String(err)}` };
10276
+ }
10277
+ }
10278
+ function setPreparedJobShadowObserver(fn) {
10279
+ verdictObserver = typeof fn === "function" ? fn : null;
10280
+ }
10281
+ async function runPreparedJobShadow(options = {}) {
10282
+ const result = await preparedJobShadowPass(options);
10283
+ try {
10284
+ verdictObserver?.(result);
10285
+ } catch {
10286
+ }
10287
+ return result;
10288
+ }
10289
+ var PREPARED_JOB_MODES, PREPARED_JOB_MODE_ENV, PREPARED_JOB_SHADOW_TIMEOUT_ENV, DEFAULT_SHADOW_TIMEOUT_MS, PREPARED_JOB_SHADOW_SINK, remotePreparedJobMode, COMPARED_FIELDS, DISPATCH_MODE_DEPENDENT, sha256, sameValue, verdictObserver;
10290
+ var init_prepared_job_shadow = __esm({
10291
+ "../../scripts/virtual-office/code-runner/prepared-job-shadow.mjs"() {
10292
+ "use strict";
10293
+ init_claude_args();
10294
+ PREPARED_JOB_MODES = ["off", "shadow", "prepared"];
10295
+ PREPARED_JOB_MODE_ENV = "VO_CODE_RUNNER_PREPARED_JOB";
10296
+ PREPARED_JOB_SHADOW_TIMEOUT_ENV = "VO_PREPARED_JOB_SHADOW_TIMEOUT_MS";
10297
+ DEFAULT_SHADOW_TIMEOUT_MS = 15e3;
10298
+ PREPARED_JOB_SHADOW_SINK = join14(homedir9(), ".claude", "vo-prepared-job-shadow.jsonl");
10299
+ remotePreparedJobMode = "";
10300
+ COMPARED_FIELDS = [
10301
+ "prompt",
10302
+ "argv",
10303
+ "permission_mode",
10304
+ "dispatch_mode",
10305
+ "tier",
10306
+ "model",
10307
+ "effort",
10308
+ "max_turns",
10309
+ "max_budget_usd",
10310
+ "methodology_shape",
10311
+ "methodology_stakes"
10312
+ ];
10313
+ DISPATCH_MODE_DEPENDENT = /* @__PURE__ */ new Set([
10314
+ "prompt",
10315
+ "argv",
10316
+ "permission_mode",
10317
+ "tier",
10318
+ "model",
10319
+ "effort",
10320
+ "max_turns"
10321
+ ]);
10322
+ sha256 = (s) => createHash6("sha256").update(String(s ?? ""), "utf8").digest("hex");
10323
+ sameValue = (a, b) => Array.isArray(a) || Array.isArray(b) ? JSON.stringify(a) === JSON.stringify(b) : (a ?? null) === (b ?? null);
10324
+ verdictObserver = null;
10325
+ }
10326
+ });
10327
+
10328
+ // ../../scripts/virtual-office/code-runner/prepared-job-remote-config.mjs
10329
+ function emptyPreparedJobTally() {
10330
+ return {
10331
+ compared: 0,
10332
+ parity_ok: 0,
10333
+ parity_diverged: 0,
10334
+ unavailable: 0,
10335
+ unexplained: 0,
10336
+ diverged_fields: {},
10337
+ last_verdict_at: null
10338
+ };
10339
+ }
10340
+ function foldPreparedJobVerdict(tally, result, nowIso) {
10341
+ const verdict = result?.verdict;
10342
+ if (!verdict) return tally;
10343
+ tally.last_verdict_at = nowIso;
10344
+ if (verdict === "unavailable") {
10345
+ tally.unavailable += 1;
10346
+ return tally;
10347
+ }
10348
+ tally.compared += 1;
10349
+ if (verdict === "parity_ok") tally.parity_ok += 1;
10350
+ else if (verdict === "parity_diverged") tally.parity_diverged += 1;
10351
+ const record = result.record || {};
10352
+ tally.unexplained += (record.unexplained_fields || []).length;
10353
+ for (const field of record.divergent_fields || []) {
10354
+ const known = Object.prototype.hasOwnProperty.call(tally.diverged_fields, field);
10355
+ if (!known && Object.keys(tally.diverged_fields).length >= MAX_DIVERGED_FIELD_KEYS) continue;
10356
+ tally.diverged_fields[field] = (tally.diverged_fields[field] || 0) + 1;
10357
+ }
10358
+ return tally;
10359
+ }
10360
+ function createPreparedJobRemoteController({
10361
+ log: log2 = () => {
10362
+ },
10363
+ now = () => (/* @__PURE__ */ new Date()).toISOString(),
10364
+ apply = setRemotePreparedJobMode,
10365
+ observe = setPreparedJobShadowObserver
10366
+ } = {}) {
10367
+ const byOperator = /* @__PURE__ */ new Map();
10368
+ const tally = emptyPreparedJobTally();
10369
+ let planeSpeaksPreparedJob = false;
10370
+ let warnedNotWired = false;
10371
+ let warnedConflict = "";
10372
+ function desiredMode() {
10373
+ const modes = [...new Set(
10374
+ [...byOperator.values()].map((s) => s.mode).filter((m) => m && m !== "off")
10375
+ )];
10376
+ if (modes.length > 1) {
10377
+ const key = modes.slice().sort().join(",");
10378
+ if (warnedConflict !== key) {
10379
+ warnedConflict = key;
10380
+ log2(`prepared-job remote config: conflicting modes across served operators (${key}) \u2014 applying off`);
10381
+ }
10382
+ return "off";
10383
+ }
10384
+ return modes[0] ?? "off";
10385
+ }
10386
+ function syncEffective() {
10387
+ const mode = desiredMode();
10388
+ apply(mode);
10389
+ return mode;
10390
+ }
10391
+ observe((result) => foldPreparedJobVerdict(tally, result, now()));
10392
+ return {
10393
+ /**
10394
+ * Heartbeat payload extras. Silent until the plane has proven it speaks this
10395
+ * contract AND a pass has actually been counted — see safety property 3.
10396
+ */
10397
+ heartbeatFields() {
10398
+ if (!planeSpeaksPreparedJob || tally.last_verdict_at === null) return {};
10399
+ return {
10400
+ prepared_job_shadow: {
10401
+ schema_version: PREPARED_JOB_CONFIG_SCHEMA_VERSION,
10402
+ mode: desiredMode(),
10403
+ ...tally,
10404
+ diverged_fields: { ...tally.diverged_fields }
10405
+ }
10406
+ };
10407
+ },
10408
+ /**
10409
+ * Apply one operator's heartbeat-response echo
10410
+ * `{ schema_version, prepared_job_mode, revision }`. Returns whether the
10411
+ * echo was accepted.
10412
+ */
10413
+ applyRemoteConfig(echo, operatorId = "") {
10414
+ const scope = String(operatorId || "");
10415
+ const previous = byOperator.get(scope);
10416
+ if (!echo || echo.schema_version !== PREPARED_JOB_CONFIG_SCHEMA_VERSION || !Number.isInteger(echo.revision) || previous && echo.revision < previous.revision) {
10417
+ return false;
10418
+ }
10419
+ const raw = typeof echo.prepared_job_mode === "string" ? echo.prepared_job_mode.trim().toLowerCase() : "";
10420
+ if (!PREPARED_JOB_MODES.includes(raw)) return false;
10421
+ planeSpeaksPreparedJob = true;
10422
+ let mode = raw;
10423
+ if (mode === "prepared") {
10424
+ mode = "shadow";
10425
+ if (!warnedNotWired) {
10426
+ warnedNotWired = true;
10427
+ log2("prepared-job remote config: prepared_mode_not_wired \u2014 applying shadow; ADR-004 \xA7 11.1c owns the flip");
10428
+ }
10429
+ }
10430
+ byOperator.set(scope, { revision: echo.revision, mode });
10431
+ syncEffective();
10432
+ return true;
10433
+ },
10434
+ snapshot: () => ({
10435
+ mode: desiredMode(),
10436
+ planeSpeaksPreparedJob,
10437
+ tally: { ...tally, diverged_fields: { ...tally.diverged_fields } },
10438
+ operators: Object.fromEntries(byOperator)
10439
+ })
10440
+ };
10441
+ }
10442
+ var PREPARED_JOB_CONFIG_SCHEMA_VERSION, MAX_DIVERGED_FIELD_KEYS;
10443
+ var init_prepared_job_remote_config = __esm({
10444
+ "../../scripts/virtual-office/code-runner/prepared-job-remote-config.mjs"() {
10445
+ "use strict";
10446
+ init_prepared_job_shadow();
10447
+ PREPARED_JOB_CONFIG_SCHEMA_VERSION = 1;
10448
+ MAX_DIVERGED_FIELD_KEYS = 24;
10449
+ }
10450
+ });
10451
+
9907
10452
  // ../../scripts/virtual-office/code-runner/account-usage/shared.mjs
9908
10453
  import crypto from "node:crypto";
9909
10454
  import fs9 from "node:fs";
@@ -10524,7 +11069,7 @@ var init_error_message = __esm({
10524
11069
  });
10525
11070
 
10526
11071
  // ../../scripts/virtual-office/code-runner/watcher-coordination.mjs
10527
- import { createHash as createHash6 } from "node:crypto";
11072
+ import { createHash as createHash7 } from "node:crypto";
10528
11073
  function ciFixOccurrenceKey({ repo, prNumber, headSha, repairAttempt }) {
10529
11074
  const occurrence = JSON.stringify([
10530
11075
  String(repo).toLowerCase(),
@@ -10532,7 +11077,7 @@ function ciFixOccurrenceKey({ repo, prNumber, headSha, repairAttempt }) {
10532
11077
  String(headSha).toLowerCase(),
10533
11078
  Number(repairAttempt)
10534
11079
  ]);
10535
- return `ci-fix:v1:${createHash6("sha256").update(occurrence).digest("hex")}`;
11080
+ return `ci-fix:v1:${createHash7("sha256").update(occurrence).digest("hex")}`;
10536
11081
  }
10537
11082
  function coordinationRetryDue(entry, nowMs) {
10538
11083
  return !entry.nextRetryAt || nowMs >= entry.nextRetryAt;
@@ -10664,7 +11209,7 @@ var init_watcher_coordination = __esm({
10664
11209
  // ../../scripts/virtual-office/code-runner/watcher-state.mjs
10665
11210
  import { randomUUID as randomUUID4 } from "node:crypto";
10666
11211
  import { mkdir as mkdir3, open as open2, readFile as readFile4, rename, unlink as unlink2 } from "node:fs/promises";
10667
- import { dirname as dirname10 } from "node:path";
11212
+ import { dirname as dirname11 } from "node:path";
10668
11213
  async function readWatcherState(stateFile) {
10669
11214
  let raw;
10670
11215
  try {
@@ -10680,7 +11225,7 @@ async function readWatcherState(stateFile) {
10680
11225
  return parsed;
10681
11226
  }
10682
11227
  async function writeWatcherState(stateFile, state) {
10683
- const directory = dirname10(stateFile);
11228
+ const directory = dirname11(stateFile);
10684
11229
  await mkdir3(directory, { recursive: true });
10685
11230
  const temp = `${stateFile}.${process.pid}.${randomUUID4()}.tmp`;
10686
11231
  let handle;
@@ -11142,8 +11687,8 @@ var init_pr_watcher_github = __esm({
11142
11687
  "../../scripts/virtual-office/code-runner/pr-watcher-github.mjs"() {
11143
11688
  "use strict";
11144
11689
  init_process_runner2();
11145
- VIEW_FIELDS_WITH_CI = "state,statusCheckRollup,headRefName,headRefOid,url,isDraft,mergeStateStatus";
11146
- VIEW_FIELDS_WITHOUT_CI = "state,headRefName,headRefOid,url,isDraft,mergeStateStatus";
11690
+ VIEW_FIELDS_WITH_CI = "state,statusCheckRollup,headRefName,headRefOid,url,isDraft,mergeStateStatus,body";
11691
+ VIEW_FIELDS_WITHOUT_CI = "state,headRefName,headRefOid,url,isDraft,mergeStateStatus,body";
11147
11692
  CI_UNREADABLE_REASON = "app_token_missing_checks_read";
11148
11693
  DIAGNOSTIC_INTERVAL_MS = 30 * 60 * 1e3;
11149
11694
  lastDiagnosticAt = 0;
@@ -11209,8 +11754,8 @@ var init_enqueue_autonomous_code_task = __esm({
11209
11754
  });
11210
11755
 
11211
11756
  // ../../scripts/virtual-office/code-runner/pr-watcher.mjs
11212
- import { homedir as homedir9 } from "node:os";
11213
- import { join as join14 } from "node:path";
11757
+ import { homedir as homedir10 } from "node:os";
11758
+ import { join as join15 } from "node:path";
11214
11759
  function parsePrCiStatus(view) {
11215
11760
  const state = (view && typeof view.state === "string" ? view.state : "UNKNOWN").toUpperCase();
11216
11761
  const rollup = latestCheckRunsByName(view && Array.isArray(view.statusCheckRollup) ? view.statusCheckRollup : []);
@@ -11582,7 +12127,7 @@ var init_pr_watcher = __esm({
11582
12127
  init_watcher_merge_authority();
11583
12128
  init_superseded_pr_source();
11584
12129
  init_ci_fix_prompt();
11585
- DEFAULT_STATE_FILE = join14(homedir9(), ".vo", "dispatched-prs.json");
12130
+ DEFAULT_STATE_FILE = join15(homedir10(), ".vo", "dispatched-prs.json");
11586
12131
  FAIL_CONCLUSIONS = /* @__PURE__ */ new Set([
11587
12132
  "FAILURE",
11588
12133
  "TIMED_OUT",
@@ -11885,7 +12430,7 @@ function startControlServer({ port, getStatus, requestStop, allowedOrigin, log:
11885
12430
  server.unref?.();
11886
12431
  return server;
11887
12432
  }
11888
- function startDaemonControl({ cfg, runnerInstanceId, requestStop, getActiveCount, isRunning, startedAt, log: log2 = () => {
12433
+ function startDaemonControl({ cfg, runnerInstanceId, requestStop, getActiveCount, getActiveTaskIds = () => [], isRunning, startedAt, log: log2 = () => {
11889
12434
  }, onDuplicate = null, getUpdateStatus = () => null, getClaimGate = () => null }) {
11890
12435
  if (!cfg.controlEnabled) return null;
11891
12436
  return startControlServer({
@@ -11902,6 +12447,9 @@ function startDaemonControl({ cfg, runnerInstanceId, requestStop, getActiveCount
11902
12447
  servedOperators: cfg.servedOperators,
11903
12448
  watchEnabled: cfg.watchEnabled,
11904
12449
  activeTasks: getActiveCount(),
12450
+ // The supervisor's update-drain gate reads THESE ids (not a guess) to mark
12451
+ // in-flight work before a capped staged-update restart kills it.
12452
+ activeTaskIds: getActiveTaskIds(),
11905
12453
  startedAt: new Date(startedAt).toISOString(),
11906
12454
  uptimeSec: Math.round((Date.now() - startedAt) / 1e3),
11907
12455
  // Host version awareness — the app + `runner --status` read drift from here.
@@ -12353,13 +12901,13 @@ async function resolveModelForTier(tier, { agent = DEFAULT_AGENT2, resolveModelF
12353
12901
  if (resolved && modelCompatibleWithAgent(normalizedAgent, resolved)) return resolved;
12354
12902
  return fallbacks[effectiveTier];
12355
12903
  }
12356
- async function resolveTaskModel(task, { agent = DEFAULT_AGENT2 } = {}) {
12904
+ async function resolveTaskModel(task, { agent = DEFAULT_AGENT2, resolveModelFamily: resolver = resolveModelFamily } = {}) {
12357
12905
  const tier = task.tier && task.tier !== "auto" ? task.tier : classifyTier2(task.prompt);
12358
12906
  const pinned = typeof task.model === "string" ? task.model.trim() : "";
12359
12907
  if (pinned && modelCompatibleWithAgent(normalizeAgent(agent), pinned)) {
12360
12908
  return { tier, model: pinned };
12361
12909
  }
12362
- const model = await resolveModelForTier(tier, { agent });
12910
+ const model = await resolveModelForTier(tier, { agent, resolveModelFamily: resolver });
12363
12911
  return { tier, model };
12364
12912
  }
12365
12913
  var TASK_MODEL_AGENTS, DEFAULT_AGENT2, AGENT_TIER_FAMILIES, AGENT_TIER_FALLBACKS, AGENT_MODEL_COMPATIBILITY;
@@ -12826,8 +13374,8 @@ var init_classify_task = __esm({
12826
13374
 
12827
13375
  // ../../scripts/virtual-office/code-runner/auto-router/effort-policy.mjs
12828
13376
  import { readFileSync as readFileSync9 } from "node:fs";
12829
- import { homedir as homedir10 } from "node:os";
12830
- import { join as join15 } from "node:path";
13377
+ import { homedir as homedir11 } from "node:os";
13378
+ import { join as join16 } from "node:path";
12831
13379
  function difficultyToRung(difficulty, thresholds) {
12832
13380
  const b = thresholds.rungBounds;
12833
13381
  if (difficulty >= b.R5) return "R5";
@@ -12904,7 +13452,7 @@ var init_effort_policy = __esm({
12904
13452
  init_meta_model_catalog();
12905
13453
  RUNG_ORDER = ["R1", "R2", "R3", "R4", "R5"];
12906
13454
  rungIndex = (rung) => RUNG_ORDER.indexOf(rung);
12907
- DEFAULT_CODEX_MODELS_CACHE = join15(homedir10(), ".codex", "models_cache.json");
13455
+ DEFAULT_CODEX_MODELS_CACHE = join16(homedir11(), ".codex", "models_cache.json");
12908
13456
  }
12909
13457
  });
12910
13458
 
@@ -13034,9 +13582,9 @@ var init_role_cost_shadow = __esm({
13034
13582
  });
13035
13583
 
13036
13584
  // ../../scripts/virtual-office/code-runner/auto-router/auto-router.mjs
13037
- import { readFileSync as readFileSync10, appendFileSync, mkdirSync as mkdirSync8 } from "node:fs";
13038
- import { homedir as homedir11 } from "node:os";
13039
- import { join as join16, dirname as dirname11 } from "node:path";
13585
+ import { readFileSync as readFileSync10, appendFileSync as appendFileSync2, mkdirSync as mkdirSync9 } from "node:fs";
13586
+ import { homedir as homedir12 } from "node:os";
13587
+ import { join as join17, dirname as dirname12 } from "node:path";
13040
13588
  import { fileURLToPath as fileURLToPath7 } from "node:url";
13041
13589
  function getAutoRouterMode(env2 = process.env) {
13042
13590
  const raw = String(env2.VO_CODE_RUNNER_AUTO_ROUTER || "").trim().toLowerCase();
@@ -13044,8 +13592,8 @@ function getAutoRouterMode(env2 = process.env) {
13044
13592
  }
13045
13593
  function loadThresholds() {
13046
13594
  if (!cachedThresholds) {
13047
- const here = dirname11(fileURLToPath7(import.meta.url));
13048
- cachedThresholds = JSON.parse(readFileSync10(join16(here, "thresholds.json"), "utf8"));
13595
+ const here = dirname12(fileURLToPath7(import.meta.url));
13596
+ cachedThresholds = JSON.parse(readFileSync10(join17(here, "thresholds.json"), "utf8"));
13049
13597
  }
13050
13598
  return cachedThresholds;
13051
13599
  }
@@ -13111,9 +13659,9 @@ function formatDecisionReason(decision, maxLen = 480) {
13111
13659
  const s = `[${decision.routerVersion}] ${decision.taskClass} d=${decision.difficulty} c=${decision.confidence} \u2192 ${decision.rung}/${decision.tier}${decision.effort ? ` effort=${decision.effort}` : ""} turns=${decision.maxTurns} $${decision.maxBudgetUsd}${decision.flags.length ? ` [${decision.flags.join(",")}]` : ""} :: ${decision.reasons.join("; ")}`;
13112
13660
  return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
13113
13661
  }
13114
- function appendDecisionFallback(decision, { path: path22 = DECISION_FALLBACK_PATH, append = appendFileSync, mkdir: mkdir5 = mkdirSync8, task, thresholds, roleCostInputs } = {}) {
13662
+ function appendDecisionFallback(decision, { path: path22 = DECISION_FALLBACK_PATH, append = appendFileSync2, mkdir: mkdir5 = mkdirSync9, task, thresholds, roleCostInputs } = {}) {
13115
13663
  try {
13116
- mkdir5(dirname11(path22), { recursive: true });
13664
+ mkdir5(dirname12(path22), { recursive: true });
13117
13665
  append(path22, `${JSON.stringify(decision)}
13118
13666
  `, "utf8");
13119
13667
  if (isRouterDecision(decision)) {
@@ -13137,7 +13685,7 @@ var init_auto_router = __esm({
13137
13685
  init_effort_policy();
13138
13686
  init_role_cost_shadow();
13139
13687
  ROUTER_VERSION = "0.1.0";
13140
- DECISION_FALLBACK_PATH = join16(homedir11(), ".claude", "vo-auto-router-decisions.jsonl");
13688
+ DECISION_FALLBACK_PATH = join17(homedir12(), ".claude", "vo-auto-router-decisions.jsonl");
13141
13689
  MODES = /* @__PURE__ */ new Set(["off", "shadow", "on"]);
13142
13690
  cachedThresholds = null;
13143
13691
  isRouterDecision = (d) => Boolean(d && typeof d === "object" && typeof d.taskClass === "string" && typeof d.confidence === "number");
@@ -13373,6 +13921,17 @@ var init_redact_tokens = __esm({
13373
13921
  }
13374
13922
  });
13375
13923
 
13924
+ // ../../scripts/ci/check-consensus-receipt-core.mjs
13925
+ var RECEIPT_MARKER_RE, UNAVAILABILITY_RE;
13926
+ var init_check_consensus_receipt_core = __esm({
13927
+ "../../scripts/ci/check-consensus-receipt-core.mjs"() {
13928
+ "use strict";
13929
+ init_methodology_composer();
13930
+ RECEIPT_MARKER_RE = /receipt id:\s*[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/iu;
13931
+ UNAVAILABILITY_RE = /consensus[^.\n]{0,80}(not available|unavailable|not permitted|could not be reached|no receipt_id)/iu;
13932
+ }
13933
+ });
13934
+
13376
13935
  // ../../scripts/virtual-office/code-runner/task-helpers.mjs
13377
13936
  function makeSafeProgress(log2) {
13378
13937
  return async (client, id, patch) => {
@@ -13397,6 +13956,17 @@ ${String(run?.lastAgentMessage || "")}`;
13397
13956
  const missing = found.filter((line) => !String(slicedBodyText || "").includes(line));
13398
13957
  return missing.length ? ["", "### Consensus evidence (preserved past truncation)", "", ...missing.map((line) => redactSecrets(line))] : [];
13399
13958
  }
13959
+ function consensusUnavailabilityLine(stakes) {
13960
+ const signal = String(stakes ?? "").replace(/\s+/gu, " ").trim().slice(0, 80) || "unspecified";
13961
+ return `Consensus judgment was not available in this headless session (no receipt_id) \u2014 automated declaration by the runner; stakes signal: ${signal}.`;
13962
+ }
13963
+ function withConsensusDeclaration(body, stakes) {
13964
+ const text = String(body ?? "");
13965
+ if (RECEIPT_MARKER_RE.test(text) || UNAVAILABILITY_RE.test(text)) return text;
13966
+ return `${text}
13967
+
13968
+ ${consensusUnavailabilityLine(stakes)}`;
13969
+ }
13400
13970
  function buildPrBody(task, run, files, { armAutoMerge = false } = {}) {
13401
13971
  const governedStakes = matchGovernedStakes({ prompt: String(task.prompt || "") });
13402
13972
  const slicedSections = [
@@ -13422,15 +13992,20 @@ function buildPrBody(task, run, files, { armAutoMerge = false } = {}) {
13422
13992
  "",
13423
13993
  // A budget/turn-capped run ends with no assistant text (summary = the bare
13424
13994
  // subtype); its LAST message is the honest report the operator needs.
13425
- ...run.lastAgentMessage ? ["### Last agent message before the cap", "", redactSecrets(String(run.lastAgentMessage)).slice(0, 2e3), ""] : []
13995
+ ...run.lastAgentMessage ? ["### Last agent message before the cap", "", redactSecrets(String(run.lastAgentMessage)).slice(0, 2e3), ""] : [],
13996
+ // Completion-gate failures salvaged against a budget/turn-truncated run
13997
+ // (D4, incident afc90342) — the gate output that would otherwise have
13998
+ // only lived in a terminal-failure message the runner never publishes.
13999
+ ...run.gateFailureNote ? ["### Completion gate output (not yet passing)", "", redactSecrets(String(run.gateFailureNote)).slice(0, 2e3), ""] : []
13426
14000
  ];
13427
- return [
14001
+ const composed = [
13428
14002
  ...slicedSections,
13429
14003
  // Receipt lines the slices dropped — the gate reads only this body.
13430
14004
  ...preservedReceiptLines(run, slicedSections.join("\n")),
13431
14005
  "---",
13432
14006
  armAutoMerge ? "_Opened by the AlgoHQ code-runner daemon. After CI passes, the watcher must obtain a durable consensus receipt and merge the exact verified SHA._" : "_Opened by the AlgoHQ code-runner daemon. This PR awaits the verify-before-act gate / operator review \u2014 it is NOT auto-merged._"
13433
14007
  ].filter((l) => l !== "").join("\n");
14008
+ return governedStakes ? withConsensusDeclaration(composed, governedStakes) : composed;
13434
14009
  }
13435
14010
  async function mintRunnerGithubTokens({ client, taskId, log: log2, repo = null, requirePublish = false }) {
13436
14011
  const publishToken = (await client.getInstallationToken({ required: requirePublish }))?.token ?? null;
@@ -13451,6 +14026,7 @@ var init_task_helpers = __esm({
13451
14026
  "use strict";
13452
14027
  init_redact_tokens();
13453
14028
  init_methodology_composer();
14029
+ init_check_consensus_receipt_core();
13454
14030
  RECEIPT_LINE_RE = /receipt id:\s*[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/giu;
13455
14031
  }
13456
14032
  });
@@ -15245,8 +15821,8 @@ var init_cancellation_probe = __esm({
15245
15821
  });
15246
15822
 
15247
15823
  // ../../scripts/virtual-office/code-runner/detached-economics-spool.mjs
15248
- import { homedir as homedir12 } from "node:os";
15249
- import { dirname as dirname12, join as join17 } from "node:path";
15824
+ import { homedir as homedir13 } from "node:os";
15825
+ import { dirname as dirname13, join as join18 } from "node:path";
15250
15826
  import { mkdir as mkdir4, readFile as readFile5, rename as rename2, writeFile as writeFile4 } from "node:fs/promises";
15251
15827
  function withLock(operation) {
15252
15828
  const result = serialized.then(operation, operation);
@@ -15264,7 +15840,7 @@ async function readEntries(file) {
15264
15840
  }
15265
15841
  }
15266
15842
  async function writeEntries(file, entries) {
15267
- await mkdir4(dirname12(file), { recursive: true });
15843
+ await mkdir4(dirname13(file), { recursive: true });
15268
15844
  const temp = `${file}.${process.pid}.tmp`;
15269
15845
  await writeFile4(temp, `${JSON.stringify(entries)}
15270
15846
  `, "utf8");
@@ -15310,7 +15886,7 @@ var DEFAULT_FILE, serialized;
15310
15886
  var init_detached_economics_spool = __esm({
15311
15887
  "../../scripts/virtual-office/code-runner/detached-economics-spool.mjs"() {
15312
15888
  "use strict";
15313
- DEFAULT_FILE = join17(homedir12(), ".vo", "detached-run-economics.json");
15889
+ DEFAULT_FILE = join18(homedir13(), ".vo", "detached-run-economics.json");
15314
15890
  serialized = Promise.resolve();
15315
15891
  }
15316
15892
  });
@@ -15688,6 +16264,19 @@ async function processOneTask(client, task, cfg, runnerInstanceId, swarmAdmissio
15688
16264
  allowMissingKnowledgeContext: process.env.VO_CODE_RUNNER_ALLOW_MISSING_KNOWLEDGE_CONTEXT === "1",
15689
16265
  attachmentManifestMarkdown: attachmentBundle.manifestMarkdown
15690
16266
  }) });
16267
+ await runPreparedJobShadow({ client, task, agent: sel.agent, env: process.env, log, local: {
16268
+ // ADR-004 § 11.1b SHADOW: default OFF; return value deliberately unread — slice C owns consumption
16269
+ prompt: effortPrompt,
16270
+ dispatchMode,
16271
+ tier,
16272
+ model,
16273
+ permissionMode: effectivePermissionMode,
16274
+ maxTurns: effectiveMaxTurns,
16275
+ effort: effectiveEffort,
16276
+ maxBudgetUsd: effectiveMaxBudgetUsd,
16277
+ methodology,
16278
+ attachmentManifestMarkdown: attachmentBundle.manifestMarkdown
16279
+ } });
15691
16280
  assertRunnerGovernors({
15692
16281
  agent: sel.agent,
15693
16282
  // Only persisted operator caps are hard contracts. Router/global values
@@ -15803,7 +16392,7 @@ async function processOneTask(client, task, cfg, runnerInstanceId, swarmAdmissio
15803
16392
  }
15804
16393
  if (await taskWasCancelled({ client, id, run, safeProgress, log })) return;
15805
16394
  if (await gateTestGenTaskOrFail({ client, id, task, files, worktreeDir: wt.worktreeDir, log })) return;
15806
- if (await enforceCompletionGateOrFail({ client, id, task, worktreeDir: wt.worktreeDir, log })) return;
16395
+ if (await enforceCompletionGateOrFail({ client, id, task, worktreeDir: wt.worktreeDir, run, truncated: partial, log })) return;
15807
16396
  const publicationTarget = await resolvePublicationTarget({ task, continuationRestore, worktreeDir: wt.worktreeDir, githubToken, allowAmbientGithubFallback: cfg.allowAmbientGithub });
15808
16397
  const localBranch = await resolveOrCreateBranchAsync(wt.worktreeDir, "vo/code-task");
15809
16398
  const publicationBranch = publicationTarget.targetBranch || localBranch;
@@ -15896,6 +16485,7 @@ async function main({ env: env2 = process.env, once: once2 = false } = {}) {
15896
16485
  let reconcileStale = true;
15897
16486
  let stopping = false;
15898
16487
  let active = 0;
16488
+ const activeTaskIds = /* @__PURE__ */ new Set();
15899
16489
  const stop = (sig) => {
15900
16490
  if (stopping) return;
15901
16491
  stopping = true;
@@ -15910,6 +16500,7 @@ async function main({ env: env2 = process.env, once: once2 = false } = {}) {
15910
16500
  runnerInstanceId,
15911
16501
  requestStop: () => stop("web-control"),
15912
16502
  getActiveCount: () => active,
16503
+ getActiveTaskIds: () => [...activeTaskIds],
15913
16504
  isRunning: () => !stopping,
15914
16505
  startedAt,
15915
16506
  log,
@@ -15950,7 +16541,7 @@ async function main({ env: env2 = process.env, once: once2 = false } = {}) {
15950
16541
  const agentAvailability = makeAgentAvailabilityProvider({ onError: (e) => log(`agent probe failed: ${e.message}`) });
15951
16542
  await agentAvailability.ready();
15952
16543
  const accountUsage = makeAccountUsageProvider();
15953
- const loopTick = makeLoopTicks({ client, cfg, env: env2, log, getActive: () => active, runnerInstanceId, capacityController, localModelController: createLocalModelRemoteController({ env: env2, log }), getAgentAvailability: () => agentAvailability.get(), getAccountUsage: () => accountUsage.get() });
16544
+ const loopTick = makeLoopTicks({ client, cfg, env: env2, log, getActive: () => active, runnerInstanceId, capacityController, localModelController: createLocalModelRemoteController({ env: env2, log }), preparedJobController: createPreparedJobRemoteController({ log }), getAgentAvailability: () => agentAvailability.get(), getAccountUsage: () => accountUsage.get() });
15954
16545
  const backoff = makeReconnectBackoff({ baseMs: cfg.pollSec * 1e3, log });
15955
16546
  let detachedFlushRunning = false;
15956
16547
  while (!stopping) {
@@ -16000,6 +16591,7 @@ async function main({ env: env2 = process.env, once: once2 = false } = {}) {
16000
16591
  }
16001
16592
  log(`claimed task ${task.code_task_id} (${task.repo})`);
16002
16593
  active += 1;
16594
+ activeTaskIds.add(task.code_task_id);
16003
16595
  const runTask = task.kind === "inference" ? processInferenceTask(client, task, cfg, { safeProgress, runnerStagePatch, log }) : processOneTask(client, task, cfg, runnerInstanceId, { availableAgents: claimAgents.availableAgents, accountUsage: accountUsage.get() });
16004
16596
  const done = runTask.catch(async (error) => {
16005
16597
  log(`task ${task.code_task_id} unhandled runner error: ${error.message}`);
@@ -16019,6 +16611,7 @@ async function main({ env: env2 = process.env, once: once2 = false } = {}) {
16019
16611
  });
16020
16612
  }).finally(() => {
16021
16613
  active -= 1;
16614
+ activeTaskIds.delete(task.code_task_id);
16022
16615
  });
16023
16616
  if (once2) {
16024
16617
  await done;
@@ -16052,6 +16645,7 @@ var init_code_runner_daemon = __esm({
16052
16645
  init_runner_capacity();
16053
16646
  init_agent_availability();
16054
16647
  init_local_model_remote_config();
16648
+ init_prepared_job_remote_config();
16055
16649
  init_account_usage2();
16056
16650
  init_pr_watcher();
16057
16651
  init_existing_pr_target();
@@ -16061,6 +16655,7 @@ var init_code_runner_daemon = __esm({
16061
16655
  init_claim_scoping_log();
16062
16656
  init_reconnect_backoff();
16063
16657
  init_task_helpers();
16658
+ init_prepared_job_shadow();
16064
16659
  init_agent_process_env();
16065
16660
  init_sandbox_config();
16066
16661
  init_inference_task_runner();