opencode-swarm 7.199.6 → 7.200.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
  2. package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
  3. package/dist/cli/attest-task-sg8b5a5j.js +2209 -0
  4. package/dist/cli/{auto-checkpoint-gv21fb1h.js → auto-checkpoint-bywgxh27.js} +9 -9
  5. package/dist/cli/{checkpoint-rd1bt793.js → checkpoint-k2092cbw.js} +20 -18
  6. package/dist/cli/{coder-settlement-21zd1g3a.js → coder-settlement-y0hkcngn.js} +12 -12
  7. package/dist/cli/{config-doctor-mxe9nr78.js → config-doctor-0fnrwkga.js} +16 -16
  8. package/dist/cli/{core-7bd1sd36.js → core-mfyaj8b4.js} +3 -3
  9. package/dist/cli/{curation-policy-w9y0db1n.js → curation-policy-fth5n93x.js} +6 -6
  10. package/dist/cli/{curator-7rf98h3k.js → curator-1s64jkc3.js} +44 -44
  11. package/dist/cli/{curator-drift-21y19fnz.js → curator-drift-famx6p6s.js} +8 -8
  12. package/dist/cli/curator-llm-factory-vya4epq6.js +82 -0
  13. package/dist/cli/{doctor-knowledge-receipt-phase-id-6pdjxgfa.js → doctor-knowledge-receipt-phase-id-v4y6pbek.js} +9 -9
  14. package/dist/cli/{evidence-summary-service-vdcx7fqd.js → evidence-summary-service-rd7y6yjq.js} +20 -20
  15. package/dist/cli/{gate-evidence-ernx9gck.js → gate-evidence-kama66h5.js} +15 -7
  16. package/dist/cli/guardrail-explain-8fkhq0cg.js +83 -0
  17. package/dist/cli/{guardrail-log-jr6b9rt3.js → guardrail-log-gdj19fq5.js} +7 -7
  18. package/dist/cli/{guardrail-reset-0qyt8vpd.js → guardrail-reset-bmg6czzk.js} +44 -44
  19. package/dist/cli/{hive-promoter-2qwxrrsc.js → hive-promoter-ychygdgc.js} +44 -44
  20. package/dist/cli/{index-s4wbe96z.js → index-0ptf66x5.js} +4 -4
  21. package/dist/cli/{index-cyp3r8ar.js → index-0tygsk8b.js} +10 -10
  22. package/dist/cli/{index-b9f2j9bx.js → index-12h2rtdj.js} +3 -3
  23. package/dist/cli/{index-eyq1q1xn.js → index-1v277wxc.js} +2 -2
  24. package/dist/cli/{index-syaa76vg.js → index-2dm42tgp.js} +48 -46
  25. package/dist/cli/{index-exj9yb0x.js → index-2hnnkj64.js} +1979 -1945
  26. package/dist/cli/{index-7m2gcmm7.js → index-2m740hyt.js} +6 -6
  27. package/dist/cli/{index-cs1d9e03.js → index-2w5grmmj.js} +2 -2
  28. package/dist/cli/{index-88d5kpjj.js → index-3020n6d9.js} +1 -1
  29. package/dist/cli/{index-vgb679vr.js → index-3exe6k66.js} +3 -3
  30. package/dist/cli/{index-gx2vp8gx.js → index-3t46mez1.js} +27 -1
  31. package/dist/cli/{index-38fgg593.js → index-3zspah3v.js} +2 -2
  32. package/dist/cli/{index-f02p4yn4.js → index-51dw4bjc.js} +2 -2
  33. package/dist/cli/{index-hx2f3j9w.js → index-5snwc3dz.js} +2 -2
  34. package/dist/cli/{index-eqw5vq9r.js → index-b0d8ra32.js} +1 -1
  35. package/dist/cli/{index-tsg61z0r.js → index-b4kdms7x.js} +2 -2
  36. package/dist/cli/{index-cwg99gea.js → index-bn3aa5q1.js} +7 -7
  37. package/dist/cli/{index-dtwj4hsk.js → index-c2k7q723.js} +2 -2
  38. package/dist/cli/{index-tqtfjzb0.js → index-c9g3hkjz.js} +3 -3
  39. package/dist/cli/{index-r227g76y.js → index-dgyddtje.js} +6 -6
  40. package/dist/cli/{index-270zfq1f.js → index-epzadpmm.js} +7 -7
  41. package/dist/cli/{index-txh6dtnj.js → index-f6nrw8am.js} +44 -44
  42. package/dist/cli/{index-n1ddn12j.js → index-g57p8p1k.js} +1 -1
  43. package/dist/cli/{index-9y6yk1n0.js → index-na6ph1fp.js} +1 -1
  44. package/dist/cli/{index-bef4nhtj.js → index-nawp90n7.js} +4 -4
  45. package/dist/cli/{index-3mzc5rqc.js → index-nzfq1ms2.js} +3 -3
  46. package/dist/cli/{index-0bw1jyen.js → index-p6v544jn.js} +1 -1
  47. package/dist/cli/{index-s5tgnsmh.js → index-parkaa70.js} +6 -6
  48. package/dist/cli/{index-exr153j1.js → index-pe77h482.js} +5 -5
  49. package/dist/cli/{index-dz15f98h.js → index-q8vfw61p.js} +1 -1
  50. package/dist/cli/{index-s9hekeej.js → index-qaqyq25k.js} +7 -7
  51. package/dist/cli/{index-jhjmf5sn.js → index-qzakbjcg.js} +3 -3
  52. package/dist/cli/{index-2cb644vj.js → index-rzkmg02a.js} +918 -154
  53. package/dist/cli/{index-0je0mees.js → index-s3w41p1x.js} +1 -1
  54. package/dist/cli/{index-zzpy5cx3.js → index-s8eac99p.js} +12 -8
  55. package/dist/cli/{index-j3rfbs45.js → index-s9y49avf.js} +2 -2
  56. package/dist/cli/{index-dqkr60bw.js → index-sva5swrs.js} +172 -14
  57. package/dist/cli/{index-3ct8kgfj.js → index-sz67z90q.js} +4 -4
  58. package/dist/cli/{index-gdyqdhz1.js → index-th667k1y.js} +4 -4
  59. package/dist/cli/{index-jmhn6ab5.js → index-traz987v.js} +2 -2
  60. package/dist/cli/{index-0veqvgny.js → index-v1h70r3y.js} +1 -1
  61. package/dist/cli/{index-snx2vb1x.js → index-ves1rtqt.js} +1 -1
  62. package/dist/cli/{index-qbhjey8k.js → index-vtkgg2qn.js} +3 -3
  63. package/dist/cli/{index-x6rv0e00.js → index-w2bhrp6z.js} +21 -14
  64. package/dist/cli/{index-4cyc18bc.js → index-wgf1780e.js} +7 -7
  65. package/dist/cli/{index-b3ws03kp.js → index-xyvsdn07.js} +1 -1
  66. package/dist/cli/{index-zbygz217.js → index-ypxq0x7r.js} +2 -2
  67. package/dist/cli/{index-t67n8jhb.js → index-z9mysg5m.js} +2 -2
  68. package/dist/cli/index.js +45 -45
  69. package/dist/cli/{knowledge-escalator-rsj9nqqt.js → knowledge-escalator-zxd76jna.js} +15 -15
  70. package/dist/cli/{knowledge-events-appww5kb.js → knowledge-events-z8h0wmaw.js} +13 -13
  71. package/dist/cli/{knowledge-link-t0ce3mw7.js → knowledge-link-wfhsfyn2.js} +5 -5
  72. package/dist/cli/{knowledge-store-n76rzv27.js → knowledge-store-g2gm13s8.js} +6 -6
  73. package/dist/cli/{knowledge-validator-ycxvjasa.js → knowledge-validator-2sech2sx.js} +8 -8
  74. package/dist/cli/{mcp-jy0gk3c8.js → mcp-t88363gj.js} +1 -1
  75. package/dist/cli/{model-preflight-rg0mppzf.js → model-preflight-akj8g1m2.js} +44 -44
  76. package/dist/cli/{pending-delegations-e6brjxp2.js → pending-delegations-bqp6b6as.js} +13 -13
  77. package/dist/cli/{pr-subscriptions-vjsb5ydq.js → pr-subscriptions-wxjvkg56.js} +12 -12
  78. package/dist/cli/{pr-workflow-gate-bj66aa9k.js → pr-workflow-gate-2wcrfa6g.js} +44 -44
  79. package/dist/cli/{runner-wq954cda.js → runner-s1a73y5h.js} +6 -6
  80. package/dist/cli/{scan-cursor-kkg94g0t.js → scan-cursor-8br4x41t.js} +7 -7
  81. package/dist/cli/{schema-d1exxwv8.js → schema-mc419qh8.js} +1 -1
  82. package/dist/cli/{scope-persistence-3v9hce7b.js → scope-persistence-5gyjt70q.js} +16 -16
  83. package/dist/cli/{server-jkcwkh8t.js → server-bp247fqe.js} +46 -46
  84. package/dist/cli/{skill-generator-wg8qfdm8.js → skill-generator-q4afafh3.js} +17 -17
  85. package/dist/cli/{snapshot-coordination-init-xyffgya9.js → snapshot-coordination-init-b4kmrgh7.js} +44 -44
  86. package/dist/cli/{speckit-checkoff-61xn2c2v.js → speckit-checkoff-1v02b2dt.js} +4 -4
  87. package/dist/cli/{telemetry-gena5typ.js → telemetry-cr8q16wk.js} +1 -1
  88. package/dist/cli/{workspace-snapshot-hzhz0rxw.js → workspace-snapshot-93gzfac2.js} +3 -3
  89. package/dist/cli/{worktree-collision-ownership-gsv009xc.js → worktree-collision-ownership-84m9f5an.js} +14 -14
  90. package/dist/cli/{worktree-isolation-3sdvs69a.js → worktree-isolation-xwbszhja.js} +44 -44
  91. package/dist/commands/attest.d.ts +10 -0
  92. package/dist/commands/close/internals.d.ts +1 -1
  93. package/dist/commands/close/orchestrator.d.ts +7 -0
  94. package/dist/commands/destructive-purge.d.ts +15 -0
  95. package/dist/commands/git-status-read.d.ts +23 -0
  96. package/dist/commands/index.d.ts +1 -0
  97. package/dist/commands/registry.d.ts +9 -1
  98. package/dist/commands/rollback-gate.d.ts +77 -10
  99. package/dist/config/plan-schema.d.ts +44 -0
  100. package/dist/gate-evidence.d.ts +138 -1
  101. package/dist/git/branch.d.ts +22 -0
  102. package/dist/index.js +570 -562
  103. package/dist/session/snapshot-coordination-init.d.ts +34 -0
  104. package/dist/session/snapshot-writer.d.ts +5 -1
  105. package/dist/tools/attest-task.d.ts +67 -0
  106. package/dist/tools/checkpoint.d.ts +17 -0
  107. package/dist/tools/phase-complete.d.ts +12 -0
  108. package/dist/tools/save-plan.d.ts +16 -0
  109. package/dist/tools/update-task-status.d.ts +1 -1
  110. package/dist/workflow/task-terminal.d.ts +1 -0
  111. package/dist/workflow/workflow-wal-schema.d.ts +2 -0
  112. package/package.json +1 -1
  113. package/dist/cli/curator-llm-factory-ab821je6.js +0 -82
  114. package/dist/cli/guardrail-explain-7jef0dhs.js +0 -83
