@iowarp/clio-coder 0.3.7 → 0.3.8

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 (223) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +7 -2
  3. package/dist/{acp-SK4MD6MM.js → acp-U67UHUK2.js} +13 -13
  4. package/dist/{agents-2FN2K6ME.js → agents-YU6SGALZ.js} +35 -33
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-QIYZWM5I.js → auth-5ZPJOIVG.js} +32 -24
  7. package/dist/builtins-C6JMZVV6.js +17 -0
  8. package/dist/{chunk-YD734TPH.js → chunk-26LEYJZH.js} +2 -2
  9. package/dist/{chunk-TSHXZTOQ.js → chunk-2HEJ2F35.js} +5 -5
  10. package/dist/{chunk-WJHBC77E.js → chunk-2HFZQUHL.js} +5 -5
  11. package/dist/{chunk-FO5ZOVUY.js → chunk-3BINW3FP.js} +5 -5
  12. package/dist/{chunk-EOOQZZDE.js → chunk-4SPRNWDE.js} +18 -18
  13. package/dist/{chunk-EBEFWSGL.js → chunk-5DHKRSMQ.js} +7 -7
  14. package/dist/{chunk-OBMAI2DP.js → chunk-5H3GB5BO.js} +11 -9
  15. package/dist/{chunk-JTSEDYVQ.js → chunk-5Q2VVUKB.js} +7 -7
  16. package/dist/{chunk-VQNODYQ4.js → chunk-7RFXX52T.js} +294 -3704
  17. package/dist/{chunk-XEGB6BCN.js → chunk-7RGZWPB6.js} +5 -5
  18. package/dist/{chunk-GH5622CP.js → chunk-A2NJGIB3.js} +2 -2
  19. package/dist/{chunk-CEYBNUGC.js → chunk-A3WNZD3P.js} +323 -27
  20. package/dist/{chunk-D4MDIG46.js → chunk-B5CSFE7B.js} +7 -7
  21. package/dist/{chunk-2SFS6XQE.js → chunk-DGSYXYMX.js} +3 -2
  22. package/dist/{chunk-ZWLZP4ZT.js → chunk-DYIM5TJT.js} +98 -12
  23. package/dist/{chunk-KCMKRQX4.js → chunk-E77JEWSD.js} +42 -49
  24. package/dist/{chunk-J7PIKKWC.js → chunk-EMYUUSFG.js} +7 -7
  25. package/dist/{chunk-JRIO5UD2.js → chunk-EQ63NRB7.js} +5 -5
  26. package/dist/{chunk-UVDSQ6LW.js → chunk-FBVTI2TJ.js} +74 -28
  27. package/dist/{chunk-BMWK7ZIZ.js → chunk-FHJEP5SW.js} +13 -13
  28. package/dist/{chunk-FOT2FX5J.js → chunk-GN57SG4G.js} +7 -7
  29. package/dist/{chunk-SROCI7ZU.js → chunk-GPIEI3LY.js} +5 -5
  30. package/dist/{chunk-UFQ3F4FW.js → chunk-GU2UIAFZ.js} +4 -4
  31. package/dist/{chunk-UND3GU2L.js → chunk-H7IXIC72.js} +2 -2
  32. package/dist/{chunk-VREKEFLL.js → chunk-HLE42MG7.js} +3 -3
  33. package/dist/{chunk-465YSENW.js → chunk-IFBNV6H6.js} +3 -3
  34. package/dist/{chunk-LADCF22A.js → chunk-IGWKHNIQ.js} +113 -54
  35. package/dist/chunk-IIZWH4XA.js +172 -0
  36. package/dist/{chunk-UHXRNZ2J.js → chunk-IJ7RPIYJ.js} +4 -4
  37. package/dist/{chunk-M4AKACEO.js → chunk-J3YUBZWY.js} +2 -2
  38. package/dist/{chunk-AB4XIIVB.js → chunk-JOZYP4GM.js} +6 -6
  39. package/dist/{chunk-ZGH7FGS5.js → chunk-K4XHGFR5.js} +742 -12
  40. package/dist/{chunk-EELBMBT6.js → chunk-KTYTFRMB.js} +62 -5
  41. package/dist/chunk-LU7P4LHA.js +33 -0
  42. package/dist/{chunk-DQA7QLMD.js → chunk-ME6CCNFO.js} +9 -24
  43. package/dist/{chunk-KZ2H5X4G.js → chunk-MXKJU4JB.js} +88 -14
  44. package/dist/{chunk-DMD2AGVS.js → chunk-N22QMJKY.js} +20 -18
  45. package/dist/chunk-NMPKI6XL.js +3006 -0
  46. package/dist/chunk-NUGM5KR6.js +165 -0
  47. package/dist/{chunk-5C77SEEY.js → chunk-P43ETTHK.js} +2 -2
  48. package/dist/{chunk-JNXPYBB4.js → chunk-PMDBGQSJ.js} +2 -2
  49. package/dist/chunk-PT7HYKEM.js +165 -0
  50. package/dist/{chunk-GEYXPTRF.js → chunk-RWSI4YD7.js} +2 -2
  51. package/dist/{chunk-C4JBQ5SR.js → chunk-TANS5ZJS.js} +6 -6
  52. package/dist/{chunk-YTYFXUI3.js → chunk-TB5666IT.js} +9 -9
  53. package/dist/{chunk-UUANF5CR.js → chunk-TLQJPP24.js} +375 -687
  54. package/dist/{chunk-OB5HIGJY.js → chunk-TT36MB5S.js} +2 -1
  55. package/dist/{chunk-DJNLUABN.js → chunk-TTHACPOM.js} +135 -17
  56. package/dist/{chunk-6M7VS3J3.js → chunk-TYPGUK6W.js} +4 -4
  57. package/dist/{chunk-THKY7CD7.js → chunk-U6MBIEMB.js} +108 -24
  58. package/dist/{chunk-PD3MESLB.js → chunk-VAWNZU7Z.js} +4 -4
  59. package/dist/{chunk-IR4CFBFN.js → chunk-VCBR6CU7.js} +12 -12
  60. package/dist/{chunk-WHJYKASB.js → chunk-VHN4MY6O.js} +2 -2
  61. package/dist/{chunk-MXI6J5JF.js → chunk-VWZOAB7K.js} +10 -10
  62. package/dist/{chunk-QCTRSGHQ.js → chunk-WLFILSD5.js} +36 -36
  63. package/dist/{chunk-5UJ6ECTS.js → chunk-WNIJTQQK.js} +6 -6
  64. package/dist/{chunk-4DWFMQDR.js → chunk-WSB3FPX7.js} +68 -20
  65. package/dist/{chunk-3HAPLH5M.js → chunk-WWCZ5F23.js} +112 -10
  66. package/dist/{chunk-X2KV5FXT.js → chunk-WXY7KU3G.js} +2 -2
  67. package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
  68. package/dist/{chunk-DOOEX22V.js → chunk-XWSF374K.js} +4 -4
  69. package/dist/{chunk-6TUKSZVF.js → chunk-YS5VLNH5.js} +8 -8
  70. package/dist/{chunk-ZZMN5OM4.js → chunk-ZNLWCMVZ.js} +2 -2
  71. package/dist/{chunk-WHGPSPT5.js → chunk-ZVJ5BLO2.js} +2 -2
  72. package/dist/cli/index.js +31 -31
  73. package/dist/{clio-WBVQEBKO.js → clio-QVTYJ57A.js} +8 -8
  74. package/dist/code-nav-FGGFIE7L.js +2 -2
  75. package/dist/codewiki/build-worker.js +4 -4
  76. package/dist/{components-F7OEATSO.js → components-ZFA3SAER.js} +8 -8
  77. package/dist/{config-TRBL3RCF.js → config-LW5IJFQN.js} +58 -53
  78. package/dist/{configure-OLCVPHNM.js → configure-7XIZCOU4.js} +26 -21
  79. package/dist/{context-XEWE3MOJ.js → context-L3WL3X7K.js} +47 -41
  80. package/dist/{context-WFPKQSM6.js → context-N52ZA626.js} +22 -22
  81. package/dist/{context-MJIJ6GOX.js → context-Y6Y7QPR6.js} +12 -12
  82. package/dist/{context-clear-KNOS2JPB.js → context-clear-MBQRLSDQ.js} +47 -41
  83. package/dist/{context-index-SSR5ECNE.js → context-index-HVMFQHK3.js} +5 -5
  84. package/dist/{context-working-set-EUXAZI6N.js → context-working-set-GS6DSO7F.js} +14 -14
  85. package/dist/{dispatch-runner-B7MTOVKL.js → dispatch-runner-22ZCNOM3.js} +83 -55
  86. package/dist/{docs-FLJTIDSE.js → docs-7LQ23DLM.js} +8 -8
  87. package/dist/{doctor-RN4YKO2X.js → doctor-M7YEDGAE.js} +24 -20
  88. package/dist/{eval-RUBJVSNQ.js → eval-BEC2WHDA.js} +71 -19
  89. package/dist/{evidence-JZNBUOQZ.js → evidence-REJUMSKM.js} +62 -56
  90. package/dist/{evolve-FJVC4KKI.js → evolve-PY5ZBA5K.js} +41 -35
  91. package/dist/{extensions-IQL36S7K.js → extensions-HVKU65YU.js} +6 -6
  92. package/dist/{fleet-BDKYJFCP.js → fleet-7WZEWRFA.js} +72 -67
  93. package/dist/{fleet-commands-ZFIWZSB3.js → fleet-commands-UVHWM76J.js} +10 -10
  94. package/dist/{fleet-graph-Y6HPXIVF.js → fleet-graph-6ULH7PES.js} +13 -13
  95. package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-J53T6CCE.js} +5 -5
  96. package/dist/{fleet-validate-BIYREGIK.js → fleet-validate-72PC4SLA.js} +17 -17
  97. package/dist/{init-LQUB5COQ.js → init-OG3TPGQG.js} +61 -56
  98. package/dist/{library-NJAHIGG4.js → library-CNTMPLRF.js} +18 -18
  99. package/dist/{memory-OG6HOYKM.js → memory-6IS7F275.js} +43 -37
  100. package/dist/{models-5ZG5XY7J.js → models-ENRJDA5W.js} +33 -28
  101. package/dist/{monitor-TJ7AMTGB.js → monitor-XLDVO7TN.js} +56 -38
  102. package/dist/{orchestrator-WZYB54DM.js → orchestrator-6KSPYRHA.js} +421 -303
  103. package/dist/{paths-XUC7GS6E.js → paths-DBXMZMDU.js} +5 -5
  104. package/dist/registry-LG64LTF4.js +11 -0
  105. package/dist/{reset-PXQT45IY.js → reset-RZ4ER727.js} +10 -10
  106. package/dist/{run-FQ74YF62.js → run-Y2CNK5RU.js} +79 -74
  107. package/dist/{share-FW7SVCL3.js → share-A55GYP6Z.js} +16 -16
  108. package/dist/{skills-7E7IRB3R.js → skills-ALC5J6AT.js} +19 -19
  109. package/dist/{skills-eval-LI75W6OK.js → skills-eval-JPBEBYQU.js} +52 -47
  110. package/dist/support-MIETYA5E.js +38 -0
  111. package/dist/{targets-4CIFKCTW.js → targets-VGNXIR3S.js} +42 -33
  112. package/dist/{terminal-lease-WUZY7ZV5.js → terminal-lease-WOBR64YA.js} +3 -3
  113. package/dist/{uninstall-7FV7IP4E.js → uninstall-ZJF5H5ZN.js} +8 -8
  114. package/dist/{upgrade-K2HVIVMQ.js → upgrade-FUSUAGHR.js} +27 -25
  115. package/dist/{usage-GTZELZQX.js → usage-N4MKVHKD.js} +51 -46
  116. package/dist/{verifiers-RLAHT27O.js → verifiers-YAWOJ3H2.js} +13 -13
  117. package/dist/{verify-BX3BRKH5.js → verify-LTDHYBGY.js} +9 -9
  118. package/dist/{wiki-generate-ASIFASCN.js → wiki-generate-6M7GHTBJ.js} +66 -61
  119. package/dist/worker/entry.js +68 -61
  120. package/docs/alcf-provider.md +1 -1
  121. package/docs/architecture.md +1 -1
  122. package/docs/artifact-versions.md +6 -5
  123. package/docs/built-in-agents.md +1 -1
  124. package/docs/commands-and-modes.md +2 -2
  125. package/docs/configuration-and-targets.md +8 -3
  126. package/docs/context-engine.md +1 -1
  127. package/docs/documentation-guide.md +1 -1
  128. package/docs/eval-runner.md +1 -1
  129. package/docs/evals-internal.md +1 -1
  130. package/docs/evidence-and-memory.md +70 -6
  131. package/docs/evolution.md +1 -1
  132. package/docs/extensions-and-sharing.md +1 -1
  133. package/docs/fleet-dispatch.md +34 -9
  134. package/docs/glossary.md +21 -1
  135. package/docs/installation-and-lifecycle.md +1 -1
  136. package/docs/middleware-and-components.md +1 -1
  137. package/docs/model-catalog.md +1 -1
  138. package/docs/observability.md +2 -2
  139. package/docs/proactive-memory.md +1 -1
  140. package/docs/prompt-envelope-and-tools.md +4 -2
  141. package/docs/provider-adapter-cookbook.md +1 -1
  142. package/docs/release-cut-checklist.md +41 -38
  143. package/docs/safety-model.md +1 -1
  144. package/docs/scientific-validation.md +1 -1
  145. package/docs/skills-marketplace.md +1 -1
  146. package/docs/tool-usage.md +1 -1
  147. package/docs/trace-store.md +1 -1
  148. package/docs/tui-design.md +1 -1
  149. package/docs/worker-dispatch-mechanics.md +1 -1
  150. package/package.json +1 -2
  151. package/src/cli/argv.ts +5 -0
  152. package/src/cli/configure.ts +107 -23
  153. package/src/cli/doctor.ts +5 -1
  154. package/src/cli/evidence.ts +30 -25
  155. package/src/cli/fleet-preflight.ts +2 -12
  156. package/src/cli/shared.ts +1 -0
  157. package/src/cli/targets.ts +4 -1
  158. package/src/cli/validate-model.ts +60 -5
  159. package/src/core/bus-events.ts +25 -0
  160. package/src/core/commit-attribution.ts +4 -4
  161. package/src/core/path-boundary.ts +100 -0
  162. package/src/domains/agents/extension.ts +2 -11
  163. package/src/domains/agents/fleet-contract.ts +30 -12
  164. package/src/domains/agents/recipe.ts +7 -1
  165. package/src/domains/agents/registry.ts +73 -5
  166. package/src/domains/agents/result-contract.ts +128 -17
  167. package/src/domains/agents/write-boundary.ts +15 -50
  168. package/src/domains/context/project-rules.ts +51 -1
  169. package/src/domains/dispatch/assignment-reconcile.ts +22 -5
  170. package/src/domains/dispatch/assignment-store.ts +151 -14
  171. package/src/domains/dispatch/contract.ts +15 -1
  172. package/src/domains/dispatch/delegation-plan.ts +2 -5
  173. package/src/domains/dispatch/execution-role.ts +9 -1
  174. package/src/domains/dispatch/extension.ts +156 -67
  175. package/src/domains/dispatch/fleet-run.ts +57 -3
  176. package/src/domains/dispatch/gate-role-prompts.ts +38 -0
  177. package/src/domains/dispatch/index.ts +3 -1
  178. package/src/domains/dispatch/intent-requirements.ts +40 -0
  179. package/src/domains/dispatch/intent.ts +84 -8
  180. package/src/domains/dispatch/path-scope.ts +370 -0
  181. package/src/domains/dispatch/receipt-integrity.ts +2 -1
  182. package/src/domains/dispatch/types.ts +14 -7
  183. package/src/domains/dispatch/validation.ts +6 -3
  184. package/src/domains/dispatch/write-boundary-enforcer.ts +45 -0
  185. package/src/domains/dispatch/write-boundary.ts +201 -22
  186. package/src/domains/eval/metrics/evidence.ts +79 -2
  187. package/src/domains/eval/runners/clio-run.ts +12 -2
  188. package/src/domains/evidence/build.ts +69 -11
  189. package/src/domains/evidence/index.ts +21 -0
  190. package/src/domains/evidence/provenance.ts +46 -11
  191. package/src/domains/evidence/trust-projection.ts +274 -0
  192. package/src/domains/evidence/trust-status.ts +145 -17
  193. package/src/domains/evidence/types.ts +4 -0
  194. package/src/domains/extensions/discovery.ts +88 -1
  195. package/src/domains/extensions/resources.ts +20 -8
  196. package/src/domains/extensions/state.ts +6 -2
  197. package/src/domains/extensions/types.ts +4 -1
  198. package/src/domains/lifecycle/doctor.ts +140 -1
  199. package/src/domains/prompts/contract.ts +3 -5
  200. package/src/domains/providers/extension.ts +30 -2
  201. package/src/domains/resources/common-loader.ts +3 -0
  202. package/src/domains/resources/prompts/loader.ts +119 -14
  203. package/src/domains/safety/policy-engine.ts +5 -5
  204. package/src/domains/safety/run-effects.ts +64 -1
  205. package/src/domains/safety/scope.ts +7 -12
  206. package/src/engine/acp/server.ts +4 -1
  207. package/src/engine/prompt-templates.ts +18 -1
  208. package/src/engine/worker-runtime.ts +6 -3
  209. package/src/interactive/dispatch-board.ts +53 -3
  210. package/src/interactive/interactive-event-projection.ts +14 -0
  211. package/src/interactive/overlays/settings.ts +141 -47
  212. package/src/interactive/slash-commands.ts +7 -2
  213. package/src/interactive/view/artifacts.ts +42 -9
  214. package/src/interactive/view/view-overlay.ts +15 -3
  215. package/src/interactive/worker-receipts.ts +14 -2
  216. package/src/interactive/worker-stream.ts +8 -0
  217. package/src/tools/dispatch-admission.ts +12 -13
  218. package/src/tools/dispatch-arguments.ts +27 -0
  219. package/src/tools/dispatch-plan.ts +29 -0
  220. package/src/tools/dispatch-runner.ts +48 -13
  221. package/src/tools/monitor.ts +13 -0
  222. package/src/tools/worker-evidence.ts +19 -13
  223. package/src/worker/spec-contract.ts +2 -1
