@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
@@ -29,8 +29,8 @@ import { extractRunProvenance, provenanceTranscriptLines } from "./provenance.js
29
29
  import { createRedactionTally, redactSecretsDeep, redactSecretsText } from "./redact.js";
30
30
  import { buildEvidenceTrustStatusFile } from "./run-trust.js";
31
31
  import { EVIDENCE_FILES, evidenceDirectory, findingsFile } from "./store.js";
32
- import type { TrustArtifactReference } from "./trust-status.js";
33
- import { inspectRunReceiptTrustStatus } from "./trust-status.js";
32
+ import type { CanonicalTrustStatus, TrustArtifactReference } from "./trust-status.js";
33
+ import { inspectRunReceiptTrustStatus, retiredIntegrityVersionOf } from "./trust-status.js";
34
34
  import {
35
35
  EVIDENCE_VERSION,
36
36
  type EvidenceAuditLinkedRow,
@@ -45,6 +45,7 @@ import {
45
45
  type EvidenceReceiptFile,
46
46
  type EvidenceRunLink,
47
47
  type EvidenceRunSource,
48
+ type EvidenceSeverity,
48
49
  type EvidenceTag,
49
50
  type EvidenceToolEvent,
50
51
  type EvidenceTrustStatusFile,
@@ -195,7 +196,10 @@ export async function buildEvidence(options: BuildEvidenceOptions): Promise<Evid
195
196
  redactedToolEvents,
196
197
  protectedArtifacts,
197
198
  );
198
- const transcript = redactSecretsText(renderTranscript(overview, redactedRunSources, sessionLinks), tally);
199
+ const transcript = redactSecretsText(
200
+ renderTranscript(overview, redactedRunSources, sessionLinks, trustStatusRaw),
201
+ tally,
202
+ );
199
203
  const finalOverview: EvidenceOverview = { ...overview, redactionCount: tally.count };
200
204
  await writeEvidenceFiles(
201
205
  directory,
@@ -285,8 +289,14 @@ function buildFindings(
285
289
  const status = trustByRun.get(source.envelope.id);
286
290
  if (status === undefined) throw new Error(`canonical trust status missing for run ${source.envelope.id}`);
287
291
  if (source.receiptError !== null) {
288
- const tag = source.receiptIntegrityFailed ? "receipt-integrity" : "unknown";
289
- findings.push(finding(findings.length, "warn", tag, source.envelope.id, source.receiptError));
292
+ // The canonical axis, not the raw reason string, says whether the seal
293
+ // was retired: `receipt-retired` is the expected state of every run
294
+ // that predates an integrity bump and is an info row, while
295
+ // `receipt-integrity` stays the warning for a seal that was checked
296
+ // and rejected.
297
+ const retired = retiredIntegrityVersionOf(status.artifactIntegrity) !== null;
298
+ const tag = retired ? "receipt-retired" : source.receiptIntegrityFailed ? "receipt-integrity" : "unknown";
299
+ findings.push(finding(findings.length, retired ? "info" : "warn", tag, source.envelope.id, source.receiptError));
290
300
  }
291
301
  if (
292
302
  isSuccessfulRun(source) &&
@@ -359,6 +369,13 @@ function buildFindings(
359
369
  ),
360
370
  );
361
371
  }
372
+ // The remaining axes were never read here, so a run could finish with
373
+ // no independent review, a contradictory context record, or a mutation
374
+ // nobody validated, and findings.md said nothing. Each finding is
375
+ // selected from the canonical state the way the validation and
376
+ // autonomy findings above are, with the detailed record left in
377
+ // trust-status.json.
378
+ findings.push(...axisFindings(findings.length, source, status));
362
379
  if (source.envelope.status === "stale" || source.envelope.status === "dead") {
363
380
  findings.push(
364
381
  finding(findings.length, "warn", "timeout", source.envelope.id, `run status ${source.envelope.status}`),
@@ -601,7 +618,7 @@ async function writeEvidenceFiles(
601
618
  await writeJson(join(directory, "overview.json"), overview);
602
619
  await writeFile(
603
620
  join(directory, "transcript.md"),
604
- transcript ?? renderTranscript(overview, runSources, sessionLinks),
621
+ transcript ?? renderTranscript(overview, runSources, sessionLinks, trustStatus),
605
622
  "utf8",
606
623
  );
607
624
  await writeJsonl(join(directory, "trace.raw.jsonl"), rawTraceRows(runSources));
@@ -636,9 +653,11 @@ function cleanedTraceRows(
636
653
  const rows: EvidenceCleanTraceRow[] = [];
637
654
  for (const source of runSources) {
638
655
  const envelope = source.envelope;
639
- // Clean trace rows project only provenance carried by the sealed receipt.
656
+ // Clean trace rows project only provenance carried by an authenticated
657
+ // receipt: a rejected or retired seal contributes none of its fields.
640
658
  // Runs without receipt provenance keep the standard row shape.
641
- const provenance = source.receipt === null ? {} : extractRunProvenance(source.receipt);
659
+ const receipt = authenticatedReceipt(source);
660
+ const provenance = receipt === null ? {} : extractRunProvenance(receipt);
642
661
  rows.push({
643
662
  kind: "run",
644
663
  runId: envelope.id,
@@ -1258,7 +1277,9 @@ function renderTranscript(
1258
1277
  overview: EvidenceOverview,
1259
1278
  runSources: ReadonlyArray<EvidenceRunSource>,
1260
1279
  sessionLinks: SessionLinkResult,
1280
+ trustStatus: EvidenceTrustStatusFile,
1261
1281
  ): string {
1282
+ const trustByRun = new Map(trustStatus.runs.map((entry) => [entry.runId, entry.status]));
1262
1283
  const lines = [
1263
1284
  `# Evidence ${overview.evidenceId}`,
1264
1285
  "",
@@ -1274,10 +1295,11 @@ function renderTranscript(
1274
1295
  `- ${envelope.id} status=${envelope.status} exit=${exitCode ?? "?"} agent=${envelope.agentId} target=${envelope.targetId}`,
1275
1296
  );
1276
1297
  lines.push(` task: ${truncateText(envelope.task, MAX_TASK_CHARS)}`);
1277
- // Run section rendering reads provenance from the sealed receipt and adds
1278
- // sentences only for fields that are present.
1298
+ // Run section rendering adds a sentence per provenance field the
1299
+ // canonical projection admits; a rejected or retired seal adds none.
1279
1300
  if (source.receipt !== null) {
1280
- for (const line of provenanceTranscriptLines(extractRunProvenance(source.receipt))) {
1301
+ const status = trustByRun.get(envelope.id);
1302
+ for (const line of provenanceTranscriptLines(extractRunProvenance(source.receipt), status)) {
1281
1303
  lines.push(` ${line}`);
1282
1304
  }
1283
1305
  }
@@ -1438,6 +1460,39 @@ function renderSessionTranscriptEntry(linked: LinkedSessionEntry): string[] {
1438
1460
  return [`${prefix} ${String(_exhaustive)}`];
1439
1461
  }
1440
1462
 
1463
+ /** Independent review, context provenance, and completion evidence, read off the canonical axes. */
1464
+ function axisFindings(offset: number, source: EvidenceRunSource, status: CanonicalTrustStatus): EvidenceFinding[] {
1465
+ const out: EvidenceFinding[] = [];
1466
+ const runId = source.envelope.id;
1467
+ const next = (severity: EvidenceSeverity, tag: EvidenceTag, message: string): void => {
1468
+ out.push(finding(offset + out.length, severity, tag, runId, message));
1469
+ };
1470
+ const review = status.independentReview.state;
1471
+ if (review === "failed") {
1472
+ next("warn", "independent-review", "independent review failed for this run");
1473
+ } else if (review === "not_independent") {
1474
+ next("warn", "independent-review", "review was not independent of the run it judged");
1475
+ } else if (review === "inconclusive") {
1476
+ next("info", "independent-review", "independent review was inconclusive");
1477
+ } else if (isSuccessfulRun(source) && (review === "absent" || review === "unknown")) {
1478
+ next("info", "independent-review", "run was not independently reviewed; its result rests on its own receipt");
1479
+ }
1480
+ if (status.contextProvenance.state === "invalid") {
1481
+ next("warn", "context-provenance", "context provenance record is contradictory; see trust-status.json");
1482
+ }
1483
+ const completion = status.completionEvidence.state;
1484
+ if (completion === "incomplete") {
1485
+ next(
1486
+ "warn",
1487
+ "completion-evidence",
1488
+ "run mutated the workspace and finished without validation evidence at the completion boundary",
1489
+ );
1490
+ } else if (completion === "limited") {
1491
+ next("info", "completion-evidence", "run finished with an explicit limitation instead of validation evidence");
1492
+ }
1493
+ return out;
1494
+ }
1495
+
1441
1496
  function renderFindings(findings: ReadonlyArray<EvidenceFinding>): string {
1442
1497
  if (findings.length === 0) return "# Findings\n\nNo findings.\n";
1443
1498
  const lines = ["# Findings", ""];
@@ -1507,6 +1562,9 @@ async function readReceipt(
1507
1562
  }
1508
1563
  const integrity = inspectRunReceiptTrustStatus(receipt, envelope).integrity;
1509
1564
  if (!integrity.ok) {
1565
+ // A retired seal is set aside unread, the way a missing receipt is; it
1566
+ // is not a failed one, and its reason already names both versions.
1567
+ if (integrity.retired !== undefined) return { receipt, error: integrity.reason, integrityFailed: false };
1510
1568
  return { receipt, error: `receipt integrity: ${integrity.reason}`, integrityFailed: true };
1511
1569
  }
1512
1570
  return { receipt, error: null, integrityFailed: false };
@@ -5,6 +5,7 @@ export { buildEvalEvidence, evalEvidenceId } from "./eval.js";
5
5
  export { FINISH_CONTRACT_EVIDENCE_TAGS, finishContractEvidenceTags } from "./finish-contract-map.js";
6
6
  export type { RunEscalationCounts, RunProvenanceView } from "./provenance.js";
7
7
  export {
8
+ admitRunProvenance,
8
9
  extractRunProvenance,
9
10
  hasRunProvenance,
10
11
  PERSONA_HASH_PREFIX_CHARS,
@@ -22,6 +23,20 @@ export {
22
23
  loadEvidenceRunProvenance,
23
24
  loadEvidenceTrustStatus,
24
25
  } from "./store.js";
26
+ export type { TrustSummaryProjection, TrustVerdict } from "./trust-projection.js";
27
+ export {
28
+ formatTrustAxes,
29
+ formatTrustSummary,
30
+ formatTrustSummaryLine,
31
+ summarizeTrustStatus,
32
+ TRUST_STATE_WORDS,
33
+ TRUST_SUMMARY_MAX_REFS,
34
+ TRUST_SUMMARY_VERSION,
35
+ TRUST_VERDICTS,
36
+ trustStateWord,
37
+ trustSummaryReferences,
38
+ trustVerdict,
39
+ } from "./trust-projection.js";
25
40
  export type {
26
41
  AbsentTrustStatus,
27
42
  AdaptFinishContractTrustOptions,
@@ -35,6 +50,8 @@ export type {
35
50
  GroundedEvidenceValidationInput,
36
51
  IndependentReviewStatus,
37
52
  PersistedRunReceiptTrustFacts,
53
+ ReceiptIntegrityOutcome,
54
+ RetiredReceiptIntegrity,
38
55
  RunReceiptTrustInspection,
39
56
  TrustAbsenceReason,
40
57
  TrustArtifactKind,
@@ -63,12 +80,16 @@ export {
63
80
  inspectRunReceiptTrustStatus,
64
81
  normalizeTrustStatus,
65
82
  projectTrustStatus,
83
+ retiredIntegrityVersionOf,
84
+ retiredReceiptIntegrity,
85
+ retiredReceiptIntegrityReason,
66
86
  TRUST_STATUS_AXES,
67
87
  TRUST_STATUS_MAX_ARTIFACT_REFERENCES,
68
88
  TRUST_STATUS_MAX_IDENTIFIER_LENGTH,
69
89
  TRUST_STATUS_STATES,
70
90
  TRUST_STATUS_VERSION,
71
91
  validateTrustStatus,
92
+ verifyReceiptIntegrityOutcome,
72
93
  } from "./trust-status.js";
73
94
  export type {
74
95
  EvidenceAuditLinkedRow,
@@ -4,6 +4,7 @@ import type {
4
4
  RunReceipt,
5
5
  RunReceiptAutonomyEnforcement,
6
6
  } from "../dispatch/types.js";
7
+ import type { CanonicalTrustStatus } from "./trust-status.js";
7
8
 
8
9
  /**
9
10
  * Worker permission-escalation counters projected from sealed receipt
@@ -50,6 +51,33 @@ export function extractRunProvenance(receipt: ProvenanceReceipt): RunProvenanceV
50
51
  return view;
51
52
  }
52
53
 
54
+ /**
55
+ * The slice of a provenance view the canonical projection admits. The
56
+ * projection is the only thing that decides whether an axis is reported, so
57
+ * the autonomy detail (`autonomy=`, `mode=`, `dangerousBypass=`) is kept only
58
+ * when the projection reports the autonomy axis in a recorded state, and the
59
+ * non-axis provenance (pipeline, persona override, escalations) only when the
60
+ * seal that carries it verified. With no projection at hand no axis detail is
61
+ * admitted at all, whatever the receipt says; the non-axis provenance passes
62
+ * through for a caller that prints it beside its own integrity banner.
63
+ */
64
+ export function admitRunProvenance(view: RunProvenanceView, status?: CanonicalTrustStatus): RunProvenanceView {
65
+ const admitted: RunProvenanceView = {};
66
+ if (status === undefined || status.artifactIntegrity.state === "verified") {
67
+ if (view.pipeline !== undefined) admitted.pipeline = view.pipeline;
68
+ if (view.personaOverride !== undefined) admitted.personaOverride = view.personaOverride;
69
+ if (view.escalation !== undefined) admitted.escalation = view.escalation;
70
+ }
71
+ const autonomy = status?.autonomyEnforcement.state;
72
+ if (
73
+ view.autonomyEnforcement !== undefined &&
74
+ (autonomy === "enforced" || autonomy === "approximated" || autonomy === "bypassed")
75
+ ) {
76
+ admitted.autonomyEnforcement = view.autonomyEnforcement;
77
+ }
78
+ return admitted;
79
+ }
80
+
53
81
  /** True when at least one provenance field set is present. */
54
82
  export function hasRunProvenance(view: RunProvenanceView): boolean {
55
83
  return (
@@ -144,10 +172,15 @@ function formatPersonaHashPrefix(promptHash: string): string {
144
172
  }
145
173
 
146
174
  /**
147
- * Human transcript sentences for each present provenance field set.
148
- * An empty view adds no lines to the transcript run section.
175
+ * Human transcript sentences for each admitted provenance field set, gated
176
+ * through {@link admitRunProvenance}. The autonomy line carries only the
177
+ * detail the canonical projection does not: the policy name, the external
178
+ * mode, and the bypass flag. The axis itself (mediated, approximated,
179
+ * bypassed) is printed by the trust summary and nowhere else, so one
180
+ * autonomy fact never appears in two vocabularies on one screen.
149
181
  */
150
- export function provenanceTranscriptLines(view: RunProvenanceView): string[] {
182
+ export function provenanceTranscriptLines(source: RunProvenanceView, status?: CanonicalTrustStatus): string[] {
183
+ const view = admitRunProvenance(source, status);
151
184
  const lines: string[] = [];
152
185
  if (view.pipeline !== undefined) {
153
186
  const { fromRunId, position, inputBytes, inputTruncated } = view.pipeline;
@@ -163,20 +196,22 @@ export function provenanceTranscriptLines(view: RunProvenanceView): string[] {
163
196
  lines.push(`escalations: ${requested} requested, ${approved} approved, ${denied} denied, ${timedOut} timed out`);
164
197
  }
165
198
  if (view.autonomyEnforcement !== undefined) {
166
- const { grade, autonomy, externalMode, dangerousBypass } = view.autonomyEnforcement;
199
+ const { autonomy, externalMode, dangerousBypass } = view.autonomyEnforcement;
167
200
  const mode = externalMode !== undefined ? ` mode=${externalMode}` : "";
168
201
  const bypass = dangerousBypass === true ? " dangerousBypass=true" : "";
169
- lines.push(`autonomy enforcement: ${grade} autonomy=${autonomy}${mode}${bypass}`);
202
+ lines.push(`autonomy: ${autonomy}${mode}${bypass}`);
170
203
  }
171
204
  return lines;
172
205
  }
173
206
 
174
207
  /**
175
- * Compact ` key=value` suffix for the dispatch tool's per-run and CLI lines.
176
- * The leading space lets callers append it directly. An empty provenance view
177
- * returns an empty string.
208
+ * Compact ` key=value` suffix for the dispatch tool's per-run and CLI lines,
209
+ * gated through {@link admitRunProvenance} on the same terms as the
210
+ * transcript lines. The leading space lets callers append it directly. An
211
+ * empty admitted view returns an empty string.
178
212
  */
179
- export function provenanceCompactSuffix(view: RunProvenanceView): string {
213
+ export function provenanceCompactSuffix(source: RunProvenanceView, status?: CanonicalTrustStatus): string {
214
+ const view = admitRunProvenance(source, status);
180
215
  const parts: string[] = [];
181
216
  if (view.pipeline !== undefined) {
182
217
  const { fromRunId, position, inputBytes, inputTruncated } = view.pipeline;
@@ -191,10 +226,10 @@ export function provenanceCompactSuffix(view: RunProvenanceView): string {
191
226
  parts.push(`escalations=${requested}req/${approved}appr/${denied}deny/${timedOut}timeout`);
192
227
  }
193
228
  if (view.autonomyEnforcement !== undefined) {
194
- const { grade, autonomy, externalMode, dangerousBypass } = view.autonomyEnforcement;
229
+ const { autonomy, externalMode, dangerousBypass } = view.autonomyEnforcement;
195
230
  const mode = externalMode !== undefined ? `/${externalMode}` : "";
196
231
  const bypass = dangerousBypass === true ? "/bypass" : "";
197
- parts.push(`enforcement=${grade}:${autonomy}${mode}${bypass}`);
232
+ parts.push(`autonomy=${autonomy}${mode}${bypass}`);
198
233
  }
199
234
  return parts.length === 0 ? "" : ` ${parts.join(" ")}`;
200
235
  }
@@ -0,0 +1,274 @@
1
+ import { RUN_RECEIPT_INTEGRITY_VERSION } from "../dispatch/receipt-integrity.js";
2
+ import {
3
+ type CanonicalTrustStatus,
4
+ retiredIntegrityVersionOf,
5
+ TRUST_STATUS_AXES,
6
+ type TRUST_STATUS_STATES,
7
+ type TrustArtifactReference,
8
+ type TrustStatusAxis,
9
+ } from "./trust-status.js";
10
+
11
+ /**
12
+ * The one projection of the canonical trust status every operator surface
13
+ * renders. The six-axis model stays the source of truth and is never
14
+ * collapsed into a score here; this module only fixes the words each state is
15
+ * called and the order the axes are read in, so the dispatch line, the
16
+ * monitor block, `evidence inspect`, `findings.md`, the Alt+W board, the
17
+ * receipt view, the eval bridge, and the ACP wire cannot each spell the same
18
+ * fact differently.
19
+ *
20
+ * Two shapes leave this module. `formatTrustSummary` is the compact human
21
+ * line: it answers who claims the result, what was observed, what was
22
+ * independently checked, and what is still unknown, without receipt
23
+ * internals. `summarizeTrustStatus` is the bounded, versioned machine record
24
+ * behind that line, carrying the axis states and typed references back to
25
+ * the artifacts the detailed model cites.
26
+ */
27
+
28
+ export const TRUST_SUMMARY_VERSION = 1 as const;
29
+
30
+ /** Reference cap for the machine projection; the canonical model keeps up to 16 per axis. */
31
+ export const TRUST_SUMMARY_MAX_REFS = 8;
32
+
33
+ /**
34
+ * How much the run's result can be leaned on, read off the axes in a fixed
35
+ * order. It is a presentation tier for styling and sorting, never a score:
36
+ * `reviewed` is the only tier that may be styled as independently verified.
37
+ */
38
+ export type TrustVerdict = "reviewed" | "grounded" | "unverified" | "compromised" | "unknown";
39
+
40
+ export const TRUST_VERDICTS: ReadonlyArray<TrustVerdict> = [
41
+ "reviewed",
42
+ "grounded",
43
+ "unverified",
44
+ "compromised",
45
+ "unknown",
46
+ ];
47
+
48
+ /** Bounded, versioned machine projection with references to the detailed artifacts. */
49
+ export interface TrustSummaryProjection {
50
+ version: typeof TRUST_SUMMARY_VERSION;
51
+ verdict: TrustVerdict;
52
+ /** The compact human line, byte-identical to what the text surfaces print. */
53
+ text: string;
54
+ /** Every axis state, in canonical vocabulary, for machine consumers. */
55
+ axes: Record<TrustStatusAxis, string>;
56
+ /** Who asserts the validation fact: `<authority kind>:<id>`, or `worker` when only the run's own prose exists. */
57
+ claimant: string;
58
+ /** Axes that answer nothing, so a consumer knows what remains unknown. */
59
+ unknown: TrustStatusAxis[];
60
+ /** `<artifact kind>:<id>` pointers to the detailed records, sorted, unique, capped. */
61
+ refs: string[];
62
+ }
63
+
64
+ type AxisStates = { [Axis in TrustStatusAxis]: (typeof TRUST_STATUS_STATES)[Axis][number] };
65
+
66
+ /**
67
+ * The standardized word for every state. A word is what an operator reads;
68
+ * the state id is what a machine reads. `mediated` names the `enforced`
69
+ * autonomy state because that is the receipt grade and the documented
70
+ * meaning: Clio's own safety gate mediated the run. `inferred` names an
71
+ * ungrounded validation claim: the worker said it validated, nothing was
72
+ * observed to have run.
73
+ */
74
+ export const TRUST_STATE_WORDS: { [Axis in TrustStatusAxis]: Record<AxisStates[Axis], string> } = {
75
+ artifactIntegrity: {
76
+ verified: "sealed",
77
+ failed: "seal broken",
78
+ absent: "no receipt",
79
+ unknown: "seal unchecked",
80
+ not_applicable: "seal not applicable",
81
+ },
82
+ validationGrounding: {
83
+ validated: "grounded",
84
+ failed: "validation failed",
85
+ ungrounded: "inferred: validation claimed, none observed",
86
+ absent: "no validation observed",
87
+ unknown: "validation unknown",
88
+ not_applicable: "validation not applicable",
89
+ },
90
+ independentReview: {
91
+ passed: "independently reviewed: pass",
92
+ failed: "independently reviewed: fail",
93
+ inconclusive: "independent review inconclusive",
94
+ not_independent: "review not independent",
95
+ absent: "not independently reviewed",
96
+ unknown: "independent review unknown",
97
+ not_applicable: "independent review not applicable",
98
+ },
99
+ contextProvenance: {
100
+ recorded: "context recorded",
101
+ invalid: "context record invalid",
102
+ absent: "context not recorded",
103
+ unknown: "context unknown",
104
+ not_applicable: "context not applicable",
105
+ },
106
+ autonomyEnforcement: {
107
+ enforced: "mediated",
108
+ approximated: "approximated",
109
+ bypassed: "bypassed",
110
+ absent: "autonomy not recorded",
111
+ unknown: "autonomy unknown",
112
+ not_applicable: "autonomy not applicable",
113
+ },
114
+ completionEvidence: {
115
+ evidenced: "completion evidenced",
116
+ incomplete: "completion unevidenced",
117
+ limited: "completion limited",
118
+ absent: "completion not recorded",
119
+ unknown: "completion unknown",
120
+ not_applicable: "completion not applicable",
121
+ },
122
+ };
123
+
124
+ /** The word for one axis state; unknown input never throws, it reads as unknown. */
125
+ export function trustStateWord<Axis extends TrustStatusAxis>(axis: Axis, state: string): string {
126
+ const words = TRUST_STATE_WORDS[axis] as Record<string, string>;
127
+ return words[state] ?? words.unknown ?? "unknown";
128
+ }
129
+
130
+ function authorityOf(status: CanonicalTrustStatus, axis: TrustStatusAxis): string | null {
131
+ const entry = status[axis];
132
+ return entry.state === "absent" ? null : `${entry.authority.kind}:${entry.authority.id}`;
133
+ }
134
+
135
+ /**
136
+ * A seal this build does not verify because its version is retired names
137
+ * that version and the one in force, so an intact receipt from the previous
138
+ * release never reads as "seal broken" or as merely unchecked. The state
139
+ * behind the clause is `unknown`, which is what it is: nothing was checked.
140
+ */
141
+ function integrityClause(status: CanonicalTrustStatus): string {
142
+ const retired = retiredIntegrityVersionOf(status.artifactIntegrity);
143
+ if (retired !== null) return `seal v${retired} retired (this build verifies v${RUN_RECEIPT_INTEGRITY_VERSION})`;
144
+ return trustStateWord("artifactIntegrity", status.artifactIntegrity.state);
145
+ }
146
+
147
+ /**
148
+ * The validation clause names its claimant, because "grounded" alone hides
149
+ * the difference between a host-run check and a self-reported one.
150
+ */
151
+ function validationClause(status: CanonicalTrustStatus): string {
152
+ const entry = status.validationGrounding;
153
+ const word = trustStateWord("validationGrounding", entry.state);
154
+ if (entry.state === "absent") return word;
155
+ if (entry.state === "validated" || entry.state === "failed") return `${word} by ${entry.authority.id}`;
156
+ // A named external system that could not observe the run is worth naming;
157
+ // the historical-format placeholder is not an authority anyone can ask.
158
+ if (entry.state === "unknown" && entry.authority.kind !== "unknown") return `${word} (${entry.authority.id})`;
159
+ return word;
160
+ }
161
+
162
+ /** External runtimes name themselves on the autonomy clause so approximation is never anonymous. */
163
+ function autonomyClause(status: CanonicalTrustStatus): string {
164
+ const entry = status.autonomyEnforcement;
165
+ const word = trustStateWord("autonomyEnforcement", entry.state);
166
+ if (entry.state !== "approximated" && entry.state !== "bypassed") return word;
167
+ return `${word} (${entry.authority.id})`;
168
+ }
169
+
170
+ /**
171
+ * The compact human body. Clause order is fixed: integrity, validation with
172
+ * its claimant, independent review, autonomy, context, completion. Every
173
+ * surface prints this body verbatim, so two surfaces can only disagree by
174
+ * reading different canonical input.
175
+ */
176
+ export function formatTrustSummary(status: CanonicalTrustStatus): string {
177
+ return [
178
+ integrityClause(status),
179
+ validationClause(status),
180
+ trustStateWord("independentReview", status.independentReview.state),
181
+ autonomyClause(status),
182
+ trustStateWord("contextProvenance", status.contextProvenance.state),
183
+ trustStateWord("completionEvidence", status.completionEvidence.state),
184
+ ].join("; ");
185
+ }
186
+
187
+ /** The body under its versioned label, for surfaces that print one line per run. */
188
+ export function formatTrustSummaryLine(status: CanonicalTrustStatus): string {
189
+ return `trust v${TRUST_SUMMARY_VERSION}: ${formatTrustSummary(status)}`;
190
+ }
191
+
192
+ /**
193
+ * The drill-down token line: every axis in canonical state ids. This is the
194
+ * one machine-readable text form; `evidence inspect` and the dispatch and
195
+ * monitor labels all print it from here.
196
+ */
197
+ export function formatTrustAxes(status: CanonicalTrustStatus): string {
198
+ return [`trust_status=v${status.version}`, ...TRUST_STATUS_AXES.map((axis) => `${axis}:${status[axis].state}`)].join(
199
+ " ",
200
+ );
201
+ }
202
+
203
+ function isUnanswered(status: CanonicalTrustStatus, axis: TrustStatusAxis): boolean {
204
+ const state = status[axis].state;
205
+ return state === "absent" || state === "unknown";
206
+ }
207
+
208
+ /**
209
+ * Read the tier off the axes in priority order. A broken seal, a bypassed
210
+ * gate, a failed or inferred validation, a failed or correlated review, or a
211
+ * contradictory context record compromises the result whatever else holds.
212
+ * An unchecked or missing seal leaves it unknown. Only an authenticated
213
+ * independent pass is `reviewed`; observed validation without one is
214
+ * `grounded`; a sealed receipt with nothing observed is `unverified`.
215
+ */
216
+ export function trustVerdict(status: CanonicalTrustStatus): TrustVerdict {
217
+ const integrity = status.artifactIntegrity.state;
218
+ const validation = status.validationGrounding.state;
219
+ const review = status.independentReview.state;
220
+ const autonomy = status.autonomyEnforcement.state;
221
+ if (
222
+ integrity === "failed" ||
223
+ autonomy === "bypassed" ||
224
+ validation === "failed" ||
225
+ validation === "ungrounded" ||
226
+ review === "failed" ||
227
+ review === "not_independent" ||
228
+ status.contextProvenance.state === "invalid"
229
+ ) {
230
+ return "compromised";
231
+ }
232
+ if (integrity !== "verified") return "unknown";
233
+ if (review === "passed") return "reviewed";
234
+ if (validation === "validated") return "grounded";
235
+ return "unverified";
236
+ }
237
+
238
+ function claimantOf(status: CanonicalTrustStatus): string {
239
+ const state = status.validationGrounding.state;
240
+ if (state === "absent" || state === "ungrounded") return "worker";
241
+ return authorityOf(status, "validationGrounding") ?? "worker";
242
+ }
243
+
244
+ function referenceKey(reference: TrustArtifactReference): string {
245
+ return `${reference.kind}:${reference.id}`;
246
+ }
247
+
248
+ /** Every artifact the axes cite, as bounded pointers a consumer can resolve. */
249
+ export function trustSummaryReferences(status: CanonicalTrustStatus): string[] {
250
+ const keys = new Set<string>();
251
+ for (const axis of TRUST_STATUS_AXES) {
252
+ const entry = status[axis];
253
+ if (entry.state === "absent") continue;
254
+ for (const reference of entry.artifacts) keys.add(referenceKey(reference));
255
+ }
256
+ return [...keys].sort().slice(0, TRUST_SUMMARY_MAX_REFS);
257
+ }
258
+
259
+ /** The bounded machine projection. Flat by design so a depth-capped wire keeps it whole. */
260
+ export function summarizeTrustStatus(status: CanonicalTrustStatus): TrustSummaryProjection {
261
+ const axes = Object.fromEntries(TRUST_STATUS_AXES.map((axis) => [axis, status[axis].state])) as Record<
262
+ TrustStatusAxis,
263
+ string
264
+ >;
265
+ return {
266
+ version: TRUST_SUMMARY_VERSION,
267
+ verdict: trustVerdict(status),
268
+ text: formatTrustSummary(status),
269
+ axes,
270
+ claimant: claimantOf(status),
271
+ unknown: TRUST_STATUS_AXES.filter((axis) => isUnanswered(status, axis)),
272
+ refs: trustSummaryReferences(status),
273
+ };
274
+ }