@@ -9,7 +9,7 @@ import {
9
9
  readEvaluationRun,
10
10
  saveEvaluationRun,
11
11
  saveTaskSetSnapshot
12
- } from "./index-hx2f3j9w.js";
12
+ } from "./index-5snwc3dz.js";
13
13
  import {
14
14
  canonicalHash,
15
15
  computeCandidateInputContentHash,
@@ -4,30 +4,30 @@ import {
4
4
  projectDbExists,
5
5
  withImmediateTransaction,
6
6
  withProjectDbReadOnly
7
- } from "./index-snx2vb1x.js";
7
+ } from "./index-ves1rtqt.js";
8
8
  import {
9
9
  derivePlanId,
10
10
  derivePlanIdentityHash
11
11
  } from "./index-7pmbnjvj.js";
12
12
  import {
13
13
  withEvidenceLock
14
- } from "./index-dz15f98h.js";
14
+ } from "./index-q8vfw61p.js";
15
15
  import {
16
16
  assertProjectRoot
17
17
  } from "./index-t7hmqgjy.js";
18
18
  import {
19
19
  emit
20
- } from "./index-dtwj4hsk.js";
20
+ } from "./index-c2k7q723.js";
21
21
  import {
22
22
  ExecutionProfileSchema,
23
23
  PlanSchema,
24
24
  TaskStatusSchema,
25
25
  normalizeCurrentPhaseInPlace
26
- } from "./index-gx2vp8gx.js";
26
+ } from "./index-3t46mez1.js";
27
27
  import {
28
28
  init_loader,
29
29
  loadPluginConfig
30
- } from "./index-88d5kpjj.js";
30
+ } from "./index-3020n6d9.js";
31
31
  import {
32
32
  criticalWarn,
33
33
  init_logger,
@@ -36,7 +36,7 @@ import {
36
36
  import {
37
37
  init_package,
38
38
  package_default
39
- } from "./index-0bw1jyen.js";
39
+ } from "./index-p6v544jn.js";
40
40
 
41
41
  // src/plan/planning-profile.ts
42
42
  init_loader();
@@ -1179,7 +1179,9 @@ function computePlanLedgerHash(plan) {
1179
1179
  acceptance: task.acceptance,
1180
1180
  files_touched: [...task.files_touched].sort(),
1181
1181
  evidence_path: task.evidence_path,
1182
- blocked_reason: task.blocked_reason
1182
+ blocked_reason: task.blocked_reason,
1183
+ evidence_class: task.evidence_class,
1184
+ evidence_anchors: task.evidence_anchors
1183
1185
  }))