@@ -21,6 +21,7 @@ import { AGENT_AUTOMATION_AUTHORITIES, type AgentAutomationAuthority } from "../
21
21
  import type { DispatchRequest } from "../domains/dispatch/contract.js";
22
22
  import { type ExecutionRole, isExecutionRole } from "../domains/dispatch/execution-role.js";
23
23
  import { type DispatchIntent, isDispatchIntent } from "../domains/dispatch/intent.js";
24
+ import { resolveDispatchPathScope } from "../domains/dispatch/path-scope.js";
24
25
  import {
25
26
  type ApprovedAssignmentRoute,
26
27
  cloneApprovedAssignmentRoute,
@@ -246,6 +247,33 @@ function safeField(value: string): string {
246
247
  return result;
247
248
  }
248
249
 
250
+ function renderLegacyPathScope(task: DispatchPlanTaskView): string[] {
251
+ if (task.intent !== undefined) return [];
252
+ const scope = resolveDispatchPathScope({
253
+ agentId: task.agent,
254
+ executionRole: task.executionRole,
255
+ task: task.task,
256
+ ...(task.briefing !== undefined ? { briefing: task.briefing } : {}),
257
+ });
258
+ const lines = [" scope mode=legacy-inferred"];
259
+ for (const [policy, entries] of [
260
+ ["working_context", scope.provenance.workingContextPaths],
261
+ ["write_boundary", scope.provenance.writeBoundaries],
262
+ ] as const) {
263
+ for (const entry of entries) {
264
+ for (const evidence of entry.evidence) {
265
+ lines.push(
266
+ ` scope ${policy} path=${JSON.stringify(safeField(entry.path))} provenance=${evidence.provenance} source=${evidence.source} confidence=${evidence.confidence} reason=${evidence.reason}`,
267
+ );
268
+ }
269
+ }
270
+ }
271
+ if (scope.provenance.workingContextPaths.length === 0 && scope.provenance.writeBoundaries.length === 0) {
272
+ lines.push(" scope policy_paths=none");
273
+ }
274
+ return lines;
275
+ }
276
+
249
277
  function taskViews(args: Record<string, unknown>): DispatchPlanTaskView[] {
250
278
  const tasks = Array.isArray(args.tasks) ? args.tasks : [];
251
279
  const sharedAgent = str(args.agent) ?? "coder";
@@ -417,6 +445,7 @@ function renderPlanText(
417
445
  const serialized = JSON.stringify(task.intent);
418
446
  lines.push(` intent_sha256=${createHash("sha256").update(serialized, "utf8").digest("hex")}`);
419
447
  }
448
+ lines.push(...renderLegacyPathScope(task));
420
449
  for (const check of task.resolvedVerification ?? []) {
421
450
  lines.push(
422
451
  ` verification check=${safeField(check.check)} argv=${JSON.stringify(check.argv)} cwd=${JSON.stringify(check.cwd)} timeout_ms=${check.timeoutMs}`,
@@ -38,12 +38,15 @@ import {
38
38
  type CompeteStance,
39
39
  JUDGE_GATE_PROMPT,
40
40
  REVIEWER_GATE_PROMPT,
41
+ renderCouncilVoteMemberTask,
41
42
  } from "../domains/dispatch/gate-role-prompts.js";
43
+ import { renderDispatchReviewerTask } from "../domains/dispatch/intent-requirements.js";
42
44
  import { UNVERIFIABLE_RECEIPT_VERIFICATION } from "../domains/dispatch/receipt-findings.js";
43
45
  import { type ReceiptIntegrityResult, verifyReceiptIntegrity } from "../domains/dispatch/receipt-integrity.js";
44
46
  import { explainRouteDecision } from "../domains/dispatch/routing-intent.js";
45
47
  import type { RunGateProvenance, RunGateSubjectRef, RunPlanProvenance, RunReceipt } from "../domains/dispatch/types.js";
46
48
  import { extractRunProvenance, provenanceCompactSuffix } from "../domains/evidence/provenance.js";
49
+ import { summarizeTrustStatus } from "../domains/evidence/trust-projection.js";
47
50
  import { adaptRunReceiptTrustStatus } from "../domains/evidence/trust-status.js";
48
51
  import type { AutonomyLevel } from "../domains/safety/autonomy.js";
49
52
  import {
@@ -580,6 +583,10 @@ function dispatchDetails(
580
583
  hostVerification: integrity.ok ? (receipt.hostVerification ?? null) : null,
581
584
  receiptIntegrity: integrity,
582
585
  trustStatus,
586
+ // The bounded projection sits shallow and flat on purpose: a
587
+ // depth-capped wire (ACP rawOutput) keeps it whole while the
588
+ // canonical status's nested references fall off the end.
589
+ trust: summarizeTrustStatus(trustStatus),
583
590
  ...(receipt.outcome !== undefined && receipt.outcome !== "succeeded"
584
591
  ? { outcome: receipt.outcome, outcomeDetail: receipt.outcomeDetail ?? null }
585
592
  : {}),
@@ -632,15 +639,6 @@ function competeCorrelation(
632
639
  return gateCorrelationOf(subject, decider);
633
640
  }
634
641
 
635
- function reviewerTask(originalTask: string, builderRunId: string, cycle: number): string {
636
- return [
637
- `Review the work of builder run ${builderRunId} (review cycle ${cycle}).`,
638
- "The builder's final answer is provided as input data; verify it against the workspace, do not trust it blindly.",
639
- "Original task the builder was given:",
640
- originalTask,
641
- ].join("\n\n");
642
- }
643
-
644
642
  type ReviewGateSettings = DispatchReviewSettings;
645
643
 
646
644
  const REVIEW_SINGLE_TASK_MESSAGE =
@@ -787,7 +785,7 @@ async function runReviewGated(
787
785
  const reviewerRequest: DispatchRequest = {
788
786
  agentId: gateDeciderAgentId(review.reviewer),
789
787
  executionRole: "reviewer",
790
- task: reviewerTask(base.task, builder.receipt.runId, cycle),
788
+ task: renderDispatchReviewerTask(base.task, builder.receipt.runId, cycle, base.intent),
791
789
  systemPrompt: REVIEWER_GATE_PROMPT,
792
790
  autonomy: "read-only",
793
791
  gate: { role: "reviewer", group, cycle, subjects: [subjectRef(builder.receipt)] },
@@ -1797,10 +1795,19 @@ function competeResult(
1797
1795
  const COUNCIL_BRIEFING_MAX_BYTES = 8 * 1024;
1798
1796
  const COUNCIL_BRIEFING_TRUNCATION = "\n[council peer briefing truncated]";
1799
1797
 
1798
+ /**
1799
+ * The verdict a council answer casts, lower-cased.
1800
+ *
1801
+ * A tally groups by the exact string, so folding case is the difference
1802
+ * between two members who both said yes agreeing and splitting into a
1803
+ * `no_majority` the operator has to read past. Folding happens here, at the one
1804
+ * place a verdict is ever read, so the reported member verdict and the tally
1805
+ * key can never disagree.
1806
+ */
1800
1807
  function councilVerdict(text: string): string | undefined {
1801
1808
  const parsed = parseJsonObjectPayload(text);
1802
1809
  return parsed.ok && typeof parsed.value.verdict === "string" && parsed.value.verdict.trim().length > 0
1803
- ? parsed.value.verdict.trim()
1810
+ ? parsed.value.verdict.trim().toLowerCase()
1804
1811
  : undefined;
1805
1812
  }
1806
1813
 
@@ -1866,11 +1873,32 @@ async function runCouncil(
1866
1873
  }
1867
1874
  const position = (round - 1) * council.members.length + index + 1;
1868
1875
  const pinned = council.resolvedTasks?.find((task) => task.role === "member" && task.position === position);
1876
+ let voteTask = base.task;
1877
+ if (council.synthesis === "vote") {
1878
+ if (pinned !== undefined) voteTask = pinned.task;
1879
+ else if (council.resolvedTasks !== undefined)
1880
+ throw new Error(`dispatch: resolved council plan has no member task at position ${position}`);
1881
+ else voteTask = renderCouncilVoteMemberTask(base.task);
1882
+ }
1869
1883
  const request: DispatchRequest = {
1870
1884
  ...base,
1871
1885
  executionRole: "researcher",
1872
1886
  autonomy: "read-only",
1873
1887
  toolProfile: "council-read-only",
1888
+ // A vote is a majority over the members' verdict fields, so a vote
1889
+ // council asks each member for one and seals the ballot it asked
1890
+ // for. The seated recipe is untouched: the ask is a task suffix and
1891
+ // the postcondition is an override, so the member is still the
1892
+ // agent the operator seated, and any recipe can be voted with.
1893
+ // Admission already composed the suffix into each resolved member
1894
+ // task, so reuse its exact bytes. The fallback supports dispatch
1895
+ // contracts that have no resolved admission artifact.
1896
+ ...(council.synthesis === "vote"
1897
+ ? {
1898
+ task: voteTask,
1899
+ resultContractOverride: { kind: "council-ballot" as const },
1900
+ }
1901
+ : {}),
1874
1902
  target: member.target,
1875
1903
  ...(member.model ? { model: member.model } : {}),
1876
1904
  ...(member.thinking ? { thinkingLevel: member.thinking as NonNullable<DispatchRequest["thinkingLevel"]> } : {}),
@@ -1911,7 +1939,11 @@ async function runCouncil(
1911
1939
  label: run.receipt.council?.label ?? "member",
1912
1940
  runId: run.receipt.runId,
1913
1941
  round: run.receipt.council?.round ?? 1,
1914
- answer: text,
1942
+ // A ballot's prose lives in its `text` field, so the report carries the
1943
+ // member's answer rather than its wire envelope, the same way the judge
1944
+ // line already does. A member answering any other shape has no `text`
1945
+ // key and keeps its whole answer.
1946
+ answer: councilJudgeText(text),
1915
1947
  ...(verdict !== undefined ? { verdict } : {}),
1916
1948
  ...(failed ? { failed: { reason: pipelineFailureReason(run.receipt) } } : {}),
1917
1949
  };
@@ -1967,13 +1999,16 @@ async function runCouncil(
1967
1999
  judgeRunId: judgeRun.receipt.runId,
1968
2000
  };
1969
2001
  }
1970
- if (council.synthesis !== "judge" && prior.size > 0 && deps.dispatch.sealCouncilSynthesis !== undefined) {
2002
+ if (prior.size > 0 && deps.dispatch.sealCouncilSynthesis !== undefined) {
1971
2003
  const finalRuns = [...prior.values()];
1972
2004
  const template = finalRuns[0];
1973
2005
  if (template === undefined) throw new Error("council synthesis has no final member receipt");
1974
2006
  // The sealed text is the whole council-report, not the synthesis alone:
1975
2007
  // /share <synthesis runId> reads this receipt to bring every final
1976
2008
  // member's labelled answer and the synthesis line into the main context.
2009
+ // A judge council seals it on the same terms: the judge run's own
2010
+ // receipt holds only its {"verdict","text"} payload, which carries no
2011
+ // member answers and no roster labels for the main agent to act on.
1977
2012
  const text = JSON.stringify({ members, synthesis } satisfies CouncilReport);
1978
2013
  const receipt = await deps.dispatch.sealCouncilSynthesis({
1979
2014
  group,
@@ -17,6 +17,7 @@ import {
17
17
  type RunReceipt,
18
18
  type RunReceiptVerification,
19
19
  } from "../domains/dispatch/types.js";
20
+ import { summarizeTrustStatus } from "../domains/evidence/trust-projection.js";
20
21
  import {
21
22
  adaptRunReceiptTrustStatus,
22
23
  type CanonicalTrustStatus,
@@ -389,6 +390,7 @@ function runReceipt(deps: MonitorToolDeps, runId: string): ToolResult {
389
390
  receiptPath: run.receiptPath,
390
391
  receiptIntegrity,
391
392
  trustStatus,
393
+ trust: summarizeTrustStatus(trustStatus),
392
394
  ...(receipt !== null && receiptIntegrity.ok
393
395
  ? {
394
396
  evidenceVerification: receipt.verification,
@@ -455,6 +457,17 @@ function durableRunEvidence(run: RunEnvelope | null): DurableRunEvidence {
455
457
  const inspection = inspectRunReceiptTrustStatus(receipt, run);
456
458
  const integrity = inspection.integrity;
457
459
  if (!integrity.ok) {
460
+ // A retired seal is set aside unread, as a missing receipt is. It is
461
+ // not a failed one, so it never reads as tampering here either.
462
+ if (integrity.retired !== undefined) {
463
+ return {
464
+ ...unavailableRunEvidence(
465
+ integrity.reason,
466
+ `${integrity.reason}; worker text is unavailable and validation is unknown.`,
467
+ ),
468
+ trustStatus: inspection.status,
469
+ };
470
+ }
458
471
  return {
459
472
  ...unavailableRunEvidence(
460
473
  integrity.reason,
@@ -7,6 +7,7 @@ import {
7
7
  } from "../domains/dispatch/budget-envelope.js";
8
8
  import type { ReceiptIntegrityResult } from "../domains/dispatch/receipt-integrity.js";
9
9
  import type { RunReceipt, RunReceiptVerification } from "../domains/dispatch/types.js";
10
+ import { formatTrustAxes, formatTrustSummary } from "../domains/evidence/trust-projection.js";
10
11
  import { adaptRunReceiptTrustStatus, type CanonicalTrustStatus } from "../domains/evidence/trust-status.js";
11
12
  import { receiptResponseModelIdObservationLabel } from "./dispatch-event-text.js";
12
13
 
@@ -128,9 +129,9 @@ export function receiptEvidenceLabels(
128
129
  integrity: ReceiptIntegrityResult,
129
130
  ): string[] {
130
131
  const status = adaptRunReceiptTrustStatus({ ...receipt, verification: verification }, { integrity });
131
- const canonical = canonicalTrustLabel(status);
132
+ const canonical = canonicalTrustLabels(status);
132
133
  if (!integrity.ok) {
133
- return [canonical, `receipt_integrity=FAILED reason=${JSON.stringify(integrity.reason)}`];
134
+ return [...canonical, `receipt_integrity=FAILED reason=${JSON.stringify(integrity.reason)}`];
134
135
  }
135
136
  const briefing =
136
137
  receipt.briefing === undefined
@@ -154,7 +155,7 @@ export function receiptEvidenceLabels(
154
155
  `budget_reason=${JSON.stringify(formatBudgetReasons(receipt.budget))}`,
155
156
  ];
156
157
  return [
157
- canonical,
158
+ ...canonical,
158
159
  `receipt_integrity=verified/v${receipt.integrity.version}/${receipt.integrity.algorithm}`,
159
160
  `evidence_verification=${verification.state}/${verification.basis}`,
160
161
  `host_verification=${receipt.hostVerification?.status ?? "not_requested"}`,
@@ -167,16 +168,13 @@ export function receiptEvidenceLabels(
167
168
  ];
168
169
  }
169
170
 
170
- function canonicalTrustLabel(status: CanonicalTrustStatus): string {
171
- return [
172
- `trust_status=v${status.version}`,
173
- `artifactIntegrity:${status.artifactIntegrity.state}`,
174
- `validationGrounding:${status.validationGrounding.state}`,
175
- `independentReview:${status.independentReview.state}`,
176
- `contextProvenance:${status.contextProvenance.state}`,
177
- `autonomyEnforcement:${status.autonomyEnforcement.state}`,
178
- `completionEvidence:${status.completionEvidence.state}`,
179
- ].join(" ");
171
+ /**
172
+ * The compact projection first, then the canonical axis line, both from the
173
+ * shared projection so the dispatch and monitor text can never spell a state
174
+ * differently from `evidence inspect` or the board.
175
+ */
176
+ function canonicalTrustLabels(status: CanonicalTrustStatus): string[] {
177
+ return [`trust=${JSON.stringify(formatTrustSummary(status))}`, formatTrustAxes(status)];
180
178
  }
181
179
 
182
180
  /**
@@ -192,6 +190,14 @@ export function workerTextLabel(status: CanonicalTrustStatus): string {
192
190
  return "reconnaissance output (advisory leads, not validation evidence):";
193
191
  case "unknown":
194
192
  return "worker claims (validation not observable at this layer):";
193
+ // The three remaining states were one label. The evidence bundle tells
194
+ // a failed check, an inferred claim, and no validation at all apart, so
195
+ // the terminal must too or it hands the operator a coarser verdict than
196
+ // the report for the same run.
197
+ case "failed":
198
+ return "worker claims (validation failed; a check ran and did not pass):";
199
+ case "ungrounded":
200
+ return "worker claims (inferred; validation claimed, none observed):";
195
201
  default:
196
202
  return "worker claims (unverified prose):";
197
203
  }
@@ -162,7 +162,8 @@ interface WorkerSpecFields {
162
162
  */
163
163
  autonomy?: AutonomyLevel;
164
164
  /**
165
- * Absolute directories write-class tool calls are confined to for this run.
165
+ * Absolute path boundaries write-class tool calls are confined to for this run.
166
+ * Exact files omit a trailing slash and subtrees retain one.
166
167
  * Enforced at the shared worker safety seam so a write/edit target outside
167
168
  * every root is a final block. Only set on runtimes that mediate per-tool
168
169
  * calls (native, claude-sdk); dispatch refuses it on subprocess runtimes.