1184
1186
  }))
1185
1187
  };
@@ -1207,7 +1209,9 @@ function computePlanStructureHash(plan) {
1207
1209
  acceptance: task.acceptance,
1208
1210
  files_touched: [...task.files_touched].sort(),
1209
1211
  evidence_path: task.evidence_path,
1210
- blocked_reason: task.blocked_reason
1212
+ blocked_reason: task.blocked_reason,
1213
+ evidence_class: task.evidence_class,
1214
+ evidence_anchors: task.evidence_anchors
1211
1215
  }))
1212
1216
  }))
1213
1217
  };
@@ -4,7 +4,7 @@ import {
4
4
  getProjectDb,
5
5
  projectDbExists,
6
6
  withImmediateTransaction
7
- } from "./index-snx2vb1x.js";
7
+ } from "./index-ves1rtqt.js";
8
8
  import {
9
9
  derivePlanId,
10
10
  derivePlanIdentityHash
@@ -426,4 +426,4 @@ function getEffectiveGates(profile, sessionOverrides) {
426
426
  }
427
427
  return merged;
428
428
  }
429
- export { formatLegacyQaBindingOnlyCall, DEFAULT_QA_GATES, getProfileLookupForIdentity, setGatesForIdentity, computeProfileHash, getEffectiveGates };
429
+ export { formatLegacyQaBindingOnlyCall, formatLegacyQaBindingRecovery, DEFAULT_QA_GATES, getProfileLookupForIdentity, setGatesForIdentity, computeProfileHash, getEffectiveGates };
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  autoCommitDirty,
4
4
  cleanUntrackedFiles
5
- } from "./index-vgb679vr.js";
5
+ } from "./index-3exe6k66.js";
6
6
  import {
7
7
  isSpawnCwdMissing,
8
8
  isSpawnCwdUnreadable
9
9
  } from "./index-spggmr30.js";
10
10
  import {
11
11
  validateSwarmPath
12
- } from "./index-b3ws03kp.js";
12
+ } from "./index-xyvsdn07.js";
13
13
  import {
14
14
  init_path_identity,
15
15
  isPathWithinDeclaredScope,
@@ -19,13 +19,13 @@ import {
19
19
  atomicWriteFile,
20
20
  taskEvidencePath,
21
21
  withTaskEvidenceLock
22
- } from "./index-jmhn6ab5.js";
22
+ } from "./index-traz987v.js";
23
23
  import {
24
24
  assertProjectRoot
25
25
  } from "./index-t7hmqgjy.js";
26
26
  import {
27
27
  telemetry
28
- } from "./index-dtwj4hsk.js";
28
+ } from "./index-c2k7q723.js";
29
29
  import {
30
30
  advisoryWarn,
31
31
  init_git_executable,
@@ -46,6 +46,7 @@ import {
46
46
 
47
47
  // src/gate-evidence.ts
48
48
  init_zod();
49
+ import { createHash as createHash2 } from "crypto";
49
50
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, realpathSync as realpathSync2, statSync as statSync2 } from "fs";
50
51
  import * as path4 from "path";
51
52
 
@@ -222,6 +223,53 @@ async function readTaskGateRequirementsReceipts(directory, taskId) {
222
223
  }
223
224
  return receipts;
224
225
  }
226
+ function readTaskGateRequirementsReceiptsSync(directory, taskId) {
227
+ const filePath = safeTaskGateRequirementsReceiptPath(directory, taskId, false);
228
+ const text = readBoundedTextFile(filePath);
229
+ if (text === null)
230
+ return [];
231
+ const receipts = [];
232
+ for (const line of text.split(`
233
+ `)) {
234
+ if (!line.trim())
235
+ continue;
236
+ const parsed = TaskGateRequirementsReceiptSchema.parse(JSON.parse(line));
237
+ if (parsed.taskId !== taskId || parsed.routeBinding !== undefined && parsed.routeBinding.taskId !== taskId) {
238
+ throw new Error(`TASK_GATE_REQUIREMENTS_IDENTITY_MISMATCH: expected ${taskId}, found ${parsed.taskId}`);
239
+ }
240
+ const { chainHash, ...withoutChainHash } = parsed;
241
+ if (computeChainHash(withoutChainHash) !== chainHash) {
242
+ throw new Error(`TASK_GATE_REQUIREMENTS_CHAIN_MISMATCH: receipt for ${taskId} failed hash validation`);
243
+ }
244
+ const previousChainHash = receipts.at(-1)?.chainHash ?? null;
245
+ if (parsed.previousChainHash !== previousChainHash) {
246
+ throw new Error(`TASK_GATE_REQUIREMENTS_CHAIN_MISMATCH: receipt for ${taskId} failed linkage validation`);
247
+ }
248
+ receipts.push(parsed);
249
+ }
250
+ return receipts;
251
+ }
252
+ function routeEvidenceFromTaskGateRequirements(receipts) {
253
+ const latestByDispatch = new Map;
254
+ for (const receipt of receipts) {
255
+ const binding = receipt.routeBinding;
256
+ if (!binding)
257
+ continue;
258
+ const dispatchKey = [
259
+ binding.role,
260
+ binding.sessionId,
261
+ binding.taskId,
262
+ binding.callId,
263
+ binding.childSessionId,
264
+ String(binding.generation)
265
+ ].join("\x00");
266
+ latestByDispatch.set(dispatchKey, binding);
267
+ }
268
+ return [...latestByDispatch.values()];
269
+ }
270
+ function isLegacyTaskGateRequirementsChain(receipts) {
271
+ return receipts.length > 0 && receipts.every((receipt) => !receipt.routeBinding);
272
+ }
225
273
  function deriveReceiptRole(event) {
226
274
  switch (event.type) {
227
275
  case "accepted_mutation":
@@ -344,6 +392,12 @@ function sanitizeTaskId(taskId) {
344
392
  }
345
393
  throw new Error(`Invalid task ID: must be alphanumeric (ASCII) with optional hyphens, underscores, or dots, got "${taskId}"`);
346
394
  }
395
+ function validateTaskIdFormat(taskId) {
396
+ if (!STRICT_TASK_ID_PATTERN.test(taskId)) {
397
+ return `Invalid taskId "${taskId}". Must match pattern N.M or N.M.P (e.g., "1.1", "1.2.3")`;
398
+ }
399
+ return;
400
+ }
347
401
 
348
402
  // src/workflow/workflow-wal-file.ts
349
403
  import * as fs4 from "fs";
@@ -1493,7 +1547,7 @@ function parseTaskRepairWal(raw, filePath, expectedTaskId) {
1493
1547
  }
1494
1548
  function parseTaskTerminalWal(raw, filePath, expectedTaskId) {
1495
1549
  const parsed = parseWalObject(raw, filePath, "TASK_TERMINAL_WAL_UNREADABLE", "Preserve this file and reconcile the task terminal transition before moving it aside.");
1496
- if (parsed.version !== 1 && parsed.version !== 2 || parsed.state !== "PREPARED" && parsed.state !== "COMMITTED" && parsed.state !== "ABORTED" || typeof parsed.taskId !== "string" || !TASK_ID_PATTERN.test(parsed.taskId) || typeof parsed.transitionId !== "string" || parsed.transitionId.length === 0 || parsed.transitionId.length > 512 || typeof parsed.actor !== "string" || parsed.actor.length === 0 || parsed.actor.length > 512 || typeof parsed.oldPlanStatus !== "string" || parsed.oldPlanStatus.length === 0 || parsed.oldPlanStatus.length > 128 || parsed.newPlanStatus !== "completed" && parsed.newPlanStatus !== "blocked" && parsed.newPlanStatus !== "closed" || typeof parsed.oldWorkflowState !== "string" || !WORKFLOW_STATES.has(parsed.oldWorkflowState) || parsed.newWorkflowState !== "complete" && parsed.newWorkflowState !== "blocked" && parsed.newWorkflowState !== "closed" || !Number.isInteger(parsed.generation) || (parsed.generation ?? -1) < 0 || typeof parsed.qaExempt !== "boolean" || parsed.readOnlyNoMutation !== undefined && typeof parsed.readOnlyNoMutation !== "boolean" || typeof parsed.recordedAt !== "string" || !Number.isFinite(Date.parse(parsed.recordedAt))) {
1550
+ if (parsed.version !== 1 && parsed.version !== 2 || parsed.state !== "PREPARED" && parsed.state !== "COMMITTED" && parsed.state !== "ABORTED" || typeof parsed.taskId !== "string" || !TASK_ID_PATTERN.test(parsed.taskId) || typeof parsed.transitionId !== "string" || parsed.transitionId.length === 0 || parsed.transitionId.length > 512 || typeof parsed.actor !== "string" || parsed.actor.length === 0 || parsed.actor.length > 512 || typeof parsed.oldPlanStatus !== "string" || parsed.oldPlanStatus.length === 0 || parsed.oldPlanStatus.length > 128 || parsed.newPlanStatus !== "completed" && parsed.newPlanStatus !== "blocked" && parsed.newPlanStatus !== "closed" || typeof parsed.oldWorkflowState !== "string" || !WORKFLOW_STATES.has(parsed.oldWorkflowState) || parsed.newWorkflowState !== "complete" && parsed.newWorkflowState !== "blocked" && parsed.newWorkflowState !== "closed" || !Number.isInteger(parsed.generation) || (parsed.generation ?? -1) < 0 || typeof parsed.qaExempt !== "boolean" || parsed.readOnlyNoMutation !== undefined && typeof parsed.readOnlyNoMutation !== "boolean" || parsed.externalEvidence !== undefined && typeof parsed.externalEvidence !== "boolean" || typeof parsed.recordedAt !== "string" || !Number.isFinite(Date.parse(parsed.recordedAt))) {
1497
1551
  formatUnreadableMessage("TASK_TERMINAL_WAL_UNREADABLE", filePath, "is not a valid terminal WAL", "Preserve this file and reconcile the task terminal transition before moving it aside.");
1498
1552
  }
1499
1553
  if (parsed.version === 2 && (typeof parsed.planIdentityHash !== "string" || !SHA256_PATTERN.test(parsed.planIdentityHash) || typeof parsed.planEpoch !== "string" || !UUID_PATTERN.test(parsed.planEpoch))) {
@@ -1733,7 +1787,9 @@ var TASK_WORKFLOW_OUTCOMES = [
1733
1787
  "task_completed",
1734
1788
  "task_blocked",
1735
1789
  "task_closed",
1736
- "repair_idle"
1790
+ "repair_idle",
1791
+ "external_evidence_attested",
1792
+ "external_evidence_revoked"
1737
1793
  ];
1738
1794
  var MAX_PLAN_SCOPE_INSPECTION_BYTES = 4 * 1024 * 1024;
1739
1795
  function readCurrentTaskDeclaredFiles(directory, taskId) {
@@ -1799,6 +1855,30 @@ var GateEvidenceSchema = exports_external.object({
1799
1855
  timestamp: exports_external.string(),
1800
1856
  agent: exports_external.string()
1801
1857
  }).passthrough();
1858
+ var ExternalEvidenceBundleSchema = exports_external.object({
1859
+ class: exports_external.literal("external_git"),
1860
+ transitionId: exports_external.string().min(1).max(512),
1861
+ declarationDigest: exports_external.string().regex(/^[a-f0-9]{64}$/),
1862
+ anchors: exports_external.array(exports_external.object({
1863
+ command: exports_external.string().min(1).max(400),
1864
+ expect: exports_external.string().max(4096).optional(),
1865
+ expect_prefix: exports_external.string().min(1).max(4096).optional(),
1866
+ matched: exports_external.boolean(),
1867
+ exit_code: exports_external.number().int(),
1868
+ stdout: exports_external.string().max(4096)
1869
+ })).min(1).max(16).superRefine((anchors, ctx) => {
1870
+ anchors.forEach((anchor, index) => {
1871
+ if (anchor.expect === undefined && anchor.expect_prefix === undefined) {
1872
+ ctx.addIssue({
1873
+ code: exports_external.ZodIssueCode.custom,
1874
+ message: `anchor ${index} must carry expect and/or a non-empty expect_prefix`,
1875
+ path: [index]
1876
+ });
1877
+ }
1878
+ });
1879
+ }),
1880
+ attestedAt: exports_external.string().min(1)
1881
+ });
1802
1882
  var TaskWorkflowMetadataSchema = exports_external.object({
1803
1883
  schema: exports_external.literal(TASK_WORKFLOW_SCHEMA_MARKER),
1804
1884
  generation: exports_external.number().int().min(0),
@@ -1816,7 +1896,8 @@ var TaskWorkflowMetadataSchema = exports_external.object({
1816
1896
  generation: exports_external.literal(0),
1817
1897
  transitionId: exports_external.string().min(1).max(512),
1818
1898
  declaredFiles: exports_external.array(exports_external.string()).length(0)
1819
- }).optional()
1899
+ }).optional(),
1900
+ externalEvidence: ExternalEvidenceBundleSchema.optional()
1820
1901
  });
1821
1902
  var TaskEvidenceSchema = exports_external.object({
1822
1903
  taskId: exports_external.string(),
@@ -1903,6 +1984,10 @@ function getEventOutcome(event) {
1903
1984
  return "task_closed";
1904
1985
  case "repair_idle":
1905
1986
  return "repair_idle";
1987
+ case "external_evidence_attested":
1988
+ return "external_evidence_attested";
1989
+ case "external_evidence_revoked":
1990
+ return "external_evidence_revoked";
1906
1991
  }
1907
1992
  }
1908
1993
  function isAuthoritativeWorkflowMetadata(workflow) {
@@ -1978,8 +2063,9 @@ function deriveApplicableGateSet(evidence, options) {
1978
2063
  }
1979
2064
  const workflow = getTaskWorkflowSnapshot(evidence);
1980
2065
  const readOnlyNoMutation = isNoMutationSettlementMetadata(workflow) && (options?.currentDeclaredFiles === undefined ? true : options.currentDeclaredFiles !== null && options.currentDeclaredFiles.length === 0);
2066
+ const externalEvidenceMatched = workflow.lastOutcome === "external_evidence_attested" && (workflow.externalEvidence?.anchors.length ?? 0) > 0 && workflow.externalEvidence.anchors.every((anchor) => anchor.matched);
1981
2067
  const requiredGates = [...new Set(evidence.required_gates ?? [])];
1982
- if (!readOnlyNoMutation && !requiredGates.includes("pre_check")) {
2068
+ if (!readOnlyNoMutation && !externalEvidenceMatched && !requiredGates.includes("pre_check")) {
1983
2069
  requiredGates.unshift("pre_check");
1984
2070
  }
1985
2071
  const satisfiedGates = requiredGates.filter((gate) => evidence.gates?.[gate] != null);
@@ -1993,6 +2079,47 @@ function deriveApplicableGateSet(evidence, options) {
1993
2079
  function isReadOnlyNoMutationEligible(evidence, options) {
1994
2080
  return deriveApplicableGateSet(evidence, options).readOnlyNoMutation;
1995
2081
  }
2082
+ function computeExternalDeclarationDigest(input) {
2083
+ const canonical = {
2084
+ taskId: input.taskId,
2085
+ evidence_class: input.evidence_class,
2086
+ evidence_anchors: input.evidence_anchors.map((anchor) => ({
2087
+ command: anchor.command,
2088
+ expect: anchor.expect,
2089
+ expect_prefix: anchor.expect_prefix
2090
+ })),
2091
+ plan_title: input.plan_title,
2092
+ plan_swarm: input.plan_swarm,
2093
+ generation: input.generation
2094
+ };
2095
+ return createHash2("sha256").update(JSON.stringify(canonical)).digest("hex");
2096
+ }
2097
+ function externalProofCurrent(plan, planTask, evidence) {
2098
+ if (planTask.evidence_class !== "external_git")
2099
+ return false;
2100
+ const workflow = evidence?.workflow;
2101
+ if (!workflow)
2102
+ return false;
2103
+ const bundle = workflow.externalEvidence;
2104
+ if (!bundle || bundle.anchors.length === 0)
2105
+ return false;
2106
+ if (!bundle.anchors.every((anchor) => anchor.matched))
2107
+ return false;
2108
+ return bundle.declarationDigest === computeExternalDeclarationDigest({
2109
+ taskId: planTask.id,
2110
+ evidence_class: "external_git",
2111
+ evidence_anchors: planTask.evidence_anchors ?? [],
2112
+ plan_title: plan.title,
2113
+ plan_swarm: plan.swarm,
2114
+ generation: workflow.generation
2115
+ });
2116
+ }
2117
+ function isExternalEvidenceInitialCompletionEligible(plan, planTask, evidence) {
2118
+ if (!externalProofCurrent(plan, planTask, evidence))
2119
+ return false;
2120
+ const snapshot = getTaskWorkflowSnapshot(evidence);
2121
+ return snapshot.authoritative && snapshot.state === "idle";
2122
+ }
1996
2123
  function reduceTaskWorkflowSnapshot(current, event, context) {
1997
2124
  if ((current.state === "complete" || current.state === "blocked" || current.state === "closed") && event.type !== "repair_idle" && !(current.state === "complete" && event.type === "task_completed" || current.state === "blocked" && event.type === "task_blocked" || current.state === "blocked" && event.type === "task_closed" || current.state === "blocked" && event.type === "stage_a_passed" && event.settlementRecovery === true)) {
1998
2125
  throw new Error(`TASK_WORKFLOW_TERMINAL: cannot apply ${event.type} from ${current.state}`);
@@ -2011,15 +2138,24 @@ function reduceTaskWorkflowSnapshot(current, event, context) {
2011
2138
  ...current.forcedCompletion === true ? { forcedCompletion: true } : {},
2012
2139
  ...current.supervisedRecovery === true ? { supervisedRecovery: true } : {},
2013
2140
  ...current.settlementRecovery === true ? { settlementRecovery: true } : {},
2014
- ...current.noMutationSettlement ? { noMutationSettlement: current.noMutationSettlement } : {}
2141
+ ...current.noMutationSettlement ? { noMutationSettlement: current.noMutationSettlement } : {},
2142
+ ...current.externalEvidence ? { externalEvidence: current.externalEvidence } : {}
2015
2143
  };
2016
2144
  switch (event.type) {
2017
2145
  case "dispatch_attempted": {
2018
- const { noMutationSettlement: _clearedSettlement, ...withoutSettlement } = base;
2146
+ const {
2147
+ noMutationSettlement: _clearedSettlement,
2148
+ externalEvidence: _clearedExternalEvidence,
2149
+ ...withoutSettlement
2150
+ } = base;
2019
2151
  return withoutSettlement;
2020
2152
  }
2021
2153
  case "dispatch_no_mutation": {
2022
- const { noMutationSettlement: _clearedSettlement, ...withoutSettlement } = base;
2154
+ const {
2155
+ noMutationSettlement: _clearedSettlement,
2156
+ externalEvidence: _clearedExternalEvidence,
2157
+ ...withoutSettlement
2158
+ } = base;
2023
2159
  return {
2024
2160
  ...withoutSettlement,
2025
2161
  retryCount: Math.min(current.retryCount + 1, 3),
@@ -2046,7 +2182,11 @@ function reduceTaskWorkflowSnapshot(current, event, context) {
2046
2182
  retryEpoch: current.retryEpoch || current.generation + 1
2047
2183
  };
2048
2184
  case "accepted_mutation": {
2049
- const { noMutationSettlement: _clearedSettlement, ...withoutSettlement } = base;
2185
+ const {
2186
+ noMutationSettlement: _clearedSettlement,
2187
+ externalEvidence: _clearedExternalEvidence,
2188
+ ...withoutSettlement
2189
+ } = base;
2050
2190
  if (event.context?.settlementFailed === true) {
2051
2191
  return {
2052
2192
  ...withoutSettlement,
@@ -2110,9 +2250,26 @@ function reduceTaskWorkflowSnapshot(current, event, context) {
2110
2250
  ...base,
2111
2251
  state: current.state
2112
2252
  };
2253
+ case "external_evidence_attested": {
2254
+ if (current.state !== "idle") {
2255
+ throw new Error(`TASK_WORKFLOW_EXTERNAL_ATTEST_STATE: external evidence can only be attested from idle (task never entered the coder QA lifecycle), not ${current.state}`);
2256
+ }
2257
+ if (current.externalEvidence?.transitionId === event.bundle.transitionId) {
2258
+ return { ...base };
2259
+ }
2260
+ return { ...base, externalEvidence: event.bundle };
2261
+ }
2262
+ case "external_evidence_revoked": {
2263
+ const {
2264
+ externalEvidence: _revokedExternalEvidence,
2265
+ ...withoutExternalEvidence
2266
+ } = base;
2267
+ return withoutExternalEvidence;
2268
+ }
2113
2269
  case "task_completed": {
2114
2270
  const readOnlyNoMutation = event.readOnlyNoMutation === true && current.state === "idle" && current.generation === 0 && isNoMutationSettlementMetadata(current) && context.requiredGates.every((gate) => context.gates[gate] != null);
2115
- if (event.qaExempt !== true && current.state !== "tests_run" && current.state !== "complete" && !(current.state === "pre_check_passed" && context.gates.council != null) && !readOnlyNoMutation) {
2271
+ const externalAdmitted = event.externalEvidence === true && current.externalEvidence !== undefined && current.externalEvidence.anchors.length > 0 && current.externalEvidence.anchors.every((anchor) => anchor.matched) && (current.state === "idle" || current.state === "complete");
2272
+ if (event.qaExempt !== true && current.state !== "tests_run" && current.state !== "complete" && !(current.state === "pre_check_passed" && context.gates.council != null) && !readOnlyNoMutation && !externalAdmitted) {
2116
2273
  throw new Error(`TASK_WORKFLOW_QA_REQUIRED: cannot complete from ${current.state}`);
2117
2274
  }
2118
2275
  return {
@@ -2137,6 +2294,7 @@ function reduceTaskWorkflowSnapshot(current, event, context) {
2137
2294
  supervisedRecovery: _clearedMarker,
2138
2295
  settlementRecovery: _clearedSettlementMarker,
2139
2296
  noMutationSettlement: _clearedSettlement,
2297
+ externalEvidence: _clearedExternalEvidence,
2140
2298
  ...withoutForced
2141
2299
  } = base;
2142
2300
  return {
@@ -2505,4 +2663,4 @@ function compareTaskWorkflowStateRank(left, right) {
2505
2663
  return WORKFLOW_STATE_RANK[left] - WORKFLOW_STATE_RANK[right];
2506
2664
  }
2507
2665
 
2508
- export { isStrictTaskId, sanitizeTaskId, listRecoveryRecords, recoveryReadErrored, _internals, SOURCE_WORKTREE_GONE_STAGE, SOURCE_WORKTREE_UNCERTAIN_STAGE, getMergeStrategy, recoverMergeBackFromImmutableCoordinates, reconcileLandedMerge, postMergeCleanup, pruneStaleWorktreeMetadata, attemptMergeBackFromDirty, cleanupOrphanedBranches, startupOrphanRecovery, readWorkflowWalFile, writeWorkflowWalFile, _internals3 as _internals1, TASK_WORKFLOW_SCHEMA_MARKER, readCurrentTaskDeclaredFiles, TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL, assertTaskEvidenceWriteAllowed, parseTaskEvidence, DEFAULT_REQUIRED_GATES, isValidTaskId, getTaskWorkflowSnapshot, deriveApplicableGateSet, isReadOnlyNoMutationEligible, reduceTaskWorkflowSnapshot, deriveRequiredGates, expandRequiredGates, transitionTaskWorkflowEvidence, transitionTaskWorkflowEvidenceWithStatus, withTaskEvidenceTransaction, ensureTaskGateRequirementsReceiptForSettledTransition, recordGateEvidence, recordTodoScanEvidence, recordAgentDispatch, readTaskEvidence, readTaskEvidenceState, readTaskEvidenceRaw, hasPassedAllGates, compareTaskWorkflowStateRank };
2666
+ export { readTaskGateRequirementsReceiptsSync, routeEvidenceFromTaskGateRequirements, isLegacyTaskGateRequirementsChain, isStrictTaskId, sanitizeTaskId, validateTaskIdFormat, listRecoveryRecords, recoveryReadErrored, _internals, SOURCE_WORKTREE_GONE_STAGE, SOURCE_WORKTREE_UNCERTAIN_STAGE, getMergeStrategy, recoverMergeBackFromImmutableCoordinates, reconcileLandedMerge, postMergeCleanup, pruneStaleWorktreeMetadata, attemptMergeBackFromDirty, cleanupOrphanedBranches, startupOrphanRecovery, readWorkflowWalFile, writeWorkflowWalFile, _internals3 as _internals1, TASK_WORKFLOW_SCHEMA_MARKER, readCurrentTaskDeclaredFiles, TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL, assertTaskEvidenceWriteAllowed, ExternalEvidenceBundleSchema, parseTaskEvidence, DEFAULT_REQUIRED_GATES, isValidTaskId, getTaskWorkflowSnapshot, deriveApplicableGateSet, isReadOnlyNoMutationEligible, computeExternalDeclarationDigest, externalProofCurrent, isExternalEvidenceInitialCompletionEligible, reduceTaskWorkflowSnapshot, deriveRequiredGates, expandRequiredGates, transitionTaskWorkflowEvidence, transitionTaskWorkflowEvidenceWithStatus, withTaskEvidenceTransaction, ensureTaskGateRequirementsReceiptForSettledTransition, recordGateEvidence, recordTodoScanEvidence, recordAgentDispatch, readTaskEvidence, readTaskEvidenceState, readTaskEvidenceRaw, hasPassedAllGates, compareTaskWorkflowStateRank };
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  authorizeCuration
4
- } from "./index-0veqvgny.js";
4
+ } from "./index-v1h70r3y.js";
5
5
  import {
6
6
  findNearDuplicate,
7
7
  inferTags,
@@ -9,13 +9,13 @@ import {
9
9
  resolveSwarmKnowledgePath,
10
10
  resolveSwarmRejectedPath,
11
11
  transactKnowledge
12
- } from "./index-cwg99gea.js";
12
+ } from "./index-bn3aa5q1.js";
13
13
  import {
14
14
  resolveKnowledgeStoreDir
15
- } from "./index-n1ddn12j.js";
15
+ } from "./index-g57p8p1k.js";
16
16
  import {
17
17
  atomicWriteFile
18
- } from "./index-jmhn6ab5.js";
18
+ } from "./index-traz987v.js";
19
19
  import {
20
20
  require_proper_lockfile
21
21
  } from "./index-7g4c7s5r.js";
@@ -5,18 +5,18 @@ import {
5
5
  import {
6
6
  effectiveRetrievalOutcomes,
7
7
  readAuthoritativeKnowledgeCounterRollups
8
- } from "./index-s4wbe96z.js";
8
+ } from "./index-0ptf66x5.js";
9
9
  import {
10
10
  ALLOWED_SKILL_PATH_PREFIXES,
11
11
  validateSkillPath
12
- } from "./index-3ct8kgfj.js";
12
+ } from "./index-sz67z90q.js";
13
13
  import {
14
14
  computeOutcomeSignal,
15
15
  readKnowledge,
16
16
  resolveHiveKnowledgePath,
17
17
  resolveSwarmKnowledgePath,
18
18
  transactKnowledge
19
- } from "./index-cwg99gea.js";
19
+ } from "./index-bn3aa5q1.js";
20
20
  import {
21
21
  appendCappedJsonl,
22
22
  resolveRetentionCap
@@ -27,7 +27,7 @@ import {
27
27
  import {
28
28
  atomicWriteFileAnyRoot,
29
29
  atomicWriteSwarmFile
30
- } from "./index-270zfq1f.js";
30
+ } from "./index-epzadpmm.js";
31
31
  import {
32
32
  advisoryWarn,
33
33
  init_warning_buffer
@@ -1,10 +1,10 @@
1
1
  // @bun
2
2
  import {
3
3
  withEvidenceLock
4
- } from "./index-dz15f98h.js";
4
+ } from "./index-q8vfw61p.js";
5
5
  import {
6
6
  atomicWriteFileAnyRoot
7
- } from "./index-270zfq1f.js";
7
+ } from "./index-epzadpmm.js";
8
8
 
9
9
  // src/evidence/task-file.ts
10
10
  import * as path from "path";
@@ -11,7 +11,7 @@ import {
11
11
  readLinkPointer,
12
12
  resolveKnowledgeStoreDir,
13
13
  resolveLinkDir
14
- } from "./index-n1ddn12j.js";
14
+ } from "./index-g57p8p1k.js";
15
15
 
16
16
  // src/knowledge/curation-policy.ts
17
17
  import { readFile as readFile2 } from "fs/promises";
@@ -11,7 +11,7 @@ import {
11
11
  } from "./index-te9hq2f4.js";
12
12
  import {
13
13
  atomicWriteSwarmFileSync
14
- } from "./index-270zfq1f.js";
14
+ } from "./index-epzadpmm.js";
15
15
 
16
16
  // src/db/project-db.ts
17
17
  import { existsSync, mkdirSync, unlinkSync } from "fs";
@@ -1,14 +1,14 @@
1
1
  // @bun
2
2
  import {
3
3
  writeSpeckitCheckoffLedger
4
- } from "./index-38fgg593.js";
4
+ } from "./index-3zspah3v.js";
5
5
  import {
6
6
  validateSpecContent
7
7
  } from "./index-0725jpp7.js";
8
8
  import {
9
9
  init_loader,
10
10
  readSddSourceSetting
11
- } from "./index-88d5kpjj.js";
11
+ } from "./index-3020n6d9.js";
12
12
  import {
13
13
  advisoryWarn,
14
14
  init_warning_buffer
@@ -20,7 +20,7 @@ import {
20
20
  import {
21
21
  SDD_SOURCES,
22
22
  init_schema
23
- } from "./index-0bw1jyen.js";
23
+ } from "./index-p6v544jn.js";
24
24
 
25
25
  // src/sdd/effective-spec.ts
26
26
  init_loader();
@@ -4,7 +4,7 @@ import {
4
4
  } from "./index-6b295cas.js";
5
5
  import {
6
6
  readEffectiveSpecSync
7
- } from "./index-qbhjey8k.js";
7
+ } from "./index-vtkgg2qn.js";
8
8
  import {
9
9
  _internals,
10
10
  clearWorktreeMergeStatus,
@@ -20,7 +20,7 @@ import {
20
20
  estimateTokens,
21
21
  readSwarmFileAsync,
22
22
  validateSwarmPath
23
- } from "./index-b3ws03kp.js";
23
+ } from "./index-xyvsdn07.js";
24
24
  import {
25
25
  LedgerStaleWriterError,
26
26
  appendLedgerEvent,
@@ -39,7 +39,7 @@ import {
39
39
  replayFromLedgerWithStatus,
40
40
  takeSnapshotEvent,
41
41
  takeSnapshotWithRetry
42
- } from "./index-zzpy5cx3.js";
42
+ } from "./index-s8eac99p.js";
43
43
  import {
44
44
  deleteCoordinationStateWithinTransaction,
45
45
  getCoordinationStateRaw,
@@ -48,16 +48,16 @@ import {
48
48
  transitionCoordinationState,
49
49
  transitionCoordinationStateWithinTransaction,
50
50
  withCoordinationTransaction
51
- } from "./index-9y6yk1n0.js";
51
+ } from "./index-na6ph1fp.js";
52
52
  import {
53
53
  DURABILITY_CLASSES,
54
54
  getProjectDb,
55
55
  projectDbExists,
56
56
  withDurabilityClass
57
- } from "./index-snx2vb1x.js";
57
+ } from "./index-ves1rtqt.js";
58
58
  import {
59
59
  appendCoreEventSync
60
- } from "./index-3mzc5rqc.js";
60
+ } from "./index-nzfq1ms2.js";
61
61
  import {
62
62
  derivePlanId,
63
63
  derivePlanIdentityHash
@@ -67,7 +67,7 @@ import {
67
67
  } from "./index-t7hmqgjy.js";
68
68
  import {
69
69
  emit
70
- } from "./index-dtwj4hsk.js";
70
+ } from "./index-c2k7q723.js";
71
71
  import {
72
72
  canonicalRootKeyFresh
73
73
  } from "./index-te9hq2f4.js";
@@ -78,18 +78,18 @@ import {
78
78
  atomicWriteSwarmFileSync,
79
79
  invalidateCachedArtifact,
80
80
  readCachedParsedFile
81
- } from "./index-270zfq1f.js";
81
+ } from "./index-epzadpmm.js";
82
82
  import {
83
83
  PlanSchema,
84
84
  normalizeCurrentPhaseInPlace,
85
85
  resolveActivePhaseId
86
- } from "./index-gx2vp8gx.js";
86
+ } from "./index-3t46mez1.js";
87
87
  import {
88
88
  init_config,
89
89
  init_loader,
90
90
  isEpicModeConfigEnabled,
91
91
  loadPluginConfigWithMeta
92
- } from "./index-88d5kpjj.js";
92
+ } from "./index-3020n6d9.js";
93
93
  import {
94
94
  bunHash,
95
95
  bunWrite,
@@ -1600,7 +1600,9 @@ function computePlanContentHash(plan) {
1600
1600
  acceptance: task.acceptance,
1601
1601
  files_touched: [...task.files_touched].sort(),
1602
1602
  evidence_path: task.evidence_path,
1603
- blocked_reason: task.blocked_reason
1603
+ blocked_reason: task.blocked_reason,
1604
+ evidence_class: task.evidence_class,
1605
+ evidence_anchors: task.evidence_anchors
1604
1606
  })).sort((a, b) => compareTaskIds(a.id, b.id))
1605
1607
  })).sort((a, b) => a.id - b.id)
1606
1608
  };
@@ -2668,7 +2670,7 @@ ${markdown}`;
2668
2670
  }
2669
2671
  }
2670
2672
  async function defaultMaybeSaveAutoCheckpoint(directory, plan) {
2671
- const { maybeSaveAutoCheckpoint } = await import("./auto-checkpoint-gv21fb1h.js");
2673
+ const { maybeSaveAutoCheckpoint } = await import("./auto-checkpoint-bywgxh27.js");
2672
2674
  return maybeSaveAutoCheckpoint(directory, plan);
2673
2675
  }
2674
2676
  async function updateTaskStatus(directory, taskId, status, options) {
@@ -2744,7 +2746,7 @@ async function updateTaskStatus(directory, taskId, status, options) {
2744
2746
  if (status === "completed") {
2745
2747
  try {
2746
2748
  const completedTask = updatedPlan.phases.flatMap((phase) => phase.tasks).find((candidate) => candidate.id === taskId);
2747
- const { maybePropagateSpeckitCheckoff } = await import("./speckit-checkoff-61xn2c2v.js");
2749
+ const { maybePropagateSpeckitCheckoff } = await import("./speckit-checkoff-1v02b2dt.js");
2748
2750
  await maybePropagateSpeckitCheckoff(directory, {
2749
2751
  taskId,
2750
2752
  frRefs: completedTask?.fr_refs ?? [],
@@ -2843,6 +2845,11 @@ Phase: ${currentPhase} [${phaseStatus}] | Updated: ${now}
2843
2845
  const sortedFiles = [...task.files_touched].sort();
2844
2846
  suffix += ` (files_touched: ${JSON.stringify(sortedFiles)})`;
2845
2847
  }
2848
+ if (task.evidence_class === "external_git") {
2849
+ const anchorCommands = (task.evidence_anchors ?? []).map((anchor) => anchor.command).join("; ");
2850
+ const anchorsSummary = anchorCommands.length > 120 ? `${anchorCommands.slice(0, 117)}...` : anchorCommands;
2851
+ suffix += ` \u2014 external evidence: external_git (anchors: ${anchorsSummary})`;
2852
+ }
2846
2853
  if (phase.id === currentPhase && task.status === "in_progress" && !currentTaskMarked) {
2847
2854
  suffix += " \u2190 CURRENT";
2848
2855
  currentTaskMarked = true;
@@ -3084,4 +3091,4 @@ function migrateLegacyPlan(planContent, swarmId) {
3084
3091
  return plan;
3085
3092
  }
3086
3093
 
3087
- export { EPIC_MODE_CONFIG_DISABLED_MESSAGE, isEpicModeConfigEnabledForDirectory, epicSentinelExists, computeEpicKey, planIdentityOf, readLedgerRootDigest, inspectEpic, getOpenEpic, isEpicOpenForProject, createEpicRecord, updateEpicRecord, readPlanTaskRef, markEpicClosing, recordEpicBranch, recordEpicLandingAttempt, deleteEpicState, repairEpicSentinel, buildTaskCompletionDescriptor, ensureTaskCheckpointReceipt, updateTaskCheckpointReceipt, relevantMergeFailureForProject, describeMergeFailuresForStatus, clearMergeFailureCommand, getRunMemorySummary, PlanRecoverySupersededError, loadPlanJsonOnly, loadPlan, withPlanLifecycleLock, savePlan, closePlanTerminalState, updateTaskStatus, derivePlanMarkdown, getCurrentTaskId };
3094
+ export { EPIC_MODE_CONFIG_DISABLED_MESSAGE, isEpicModeConfigEnabledForDirectory, epicSentinelExists, computeEpicKey, planIdentityOf, readLedgerRootDigest, inspectEpic, getOpenEpic, isEpicOpenForProject, createEpicRecord, updateEpicRecord, readPlanTaskRef, markEpicClosing, recordEpicBranch, recordEpicLandingAttempt, deleteEpicState, repairEpicSentinel, buildTaskCompletionDescriptor, ensureTaskCheckpointReceipt, updateTaskCheckpointReceipt, relevantMergeFailureForProject, describeMergeFailuresForStatus, clearMergeFailureCommand, recordTaskAttempt, getRunMemorySummary, PlanRecoverySupersededError, loadPlanJsonOnly, loadPlan, withPlanLifecycleLock, savePlan, closePlanTerminalState, updateTaskStatus, derivePlanMarkdown, getCurrentTaskId };