@iowarp/clio-coder 0.3.2 → 0.3.4

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 (259) hide show
  1. package/CHANGELOG.md +269 -458
  2. package/CONTRIBUTING.md +1 -1
  3. package/README.md +3 -3
  4. package/dist/{acp-BIYHVZIM.js → acp-S5R4RR5B.js} +7 -6
  5. package/dist/{agents-YT6SSRIT.js → agents-P6DMMVZY.js} +24 -21
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-5TWEIYDN.js → auth-2XCZLPKS.js} +12 -8
  8. package/dist/{chunk-GGXXDWE4.js → chunk-22NAGB7X.js} +2 -2
  9. package/dist/{chunk-WMSVI4G2.js → chunk-2LZI5CAG.js} +133 -13
  10. package/dist/{chunk-OAO4GE4M.js → chunk-2TZWSW76.js} +2 -2
  11. package/dist/{chunk-OOJYHWRB.js → chunk-34475P3I.js} +2 -2
  12. package/dist/{chunk-WVO7V2QY.js → chunk-35MKKU5R.js} +4 -4
  13. package/dist/{chunk-LBNRH5WM.js → chunk-3HZ5RWN2.js} +5 -5
  14. package/dist/{chunk-AGYYIBLL.js → chunk-3JLKSKD7.js} +2 -2
  15. package/dist/{chunk-MBS4V7ZP.js → chunk-4JUF2NNX.js} +7 -7
  16. package/dist/{chunk-ZDOOVTXZ.js → chunk-4OC57DA6.js} +27 -4
  17. package/dist/chunk-5M54SPOL.js +926 -0
  18. package/dist/{chunk-STBPMHSX.js → chunk-7RXG6QRZ.js} +51 -11
  19. package/dist/{chunk-77VKQEHF.js → chunk-A2GZF7DC.js} +5 -5
  20. package/dist/{chunk-A3CYT5EX.js → chunk-AD2SYQYC.js} +55 -2
  21. package/dist/chunk-AOCYTWAV.js +449 -0
  22. package/dist/chunk-BEY543CS.js +258 -0
  23. package/dist/{chunk-6N5PTWMY.js → chunk-BP4OYD6A.js} +32 -13
  24. package/dist/chunk-BPGS2WCQ.js +612 -0
  25. package/dist/{chunk-J5HN4RYU.js → chunk-BRXQQJFP.js} +8 -8
  26. package/dist/chunk-CFGTUFWB.js +67 -0
  27. package/dist/{chunk-CBCAPZAA.js → chunk-E25LMLRW.js} +2 -2
  28. package/dist/{chunk-G2DE3C7R.js → chunk-EDRHSCIE.js} +4 -4
  29. package/dist/{chunk-4KLWL3UC.js → chunk-EFADSJET.js} +2 -2
  30. package/dist/{chunk-M6SHUN7Q.js → chunk-FO5ZOVUY.js} +2 -2
  31. package/dist/chunk-FYYLNIL5.js +313 -0
  32. package/dist/{chunk-EPVUXGXG.js → chunk-HV5X7OR2.js} +14 -12
  33. package/dist/{chunk-TZTZS7QK.js → chunk-HXG4IURW.js} +5 -3
  34. package/dist/{chunk-IGLFWIYI.js → chunk-K6WL7QZT.js} +3 -3
  35. package/dist/chunk-K7VKOLQQ.js +15 -0
  36. package/dist/{chunk-BMEMKKIT.js → chunk-KOHPCX4K.js} +2 -2
  37. package/dist/{chunk-V4RXGQ5Q.js → chunk-KRPY7NTG.js} +10 -7
  38. package/dist/chunk-LL4KHSZI.js +22 -0
  39. package/dist/{chunk-KJ5LWLOE.js → chunk-MEQ45TQ4.js} +15 -9
  40. package/dist/{chunk-5UUP6MWO.js → chunk-MV3K5QF2.js} +5 -436
  41. package/dist/{chunk-AO4RKG4M.js → chunk-N4CZJQRK.js} +5 -5
  42. package/dist/{chunk-ARBGF5F7.js → chunk-NILBFAPG.js} +14 -8
  43. package/dist/chunk-OZNBF4L3.js +23 -0
  44. package/dist/{verify-G6V4D2G7.js → chunk-PCZJO5TI.js} +127 -42
  45. package/dist/chunk-QQK64KLB.js +1360 -0
  46. package/dist/{chunk-6EJV5X2W.js → chunk-QQL5RT5M.js} +979 -1619
  47. package/dist/{chunk-LZSJBIVT.js → chunk-QWU7ZBO7.js} +70 -720
  48. package/dist/{chunk-2EHAIA3X.js → chunk-RD5U66HV.js} +3 -3
  49. package/dist/{chunk-OKGUZO2U.js → chunk-SPULKLCF.js} +4 -3
  50. package/dist/{chunk-OQ33BKR3.js → chunk-TTNYS3EA.js} +3 -60
  51. package/dist/chunk-TW3WDMVS.js +677 -0
  52. package/dist/chunk-TZSKNMZG.js +434 -0
  53. package/dist/{chunk-7MNJORFF.js → chunk-UL3WSD3F.js} +6 -1
  54. package/dist/{chunk-7EYHLWU7.js → chunk-UZHIZC5S.js} +7 -7
  55. package/dist/{chunk-QTYWRVRA.js → chunk-VAWWTKDP.js} +8 -8
  56. package/dist/{chunk-X75S7HFS.js → chunk-VEZEGCGW.js} +214 -20
  57. package/dist/{chunk-OHHN2SO4.js → chunk-VMNQ6OZA.js} +98 -202
  58. package/dist/chunk-VSNATDE6.js +122 -0
  59. package/dist/chunk-W6GROXXM.js +69 -0
  60. package/dist/chunk-WPQLXFOZ.js +375 -0
  61. package/dist/{chunk-ORBHGJC5.js → chunk-WR67VIZY.js} +3 -3
  62. package/dist/{chunk-3ZXDFGR5.js → chunk-X6COSD2O.js} +5 -5
  63. package/dist/chunk-ZGVHUX3M.js +66 -0
  64. package/dist/{chunk-MAW544W2.js → chunk-ZWMF7253.js} +4 -4
  65. package/dist/{chunk-MQSRRFWA.js → chunk-ZYKPLLNQ.js} +563 -546
  66. package/dist/cli/index.js +27 -23
  67. package/dist/{clio-4LY5K2AC.js → clio-J5JIOIDS.js} +7 -6
  68. package/dist/{code-nav-7AX6FYE6.js → code-nav-AXCXSBHX.js} +5 -3
  69. package/dist/{config-GTLUW2PR.js → config-OEBMIN2U.js} +37 -27
  70. package/dist/{configure-R6A64DHX.js → configure-PUQOSIXQ.js} +16 -13
  71. package/dist/{context-5VKGUVJJ.js → context-EKDCKUUZ.js} +82 -7
  72. package/dist/{context-RW5HC47S.js → context-MGSE4Z2T.js} +33 -23
  73. package/dist/{context-JFZEJ7W5.js → context-URSXPBCK.js} +17 -9
  74. package/dist/{context-clear-6ZHBAZZT.js → context-clear-KDAJRNUK.js} +33 -23
  75. package/dist/context-working-set-SBKMPPI2.js +1552 -0
  76. package/dist/{dispatch-runner-VKBRCWQC.js → dispatch-runner-MSWN72NK.js} +43 -29
  77. package/dist/{doctor-KI767GSN.js → doctor-7BSE27PJ.js} +10 -10
  78. package/dist/{eval-XSSNATB4.js → eval-IZGDOO4H.js} +9 -8
  79. package/dist/{evidence-UA6AWDQQ.js → evidence-SR7WXB5B.js} +51 -23
  80. package/dist/{evolve-QNTFGV6Z.js → evolve-K7VE2CBX.js} +30 -20
  81. package/dist/{fleet-Q7UOMUSG.js → fleet-7XMJNQNF.js} +48 -38
  82. package/dist/{fleet-preflight-DDN536IT.js → fleet-preflight-AQNAH644.js} +3 -3
  83. package/dist/{init-WBB65ZHQ.js → init-JGNPAYXT.js} +41 -31
  84. package/dist/{memory-MD3O64RI.js → memory-4ALKDJ4Q.js} +32 -22
  85. package/dist/{models-BZU34YWD.js → models-ZMMLFJNN.js} +22 -19
  86. package/dist/{monitor-MEQA5C3I.js → monitor-2F3T5KHP.js} +55 -43
  87. package/dist/{orchestrator-CGFKEP27.js → orchestrator-ORHT43JB.js} +2507 -1896
  88. package/dist/{reset-L2FQEE3E.js → reset-NXGTYNUO.js} +4 -3
  89. package/dist/{run-IV4Q6RLN.js → run-RF4WJGMT.js} +51 -41
  90. package/dist/{share-S5BZQC5I.js → share-UT3W6E4M.js} +5 -4
  91. package/dist/{skills-LQEKRDTN.js → skills-PSACKC5Q.js} +2 -2
  92. package/dist/{skills-eval-3DC4HEWS.js → skills-eval-WJSI55RZ.js} +34 -24
  93. package/dist/{targets-C4SSGQOB.js → targets-PIIRAOYS.js} +23 -20
  94. package/dist/{terminal-lease-IT5JW2NR.js → terminal-lease-ULWXWNVY.js} +5 -4
  95. package/dist/{upgrade-7TT7SQ3G.js → upgrade-346TZ6AV.js} +18 -17
  96. package/dist/{usage-GV4PKT3M.js → usage-6KKXR32N.js} +34 -24
  97. package/dist/verifiers-4UUM6TEE.js +1214 -0
  98. package/dist/verify-X5HDROLA.js +25 -0
  99. package/dist/{wiki-generate-DQF6Z66B.js → wiki-generate-7STOCIFZ.js} +42 -31
  100. package/dist/worker/entry.js +33 -24
  101. package/docs/README.md +8 -7
  102. package/docs/acp.md +1 -1
  103. package/docs/alcf-provider.md +1 -1
  104. package/docs/architecture.md +2 -2
  105. package/docs/artifact-versions.md +1 -1
  106. package/docs/built-in-agents.md +1 -1
  107. package/docs/capacity-and-scheduling.md +1 -1
  108. package/docs/commands-and-modes.md +53 -21
  109. package/docs/config-knobs-audit.md +1 -2
  110. package/docs/configuration-and-targets.md +15 -1
  111. package/docs/context-engine.md +64 -12
  112. package/docs/context-working-set.md +194 -0
  113. package/docs/development-pipeline.md +1 -1
  114. package/docs/documentation-coverage.md +5 -5
  115. package/docs/documentation-guide.md +6 -5
  116. package/docs/environment-variables.md +2 -1
  117. package/docs/eval-runner.md +1 -1
  118. package/docs/evals-internal.md +14 -1
  119. package/docs/evidence-and-memory.md +74 -2
  120. package/docs/evolution.md +1 -1
  121. package/docs/exit-codes-and-output.md +1 -1
  122. package/docs/extensions-and-sharing.md +2 -2
  123. package/docs/fleet-dispatch.md +22 -7
  124. package/docs/glossary.md +21 -1
  125. package/docs/installation-and-lifecycle.md +6 -6
  126. package/docs/middleware-and-components.md +1 -1
  127. package/docs/model-catalog.md +7 -9
  128. package/docs/observability.md +4 -4
  129. package/docs/performance-methodology.md +2 -2
  130. package/docs/proactive-memory.md +1 -1
  131. package/docs/prompt-envelope-and-tools.md +4 -4
  132. package/docs/provider-adapter-cookbook.md +1 -1
  133. package/docs/release-cut-checklist.md +35 -35
  134. package/docs/safety-model.md +23 -4
  135. package/docs/scientific-validation.md +21 -3
  136. package/docs/session-lifecycle.md +3 -3
  137. package/docs/skills-marketplace.md +1 -1
  138. package/docs/tool-usage.md +79 -12
  139. package/docs/trace-store.md +1 -1
  140. package/docs/troubleshooting.md +1 -1
  141. package/docs/tui-design.md +2 -2
  142. package/docs/worker-dispatch-mechanics.md +11 -1
  143. package/package.json +8 -11
  144. package/skills/meta/clio-test/SKILL.md +20 -17
  145. package/skills/meta/clio-test/evals.md +3 -3
  146. package/skills/meta/clio-test/references/harness.md +35 -6
  147. package/skills/meta/clio-test/references/test-map.md +20 -10
  148. package/skills/registry.yaml +2 -2
  149. package/skills/skill-marketplace.json +1 -1
  150. package/src/cli/context-working-set.ts +513 -0
  151. package/src/cli/context.ts +8 -0
  152. package/src/cli/evidence.ts +20 -2
  153. package/src/cli/index.ts +4 -0
  154. package/src/cli/verifiers.ts +325 -0
  155. package/src/core/bash-exec.ts +39 -14
  156. package/src/core/bus-events.ts +19 -4
  157. package/src/core/config.ts +54 -0
  158. package/src/core/defaults.ts +50 -3
  159. package/src/core/git-commit-attribution.ts +46 -21
  160. package/src/core/verification-scripts.ts +6 -0
  161. package/src/domains/agents/builtins/verifier.md +3 -0
  162. package/src/domains/config/classify.ts +1 -0
  163. package/src/domains/config/keybindings.ts +3 -3
  164. package/src/domains/context/working-set/contract.ts +161 -0
  165. package/src/domains/context/working-set/defaults.ts +28 -0
  166. package/src/domains/context/working-set/engine.ts +203 -0
  167. package/src/domains/context/working-set/fold.ts +62 -0
  168. package/src/domains/context/working-set/horizon.ts +38 -0
  169. package/src/domains/context/working-set/marker.ts +103 -0
  170. package/src/domains/context/working-set/path-index.ts +436 -0
  171. package/src/domains/context/working-set/payload.ts +152 -0
  172. package/src/domains/context/working-set/policies/age-horizon.ts +55 -0
  173. package/src/domains/context/working-set/policies/index.ts +21 -0
  174. package/src/domains/context/working-set/policies/structural.ts +160 -0
  175. package/src/domains/context/working-set/project.ts +132 -0
  176. package/src/domains/context/working-set/protect.ts +109 -0
  177. package/src/domains/context/working-set/recall.ts +177 -0
  178. package/src/domains/context/working-set/replay/controls.ts +112 -0
  179. package/src/domains/context/working-set/replay/load-clio.ts +199 -0
  180. package/src/domains/context/working-set/replay/metrics.ts +185 -0
  181. package/src/domains/context/working-set/replay/reference-graph.ts +79 -0
  182. package/src/domains/context/working-set/replay/report.ts +139 -0
  183. package/src/domains/context/working-set/replay/runner.ts +325 -0
  184. package/src/domains/context/working-set/replay/synthetic.ts +422 -0
  185. package/src/domains/context/working-set/replay/trace.ts +21 -0
  186. package/src/domains/context/working-set/visible.ts +54 -0
  187. package/src/domains/evidence/build.ts +112 -45
  188. package/src/domains/evidence/eval.ts +24 -7
  189. package/src/domains/evidence/index.ts +53 -0
  190. package/src/domains/evidence/ordering.ts +12 -0
  191. package/src/domains/evidence/run-trust.ts +221 -0
  192. package/src/domains/evidence/store.ts +46 -6
  193. package/src/domains/evidence/trust-status.ts +854 -0
  194. package/src/domains/evidence/types.ts +26 -0
  195. package/src/domains/middleware/memory-intervention.ts +3 -0
  196. package/src/domains/middleware/stalled-turn.ts +165 -4
  197. package/src/domains/safety/autonomy.ts +1 -1
  198. package/src/domains/safety/default-path-policy.ts +8 -0
  199. package/src/domains/safety/finish-contract.ts +4 -3
  200. package/src/domains/safety/policy-engine.ts +48 -6
  201. package/src/domains/session/compaction/compact.ts +23 -1
  202. package/src/domains/session/compaction/cut-point.ts +2 -0
  203. package/src/domains/session/compaction/tokens.ts +16 -1
  204. package/src/domains/session/context-ledger.ts +2 -0
  205. package/src/domains/session/entries.ts +107 -1
  206. package/src/domains/session/manager.ts +9 -2
  207. package/src/domains/session/migrations/index.ts +22 -3
  208. package/src/engine/acp/server.ts +3 -0
  209. package/src/engine/agent.ts +18 -1
  210. package/src/engine/session.ts +9 -3
  211. package/src/entry/orchestrator.ts +16 -4
  212. package/src/interactive/chat-loop-messages.ts +18 -6
  213. package/src/interactive/chat-panel.ts +571 -244
  214. package/src/interactive/chat-renderer.ts +79 -39
  215. package/src/interactive/context-meter.ts +10 -0
  216. package/src/interactive/context-overlay.ts +81 -6
  217. package/src/interactive/context-recall-command.ts +110 -0
  218. package/src/interactive/editor-submit.ts +26 -1
  219. package/src/interactive/footer/widgets.ts +22 -20
  220. package/src/interactive/footer-panel.ts +6 -1
  221. package/src/interactive/interactive-application.ts +2 -0
  222. package/src/interactive/interactive-event-projection.ts +12 -0
  223. package/src/interactive/interactive-slash-runtime.ts +49 -8
  224. package/src/interactive/model-session-replay.ts +21 -0
  225. package/src/interactive/overlay-general-openers.ts +6 -0
  226. package/src/interactive/overlay-session-lifecycle.ts +8 -4
  227. package/src/interactive/overlays/ask-user.ts +146 -24
  228. package/src/interactive/renderers/tool-execution.ts +167 -56
  229. package/src/interactive/session-transcript.ts +2 -2
  230. package/src/interactive/slash-commands.ts +29 -2
  231. package/src/interactive/status/index.ts +12 -1
  232. package/src/interactive/status/reasoning.ts +87 -0
  233. package/src/interactive/status/summary.ts +13 -2
  234. package/src/interactive/transcript-detail.ts +120 -0
  235. package/src/interactive/turn-context.ts +238 -88
  236. package/src/interactive/turn-middleware.ts +6 -6
  237. package/src/tools/agent-tools.ts +11 -4
  238. package/src/tools/bash.ts +144 -82
  239. package/src/tools/builtin-tool-catalog.ts +18 -6
  240. package/src/tools/context/index.ts +105 -3
  241. package/src/tools/context/surface.ts +3 -2
  242. package/src/tools/core-bootstrap.ts +21 -0
  243. package/src/tools/dispatch-runner.ts +9 -7
  244. package/src/tools/monitor.ts +28 -20
  245. package/src/tools/presentation.ts +107 -0
  246. package/src/tools/registry.ts +65 -7
  247. package/src/tools/result-disposition.ts +550 -0
  248. package/src/tools/result-shaping.ts +262 -19
  249. package/src/tools/safe-exec.ts +2 -0
  250. package/src/tools/verify/authoring.ts +1119 -0
  251. package/src/tools/verify/catalog.ts +346 -0
  252. package/src/tools/verify/index.ts +13 -3
  253. package/src/tools/verify/scripts.ts +135 -37
  254. package/src/tools/verify/surface.ts +9 -5
  255. package/src/tools/worker-evidence.ts +35 -12
  256. package/dist/chunk-MNA4JGU4.js +0 -255
  257. package/dist/chunk-SRF2PJNW.js +0 -184
  258. package/dist/chunk-T6YILFSB.js +0 -80
  259. package/dist/chunk-VAKQQHWR.js +0 -434
@@ -1,9 +1,10 @@
1
1
  import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
2
2
  import {
3
- createRedactionTally,
4
- redactSecretsDeep,
5
- redactSecretsText
6
- } from "./chunk-4BJ5BYCE.js";
3
+ protectedArtifactFromSessionEntry,
4
+ protectedArtifactStateFromSessionEntries,
5
+ readAuditRows,
6
+ readSessionEntriesForId
7
+ } from "./chunk-QQK64KLB.js";
7
8
  import {
8
9
  FLEET_COMMAND_BASE_ENV,
9
10
  describeWriteBoundary,
@@ -23,7 +24,7 @@ import {
23
24
  sumEvalHarnessMetrics,
24
25
  verifyReceiptIntegrity,
25
26
  withReceiptIntegrity
26
- } from "./chunk-AGYYIBLL.js";
27
+ } from "./chunk-3JLKSKD7.js";
27
28
  import {
28
29
  LOCAL_NODE_ID,
29
30
  computeSettingsFingerprint,
@@ -34,10 +35,7 @@ import {
34
35
  receiptAttestationFields,
35
36
  routeFactVerdict,
36
37
  spawnNativeWorker
37
- } from "./chunk-OOJYHWRB.js";
38
- import {
39
- probeWorkspace
40
- } from "./chunk-G4BMMOKF.js";
38
+ } from "./chunk-34475P3I.js";
41
39
  import {
42
40
  AGENT_LEDGER_PROMPT_MAX_CHARS,
43
41
  RETRYABLE_OUTCOMES,
@@ -63,8 +61,6 @@ import {
63
61
  isClaudeCanonicalTool,
64
62
  isResponseSchemaRejection,
65
63
  isRunOutcomeCode,
66
- isSessionEntry,
67
- isSessionHeader,
68
64
  networkToolsDisabled,
69
65
  projectExecutionHandoffs,
70
66
  renderAgentLedger,
@@ -74,7 +70,7 @@ import {
74
70
  serializeWorkerRuntimeDescriptor,
75
71
  toolPromptHintsForNames,
76
72
  validateJobSpec
77
- } from "./chunk-MQSRRFWA.js";
73
+ } from "./chunk-ZYKPLLNQ.js";
78
74
  import {
79
75
  DEFAULT_AUTONOMY_LEVEL,
80
76
  WRITE_ROOT_REFUSED_TOOLS,
@@ -84,7 +80,7 @@ import {
84
80
  parseJsonObjectPayload,
85
81
  parseVerifierResult,
86
82
  validateRecipeResult
87
- } from "./chunk-STBPMHSX.js";
83
+ } from "./chunk-7RXG6QRZ.js";
88
84
  import {
89
85
  appliesRecipeResultContract,
90
86
  decideRoute,
@@ -107,31 +103,41 @@ import {
107
103
  sameRouteIdentity,
108
104
  toRouteCandidate,
109
105
  withAttemptRole
110
- } from "./chunk-GGXXDWE4.js";
106
+ } from "./chunk-22NAGB7X.js";
111
107
  import {
112
108
  agentSpecFingerprint,
113
109
  assertAgentSpecPolicy,
114
110
  classify,
115
- detectValidationCommand,
116
111
  isUserVisibleAgent,
117
112
  normalizeAgentSpec,
118
- protectArtifact,
119
113
  resolveAgentToolCompatibility
120
- } from "./chunk-5UUP6MWO.js";
114
+ } from "./chunk-AOCYTWAV.js";
115
+ import {
116
+ detectValidationCommand
117
+ } from "./chunk-MV3K5QF2.js";
121
118
  import {
122
119
  canonicalJson,
123
120
  endpointIdentityHash,
124
121
  parseAgentLedgerBody
125
122
  } from "./chunk-CMZWFGD2.js";
126
123
  import {
124
+ compareCodepoints
125
+ } from "./chunk-FYYLNIL5.js";
126
+ import {
127
+ isProjectVerifierCheckId,
127
128
  isVerificationScriptName
128
- } from "./chunk-7MNJORFF.js";
129
+ } from "./chunk-UL3WSD3F.js";
129
130
  import {
130
131
  canonicalizeExistingPath
131
132
  } from "./chunk-ECH6PKUQ.js";
132
133
  import {
133
134
  isSkillActivation
134
- } from "./chunk-T6YILFSB.js";
135
+ } from "./chunk-BEY543CS.js";
136
+ import {
137
+ createRedactionTally,
138
+ redactSecretsDeep,
139
+ redactSecretsText
140
+ } from "./chunk-4BJ5BYCE.js";
135
141
  import {
136
142
  truncateUtf8
137
143
  } from "./chunk-6XLNIQDB.js";
@@ -141,45 +147,28 @@ import {
141
147
  } from "./chunk-CGKSTWHD.js";
142
148
  import {
143
149
  canonicalizeWireModelId,
144
- ceilChars,
145
150
  firstRuntimeResolutionError,
146
151
  isDispatchEligibleRuntime,
147
152
  resolveEffectivePricing,
148
153
  resolveModelCapabilities,
149
154
  resolveRuntimeTarget,
150
155
  runtimeResolutionWarnings,
151
- runtimeTargetSnapshot,
152
- stripTokenizerSentinels
153
- } from "./chunk-LZSJBIVT.js";
156
+ runtimeTargetSnapshot
157
+ } from "./chunk-QWU7ZBO7.js";
154
158
  import {
155
159
  DEFAULT_DELEGATION_CONNECT_TIMEOUT_MS,
156
160
  DEFAULT_DELEGATION_TURN_TIMEOUT_MS,
157
161
  DEFAULT_SETTINGS,
158
162
  THINKING_LEVELS
159
- } from "./chunk-ZDOOVTXZ.js";
163
+ } from "./chunk-4OC57DA6.js";
160
164
  import {
161
165
  targetRequiresAuth
162
166
  } from "./chunk-4VP4KH3K.js";
163
- import {
164
- CURRENT_SESSION_FORMAT_VERSION,
165
- appendSessionFileEntry,
166
- atomicWrite,
167
- createSession,
168
- cwdHash,
169
- openSession,
170
- readSessionFileEntries,
171
- readSessionMeta,
172
- resumeSession,
173
- sessionPaths
174
- } from "./chunk-M6SHUN7Q.js";
175
- import {
176
- assertSafeId
177
- } from "./chunk-R346GLFC.js";
178
167
  import {
179
168
  gitCommitAttributionEnabled,
180
169
  reportCommitAttributionDiagnostic,
181
170
  withManagedGitCommitAttributionEnvironment
182
- } from "./chunk-X75S7HFS.js";
171
+ } from "./chunk-VEZEGCGW.js";
183
172
  import {
184
173
  MAX_TIMER_DELAY_MS,
185
174
  rawDurationMs
@@ -194,6 +183,15 @@ import {
194
183
  processAlive,
195
184
  processBirthToken
196
185
  } from "./chunk-3I7MS7N2.js";
186
+ import {
187
+ ceilChars
188
+ } from "./chunk-BPGS2WCQ.js";
189
+ import {
190
+ atomicWrite
191
+ } from "./chunk-FO5ZOVUY.js";
192
+ import {
193
+ assertSafeId
194
+ } from "./chunk-R346GLFC.js";
197
195
  import {
198
196
  GUARDRAIL_DEFAULTS,
199
197
  resolveGuardrail
@@ -208,7 +206,7 @@ import {
208
206
  } from "./chunk-6EJMN2Y3.js";
209
207
  import {
210
208
  BusChannels
211
- } from "./chunk-OQ33BKR3.js";
209
+ } from "./chunk-TTNYS3EA.js";
212
210
  import {
213
211
  readClioVersion,
214
212
  readPiMonoVersion,
@@ -1426,8 +1424,8 @@ init_esm_shims();
1426
1424
 
1427
1425
  // src/domains/evidence/build.ts
1428
1426
  init_esm_shims();
1429
- import { mkdir, readFile as readFile3, writeFile } from "node:fs/promises";
1430
- import { join as join19 } from "node:path";
1427
+ import { mkdir, readFile as readFile2, writeFile } from "node:fs/promises";
1428
+ import { join as join16 } from "node:path";
1431
1429
 
1432
1430
  // src/domains/dispatch/index.ts
1433
1431
  init_esm_shims();
@@ -12577,1521 +12575,807 @@ function createDispatchDomainModule(options = {}) {
12577
12575
  };
12578
12576
  }
12579
12577
 
12580
- // src/domains/session/index.ts
12581
- init_esm_shims();
12582
-
12583
- // src/domains/session/extension.ts
12584
- init_esm_shims();
12585
-
12586
- // src/domains/session/checkpoint.ts
12587
- init_esm_shims();
12588
- async function performCheckpoint(state, reason) {
12589
- await state.writer.persistTree();
12590
- if (stateRootRemoved()) return;
12591
- const paths = sessionPaths(state.meta);
12592
- const at = (/* @__PURE__ */ new Date()).toISOString();
12593
- const enriched = {
12594
- ...state.meta,
12595
- lastCheckpointAt: at,
12596
- lastCheckpointReason: reason ?? null
12597
- };
12598
- atomicWrite(paths.meta, JSON.stringify(enriched, null, 2));
12599
- Object.assign(state.meta, enriched);
12600
- }
12601
-
12602
- // src/domains/session/history.ts
12603
- init_esm_shims();
12604
- import { existsSync as existsSync14, readdirSync as readdirSync6, readFileSync as readFileSync12, statSync as statSync2 } from "node:fs";
12605
- import { join as join15 } from "node:path";
12606
-
12607
- // src/domains/session/compaction/session-entries.ts
12578
+ // src/domains/evidence/failure-attribution.ts
12608
12579
  init_esm_shims();
12609
- function collectSessionEntries(turns, filePath) {
12610
- const out = [];
12611
- for (const raw of turns) {
12612
- if (!isSessionEntry(raw)) {
12613
- throw new Error(
12614
- `session ledger contains an unreadable entry (missing kind discriminant): ${filePath}. Remove or compact the session to reset.`
12615
- );
12616
- }
12617
- out.push(raw);
12618
- }
12619
- return out;
12620
- }
12621
-
12622
- // src/domains/session/history.ts
12623
- function listSessionsForCwd(cwd) {
12624
- const hash = cwdHash(cwd);
12625
- const dir = join15(clioStateDir(), "sessions", hash);
12626
- if (!existsSync14(dir)) return [];
12627
- const metas = [];
12628
- for (const entry of readdirSync6(dir, { withFileTypes: true })) {
12629
- if (!entry.isDirectory()) continue;
12630
- const sessionDir = join15(dir, entry.name);
12631
- const metaPath = join15(sessionDir, "meta.json");
12632
- if (!existsSync14(metaPath)) continue;
12633
- let meta;
12634
- try {
12635
- if (!statSync2(metaPath).isFile()) continue;
12636
- const raw = readFileSync12(metaPath, "utf8");
12637
- meta = JSON.parse(raw);
12638
- } catch {
12639
- continue;
12640
- }
12641
- enrichMetaForListing(meta, join15(sessionDir, "current.jsonl"));
12642
- metas.push(meta);
12643
- }
12644
- metas.sort((a, b) => {
12645
- const aKey = a.lastActivityAt ?? a.createdAt ?? "";
12646
- const bKey = b.lastActivityAt ?? b.createdAt ?? "";
12647
- return aKey === bKey ? 0 : aKey > bKey ? -1 : 1;
12648
- });
12649
- return metas;
12650
- }
12651
- var PREVIEW_MAX_CHARS = 240;
12652
- function collapseWhitespace(text) {
12653
- return text.replace(/\s+/g, " ").trim();
12654
- }
12655
- function extractUserText(payload) {
12656
- if (typeof payload === "string") {
12657
- const collapsed = collapseWhitespace(payload);
12658
- return collapsed.length > 0 ? collapsed : null;
12580
+ function attributeEvidenceFailure(facts) {
12581
+ if (facts.outcomeCode === "worker_tool_call_cap_exhausted" || facts.outcomeCode === "loop_guard_tools_disabled_exhausted") {
12582
+ return "tool-loop";
12659
12583
  }
12660
- if (!payload || typeof payload !== "object") return null;
12661
- const obj = payload;
12662
- if (typeof obj.text === "string") {
12663
- const collapsed = collapseWhitespace(obj.text);
12664
- if (collapsed.length > 0) return collapsed;
12584
+ if (facts.outcome === "timed_out" || facts.outcome === "stalled") return "timeout";
12585
+ const diagnostic = [facts.outcomeDetail, facts.failureMessage].filter((value) => value !== null).join("\n").toLowerCase();
12586
+ if (diagnostic.length === 0) return "unknown";
12587
+ if (/\b(?:401|403)\b|unauthorized|forbidden|invalid api key|authentication/.test(diagnostic)) {
12588
+ return "auth-failure";
12665
12589
  }
12666
- if (Array.isArray(obj.content)) {
12667
- const parts = [];
12668
- for (const part of obj.content) {
12669
- if (part && typeof part === "object" && part.type === "text" && typeof part.text === "string") {
12670
- parts.push(part.text);
12671
- }
12672
- }
12673
- const joined = collapseWhitespace(parts.join(" "));
12674
- if (joined.length > 0) return joined;
12590
+ if (/\b429\b|rate[ -]?limit|too many requests|temporar(?:y|ily)|unavailable|\b50[234]\b/.test(diagnostic)) {
12591
+ return "provider-transient";
12675
12592
  }
12676
- return null;
12677
- }
12678
- function scanCurrentJsonl(currentPath) {
12679
- const result = {
12680
- firstUserMessage: null,
12681
- messageCount: 0,
12682
- lastTimestamp: null,
12683
- name: null,
12684
- labels: /* @__PURE__ */ new Map()
12685
- };
12686
- if (!existsSync14(currentPath)) return result;
12687
- const records = readSessionFileEntries(currentPath).filter((entry) => !isSessionHeader(entry));
12688
- for (const parsed of collectSessionEntries(records, currentPath)) {
12689
- if (result.lastTimestamp === null || parsed.timestamp > result.lastTimestamp) {
12690
- result.lastTimestamp = parsed.timestamp;
12691
- }
12692
- if (parsed.kind === "message" && parsed.role === "user") {
12693
- result.messageCount += 1;
12694
- if (result.firstUserMessage === null) {
12695
- const text = extractUserText(parsed.payload);
12696
- if (text !== null) result.firstUserMessage = text;
12697
- }
12698
- }
12699
- if (parsed.kind === "sessionInfo") {
12700
- const info = parsed;
12701
- if (info.name !== void 0) {
12702
- const trimmed = info.name.trim();
12703
- result.name = trimmed.length > 0 ? trimmed : null;
12704
- }
12705
- if (info.targetTurnId && info.label !== void 0) {
12706
- const existing = result.labels.get(info.targetTurnId);
12707
- if (!existing || existing.timestamp <= info.timestamp) {
12708
- result.labels.set(info.targetTurnId, { label: info.label, timestamp: info.timestamp });
12709
- }
12710
- }
12711
- }
12712
- if (parsed.kind === "label") {
12713
- const label = parsed;
12714
- const existing = result.labels.get(label.targetTurnId);
12715
- if (!existing || existing.timestamp <= label.timestamp) {
12716
- result.labels.set(label.targetTurnId, { label: label.label ?? "", timestamp: label.timestamp });
12717
- }
12718
- }
12593
+ if (/context (?:length|window)|context[_ -]?overflow|maximum context|too many tokens/.test(diagnostic)) {
12594
+ return "context-overflow";
12719
12595
  }
12720
- return result;
12721
- }
12722
- function enrichMetaForListing(meta, currentPath) {
12723
- const scan = scanCurrentJsonl(currentPath);
12724
- if (scan.name) meta.name = scan.name;
12725
- const labelValues = [...scan.labels.values()].map((entry) => entry.label.trim()).filter((label) => label.length > 0);
12726
- if (labelValues.length > 0) meta.labels = labelValues;
12727
- if (scan.firstUserMessage) {
12728
- meta.firstMessagePreview = scan.firstUserMessage.length > PREVIEW_MAX_CHARS ? `${scan.firstUserMessage.slice(0, PREVIEW_MAX_CHARS - 1)}\u2026` : scan.firstUserMessage;
12596
+ if (/module not found|cannot find module|missing (?:dependency|package)|dependency .* missing/.test(diagnostic)) {
12597
+ return "missing-dependency";
12729
12598
  }
12730
- if (scan.messageCount > 0) meta.messageCount = scan.messageCount;
12731
- const fallbackMtime = readMtimeIso(currentPath);
12732
- const activity = scan.lastTimestamp ?? fallbackMtime ?? meta.endedAt ?? meta.createdAt ?? null;
12733
- if (activity) meta.lastActivityAt = activity;
12734
- }
12735
- function readMtimeIso(path2) {
12736
- try {
12737
- return statSync2(path2).mtime.toISOString();
12738
- } catch {
12739
- return null;
12599
+ if (/wrong runtime|runtime mismatch|model mismatch|unsupported runtime/.test(diagnostic)) return "wrong-runtime";
12600
+ if (/\b(?:test|tests|pytest|ctest)\b.*(?:fail|error)|(?:fail|error).*\b(?:test|tests|pytest|ctest)\b/.test(diagnostic)) {
12601
+ return "test-failure";
12740
12602
  }
12741
- }
12742
- function enrichForkMeta(meta, parentSessionId, parentTurnId) {
12743
- Object.assign(meta, { parentSessionId, parentTurnId });
12744
- const paths = sessionPaths(meta);
12745
- atomicWrite(paths.meta, JSON.stringify(meta, null, 2));
12603
+ if (/\bbuild\b.*(?:fail|error)|(?:fail|error).*\bbuild\b/.test(diagnostic)) return "build-failure";
12604
+ return "unknown";
12746
12605
  }
12747
12606
 
12748
- // src/domains/session/manager.ts
12749
- init_esm_shims();
12750
-
12751
- // node_modules/uuid/dist-node/index.js
12752
- init_esm_shims();
12753
-
12754
- // node_modules/uuid/dist-node/stringify.js
12607
+ // src/domains/evidence/provenance.ts
12755
12608
  init_esm_shims();
12756
- var byteToHex = [];
12757
- for (let i = 0; i < 256; ++i) {
12758
- byteToHex.push((i + 256).toString(16).slice(1));
12759
- }
12760
- function unsafeStringify(arr, offset = 0) {
12761
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
12609
+ var PERSONA_HASH_PREFIX_CHARS = 12;
12610
+ function extractRunProvenance(receipt) {
12611
+ const view = {};
12612
+ if (receipt.pipeline !== void 0) view.pipeline = receipt.pipeline;
12613
+ if (receipt.personaOverride !== void 0) view.personaOverride = receipt.personaOverride;
12614
+ const escalation = escalationCountsFrom(receipt.safety);
12615
+ if (escalation !== null) view.escalation = escalation;
12616
+ if (receipt.autonomyEnforcement !== void 0) view.autonomyEnforcement = receipt.autonomyEnforcement;
12617
+ return view;
12762
12618
  }
12763
-
12764
- // node_modules/uuid/dist-node/rng.js
12765
- init_esm_shims();
12766
- var rnds8 = new Uint8Array(16);
12767
- function rng() {
12768
- return crypto.getRandomValues(rnds8);
12619
+ function hasRunProvenance(view) {
12620
+ return view.pipeline !== void 0 || view.personaOverride !== void 0 || view.escalation !== void 0 || view.autonomyEnforcement !== void 0;
12769
12621
  }
12770
-
12771
- // node_modules/uuid/dist-node/v7.js
12772
- init_esm_shims();
12773
- var _state = {};
12774
- function v7(options, buf, offset) {
12775
- let bytes;
12776
- if (options) {
12777
- bytes = v7Bytes(options.random ?? options.rng?.() ?? rng(), options.msecs, options.seq, buf, offset);
12778
- } else {
12779
- const now = Date.now();
12780
- const rnds = rng();
12781
- updateV7State(_state, now, rnds);
12782
- bytes = v7Bytes(rnds, _state.msecs, _state.seq, buf, offset);
12783
- }
12784
- return buf ?? unsafeStringify(bytes);
12785
- }
12786
- function updateV7State(state, now, rnds) {
12787
- state.msecs ??= -Infinity;
12788
- state.seq ??= 0;
12789
- if (now > state.msecs) {
12790
- state.seq = rnds[6] << 23 | rnds[7] << 16 | rnds[8] << 8 | rnds[9];
12791
- state.msecs = now;
12792
- } else {
12793
- state.seq = state.seq + 1 | 0;
12794
- if (state.seq === 0) {
12795
- state.msecs++;
12796
- }
12797
- }
12798
- return state;
12622
+ function runProvenanceFromUnknown(value) {
12623
+ if (!isRecord9(value)) return {};
12624
+ const view = {};
12625
+ const pipeline = pipelineFromUnknown(value.pipeline);
12626
+ if (pipeline !== null) view.pipeline = pipeline;
12627
+ const personaOverride = personaOverrideFromUnknown(value.personaOverride);
12628
+ if (personaOverride !== null) view.personaOverride = personaOverride;
12629
+ const escalation = escalationFromUnknown(value.safety);
12630
+ if (escalation !== null) view.escalation = escalation;
12631
+ const autonomyEnforcement = autonomyEnforcementFromUnknown(value.autonomyEnforcement);
12632
+ if (autonomyEnforcement !== null) view.autonomyEnforcement = autonomyEnforcement;
12633
+ return view;
12799
12634
  }
12800
- function v7Bytes(rnds, msecs, seq, buf, offset = 0) {
12801
- if (rnds.length < 16) {
12802
- throw new Error("Random bytes length must be >= 16");
12803
- }
12804
- if (!buf) {
12805
- buf = new Uint8Array(16);
12806
- offset = 0;
12807
- } else {
12808
- if (offset < 0 || offset + 16 > buf.length) {
12809
- throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
12810
- }
12811
- }
12812
- msecs ??= Date.now();
12813
- seq ??= rnds[6] * 127 << 24 | rnds[7] << 16 | rnds[8] << 8 | rnds[9];
12814
- buf[offset++] = msecs / 1099511627776 & 255;
12815
- buf[offset++] = msecs / 4294967296 & 255;
12816
- buf[offset++] = msecs / 16777216 & 255;
12817
- buf[offset++] = msecs / 65536 & 255;
12818
- buf[offset++] = msecs / 256 & 255;
12819
- buf[offset++] = msecs & 255;
12820
- buf[offset++] = 112 | seq >>> 28 & 15;
12821
- buf[offset++] = seq >>> 20 & 255;
12822
- buf[offset++] = 128 | seq >>> 14 & 63;
12823
- buf[offset++] = seq >>> 6 & 255;
12824
- buf[offset++] = seq << 2 & 255 | rnds[10] & 3;
12825
- buf[offset++] = rnds[11];
12826
- buf[offset++] = rnds[12];
12827
- buf[offset++] = rnds[13];
12828
- buf[offset++] = rnds[14];
12829
- buf[offset++] = rnds[15];
12830
- return buf;
12831
- }
12832
- var v7_default = v7;
12833
-
12834
- // src/domains/session/migrations/index.ts
12835
- init_esm_shims();
12836
- function runMigrations(meta, sessionPath) {
12837
- const from = meta.sessionFormatVersion ?? 1;
12838
- if (from < CURRENT_SESSION_FORMAT_VERSION) {
12839
- throw new Error(
12840
- `session metadata has an unsupported format version (expected version 3, got ${from}): ${sessionPath}. Remove the session directory to start a new session.`
12841
- );
12842
- }
12843
- return { migrated: false, from, to: from };
12635
+ function isRecord9(value) {
12636
+ return typeof value === "object" && value !== null && !Array.isArray(value);
12844
12637
  }
12845
-
12846
- // src/domains/session/manager.ts
12847
- function newTurnId() {
12848
- return v7_default();
12638
+ function finiteNumber(value) {
12639
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
12849
12640
  }
12850
- function startSession(input) {
12851
- const { meta, writer } = createSession({
12852
- cwd: input.cwd,
12853
- model: input.model ?? null,
12854
- target: input.target ?? null,
12855
- ...input.initialEntries !== void 0 ? { initialEntries: input.initialEntries } : {},
12856
- ...input.initialTree !== void 0 ? { initialTree: input.initialTree } : {},
12857
- ...input.parentSession !== void 0 ? { parentSession: input.parentSession } : {},
12858
- ...input.parentTurnId !== void 0 ? { parentTurnId: input.parentTurnId } : {}
12859
- });
12860
- return { meta, writer };
12641
+ function pipelineFromUnknown(value) {
12642
+ if (!isRecord9(value)) return null;
12643
+ const position = finiteNumber(value.position);
12644
+ const inputBytes = finiteNumber(value.inputBytes);
12645
+ if (position === null || inputBytes === null) return null;
12646
+ const fromRunId = typeof value.fromRunId === "string" ? value.fromRunId : null;
12647
+ return { fromRunId, position, inputBytes, inputTruncated: value.inputTruncated === true };
12861
12648
  }
12862
- function persistSessionMeta(state) {
12863
- if (stateRootRemoved()) return;
12864
- atomicWrite(sessionPaths(state.meta).meta, JSON.stringify(state.meta, null, 2));
12649
+ function personaOverrideFromUnknown(value) {
12650
+ if (!isRecord9(value) || typeof value.promptHash !== "string" || value.promptHash.length === 0) return null;
12651
+ return { promptHash: value.promptHash };
12865
12652
  }
12866
- function resumeSessionState(sessionId) {
12867
- const persistedMeta = readSessionMeta(sessionId);
12868
- const paths = sessionPaths(persistedMeta);
12869
- runMigrations(persistedMeta, paths.meta);
12870
- const { meta, writer, tree } = resumeSession(sessionId);
12871
- return { state: { meta, writer }, nodes: tree };
12653
+ function autonomyEnforcementFromUnknown(value) {
12654
+ if (!isRecord9(value)) return null;
12655
+ if (value.grade !== "mediated" && value.grade !== "approximated" && value.grade !== "bypassed") return null;
12656
+ if (typeof value.autonomy !== "string" || value.autonomy.length === 0) return null;
12657
+ const view = { grade: value.grade, autonomy: value.autonomy };
12658
+ if (typeof value.externalMode === "string" && value.externalMode.length > 0) view.externalMode = value.externalMode;
12659
+ if (typeof value.dangerousBypass === "boolean") view.dangerousBypass = value.dangerousBypass;
12660
+ return view;
12872
12661
  }
12873
- function appendTurn(state, input) {
12874
- const record = {
12875
- id: input.id ?? newTurnId(),
12876
- parentId: input.parentId,
12877
- at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
12878
- kind: input.kind,
12879
- payload: input.payload
12662
+ function escalationFromUnknown(safety) {
12663
+ if (!isRecord9(safety)) return null;
12664
+ const decisions = safety.decisions;
12665
+ if (!isRecord9(decisions)) return null;
12666
+ const requested = finiteNumber(decisions.escalationRequested);
12667
+ if (requested === null) return null;
12668
+ return {
12669
+ requested,
12670
+ approved: finiteNumber(decisions.escalationApproved) ?? 0,
12671
+ denied: finiteNumber(decisions.escalationDenied) ?? 0,
12672
+ timedOut: finiteNumber(decisions.escalationTimedOut) ?? 0
12880
12673
  };
12881
- const entry = {
12882
- kind: "message",
12883
- turnId: record.id,
12884
- parentTurnId: record.parentId,
12885
- timestamp: record.at,
12886
- role: record.kind,
12887
- payload: record.payload
12674
+ }
12675
+ function escalationCountsFrom(safety) {
12676
+ const decisions = safety?.decisions;
12677
+ if (decisions === void 0 || decisions.escalationRequested === void 0) return null;
12678
+ return {
12679
+ requested: decisions.escalationRequested,
12680
+ approved: decisions.escalationApproved ?? 0,
12681
+ denied: decisions.escalationDenied ?? 0,
12682
+ timedOut: decisions.escalationTimedOut ?? 0
12888
12683
  };
12889
- state.writer.appendEntry(entry, {
12890
- treeNode: {
12891
- id: record.id,
12892
- parentId: record.parentId,
12893
- at: record.at,
12894
- kind: record.kind
12895
- }
12896
- });
12897
- return record;
12898
12684
  }
12899
- function appendEntry(state, input) {
12900
- const turnId = input.turnId ?? newTurnId();
12901
- const timestamp = input.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
12902
- const entry = { ...input, turnId, timestamp };
12903
- if (!isSessionEntry(entry)) throw new Error(`session.appendEntry: invalid ${String(input.kind)} entry`);
12904
- state.writer.appendEntry(entry);
12905
- return entry;
12685
+ function formatPersonaHashPrefix(promptHash2) {
12686
+ if (promptHash2.length <= PERSONA_HASH_PREFIX_CHARS) return promptHash2;
12687
+ return `${promptHash2.slice(0, PERSONA_HASH_PREFIX_CHARS)}...`;
12906
12688
  }
12907
- function replaceEntries(state, entries) {
12908
- for (const entry of entries) {
12909
- if (!isSessionEntry(entry)) throw new Error("session.replaceEntries: invalid entry");
12689
+ function provenanceTranscriptLines(view) {
12690
+ const lines = [];
12691
+ if (view.pipeline !== void 0) {
12692
+ const { fromRunId, position, inputBytes, inputTruncated } = view.pipeline;
12693
+ const source = fromRunId ?? "unknown";
12694
+ const truncation = inputTruncated ? "input truncated" : "not truncated";
12695
+ lines.push(`pipeline: step ${position}, input ${inputBytes} bytes from ${source} (${truncation})`);
12696
+ }
12697
+ if (view.personaOverride !== void 0) {
12698
+ lines.push(`persona override: prompt hash ${formatPersonaHashPrefix(view.personaOverride.promptHash)}`);
12699
+ }
12700
+ if (view.escalation !== void 0) {
12701
+ const { requested, approved, denied, timedOut } = view.escalation;
12702
+ lines.push(`escalations: ${requested} requested, ${approved} approved, ${denied} denied, ${timedOut} timed out`);
12703
+ }
12704
+ if (view.autonomyEnforcement !== void 0) {
12705
+ const { grade, autonomy, externalMode, dangerousBypass } = view.autonomyEnforcement;
12706
+ const mode = externalMode !== void 0 ? ` mode=${externalMode}` : "";
12707
+ const bypass = dangerousBypass === true ? " dangerousBypass=true" : "";
12708
+ lines.push(`autonomy enforcement: ${grade} autonomy=${autonomy}${mode}${bypass}`);
12709
+ }
12710
+ return lines;
12711
+ }
12712
+ function provenanceCompactSuffix(view) {
12713
+ const parts = [];
12714
+ if (view.pipeline !== void 0) {
12715
+ const { fromRunId, position, inputBytes, inputTruncated } = view.pipeline;
12716
+ const from = fromRunId ?? "unknown";
12717
+ parts.push(`pipeline=step${position} from=${from} in=${inputBytes}b${inputTruncated ? " truncated" : ""}`);
12718
+ }
12719
+ if (view.personaOverride !== void 0) {
12720
+ parts.push(`persona=${formatPersonaHashPrefix(view.personaOverride.promptHash)}`);
12721
+ }
12722
+ if (view.escalation !== void 0) {
12723
+ const { requested, approved, denied, timedOut } = view.escalation;
12724
+ parts.push(`escalations=${requested}req/${approved}appr/${denied}deny/${timedOut}timeout`);
12725
+ }
12726
+ if (view.autonomyEnforcement !== void 0) {
12727
+ const { grade, autonomy, externalMode, dangerousBypass } = view.autonomyEnforcement;
12728
+ const mode = externalMode !== void 0 ? `/${externalMode}` : "";
12729
+ const bypass = dangerousBypass === true ? "/bypass" : "";
12730
+ parts.push(`enforcement=${grade}:${autonomy}${mode}${bypass}`);
12910
12731
  }
12911
- state.writer.replaceEntries(entries);
12732
+ return parts.length === 0 ? "" : ` ${parts.join(" ")}`;
12912
12733
  }
12913
12734
 
12914
- // src/domains/session/tree/fork.ts
12735
+ // src/domains/evidence/run-trust.ts
12915
12736
  init_esm_shims();
12916
12737
 
12917
- // src/domains/session/tree/active-path.ts
12738
+ // src/domains/evidence/trust-status.ts
12918
12739
  init_esm_shims();
12919
- function filterEntriesToActivePath(entries, leafTurnId) {
12920
- const messages = [];
12921
- const messagesById = /* @__PURE__ */ new Map();
12922
- for (const entry of entries) {
12923
- if (entry.kind !== "message") continue;
12924
- messages.push(entry);
12925
- messagesById.set(entry.turnId, entry);
12926
- }
12927
- const latest2 = messages[messages.length - 1];
12928
- const pinnedLeaf = resolveLeafMessage(entries, messagesById, leafTurnId);
12929
- if (!hasBranch(messages) && (pinnedLeaf === void 0 || pinnedLeaf.turnId === latest2?.turnId)) return [...entries];
12930
- const leaf = pinnedLeaf ?? latest2;
12931
- if (!leaf) return [...entries];
12932
- const pathIds = /* @__PURE__ */ new Set();
12933
- let current = leaf;
12934
- while (current && !pathIds.has(current.turnId)) {
12935
- pathIds.add(current.turnId);
12936
- if (current.parentTurnId === null) break;
12937
- current = messagesById.get(current.parentTurnId);
12938
- }
12939
- const leafIndex = entries.findIndex((entry) => entry.kind === "message" && entry.turnId === leaf.turnId);
12940
- return entries.filter((entry, index) => entryBelongsToPath(entry, pathIds, leafIndex >= 0 && index <= leafIndex));
12941
- }
12942
- function resolveLeafMessage(entries, messagesById, leafTurnId) {
12943
- if (leafTurnId === void 0) return void 0;
12944
- const direct = messagesById.get(leafTurnId);
12945
- if (direct) return direct;
12946
- const sidecar = entries.find((entry) => entry.turnId === leafTurnId);
12947
- if (!sidecar) return void 0;
12948
- const anchor = sidecarAnchorTurnId(sidecar);
12949
- return anchor === null ? void 0 : messagesById.get(anchor);
12950
- }
12951
- function sidecarAnchorTurnId(entry) {
12952
- if (entry.kind === "label") return entry.targetTurnId;
12953
- if (entry.kind === "sessionInfo") return entry.targetTurnId ?? entry.parentTurnId;
12954
- if (entry.kind === "compactionSummary" && entry.firstKeptTurnId.length > 0) return entry.firstKeptTurnId;
12955
- return entry.parentTurnId;
12956
- }
12957
- function hasBranch(messages) {
12958
- const seenParents = /* @__PURE__ */ new Set();
12959
- for (const message of messages) {
12960
- if (message.parentTurnId === null) continue;
12961
- if (seenParents.has(message.parentTurnId)) return true;
12962
- seenParents.add(message.parentTurnId);
12963
- }
12964
- return false;
12740
+ var TRUST_STATUS_VERSION = 1;
12741
+ var TRUST_STATUS_MAX_ARTIFACT_REFERENCES = 16;
12742
+ var TRUST_STATUS_MAX_IDENTIFIER_LENGTH = 512;
12743
+ var TRUST_STATUS_AXES = [
12744
+ "artifactIntegrity",
12745
+ "validationGrounding",
12746
+ "independentReview",
12747
+ "contextProvenance",
12748
+ "autonomyEnforcement",
12749
+ "completionEvidence"
12750
+ ];
12751
+ var TRUST_STATUS_STATES = {
12752
+ artifactIntegrity: ["verified", "failed", "absent", "unknown", "not_applicable"],
12753
+ validationGrounding: ["validated", "failed", "ungrounded", "absent", "unknown", "not_applicable"],
12754
+ independentReview: ["passed", "failed", "inconclusive", "not_independent", "absent", "unknown", "not_applicable"],
12755
+ contextProvenance: ["recorded", "invalid", "absent", "unknown", "not_applicable"],
12756
+ autonomyEnforcement: ["enforced", "approximated", "bypassed", "absent", "unknown", "not_applicable"],
12757
+ completionEvidence: ["evidenced", "incomplete", "limited", "absent", "unknown", "not_applicable"]
12758
+ };
12759
+ var SELF_REPORTED_ARTIFACT_KINDS = /* @__PURE__ */ new Set([
12760
+ "finish_contract_evidence",
12761
+ "run_receipt"
12762
+ ]);
12763
+ var AXIS_STATES = {
12764
+ artifactIntegrity: new Set(TRUST_STATUS_STATES.artifactIntegrity),
12765
+ validationGrounding: new Set(TRUST_STATUS_STATES.validationGrounding),
12766
+ independentReview: new Set(TRUST_STATUS_STATES.independentReview),
12767
+ contextProvenance: new Set(TRUST_STATUS_STATES.contextProvenance),
12768
+ autonomyEnforcement: new Set(TRUST_STATUS_STATES.autonomyEnforcement),
12769
+ completionEvidence: new Set(TRUST_STATUS_STATES.completionEvidence)
12770
+ };
12771
+ var AXIS_SOURCES = {
12772
+ artifactIntegrity: /* @__PURE__ */ new Set(["receipt_integrity_verification", "compatibility"]),
12773
+ validationGrounding: /* @__PURE__ */ new Set(["run_receipt", "evidence_bundle", "compatibility"]),
12774
+ independentReview: /* @__PURE__ */ new Set(["gate_decision", "compatibility"]),
12775
+ contextProvenance: /* @__PURE__ */ new Set(["run_receipt", "evidence_bundle", "compatibility"]),
12776
+ autonomyEnforcement: /* @__PURE__ */ new Set(["run_receipt", "compatibility"]),
12777
+ completionEvidence: /* @__PURE__ */ new Set(["finish_contract", "compatibility"])
12778
+ };
12779
+ var SOURCE_AUTHORITIES = {
12780
+ receipt_integrity_verification: /* @__PURE__ */ new Set(["clio"]),
12781
+ run_receipt: /* @__PURE__ */ new Set(["clio", "validator", "runtime", "external_system", "unknown"]),
12782
+ gate_decision: /* @__PURE__ */ new Set(["clio", "reviewer", "operator", "unknown"]),
12783
+ evidence_bundle: /* @__PURE__ */ new Set(["clio"]),
12784
+ finish_contract: /* @__PURE__ */ new Set(["clio"]),
12785
+ compatibility: /* @__PURE__ */ new Set(["clio", "unknown"])
12786
+ };
12787
+ var ABSENCE_REASONS = /* @__PURE__ */ new Set([
12788
+ "not_recorded",
12789
+ "not_observed",
12790
+ "artifact_missing",
12791
+ "historical_format"
12792
+ ]);
12793
+ var SOURCE_KINDS = /* @__PURE__ */ new Set([
12794
+ "receipt_integrity_verification",
12795
+ "run_receipt",
12796
+ "gate_decision",
12797
+ "evidence_bundle",
12798
+ "finish_contract",
12799
+ "compatibility"
12800
+ ]);
12801
+ var AUTHORITY_KINDS = /* @__PURE__ */ new Set([
12802
+ "clio",
12803
+ "validator",
12804
+ "reviewer",
12805
+ "operator",
12806
+ "runtime",
12807
+ "external_system",
12808
+ "unknown"
12809
+ ]);
12810
+ var ARTIFACT_KINDS = /* @__PURE__ */ new Set([
12811
+ "run_receipt",
12812
+ "validation_result",
12813
+ "gate_decision",
12814
+ "briefing",
12815
+ "project_context",
12816
+ "autonomy_policy",
12817
+ "finish_contract_evidence",
12818
+ "evidence_bundle",
12819
+ "session_entry"
12820
+ ]);
12821
+ function isRecord10(value) {
12822
+ return typeof value === "object" && value !== null && !Array.isArray(value);
12965
12823
  }
12966
- function entryBelongsToPath(entry, pathIds, atOrBeforeLeaf) {
12967
- if (entry.kind === "message") return pathIds.has(entry.turnId);
12968
- if (entry.kind === "label") return pathIds.has(entry.targetTurnId);
12969
- if (entry.kind === "sessionInfo") return entry.targetTurnId === void 0 || pathIds.has(entry.targetTurnId);
12970
- if (entry.kind === "compactionSummary" && entry.firstKeptTurnId.length > 0 && pathIds.has(entry.firstKeptTurnId)) {
12971
- return true;
12824
+ function hasExactKeys(value, keys) {
12825
+ const expected = new Set(keys);
12826
+ return Object.keys(value).length === expected.size && Object.keys(value).every((key) => expected.has(key));
12827
+ }
12828
+ function isTrustStatusIdentifier(value) {
12829
+ if (typeof value !== "string" || value.trim().length === 0 || value.length > TRUST_STATUS_MAX_IDENTIFIER_LENGTH) {
12830
+ return false;
12972
12831
  }
12973
- return entry.parentTurnId === null ? atOrBeforeLeaf : pathIds.has(entry.parentTurnId);
12832
+ for (const character of value) {
12833
+ const codePoint = character.codePointAt(0);
12834
+ if (codePoint !== void 0 && (codePoint < 32 || codePoint === 127)) return false;
12835
+ }
12836
+ return true;
12974
12837
  }
12975
-
12976
- // src/domains/session/tree/fork.ts
12977
- function linkedRecordFromEntry(entry) {
12978
- return {
12979
- id: entry.turnId,
12980
- parentId: entry.parentTurnId,
12981
- timestamp: entry.timestamp,
12982
- treeKind: entry.kind === "message" ? entry.role : null,
12983
- raw: entry
12984
- };
12838
+ function compareArtifactReferences(left, right) {
12839
+ const leftKey = `${left.kind}\0${left.id}\0${left.digest?.value ?? ""}`;
12840
+ const rightKey = `${right.kind}\0${right.id}\0${right.digest?.value ?? ""}`;
12841
+ return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0;
12985
12842
  }
12986
- function traceAncestry(records, leafTurnId) {
12987
- const byId = /* @__PURE__ */ new Map();
12988
- for (const record of records) byId.set(record.id, record);
12989
- const path2 = [];
12990
- let current = byId.get(leafTurnId);
12991
- if (!current) throw new Error(`session.fork: parent turn not found: ${leafTurnId}`);
12992
- const seen = /* @__PURE__ */ new Set();
12993
- while (current) {
12994
- if (seen.has(current.id)) throw new Error(`session.fork: cycle in parent chain at ${current.id}`);
12995
- seen.add(current.id);
12996
- path2.unshift(current);
12997
- if (current.parentId === null) break;
12998
- const next = byId.get(current.parentId);
12999
- if (!next) throw new Error(`session.fork: broken parent chain at ${current.id}`);
13000
- current = next;
12843
+ function normalizeArtifactReference(value, path2) {
12844
+ if (!isRecord10(value)) throw new Error(`${path2} must be an object`);
12845
+ if (!hasExactKeys(value, value.digest === void 0 ? ["kind", "id"] : ["kind", "id", "digest"])) {
12846
+ throw new Error(`${path2} has unknown or missing fields`);
13001
12847
  }
13002
- return path2;
13003
- }
13004
- function treeFromLinearPath(path2) {
13005
- return path2.filter((record) => record.treeKind !== null).map((record) => ({
13006
- id: record.id,
13007
- parentId: record.parentId,
13008
- at: record.timestamp,
13009
- kind: record.treeKind
13010
- }));
12848
+ if (typeof value.kind !== "string" || !ARTIFACT_KINDS.has(value.kind)) {
12849
+ throw new Error(`${path2}.kind is invalid`);
12850
+ }
12851
+ if (!isTrustStatusIdentifier(value.id)) throw new Error(`${path2}.id is invalid`);
12852
+ const reference = { kind: value.kind, id: value.id };
12853
+ if (value.digest !== void 0) {
12854
+ if (!isRecord10(value.digest) || !hasExactKeys(value.digest, ["algorithm", "value"]) || value.digest.algorithm !== "sha256" || typeof value.digest.value !== "string" || !/^[a-f0-9]{64}$/u.test(value.digest.value)) {
12855
+ throw new Error(`${path2}.digest is invalid`);
12856
+ }
12857
+ reference.digest = { algorithm: "sha256", value: value.digest.value };
12858
+ }
12859
+ return reference;
13011
12860
  }
13012
- function sessionEntryBelongsToPath(entry, pathIds, atOrBeforeForkPoint) {
13013
- if (entry.kind === "compactionSummary" && !atOrBeforeForkPoint) return false;
13014
- return entryBelongsToPath(entry, pathIds, atOrBeforeForkPoint);
13015
- }
13016
- function branchEntriesFromParent(parentMeta, leafTurnId) {
13017
- const parentCurrentPath = sessionPaths(parentMeta).current;
13018
- const records = readSessionFileEntries(parentCurrentPath).filter((entry) => !isSessionHeader(entry));
13019
- const parsed = collectSessionEntries(records, parentCurrentPath);
13020
- const linked = parsed.map(linkedRecordFromEntry);
13021
- const path2 = traceAncestry(linked, leafTurnId);
13022
- const pathIds = new Set(path2.map((record) => record.id));
13023
- const forkPointIndex = parsed.findIndex((entry) => linkedRecordFromEntry(entry).id === leafTurnId);
13024
- const entries = parsed.filter(
13025
- (entry, index) => sessionEntryBelongsToPath(entry, pathIds, forkPointIndex >= 0 && index <= forkPointIndex)
12861
+ function normalizeAttributedStatus(axis, value) {
12862
+ if (!hasExactKeys(value, ["state", "source", "authority", "artifacts"])) {
12863
+ throw new Error(`${axis} has unknown or missing fields`);
12864
+ }
12865
+ if (!isRecord10(value.source) || !hasExactKeys(value.source, ["kind", "id"])) {
12866
+ throw new Error(`${axis}.source is invalid`);
12867
+ }
12868
+ if (typeof value.source.kind !== "string" || !SOURCE_KINDS.has(value.source.kind) || !AXIS_SOURCES[axis].has(value.source.kind) || !isTrustStatusIdentifier(value.source.id)) {
12869
+ throw new Error(`${axis}.source is invalid`);
12870
+ }
12871
+ if (!isRecord10(value.authority) || !hasExactKeys(value.authority, ["kind", "id"])) {
12872
+ throw new Error(`${axis}.authority is invalid`);
12873
+ }
12874
+ if (typeof value.authority.kind !== "string" || !AUTHORITY_KINDS.has(value.authority.kind) || !SOURCE_AUTHORITIES[value.source.kind].has(
12875
+ value.authority.kind
12876
+ ) || !isTrustStatusIdentifier(value.authority.id)) {
12877
+ throw new Error(`${axis}.authority is invalid`);
12878
+ }
12879
+ if (value.source.kind === "compatibility" && value.state !== "unknown" && value.state !== "not_applicable") {
12880
+ throw new Error(`${axis} compatibility source cannot establish ${value.state}`);
12881
+ }
12882
+ if (!Array.isArray(value.artifacts) || value.artifacts.length > TRUST_STATUS_MAX_ARTIFACT_REFERENCES) {
12883
+ throw new Error(`${axis}.artifacts exceeds the bounded reference list`);
12884
+ }
12885
+ const artifacts = value.artifacts.map(
12886
+ (entry, index) => normalizeArtifactReference(entry, `${axis}.artifacts[${index}]`)
13026
12887
  );
12888
+ artifacts.sort(compareArtifactReferences);
12889
+ for (let index = 1; index < artifacts.length; index += 1) {
12890
+ if (compareArtifactReferences(
12891
+ artifacts[index - 1],
12892
+ artifacts[index]
12893
+ ) === 0) {
12894
+ throw new Error(`${axis}.artifacts contains a duplicate reference`);
12895
+ }
12896
+ }
13027
12897
  return {
13028
- parentCurrentPath,
13029
- entries,
13030
- tree: treeFromLinearPath(path2)
12898
+ state: value.state,
12899
+ source: { kind: value.source.kind, id: value.source.id },
12900
+ authority: { kind: value.authority.kind, id: value.authority.id },
12901
+ artifacts
13031
12902
  };
13032
12903
  }
13033
- function forkFromState(input) {
13034
- const parentMeta = input.from.meta;
13035
- input.from.writer.flushAppends();
13036
- const branch = branchEntriesFromParent(parentMeta, input.parentTurnId);
13037
- const cwd = input.cwd ?? parentMeta.cwd;
13038
- const next = startSession({
13039
- cwd,
13040
- model: parentMeta.model,
13041
- target: parentMeta.target,
13042
- initialEntries: branch.entries,
13043
- initialTree: branch.tree,
13044
- parentSession: branch.parentCurrentPath,
13045
- parentTurnId: input.parentTurnId
13046
- });
13047
- enrichForkMeta(next.meta, parentMeta.id, input.parentTurnId);
13048
- void input.from.writer.close();
13049
- return { next, parentMeta, nodes: branch.tree };
13050
- }
13051
-
13052
- // src/domains/session/tree/manager.ts
13053
- init_esm_shims();
13054
- import { existsSync as existsSync15, renameSync as renameSync5, rmSync as rmSync4 } from "node:fs";
13055
- import { dirname as dirname3, join as join16 } from "node:path";
13056
- function readTreeBundle(sessionId) {
13057
- const reader = openSession(sessionId);
13058
- const meta = reader.meta();
13059
- const paths = sessionPaths(meta);
13060
- const nodes = [...reader.tree()];
13061
- const entries = collectSessionEntries(reader.turns(), paths.current);
13062
- const labels = resolveLabelMap(entries);
13063
- return { sessionId, meta, nodes, entries, labels };
13064
- }
13065
- function resolveLabelMap(entries) {
13066
- const out = /* @__PURE__ */ new Map();
13067
- for (const entry of entries) {
13068
- const info = labelFields(entry);
13069
- if (!info) continue;
13070
- const existing = out.get(info.targetTurnId);
13071
- if (existing && existing.timestamp > info.timestamp) continue;
13072
- if (info.label === void 0 || info.label === "") {
13073
- out.set(info.targetTurnId, { label: "", timestamp: info.timestamp });
13074
- continue;
12904
+ function normalizeAxis(axis, value) {
12905
+ if (!isRecord10(value) || typeof value.state !== "string" || !AXIS_STATES[axis].has(value.state)) {
12906
+ throw new Error(`${axis}.state is invalid`);
12907
+ }
12908
+ if (value.state === "absent") {
12909
+ if (!hasExactKeys(value, ["state", "reason"]) || typeof value.reason !== "string" || !ABSENCE_REASONS.has(value.reason)) {
12910
+ throw new Error(`${axis} absent state is invalid`);
13075
12911
  }
13076
- out.set(info.targetTurnId, { label: info.label, timestamp: info.timestamp });
12912
+ return { state: "absent", reason: value.reason };
13077
12913
  }
13078
- return out;
13079
- }
13080
- function labelFields(entry) {
13081
- if (entry.kind === "label") return entry;
13082
- if (entry.kind !== "sessionInfo") return null;
13083
- const info = entry;
13084
- if (!info.targetTurnId) return null;
13085
- const out = {
13086
- targetTurnId: info.targetTurnId,
13087
- timestamp: info.timestamp
13088
- };
13089
- if (info.label !== void 0) out.label = info.label;
13090
- return out;
13091
- }
13092
- function appendEntryToSessionFile(sessionId, entry) {
13093
- const meta = readSessionMeta(sessionId);
13094
- const paths = sessionPaths(meta);
13095
- appendSessionFileEntry(paths.current, entry);
13096
- }
13097
- function removeSessionDirectory(sessionId) {
13098
- const meta = readSessionMeta(sessionId);
13099
- const paths = sessionPaths(meta);
13100
- const dir = dirname3(paths.meta);
13101
- rmSync4(dir, { recursive: true, force: true });
13102
- }
13103
- function tombstoneSession(sessionId) {
13104
- const meta = readSessionMeta(sessionId);
13105
- const paths = sessionPaths(meta);
13106
- if (!existsSync15(paths.meta)) return;
13107
- const tombstone = join16(dirname3(paths.meta), "meta.deleted.json");
13108
- renameSync5(paths.meta, tombstone);
13109
- }
13110
-
13111
- // src/domains/session/tree/navigator.ts
13112
- init_esm_shims();
13113
- function pickMeta(meta) {
13114
- const out = {
13115
- id: meta.id,
13116
- cwd: meta.cwd,
13117
- createdAt: meta.createdAt,
13118
- endedAt: meta.endedAt,
13119
- model: meta.model,
13120
- target: meta.target
13121
- };
13122
- if (meta.parentSessionId !== void 0) out.parentSessionId = meta.parentSessionId;
13123
- if (meta.parentTurnId !== void 0) out.parentTurnId = meta.parentTurnId;
13124
- return out;
12914
+ return normalizeAttributedStatus(axis, value);
13125
12915
  }
13126
- function computeLeafId(nodes) {
13127
- if (nodes.length === 0) return null;
13128
- const hasChild = /* @__PURE__ */ new Set();
13129
- for (const node of nodes) {
13130
- if (node.parentId) hasChild.add(node.parentId);
12916
+ function normalizeTrustStatus(value) {
12917
+ if (!isRecord10(value) || !hasExactKeys(value, ["version", ...TRUST_STATUS_AXES])) {
12918
+ throw new Error("trust status has unknown or missing fields");
13131
12919
  }
13132
- let leaf = null;
13133
- for (const node of nodes) {
13134
- if (hasChild.has(node.id)) continue;
13135
- if (!leaf || node.at >= leaf.at) leaf = node;
12920
+ if (value.version !== TRUST_STATUS_VERSION) throw new Error("trust status version is invalid");
12921
+ return {
12922
+ version: TRUST_STATUS_VERSION,
12923
+ artifactIntegrity: normalizeAxis("artifactIntegrity", value.artifactIntegrity),
12924
+ validationGrounding: normalizeAxis("validationGrounding", value.validationGrounding),
12925
+ independentReview: normalizeAxis("independentReview", value.independentReview),
12926
+ contextProvenance: normalizeAxis("contextProvenance", value.contextProvenance),
12927
+ autonomyEnforcement: normalizeAxis("autonomyEnforcement", value.autonomyEnforcement),
12928
+ completionEvidence: normalizeAxis("completionEvidence", value.completionEvidence)
12929
+ };
12930
+ }
12931
+ function absentTrustStatus(reason) {
12932
+ return { state: "absent", reason };
12933
+ }
12934
+ function composeTrustStatus(...projections) {
12935
+ const axes = {
12936
+ artifactIntegrity: absentTrustStatus("not_recorded"),
12937
+ validationGrounding: absentTrustStatus("not_recorded"),
12938
+ independentReview: absentTrustStatus("not_recorded"),
12939
+ contextProvenance: absentTrustStatus("not_recorded"),
12940
+ autonomyEnforcement: absentTrustStatus("not_recorded"),
12941
+ completionEvidence: absentTrustStatus("not_recorded")
12942
+ };
12943
+ for (const projection of projections) {
12944
+ if (projection.artifactIntegrity !== void 0) axes.artifactIntegrity = projection.artifactIntegrity;
12945
+ if (projection.validationGrounding !== void 0) axes.validationGrounding = projection.validationGrounding;
12946
+ if (projection.independentReview !== void 0) axes.independentReview = projection.independentReview;
12947
+ if (projection.contextProvenance !== void 0) axes.contextProvenance = projection.contextProvenance;
12948
+ if (projection.autonomyEnforcement !== void 0) axes.autonomyEnforcement = projection.autonomyEnforcement;
12949
+ if (projection.completionEvidence !== void 0) axes.completionEvidence = projection.completionEvidence;
12950
+ }
12951
+ return normalizeTrustStatus({ version: TRUST_STATUS_VERSION, ...axes });
12952
+ }
12953
+ function sha256Reference(kind, id, digest) {
12954
+ const reference = { kind, id };
12955
+ if (digest !== void 0 && /^[a-f0-9]{64}$/u.test(digest)) {
12956
+ reference.digest = { algorithm: "sha256", value: digest };
12957
+ }
12958
+ return reference;
12959
+ }
12960
+ function receiptReference(receipt) {
12961
+ return sha256Reference("run_receipt", receipt.runId, receipt.integrity?.digest);
12962
+ }
12963
+ function attributed(state, source, authority, artifacts) {
12964
+ return { state, source, authority, artifacts: [...artifacts].sort(compareArtifactReferences) };
12965
+ }
12966
+ function receiptSource(receipt) {
12967
+ return { kind: "run_receipt", id: receipt.runId };
12968
+ }
12969
+ function compatibilitySource(receipt, field) {
12970
+ return { kind: "compatibility", id: `run_receipt:${receipt.runId}:${field}` };
12971
+ }
12972
+ var DISPATCH_AUTHORITY = { kind: "clio", id: "dispatch" };
12973
+ var COMPATIBILITY_AUTHORITY = { kind: "unknown", id: "historical-persisted-format" };
12974
+ function adaptReceiptIntegrityStatus(receipt, verification) {
12975
+ if (receipt === null || receipt === void 0) return absentTrustStatus("artifact_missing");
12976
+ const artifacts = [receiptReference(receipt)];
12977
+ if (verification === void 0 || verification.ok && receipt.integrity === void 0) {
12978
+ return attributed(
12979
+ "unknown",
12980
+ {
12981
+ kind: "compatibility",
12982
+ id: `run_receipt:${receipt.runId}:${receipt.integrity === void 0 ? "integrity-missing" : "integrity-unchecked"}`
12983
+ },
12984
+ COMPATIBILITY_AUTHORITY,
12985
+ artifacts
12986
+ );
13136
12987
  }
13137
- return leaf?.id ?? null;
12988
+ return attributed(
12989
+ verification.ok ? "verified" : "failed",
12990
+ { kind: "receipt_integrity_verification", id: receipt.runId },
12991
+ { kind: "clio", id: "receipt-integrity" },
12992
+ artifacts
12993
+ );
13138
12994
  }
13139
- function buildTreeSnapshot(input) {
13140
- const nodesById = {};
13141
- for (const node of input.nodes) {
13142
- const entry = {
13143
- id: node.id,
13144
- parentId: node.parentId,
13145
- at: node.at,
13146
- kind: node.kind,
13147
- children: []
13148
- };
13149
- const resolved = input.labels.get(node.id);
13150
- if (resolved && resolved.label !== "") entry.label = resolved.label;
13151
- const preview = input.previews?.get(node.id);
13152
- if (preview !== void 0 && preview.length > 0) entry.preview = preview;
13153
- nodesById[node.id] = entry;
13154
- }
13155
- const rootIds = [];
13156
- for (const node of input.nodes) {
13157
- const parent = node.parentId ? nodesById[node.parentId] : void 0;
13158
- if (!parent) {
13159
- rootIds.push(node.id);
13160
- } else {
13161
- parent.children.push(node.id);
13162
- }
12995
+ function validationArtifacts(receipt) {
12996
+ const artifacts = [receiptReference(receipt)];
12997
+ for (const fact of receipt.quality?.typedValidations ?? []) {
12998
+ artifacts.push(sha256Reference("validation_result", fact.sourceId, fact.validatorDigest));
13163
12999
  }
13164
- const byTime = (a, b) => {
13165
- const na = nodesById[a];
13166
- const nb = nodesById[b];
13167
- if (!na || !nb) return a < b ? -1 : a > b ? 1 : 0;
13168
- if (na.at === nb.at) return na.id < nb.id ? -1 : na.id > nb.id ? 1 : 0;
13169
- return na.at < nb.at ? -1 : 1;
13170
- };
13171
- rootIds.sort(byTime);
13172
- for (const key of Object.keys(nodesById)) {
13173
- const entry = nodesById[key];
13174
- if (entry) entry.children.sort(byTime);
13000
+ const resultContract = receipt.quality?.resultContract;
13001
+ if (resultContract !== null && resultContract !== void 0) {
13002
+ artifacts.push(sha256Reference("validation_result", resultContract.sourceId, resultContract.validatorDigest));
13175
13003
  }
13176
- const leafId = input.leafId !== void 0 ? input.leafId : computeLeafId(input.nodes);
13177
- return {
13178
- sessionId: input.meta.id,
13179
- meta: pickMeta(input.meta),
13180
- leafId,
13181
- nodesById,
13182
- rootIds
13183
- };
13184
- }
13185
-
13186
- // src/domains/session/tree/preview.ts
13187
- init_esm_shims();
13188
- var TURN_PREVIEW_MAX_CHARS = 60;
13189
- var ESC = String.fromCharCode(27);
13190
- var ANSI_CSI_RE = new RegExp(`${ESC}\\[[0-9;?]*[ -/]*[@-~]`, "g");
13191
- var ANSI_FALLBACK_RE = new RegExp(`${ESC}[@-_]`, "g");
13192
- function stripAnsi(text) {
13193
- return text.replace(ANSI_CSI_RE, "").replace(ANSI_FALLBACK_RE, "");
13194
- }
13195
- function collapseSingleLine(text) {
13196
- return text.replace(/\s+/g, " ").trim();
13004
+ return uniqueBoundedReferences(artifacts);
13197
13005
  }
13198
- function sanitize(text) {
13199
- return collapseSingleLine(stripTokenizerSentinels(stripAnsi(text)));
13006
+ function qualityHasFailure(quality) {
13007
+ if (quality === void 0) return false;
13008
+ if (quality.typedValidations.some((fact) => !fact.passed)) return true;
13009
+ return quality.resultContract?.conformance === "fail" || quality.resultContract?.quality === "fail";
13200
13010
  }
13201
- function clamp(text, max) {
13202
- if (text.length <= max) return text;
13203
- if (max <= 1) return text.slice(0, max);
13204
- return `${text.slice(0, max - 1)}\u2026`;
13011
+ function qualityHasValidation(quality) {
13012
+ if (quality === void 0) return false;
13013
+ if (quality.typedValidations.some((fact) => fact.passed)) return true;
13014
+ return quality.resultContract?.quality === "pass";
13205
13015
  }
13206
- function extractPlainText(payload) {
13207
- if (typeof payload === "string") {
13208
- const sanitized = sanitize(payload);
13209
- return sanitized.length > 0 ? sanitized : null;
13016
+ function verificationStatus(verification, receipt, artifacts) {
13017
+ if (verification.state === "verified") {
13018
+ return attributed("validated", receiptSource(receipt), { kind: "validator", id: verification.basis }, artifacts);
13210
13019
  }
13211
- if (!payload || typeof payload !== "object") return null;
13212
- const obj = payload;
13213
- if (typeof obj.text === "string") {
13214
- const sanitized = sanitize(obj.text);
13215
- if (sanitized.length > 0) return sanitized;
13216
- }
13217
- if (Array.isArray(obj.content)) {
13218
- const parts = [];
13219
- for (const block of obj.content) {
13220
- if (!block || typeof block !== "object") continue;
13221
- const b = block;
13222
- if (b.type === "text" && typeof b.text === "string") parts.push(b.text);
13223
- }
13224
- if (parts.length > 0) {
13225
- const sanitized = sanitize(parts.join(" "));
13226
- if (sanitized.length > 0) return sanitized;
13227
- }
13020
+ if (verification.state === "unverified") return absentTrustStatus("not_observed");
13021
+ if (verification.state === "not_applicable") {
13022
+ return attributed("not_applicable", receiptSource(receipt), DISPATCH_AUTHORITY, artifacts);
13228
13023
  }
13229
- return null;
13024
+ return attributed(
13025
+ "unknown",
13026
+ receiptSource(receipt),
13027
+ verification.basis === "acp-external-unobserved" ? { kind: "external_system", id: "acp-delegation" } : COMPATIBILITY_AUTHORITY,
13028
+ artifacts
13029
+ );
13230
13030
  }
13231
- function pickToolArg(toolName, args) {
13232
- if (!args || typeof args !== "object") return "";
13233
- const a = args;
13234
- const preferred = {
13235
- read: ["path"],
13236
- write: ["path"],
13237
- edit: ["path"],
13238
- bash: ["command"],
13239
- code_nav: ["query", "mode"],
13240
- git: ["op"],
13241
- verify: ["check"],
13242
- grep: ["pattern", "query"],
13243
- search: ["query", "pattern"],
13244
- web_fetch: ["url"],
13245
- web_search: ["query"]
13246
- };
13247
- const order = preferred[toolName] ?? [];
13248
- for (const key of order) {
13249
- const value = a[key];
13250
- if (typeof value === "string" && value.length > 0) return sanitize(value);
13251
- if (typeof value === "number") return String(value);
13031
+ function adaptRunReceiptValidationStatus(receipt) {
13032
+ if (receipt === null || receipt === void 0) return absentTrustStatus("artifact_missing");
13033
+ const artifacts = validationArtifacts(receipt);
13034
+ if (qualityHasFailure(receipt.quality)) {
13035
+ return attributed("failed", receiptSource(receipt), { kind: "validator", id: "receipt-quality" }, artifacts);
13252
13036
  }
13253
- for (const [, value] of Object.entries(a)) {
13254
- if (typeof value === "string" && value.length > 0) return sanitize(value);
13255
- if (typeof value === "number" || typeof value === "boolean") return String(value);
13037
+ if ((receipt.validationGrounding?.ungrounded.length ?? 0) > 0 || receipt.validationGrounding !== void 0 && receipt.validationGrounding.claimed > receipt.validationGrounding.grounded) {
13038
+ return attributed("ungrounded", receiptSource(receipt), { kind: "validator", id: "command-grounding" }, artifacts);
13256
13039
  }
13257
- return "";
13258
- }
13259
- function extractToolCall(payload) {
13260
- if (!payload || typeof payload !== "object") return null;
13261
- const p = payload;
13262
- const toolName = typeof p.name === "string" ? p.name : typeof p.toolName === "string" ? p.toolName : null;
13263
- if (!toolName) return null;
13264
- const args = p.args !== void 0 ? p.args : p.arguments ?? p.input;
13265
- return { toolName, args };
13266
- }
13267
- function extractToolResult(payload) {
13268
- if (!payload || typeof payload !== "object") return null;
13269
- const p = payload;
13270
- if (!("toolCallId" in p) && !("result" in p) && !("isError" in p)) return null;
13271
- const isError = p.isError === true;
13272
- let text = "";
13273
- const result = p.result;
13274
- if (typeof result === "string") text = result;
13275
- else if (result && typeof result === "object") {
13276
- const r = result;
13277
- if (Array.isArray(r.content)) {
13278
- const parts = [];
13279
- for (const block of r.content) {
13280
- if (!block || typeof block !== "object") continue;
13281
- const b = block;
13282
- if (b.type === "text" && typeof b.text === "string") parts.push(b.text);
13283
- }
13284
- text = parts.join(" ");
13285
- } else if (typeof r.text === "string") {
13286
- text = r.text;
13287
- }
13040
+ if (qualityHasValidation(receipt.quality)) {
13041
+ return attributed("validated", receiptSource(receipt), { kind: "validator", id: "receipt-quality" }, artifacts);
13288
13042
  }
13289
- if (text.length === 0 && typeof p.errorMessage === "string") text = p.errorMessage;
13290
- return { isError, text: sanitize(text) };
13043
+ if (receipt.verification !== void 0) return verificationStatus(receipt.verification, receipt, artifacts);
13044
+ return attributed("unknown", compatibilitySource(receipt, "verification"), COMPATIBILITY_AUTHORITY, artifacts);
13291
13045
  }
13292
- function assistantStopMarker(payload) {
13293
- if (!payload || typeof payload !== "object") return null;
13294
- const sr = payload.stopReason;
13295
- if (sr === "aborted") return "(aborted)";
13296
- if (sr === "error") return "(error)";
13297
- return null;
13046
+ function validBriefing(briefing) {
13047
+ return Number.isSafeInteger(briefing.bytes) && briefing.bytes >= 0 && /^[a-f0-9]{64}$/u.test(briefing.contentHash);
13298
13048
  }
13299
- function buildTurnPreview(turn, max = TURN_PREVIEW_MAX_CHARS) {
13300
- const budget = Math.max(1, max);
13301
- switch (turn.kind) {
13302
- case "user": {
13303
- const text = extractPlainText(turn.payload);
13304
- return text === null ? "(empty)" : clamp(text, budget);
13305
- }
13306
- case "assistant": {
13307
- const stop = assistantStopMarker(turn.payload);
13308
- const text = extractPlainText(turn.payload);
13309
- if (text !== null) return clamp(text, budget);
13310
- if (stop !== null) return stop;
13311
- if (turn.payload && typeof turn.payload === "object" && Array.isArray(turn.payload.content)) {
13312
- const content = turn.payload.content;
13313
- const toolCalls = content.filter(
13314
- (b) => b && typeof b === "object" && b.type === "toolCall"
13315
- );
13316
- if (toolCalls.length > 0) {
13317
- const names = toolCalls.map((b) => b.name).filter((n) => typeof n === "string");
13318
- if (names.length > 0) return clamp(`(tool calls) ${names.join(", ")}`, budget);
13319
- }
13320
- }
13321
- return "(empty)";
13322
- }
13323
- case "tool_call": {
13324
- const call = extractToolCall(turn.payload);
13325
- if (!call) return "(empty)";
13326
- const arg = pickToolArg(call.toolName, call.args);
13327
- const inner = arg.length > 0 ? `"${clamp(arg, Math.max(8, budget - call.toolName.length - 4))}"` : "";
13328
- const composed = `${call.toolName}(${inner})`;
13329
- return clamp(composed, budget);
13330
- }
13331
- case "tool_result": {
13332
- const result = extractToolResult(turn.payload);
13333
- if (!result) return "(empty)";
13334
- const status = result.isError ? "err" : "ok";
13335
- const head = `[${status}]`;
13336
- if (result.text.length === 0) return head;
13337
- const remaining = Math.max(4, budget - head.length - 1);
13338
- return `${head} ${clamp(result.text, remaining)}`;
13339
- }
13340
- case "system": {
13341
- const text = extractPlainText(turn.payload);
13342
- return text === null ? "(system)" : clamp(text, budget);
13343
- }
13344
- case "checkpoint":
13345
- return "(checkpoint)";
13346
- default:
13347
- return `(${String(turn.kind)})`;
13348
- }
13049
+ function validBoundedProjectContext(context) {
13050
+ return context.tier === "bounded" && Number.isSafeInteger(context.chars) && (context.chars ?? -1) >= 0 && typeof context.contentHash === "string" && /^[a-f0-9]{64}$/u.test(context.contentHash);
13349
13051
  }
13350
-
13351
- // src/domains/session/extension.ts
13352
- function createSessionBundle(context) {
13353
- let state = null;
13354
- let currentTurnId = null;
13355
- function emitPark(sessionId, reason) {
13356
- context.bus.emit(BusChannels.SessionParked, { sessionId, reason, at: Date.now() });
13357
- }
13358
- function emitResume(sessionId, via) {
13359
- context.bus.emit(BusChannels.SessionResumed, { sessionId, via, at: Date.now() });
13360
- }
13361
- function emitTurnSwitched(sessionId, turnId) {
13362
- context.bus.emit(BusChannels.SessionTurnSwitched, { sessionId, turnId, at: Date.now() });
13363
- }
13364
- function resolveLeafOnOpen(resumed) {
13365
- const pinned = resumed.state.meta.pinnedLeafTurnId;
13366
- if (pinned && resumed.nodes.some((node) => node.id === pinned)) return pinned;
13367
- return computeLeafId(resumed.nodes);
13368
- }
13369
- async function closeCurrent(reason = "close") {
13370
- if (!state) return;
13371
- const s = state;
13372
- emitPark(s.meta.id, reason);
13373
- state = null;
13374
- currentTurnId = null;
13375
- await s.writer.close();
13376
- }
13377
- async function flushIfCurrent(sessionId) {
13378
- if (state?.meta.id === sessionId) {
13379
- await state.writer.persistTree();
13380
- }
13381
- }
13382
- function structuralTreeNodes(entries, previews) {
13383
- const nodes = [];
13384
- for (const entry of entries) {
13385
- if (entry.kind === "compactionSummary") {
13386
- nodes.push({ id: entry.turnId, parentId: entry.parentTurnId, at: entry.timestamp, kind: "compaction" });
13387
- const summarized = entry.messagesSummarized === void 0 ? "history" : `${entry.messagesSummarized} entries`;
13388
- const after = entry.tokensAfter === void 0 ? "" : ` -> ~${entry.tokensAfter}`;
13389
- previews.set(entry.turnId, `${summarized} summarized, ~${entry.tokensBefore}${after} tokens`);
13390
- continue;
13391
- }
13392
- if (entry.kind === "branchSummary") {
13393
- nodes.push({ id: entry.turnId, parentId: entry.parentTurnId, at: entry.timestamp, kind: "branch" });
13394
- const text = entry.summary.split("\n", 1)[0] ?? "";
13395
- previews.set(
13396
- entry.turnId,
13397
- text.length > 0 ? `returned from ${entry.fromTurnId}: ${text}` : `returned from ${entry.fromTurnId}`
13398
- );
13399
- }
13400
- }
13401
- return nodes;
13052
+ function contextArtifacts(receipt) {
13053
+ const artifacts = [receiptReference(receipt)];
13054
+ if (receipt.briefing !== void 0 && validBriefing(receipt.briefing)) {
13055
+ artifacts.push(sha256Reference("briefing", `${receipt.runId}:briefing`, receipt.briefing.contentHash));
13402
13056
  }
13403
- function snapshotFor(sessionId) {
13404
- const bundle = readTreeBundle(sessionId);
13405
- const meta = state?.meta.id === sessionId ? state.meta : bundle.meta;
13406
- const previews = /* @__PURE__ */ new Map();
13407
- let structural = [];
13408
- try {
13409
- for (const entry of bundle.entries) {
13410
- if (entry.kind !== "message") continue;
13411
- const text = buildTurnPreview({ kind: entry.role, payload: entry.payload });
13412
- if (text.length > 0) previews.set(entry.turnId, text);
13413
- }
13414
- structural = structuralTreeNodes(bundle.entries, previews);
13415
- } catch {
13416
- }
13417
- const persistedLeaf = bundle.meta.pinnedLeafTurnId && bundle.nodes.some((node) => node.id === bundle.meta.pinnedLeafTurnId) ? bundle.meta.pinnedLeafTurnId : computeLeafId(bundle.nodes);
13418
- return buildTreeSnapshot({
13419
- meta,
13420
- nodes: [...bundle.nodes, ...structural],
13421
- labels: bundle.labels,
13422
- previews,
13423
- // The leaf is the next append point, so it is computed over turn nodes
13424
- // only: a structural node marks a moment in the timeline, never a place
13425
- // the session continues from.
13426
- leafId: state?.meta.id === sessionId ? currentTurnId : persistedLeaf
13427
- });
13057
+ if (receipt.projectContext?.tier === "bounded" && validBoundedProjectContext(receipt.projectContext)) {
13058
+ artifacts.push(
13059
+ sha256Reference("project_context", `${receipt.runId}:project-context`, receipt.projectContext.contentHash)
13060
+ );
13428
13061
  }
13429
- const contract = {
13430
- current: () => state?.meta ?? null,
13431
- create(input) {
13432
- const cwd = input?.cwd ?? process.cwd();
13433
- const startInput = { cwd };
13434
- if (input?.model !== void 0) startInput.model = input.model;
13435
- if (input?.target !== void 0) startInput.target = input.target;
13436
- if (state) {
13437
- const prior = state;
13438
- emitPark(prior.meta.id, "create_new");
13439
- state = null;
13440
- void prior.writer.close();
13441
- }
13442
- const next = startSession(startInput);
13443
- next.meta.workspace = probeWorkspace(cwd);
13444
- persistSessionMeta(next);
13445
- state = next;
13446
- currentTurnId = null;
13447
- return next.meta;
13448
- },
13449
- append(turn) {
13450
- if (!state) throw new Error("session.append: no current session");
13451
- if (turn.parentId !== currentTurnId) {
13452
- throw new Error(
13453
- `session.append: turn parentId ${turn.parentId ?? "null"} is not this session's current leaf (expected ${currentTurnId ?? "null"}); refusing to parent a turn onto another session's turn`
13454
- );
13455
- }
13456
- const record = appendTurn(state, turn);
13457
- currentTurnId = record.id;
13458
- if (state.meta.pinnedLeafTurnId !== void 0 && state.meta.pinnedLeafTurnId !== null) {
13459
- state.meta.pinnedLeafTurnId = null;
13460
- persistSessionMeta(state);
13461
- }
13462
- return record;
13463
- },
13464
- appendEntry(entry) {
13465
- if (!state) throw new Error("session.appendEntry: no current session");
13466
- return appendEntry(state, entry);
13467
- },
13468
- replaceEntries(entries) {
13469
- if (!state) throw new Error("session.replaceEntries: no current session");
13470
- replaceEntries(state, entries);
13471
- },
13472
- recordSkillActivation(activation) {
13473
- if (!state) throw new Error("session.recordSkillActivation: no current session");
13474
- appendEntry(state, {
13475
- kind: "skillActivation",
13476
- parentTurnId: activation.turnId ?? null,
13477
- activation
13478
- });
13479
- const existing = state.meta.skillActivations ?? [];
13480
- state.meta.skillActivations = [...existing, activation];
13481
- persistSessionMeta(state);
13482
- return activation;
13483
- },
13484
- async checkpoint(reason) {
13485
- if (!state) throw new Error("session.checkpoint: no current session");
13486
- await performCheckpoint(state, reason);
13487
- },
13488
- flushAppends() {
13489
- if (!state) throw new Error("session.flushAppends: no current session");
13490
- state.writer.flushAppends();
13491
- },
13492
- resume(sessionId) {
13493
- if (state && state.meta.id === sessionId) return state.meta;
13494
- const resumed = resumeSessionState(sessionId);
13495
- if (state) {
13496
- const prior = state;
13497
- emitPark(prior.meta.id, "resume_other");
13498
- void prior.writer.close();
13499
- }
13500
- state = resumed.state;
13501
- currentTurnId = resolveLeafOnOpen(resumed);
13502
- emitResume(resumed.state.meta.id, "resume");
13503
- return resumed.state.meta;
13504
- },
13505
- fork(parentTurnId, input) {
13506
- if (!state) throw new Error("session.fork: no current session to fork from");
13507
- const prior = state;
13508
- const { next, nodes } = forkFromState({
13509
- from: prior,
13510
- parentTurnId,
13511
- ...input?.cwd !== void 0 ? { cwd: input.cwd } : {}
13512
- });
13513
- emitPark(prior.meta.id, "fork");
13514
- state = next;
13515
- currentTurnId = computeLeafId(nodes);
13516
- return next.meta;
13517
- },
13518
- tree(sessionId) {
13519
- const id = sessionId ?? state?.meta.id;
13520
- if (!id) throw new Error("session.tree: no sessionId provided and no current session");
13521
- if (state?.meta.id === id) void flushIfCurrent(id);
13522
- return snapshotFor(id);
13523
- },
13524
- switchBranch(sessionId) {
13525
- if (state?.meta.id === sessionId) return state.meta;
13526
- const resumed = resumeSessionState(sessionId);
13527
- if (state) {
13528
- const prior = state;
13529
- emitPark(prior.meta.id, "switch_branch");
13530
- void prior.writer.close();
13531
- }
13532
- state = resumed.state;
13533
- currentTurnId = resolveLeafOnOpen(resumed);
13534
- emitResume(resumed.state.meta.id, "switch_branch");
13535
- return resumed.state.meta;
13536
- },
13537
- switchTurn(turnId) {
13538
- if (!state) throw new Error("session.switchTurn: no current session");
13539
- void flushIfCurrent(state.meta.id);
13540
- const nodes = readTreeBundle(state.meta.id).nodes;
13541
- if (!nodes.some((node) => node.id === turnId)) {
13542
- throw new Error(`session.switchTurn: turn not found: ${turnId}`);
13543
- }
13544
- currentTurnId = turnId;
13545
- state.meta.pinnedLeafTurnId = turnId;
13546
- persistSessionMeta(state);
13547
- emitTurnSwitched(state.meta.id, turnId);
13548
- return state.meta;
13549
- },
13550
- editLabel(turnId, label, sessionId) {
13551
- const targetId = sessionId ?? state?.meta.id;
13552
- if (!targetId) throw new Error("session.editLabel: no sessionId provided and no current session");
13553
- if (state && state.meta.id === targetId) {
13554
- appendEntry(state, {
13555
- kind: "label",
13556
- parentTurnId: null,
13557
- targetTurnId: turnId,
13558
- label
13559
- });
13560
- return;
13561
- }
13562
- const entry = {
13563
- kind: "label",
13564
- turnId: newTurnId(),
13565
- parentTurnId: null,
13566
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13567
- targetTurnId: turnId,
13568
- label
13569
- };
13570
- appendEntryToSessionFile(targetId, entry);
13571
- },
13572
- setName(name, sessionId) {
13573
- const targetId = sessionId ?? state?.meta.id;
13574
- if (!targetId) throw new Error("session.setName: no sessionId provided and no current session");
13575
- if (state && state.meta.id === targetId) {
13576
- appendEntry(state, {
13577
- kind: "sessionInfo",
13578
- parentTurnId: null,
13579
- name
13580
- });
13581
- return;
13582
- }
13583
- const entry = {
13584
- kind: "sessionInfo",
13585
- turnId: newTurnId(),
13586
- parentTurnId: null,
13587
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13588
- name
13589
- };
13590
- appendEntryToSessionFile(targetId, entry);
13591
- },
13592
- deleteSession(id, opts) {
13593
- if (state?.meta.id === id) {
13594
- throw new Error("session.deleteSession: refusing to delete the currently open session; close() first");
13595
- }
13596
- const options = opts ?? {};
13597
- if (options.keepFiles) {
13598
- tombstoneSession(id);
13599
- } else {
13600
- removeSessionDirectory(id);
13601
- }
13602
- },
13603
- history() {
13604
- const cwd = state?.meta.cwd ?? process.cwd();
13605
- return listSessionsForCwd(cwd);
13606
- },
13607
- async close() {
13608
- await closeCurrent();
13609
- }
13610
- };
13611
- const extension = {
13612
- async start() {
13613
- },
13614
- async stop() {
13615
- if (!state) return;
13616
- try {
13617
- await performCheckpoint(state, "shutdown");
13618
- } catch (err) {
13619
- process.stderr.write(
13620
- `[clio:session] shutdown checkpoint failed: ${err instanceof Error ? err.message : String(err)}
13621
- `
13622
- );
13623
- }
13624
- await closeCurrent("shutdown");
13625
- }
13626
- };
13627
- return { extension, contract };
13062
+ return uniqueBoundedReferences(artifacts);
13628
13063
  }
13629
-
13630
- // src/domains/session/manifest.ts
13631
- init_esm_shims();
13632
- var SessionManifest = {
13633
- name: "session",
13634
- dependsOn: ["config"]
13635
- };
13636
-
13637
- // src/domains/session/archive-readers.ts
13638
- init_esm_shims();
13639
- import { readdir, readFile } from "node:fs/promises";
13640
- import { join as join17 } from "node:path";
13641
- async function readAuditRows(stateDir) {
13642
- const root = join17(stateDir, "audit");
13643
- let files;
13644
- try {
13645
- files = await readdir(root);
13646
- } catch (error) {
13647
- const err = error;
13648
- if (err.code === "ENOENT") return { rows: [], errors: [] };
13649
- return { rows: [], errors: [`audit root read error: ${err.message ?? String(err)}`] };
13064
+ function adaptRunReceiptContextStatus(receipt) {
13065
+ if (receipt === null || receipt === void 0) return absentTrustStatus("artifact_missing");
13066
+ const artifacts = contextArtifacts(receipt);
13067
+ const source = receiptSource(receipt);
13068
+ const briefingInvalid = receipt.briefing !== void 0 && !validBriefing(receipt.briefing);
13069
+ if (briefingInvalid) return attributed("invalid", source, DISPATCH_AUTHORITY, artifacts);
13070
+ const context = receipt.projectContext;
13071
+ if (context === void 0) {
13072
+ if (receipt.briefing !== void 0) return attributed("recorded", source, DISPATCH_AUTHORITY, artifacts);
13073
+ return attributed("unknown", compatibilitySource(receipt, "projectContext"), COMPATIBILITY_AUTHORITY, artifacts);
13650
13074
  }
13651
- const rows = [];
13652
- const errors = [];
13653
- for (const file of files.filter((name) => name.endsWith(".jsonl")).sort(compareStrings2)) {
13654
- const path2 = join17(root, file);
13655
- let raw;
13656
- try {
13657
- raw = await readFile(path2, "utf8");
13658
- } catch (error) {
13659
- const err = error;
13660
- errors.push(`${path2}: ${err.message ?? String(err)}`);
13661
- continue;
13662
- }
13663
- const lines = raw.split("\n");
13664
- for (let index = 0; index < lines.length; index += 1) {
13665
- const line = lines[index];
13666
- if (line === void 0 || line.length === 0) continue;
13667
- let parsed;
13668
- try {
13669
- parsed = JSON.parse(line);
13670
- } catch (error) {
13671
- const message = error instanceof Error ? error.message : String(error);
13672
- errors.push(`${path2}:${index + 1}: invalid JSON: ${message}`);
13673
- continue;
13674
- }
13675
- if (!isRecord9(parsed)) {
13676
- errors.push(`${path2}:${index + 1}: expected object`);
13677
- continue;
13678
- }
13679
- const auditKind = readOptionalString(parsed.kind) ?? "tool_call";
13680
- rows.push({
13681
- file,
13682
- line: index + 1,
13683
- row: parsed,
13684
- ts: readOptionalString(parsed.ts),
13685
- auditKind,
13686
- correlationId: readOptionalString(parsed.correlationId) ?? ""
13687
- });
13075
+ if (context.tier === "none") {
13076
+ if (context.chars !== void 0 || context.contentHash !== void 0 || context.sections !== void 0) {
13077
+ return attributed("invalid", source, DISPATCH_AUTHORITY, artifacts);
13688
13078
  }
13079
+ return receipt.briefing === void 0 ? attributed("not_applicable", source, DISPATCH_AUTHORITY, artifacts) : attributed("recorded", source, DISPATCH_AUTHORITY, artifacts);
13689
13080
  }
13690
- return { rows, errors };
13081
+ return attributed(validBoundedProjectContext(context) ? "recorded" : "invalid", source, DISPATCH_AUTHORITY, artifacts);
13691
13082
  }
13692
- async function readSessionEntriesForId(stateDir, sessionId) {
13693
- const root = join17(stateDir, "sessions");
13694
- let cwdHashes;
13695
- try {
13696
- cwdHashes = await readdir(root);
13697
- } catch (error) {
13698
- const err = error;
13699
- if (err.code === "ENOENT") return { entries: [], missing: true, errors: [] };
13700
- return { entries: [], missing: false, errors: [`session root read error: ${err.message ?? String(err)}`] };
13083
+ function adaptRunReceiptAutonomyStatus(receipt) {
13084
+ if (receipt === null || receipt === void 0) return absentTrustStatus("artifact_missing");
13085
+ const enforcement = receipt.autonomyEnforcement;
13086
+ const artifacts = [receiptReference(receipt)];
13087
+ if (enforcement === void 0) {
13088
+ return attributed("unknown", compatibilitySource(receipt, "autonomyEnforcement"), COMPATIBILITY_AUTHORITY, artifacts);
13701
13089
  }
13702
- for (const cwdHash2 of cwdHashes.sort(compareStrings2)) {
13703
- const currentPath = join17(root, cwdHash2, sessionId, "current.jsonl");
13704
- let raw;
13705
- let source = currentPath;
13706
- try {
13707
- raw = await readFile(currentPath, "utf8");
13708
- } catch (error) {
13709
- const err = error;
13710
- if (err.code === "ENOENT") {
13711
- const tmpPath = `${currentPath}.tmp`;
13712
- try {
13713
- raw = await readFile(tmpPath, "utf8");
13714
- source = tmpPath;
13715
- } catch {
13716
- continue;
13717
- }
13718
- } else if (err.code === "ENOTDIR") {
13719
- continue;
13720
- } else {
13721
- return { entries: [], missing: false, errors: [`${currentPath}: ${err.message ?? String(err)}`] };
13722
- }
13723
- }
13724
- return parseSessionEntries(raw, source);
13090
+ artifacts.push({ kind: "autonomy_policy", id: `${receipt.runId}:${enforcement.autonomy}` });
13091
+ const authority = enforcement.grade === "mediated" ? { kind: "clio", id: "safety-autonomy" } : { kind: "runtime", id: enforcement.externalMode ?? "external-runtime" };
13092
+ const state = enforcement.dangerousBypass === true || enforcement.grade === "bypassed" ? "bypassed" : enforcement.grade === "approximated" ? "approximated" : "enforced";
13093
+ return attributed(state, receiptSource(receipt), authority, artifacts);
13094
+ }
13095
+ function receiptClaimsAreAuthenticated(receipt, integrity) {
13096
+ return receipt?.integrity !== void 0 && integrity?.ok === true;
13097
+ }
13098
+ function unauthenticatedReceiptProjection(receipt) {
13099
+ if (receipt === null || receipt === void 0) {
13100
+ return {
13101
+ validationGrounding: absentTrustStatus("artifact_missing"),
13102
+ contextProvenance: absentTrustStatus("artifact_missing"),
13103
+ autonomyEnforcement: absentTrustStatus("artifact_missing")
13104
+ };
13725
13105
  }
13726
- return { entries: [], missing: true, errors: [] };
13106
+ if (receipt.integrity === void 0) {
13107
+ const artifacts = [receiptReference(receipt)];
13108
+ return {
13109
+ validationGrounding: attributed(
13110
+ "unknown",
13111
+ compatibilitySource(receipt, "canonical-projection"),
13112
+ COMPATIBILITY_AUTHORITY,
13113
+ artifacts
13114
+ ),
13115
+ contextProvenance: attributed(
13116
+ "unknown",
13117
+ compatibilitySource(receipt, "canonical-projection"),
13118
+ COMPATIBILITY_AUTHORITY,
13119
+ artifacts
13120
+ ),
13121
+ autonomyEnforcement: attributed(
13122
+ "unknown",
13123
+ compatibilitySource(receipt, "canonical-projection"),
13124
+ COMPATIBILITY_AUTHORITY,
13125
+ artifacts
13126
+ )
13127
+ };
13128
+ }
13129
+ return {
13130
+ validationGrounding: absentTrustStatus("not_observed"),
13131
+ contextProvenance: absentTrustStatus("not_observed"),
13132
+ autonomyEnforcement: absentTrustStatus("not_observed")
13133
+ };
13134
+ }
13135
+ function adaptRunReceiptTrustStatus(receipt, options = {}) {
13136
+ const authenticated2 = receiptClaimsAreAuthenticated(receipt, options.integrity);
13137
+ const receiptProjection = authenticated2 ? {
13138
+ validationGrounding: adaptRunReceiptValidationStatus(receipt),
13139
+ contextProvenance: adaptRunReceiptContextStatus(receipt),
13140
+ autonomyEnforcement: adaptRunReceiptAutonomyStatus(receipt)
13141
+ } : unauthenticatedReceiptProjection(receipt);
13142
+ return composeTrustStatus({
13143
+ artifactIntegrity: adaptReceiptIntegrityStatus(receipt, options.integrity),
13144
+ ...receiptProjection,
13145
+ independentReview: absentTrustStatus(receipt === null || receipt === void 0 ? "artifact_missing" : "not_recorded"),
13146
+ completionEvidence: absentTrustStatus(
13147
+ receipt === null || receipt === void 0 ? "artifact_missing" : "not_recorded"
13148
+ )
13149
+ });
13727
13150
  }
13728
- function parseSessionEntries(raw, source) {
13729
- const entries = [];
13730
- const errors = [];
13731
- const lines = raw.split("\n");
13732
- for (let index = 0; index < lines.length; index += 1) {
13733
- const line = lines[index];
13734
- if (line === void 0 || line.trim().length === 0) continue;
13735
- let parsed;
13151
+ function inspectRunReceiptTrustStatus(receipt, envelope) {
13152
+ let integrity;
13153
+ if (receipt === null || receipt === void 0) {
13154
+ integrity = { ok: false, reason: "receipt unavailable" };
13155
+ } else if (envelope === null || envelope === void 0) {
13156
+ integrity = { ok: false, reason: "run ledger envelope unavailable" };
13157
+ } else {
13736
13158
  try {
13737
- parsed = JSON.parse(line);
13159
+ integrity = verifyReceiptIntegrity(receipt, envelope);
13738
13160
  } catch (error) {
13739
- const message = error instanceof Error ? error.message : String(error);
13740
- errors.push(`${source}:${index + 1}: invalid JSON: ${message}`);
13741
- continue;
13742
- }
13743
- if (isSessionHeader(parsed)) continue;
13744
- if (isSessionEntry(parsed)) {
13745
- entries.push(parsed);
13746
- continue;
13161
+ integrity = {
13162
+ ok: false,
13163
+ reason: `receipt invalid: ${error instanceof Error ? error.message : String(error)}`
13164
+ };
13747
13165
  }
13748
- errors.push(
13749
- `session ledger contains an unreadable entry (missing kind discriminant): ${source}. Remove or compact the session to reset.`
13750
- );
13751
13166
  }
13752
- return { entries, missing: false, errors };
13753
- }
13754
- async function listSessionLedgerRefs(stateDir, onlyCwdHash) {
13755
- const root = join17(stateDir, "sessions");
13756
- let cwdHashes;
13757
- try {
13758
- cwdHashes = await readdir(root);
13759
- } catch {
13760
- return [];
13167
+ return {
13168
+ integrity,
13169
+ status: adaptRunReceiptTrustStatus(receipt, { integrity })
13170
+ };
13171
+ }
13172
+ function gateReference(artifact) {
13173
+ return sha256Reference("gate_decision", artifact.id, artifact.integrity.digest);
13174
+ }
13175
+ function gateAuthority(artifact) {
13176
+ if (artifact.outcome === "operator-confirmed") return { kind: "operator", id: "gate-confirmation" };
13177
+ if (artifact.outcome === "full-auto-applied") return { kind: "clio", id: "full-auto-gate-policy" };
13178
+ return { kind: "reviewer", id: artifact.decider?.runId ?? "unavailable-decider" };
13179
+ }
13180
+ function adaptGateDecisionReviewStatus(artifact, subjectRunId, verification) {
13181
+ if (artifact === null || artifact === void 0) return absentTrustStatus("artifact_missing");
13182
+ const source = { kind: "gate_decision", id: artifact.id };
13183
+ const artifacts = [gateReference(artifact)];
13184
+ const authority = gateAuthority(artifact);
13185
+ if (!artifact.subjects.some((subject) => subject.runId === subjectRunId)) return absentTrustStatus("not_recorded");
13186
+ if (verification === void 0 || !verification.ok) {
13187
+ return attributed(
13188
+ "unknown",
13189
+ source,
13190
+ verification === void 0 ? COMPATIBILITY_AUTHORITY : { kind: "unknown", id: "unauthenticated-gate-artifact" },
13191
+ artifacts
13192
+ );
13761
13193
  }
13762
- const refs = [];
13763
- for (const cwdHash2 of cwdHashes.sort(compareStrings2)) {
13764
- if (onlyCwdHash !== void 0 && cwdHash2 !== onlyCwdHash) continue;
13765
- let sessionIds;
13766
- try {
13767
- sessionIds = await readdir(join17(root, cwdHash2));
13768
- } catch {
13769
- continue;
13770
- }
13771
- for (const sessionId of sessionIds.sort(compareStrings2)) {
13772
- refs.push({ cwdHash: cwdHash2, sessionId, path: join17(root, cwdHash2, sessionId, "current.jsonl") });
13194
+ if (artifact.decider === void 0 || artifact.correlation === void 0) {
13195
+ if (artifact.outcome === "operator-confirmed" || artifact.outcome === "full-auto-applied") {
13196
+ return attributed("not_applicable", source, authority, artifacts);
13773
13197
  }
13198
+ return attributed("inconclusive", source, authority, artifacts);
13774
13199
  }
13775
- return refs;
13776
- }
13777
- function readOptionalString(value) {
13778
- return typeof value === "string" && value.length > 0 ? value : null;
13200
+ if (!artifact.correlation.independent) return attributed("not_independent", source, authority, artifacts);
13201
+ if (artifact.outcome === "pass") return attributed("passed", source, authority, artifacts);
13202
+ if (artifact.outcome === "fail") return attributed("failed", source, authority, artifacts);
13203
+ if (artifact.outcome === "winner") {
13204
+ return attributed(
13205
+ artifact.winner?.subject.runId === subjectRunId ? "passed" : "failed",
13206
+ source,
13207
+ authority,
13208
+ artifacts
13209
+ );
13210
+ }
13211
+ return attributed("inconclusive", source, authority, artifacts);
13779
13212
  }
13780
- function isRecord9(value) {
13781
- return typeof value === "object" && value !== null && !Array.isArray(value);
13213
+ function adaptGroundedEvidenceValidationStatus(input) {
13214
+ const observed = (input.artifacts ?? []).filter((artifact) => !SELF_REPORTED_ARTIFACT_KINDS.has(artifact.kind));
13215
+ if (observed.length === 0) return absentTrustStatus("not_observed");
13216
+ return attributed(
13217
+ "validated",
13218
+ { kind: "evidence_bundle", id: `${input.evidenceId}:${input.runId}` },
13219
+ { kind: "clio", id: "evidence-grounding" },
13220
+ uniqueBoundedReferences([{ kind: "evidence_bundle", id: input.evidenceId }, ...observed])
13221
+ );
13782
13222
  }
13783
- function compareStrings2(a, b) {
13784
- return a.localeCompare(b);
13223
+ function adaptFinishContractCompletionStatus(assessment, options = {}) {
13224
+ const artifacts = uniqueBoundedReferences(
13225
+ options.artifacts ?? assessment.evidence.map((evidence, index) => ({
13226
+ kind: evidence.turnId === void 0 ? "finish_contract_evidence" : "session_entry",
13227
+ id: evidence.turnId ?? `${evidence.kind}:${index + 1}`
13228
+ }))
13229
+ );
13230
+ const source = { kind: "finish_contract", id: options.sourceId ?? assessment.reason };
13231
+ const authority = { kind: "clio", id: "finish-contract" };
13232
+ if (assessment.reason === "no_mutation") return attributed("not_applicable", source, authority, artifacts);
13233
+ if (assessment.reason === "validation_evidence") return attributed("evidenced", source, authority, artifacts);
13234
+ if (assessment.reason === "explicit_limitation") return attributed("limited", source, authority, artifacts);
13235
+ return attributed("incomplete", source, authority, artifacts);
13236
+ }
13237
+ function uniqueBoundedReferences(references) {
13238
+ const sorted = [...references].sort(compareArtifactReferences);
13239
+ const unique = sorted.filter(
13240
+ (reference, index) => index === 0 || compareArtifactReferences(sorted[index - 1], reference) !== 0
13241
+ );
13242
+ return unique.slice(0, TRUST_STATUS_MAX_ARTIFACT_REFERENCES);
13785
13243
  }
13786
13244
 
13787
- // src/domains/session/protected-artifacts.ts
13245
+ // src/domains/evidence/types.ts
13788
13246
  init_esm_shims();
13789
- function protectedArtifactEntryFromArtifact(artifact, context) {
13790
- const entry = {
13791
- kind: "protectedArtifact",
13792
- parentTurnId: context.parentTurnId,
13793
- action: "protect",
13794
- artifact: artifactSnapshot(artifact)
13795
- };
13796
- if (context.toolName !== void 0) entry.toolName = context.toolName;
13797
- if (context.toolCallId !== void 0) entry.toolCallId = context.toolCallId;
13798
- if (context.runId !== void 0) entry.runId = context.runId;
13799
- if (context.correlationId !== void 0) entry.correlationId = context.correlationId;
13800
- return entry;
13801
- }
13802
- function protectedArtifactFromSessionEntry(entry) {
13803
- return protectedArtifactFromSnapshot(entry.artifact);
13804
- }
13805
- function protectedArtifactStateFromSessionEntries(entries) {
13806
- let state = { artifacts: [] };
13807
- const protectedEntries = entries.map((entry, index) => ({ entry, index })).filter((item) => item.entry.kind === "protectedArtifact").sort(compareProtectedEntryPositions);
13808
- for (const item of protectedEntries) {
13809
- if (item.entry.action !== "protect") continue;
13810
- state = protectArtifact(state, protectedArtifactFromSessionEntry(item.entry));
13811
- }
13812
- return state;
13813
- }
13814
- function artifactSnapshot(artifact) {
13815
- const snapshot = {
13816
- path: artifact.path,
13817
- protectedAt: artifact.protectedAt,
13818
- reason: artifact.reason,
13819
- source: artifact.source
13820
- };
13821
- if (artifact.validationCommand !== void 0) snapshot.validationCommand = artifact.validationCommand;
13822
- if (artifact.validationExitCode !== void 0) snapshot.validationExitCode = artifact.validationExitCode;
13823
- return snapshot;
13824
- }
13825
- function protectedArtifactFromSnapshot(snapshot) {
13826
- const artifact = {
13827
- path: snapshot.path,
13828
- protectedAt: snapshot.protectedAt,
13829
- reason: snapshot.reason,
13830
- source: snapshot.source
13831
- };
13832
- if (snapshot.validationCommand !== void 0) artifact.validationCommand = snapshot.validationCommand;
13833
- if (snapshot.validationExitCode !== void 0) artifact.validationExitCode = snapshot.validationExitCode;
13834
- return artifact;
13835
- }
13836
- function compareProtectedEntryPositions(left, right) {
13837
- return compareStrings3(left.entry.timestamp, right.entry.timestamp) || compareStrings3(left.entry.turnId, right.entry.turnId) || left.index - right.index;
13838
- }
13839
- function compareStrings3(left, right) {
13840
- if (left < right) return -1;
13841
- if (left > right) return 1;
13842
- return 0;
13843
- }
13247
+ var EVIDENCE_VERSION = 1;
13248
+ var FAILURE_CAUSE_TAG_ORDER = [
13249
+ "timeout",
13250
+ "auth-failure",
13251
+ "missing-dependency",
13252
+ "build-failure",
13253
+ "test-failure",
13254
+ "blocked-tool"
13255
+ ];
13256
+ var FAILURE_CAUSE_TAGS = new Set(FAILURE_CAUSE_TAG_ORDER);
13844
13257
 
13845
- // src/domains/session/usage.ts
13846
- init_esm_shims();
13847
- function numberAt(source, key) {
13848
- const value = source[key];
13849
- return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
13850
- }
13851
- function reasoningTokensOf(usage) {
13852
- const direct = numberAt(usage, "reasoningTokens");
13853
- if (direct > 0) return direct;
13854
- const details = usage.outputTokensDetails ?? usage.completionTokensDetails;
13855
- if (details && typeof details === "object") return numberAt(details, "reasoningTokens");
13856
- return 0;
13857
- }
13858
- function stringAt(source, ...keys) {
13859
- for (const key of keys) {
13860
- const value = source[key];
13861
- if (typeof value === "string" && value.trim().length > 0) return value;
13862
- }
13863
- return null;
13258
+ // src/domains/evidence/run-trust.ts
13259
+ function buildEvidenceTrustStatusFile(input) {
13260
+ return {
13261
+ version: EVIDENCE_VERSION,
13262
+ evidenceId: input.evidenceId,
13263
+ projection: "canonical",
13264
+ runs: input.runSources.map((source) => ({
13265
+ runId: source.envelope.id,
13266
+ status: composeEvidenceRunTrustStatus({
13267
+ evidenceId: input.evidenceId,
13268
+ source,
13269
+ gateDecisions: input.gateDecisions,
13270
+ auditRows: input.auditRows,
13271
+ validationEvidence: input.validationEvidence?.get(source.envelope.id) ?? []
13272
+ })
13273
+ }))
13274
+ };
13864
13275
  }
13865
- function ledgerUsageCalls(entries, defaults = {}) {
13866
- const calls = [];
13867
- let currentTarget = defaults.target ?? null;
13868
- let currentModel = defaults.model ?? null;
13869
- for (const entry of entries) {
13870
- if (entry?.kind === "compactionSummary") {
13871
- const usage2 = entry.usage;
13872
- if (!usage2 || usage2.totalTokens <= 0) continue;
13873
- calls.push({
13874
- providerId: currentTarget ?? "unknown",
13875
- modelId: currentModel ?? "unknown",
13876
- input: usage2.input,
13877
- output: usage2.output,
13878
- cacheRead: usage2.cacheRead,
13879
- cacheWrite: usage2.cacheWrite,
13880
- reasoningTokens: usage2.reasoning,
13881
- totalTokens: usage2.totalTokens,
13882
- costUsd: usage2.cost.total,
13883
- // A split turn runs two summarization streams under one entry; the
13884
- // provider served that many calls even though one row records them.
13885
- apiCalls: Math.max(1, Math.round(usage2.apiCalls))
13886
- });
13887
- continue;
13888
- }
13889
- if (entry?.kind === "modelChange") {
13890
- const change = entry;
13891
- if (typeof change.target === "string" && change.target.length > 0) currentTarget = change.target;
13892
- else if (typeof change.provider === "string" && change.provider.length > 0) currentTarget = change.provider;
13893
- if (typeof change.modelId === "string" && change.modelId.length > 0) currentModel = change.modelId;
13894
- continue;
13895
- }
13896
- if (entry?.kind !== "message" || entry.role !== "assistant") continue;
13897
- const payload = entry.payload;
13898
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) continue;
13899
- const record = payload;
13900
- const stopReason = record.stopReason;
13901
- if (stopReason === "aborted" || stopReason === "error") continue;
13902
- const rawUsage = record.usage;
13903
- if (!rawUsage || typeof rawUsage !== "object" || Array.isArray(rawUsage)) continue;
13904
- const usage = rawUsage;
13905
- const input = numberAt(usage, "input");
13906
- const output = numberAt(usage, "output");
13907
- const cacheRead = numberAt(usage, "cacheRead");
13908
- const cacheWrite = numberAt(usage, "cacheWrite");
13909
- const totalTokens = numberAt(usage, "totalTokens") || input + output + cacheRead + cacheWrite;
13910
- if (totalTokens === 0) continue;
13911
- const cost = usage.cost;
13912
- const costUsd = cost && typeof cost === "object" ? numberAt(cost, "total") : 0;
13913
- calls.push({
13914
- providerId: currentTarget ?? stringAt(record, "provider", "api") ?? "unknown",
13915
- modelId: currentModel ?? stringAt(record, "responseModel", "model") ?? "unknown",
13916
- input,
13917
- output,
13918
- cacheRead,
13919
- cacheWrite,
13920
- reasoningTokens: reasoningTokensOf(usage),
13921
- totalTokens,
13922
- costUsd
13276
+ function composeEvidenceRunTrustStatus(input) {
13277
+ const inspection = inspectRunReceiptTrustStatus(input.source.receipt, input.source.envelope);
13278
+ const receiptRejected = inspection.status.artifactIntegrity.state === "failed";
13279
+ let status = inspection.status;
13280
+ const grounded = input.validationEvidence.filter((artifact) => isTrustStatusIdentifier(artifact.id));
13281
+ if (grounded.length > 0 && (status.validationGrounding.state === "absent" || status.validationGrounding.state === "unknown")) {
13282
+ status = composeTrustStatus(status, {
13283
+ validationGrounding: adaptGroundedEvidenceValidationStatus({
13284
+ evidenceId: input.evidenceId,
13285
+ runId: input.source.envelope.id,
13286
+ artifacts: grounded
13287
+ })
13923
13288
  });
13924
13289
  }
13925
- return calls;
13926
- }
13927
-
13928
- // src/domains/session/index.ts
13929
- var SessionDomainModule = {
13930
- manifest: SessionManifest,
13931
- createExtension: createSessionBundle
13932
- };
13933
-
13934
- // src/domains/evidence/failure-attribution.ts
13935
- init_esm_shims();
13936
- function attributeEvidenceFailure(facts) {
13937
- if (facts.outcomeCode === "worker_tool_call_cap_exhausted" || facts.outcomeCode === "loop_guard_tools_disabled_exhausted") {
13938
- return "tool-loop";
13290
+ const gate = latestGateDecisionForRun(input.gateDecisions, input.source.envelope.id);
13291
+ if (gate !== null) {
13292
+ const artifactVerification = verifyGateDecisionArtifact(gate);
13293
+ const subject = gate.subjects.find((entry) => entry.runId === input.source.envelope.id);
13294
+ const receipt = inspection.integrity.ok ? input.source.receipt : null;
13295
+ const verification = artifactVerification.ok && subject !== void 0 && receipt?.integrity !== void 0 && subject.digest === receipt.integrity.digest ? { ok: true } : {
13296
+ ok: false,
13297
+ reason: artifactVerification.ok ? "gate subject receipt digest unavailable or mismatched" : artifactVerification.reason
13298
+ };
13299
+ status = composeTrustStatus(status, {
13300
+ independentReview: adaptGateDecisionReviewStatus(gate, input.source.envelope.id, verification)
13301
+ });
13939
13302
  }
13940
- if (facts.outcome === "timed_out" || facts.outcome === "stalled") return "timeout";
13941
- const diagnostic = [facts.outcomeDetail, facts.failureMessage].filter((value) => value !== null).join("\n").toLowerCase();
13942
- if (diagnostic.length === 0) return "unknown";
13943
- if (/\b(?:401|403)\b|unauthorized|forbidden|invalid api key|authentication/.test(diagnostic)) {
13944
- return "auth-failure";
13303
+ const finish = latestFinishContractForRun(input.auditRows, input.source.envelope.id);
13304
+ if (finish !== null) {
13305
+ const completion = adaptFinishContractCompletionStatus(finish.assessment, {
13306
+ sourceId: finish.sourceId,
13307
+ artifacts: finish.artifacts
13308
+ });
13309
+ status = composeTrustStatus(status, {
13310
+ completionEvidence: receiptRejected && completion.state === "evidenced" ? {
13311
+ state: "unknown",
13312
+ source: { kind: "finish_contract", id: finish.sourceId },
13313
+ authority: { kind: "clio", id: "finish-contract" },
13314
+ artifacts: finish.artifacts
13315
+ } : completion
13316
+ });
13945
13317
  }
13946
- if (/\b429\b|rate[ -]?limit|too many requests|temporar(?:y|ily)|unavailable|\b50[234]\b/.test(diagnostic)) {
13947
- return "provider-transient";
13318
+ return status;
13319
+ }
13320
+ function latestGateDecisionForRun(decisions, runId) {
13321
+ return decisions.filter((decision) => decision.subjects.some((subject) => subject.runId === runId)).sort(
13322
+ (left, right) => compareCodepoints(left.createdAt, right.createdAt) || left.cycle - right.cycle || compareCodepoints(left.id, right.id)
13323
+ ).at(-1) ?? null;
13324
+ }
13325
+ function latestFinishContractForRun(rows, runId) {
13326
+ const candidates = rows.filter((row) => row.auditKind === "completion_contract" && row.runId === runId && row.confidence === "exact").flatMap((row) => {
13327
+ const assessment = finishContractAssessmentFromAudit(row.row);
13328
+ if (assessment === null) return [];
13329
+ const correlationId = readOptionalString(row.row.correlationId) ?? `${runId}:completion-contract`;
13330
+ if (!isTrustStatusIdentifier(correlationId)) return [];
13331
+ const turnId = readOptionalString(row.row.turnId);
13332
+ const artifacts = [
13333
+ { kind: "finish_contract_evidence", id: correlationId },
13334
+ ...turnId === null || !isTrustStatusIdentifier(turnId) ? [] : [{ kind: "session_entry", id: turnId }]
13335
+ ];
13336
+ return [{ sourceId: correlationId, assessment, artifacts, timestamp: row.ts ?? "" }];
13337
+ }).sort(
13338
+ (left, right) => compareCodepoints(left.timestamp, right.timestamp) || compareCodepoints(left.sourceId, right.sourceId)
13339
+ );
13340
+ const latest2 = candidates.at(-1);
13341
+ return latest2 === void 0 ? null : { sourceId: latest2.sourceId, assessment: latest2.assessment, artifacts: latest2.artifacts };
13342
+ }
13343
+ function finishContractAssessmentFromAudit(row) {
13344
+ const reason = readOptionalString(row.reason);
13345
+ const decision = readOptionalString(row.decision);
13346
+ const mutatedPaths = Array.isArray(row.mutatedPaths) ? row.mutatedPaths.filter((entry) => typeof entry === "string") : [];
13347
+ const turnId = readOptionalString(row.turnId);
13348
+ const evidenceKinds = Array.isArray(row.evidenceKinds) ? row.evidenceKinds.filter(isFinishContractEvidenceKind) : [];
13349
+ const evidence = evidenceKinds.map((kind) => ({
13350
+ kind,
13351
+ summary: "recorded by the finish contract",
13352
+ ...turnId === null ? {} : { turnId }
13353
+ }));
13354
+ if (decision === "ok" && reason === "no_mutation") {
13355
+ return { kind: "ok", reason, evidence: [], mutatedPaths };
13948
13356
  }
13949
- if (/context (?:length|window)|context[_ -]?overflow|maximum context|too many tokens/.test(diagnostic)) {
13950
- return "context-overflow";
13357
+ if (decision === "ok" && reason === "validation_evidence") {
13358
+ return { kind: "ok", reason, evidence, mutatedPaths };
13951
13359
  }
13952
- if (/module not found|cannot find module|missing (?:dependency|package)|dependency .* missing/.test(diagnostic)) {
13953
- return "missing-dependency";
13360
+ if (decision === "ok" && reason === "explicit_limitation") {
13361
+ return { kind: "ok", reason, evidence: [], mutatedPaths };
13954
13362
  }
13955
- if (/wrong runtime|runtime mismatch|model mismatch|unsupported runtime/.test(diagnostic)) return "wrong-runtime";
13956
- if (/\b(?:test|tests|pytest|ctest)\b.*(?:fail|error)|(?:fail|error).*\b(?:test|tests|pytest|ctest)\b/.test(diagnostic)) {
13957
- return "test-failure";
13363
+ if (decision === "engage" && reason === "unvalidated_mutation") {
13364
+ return { kind: "engage", reason, message: "finish contract engaged", evidence: [], mutatedPaths };
13958
13365
  }
13959
- if (/\bbuild\b.*(?:fail|error)|(?:fail|error).*\bbuild\b/.test(diagnostic)) return "build-failure";
13960
- return "unknown";
13961
- }
13962
-
13963
- // src/domains/evidence/provenance.ts
13964
- init_esm_shims();
13965
- var PERSONA_HASH_PREFIX_CHARS = 12;
13966
- function extractRunProvenance(receipt) {
13967
- const view = {};
13968
- if (receipt.pipeline !== void 0) view.pipeline = receipt.pipeline;
13969
- if (receipt.personaOverride !== void 0) view.personaOverride = receipt.personaOverride;
13970
- const escalation = escalationCountsFrom(receipt.safety);
13971
- if (escalation !== null) view.escalation = escalation;
13972
- if (receipt.autonomyEnforcement !== void 0) view.autonomyEnforcement = receipt.autonomyEnforcement;
13973
- return view;
13974
- }
13975
- function hasRunProvenance(view) {
13976
- return view.pipeline !== void 0 || view.personaOverride !== void 0 || view.escalation !== void 0 || view.autonomyEnforcement !== void 0;
13977
- }
13978
- function runProvenanceFromUnknown(value) {
13979
- if (!isRecord10(value)) return {};
13980
- const view = {};
13981
- const pipeline = pipelineFromUnknown(value.pipeline);
13982
- if (pipeline !== null) view.pipeline = pipeline;
13983
- const personaOverride = personaOverrideFromUnknown(value.personaOverride);
13984
- if (personaOverride !== null) view.personaOverride = personaOverride;
13985
- const escalation = escalationFromUnknown(value.safety);
13986
- if (escalation !== null) view.escalation = escalation;
13987
- const autonomyEnforcement = autonomyEnforcementFromUnknown(value.autonomyEnforcement);
13988
- if (autonomyEnforcement !== null) view.autonomyEnforcement = autonomyEnforcement;
13989
- return view;
13990
- }
13991
- function isRecord10(value) {
13992
- return typeof value === "object" && value !== null && !Array.isArray(value);
13993
- }
13994
- function finiteNumber(value) {
13995
- return typeof value === "number" && Number.isFinite(value) ? value : null;
13996
- }
13997
- function pipelineFromUnknown(value) {
13998
- if (!isRecord10(value)) return null;
13999
- const position = finiteNumber(value.position);
14000
- const inputBytes = finiteNumber(value.inputBytes);
14001
- if (position === null || inputBytes === null) return null;
14002
- const fromRunId = typeof value.fromRunId === "string" ? value.fromRunId : null;
14003
- return { fromRunId, position, inputBytes, inputTruncated: value.inputTruncated === true };
14004
- }
14005
- function personaOverrideFromUnknown(value) {
14006
- if (!isRecord10(value) || typeof value.promptHash !== "string" || value.promptHash.length === 0) return null;
14007
- return { promptHash: value.promptHash };
14008
- }
14009
- function autonomyEnforcementFromUnknown(value) {
14010
- if (!isRecord10(value)) return null;
14011
- if (value.grade !== "mediated" && value.grade !== "approximated" && value.grade !== "bypassed") return null;
14012
- if (typeof value.autonomy !== "string" || value.autonomy.length === 0) return null;
14013
- const view = { grade: value.grade, autonomy: value.autonomy };
14014
- if (typeof value.externalMode === "string" && value.externalMode.length > 0) view.externalMode = value.externalMode;
14015
- if (typeof value.dangerousBypass === "boolean") view.dangerousBypass = value.dangerousBypass;
14016
- return view;
14017
- }
14018
- function escalationFromUnknown(safety) {
14019
- if (!isRecord10(safety)) return null;
14020
- const decisions = safety.decisions;
14021
- if (!isRecord10(decisions)) return null;
14022
- const requested = finiteNumber(decisions.escalationRequested);
14023
- if (requested === null) return null;
14024
- return {
14025
- requested,
14026
- approved: finiteNumber(decisions.escalationApproved) ?? 0,
14027
- denied: finiteNumber(decisions.escalationDenied) ?? 0,
14028
- timedOut: finiteNumber(decisions.escalationTimedOut) ?? 0
14029
- };
14030
- }
14031
- function escalationCountsFrom(safety) {
14032
- const decisions = safety?.decisions;
14033
- if (decisions === void 0 || decisions.escalationRequested === void 0) return null;
14034
- return {
14035
- requested: decisions.escalationRequested,
14036
- approved: decisions.escalationApproved ?? 0,
14037
- denied: decisions.escalationDenied ?? 0,
14038
- timedOut: decisions.escalationTimedOut ?? 0
14039
- };
14040
- }
14041
- function formatPersonaHashPrefix(promptHash2) {
14042
- if (promptHash2.length <= PERSONA_HASH_PREFIX_CHARS) return promptHash2;
14043
- return `${promptHash2.slice(0, PERSONA_HASH_PREFIX_CHARS)}...`;
13366
+ return null;
14044
13367
  }
14045
- function provenanceTranscriptLines(view) {
14046
- const lines = [];
14047
- if (view.pipeline !== void 0) {
14048
- const { fromRunId, position, inputBytes, inputTruncated } = view.pipeline;
14049
- const source = fromRunId ?? "unknown";
14050
- const truncation = inputTruncated ? "input truncated" : "not truncated";
14051
- lines.push(`pipeline: step ${position}, input ${inputBytes} bytes from ${source} (${truncation})`);
14052
- }
14053
- if (view.personaOverride !== void 0) {
14054
- lines.push(`persona override: prompt hash ${formatPersonaHashPrefix(view.personaOverride.promptHash)}`);
14055
- }
14056
- if (view.escalation !== void 0) {
14057
- const { requested, approved, denied, timedOut } = view.escalation;
14058
- lines.push(`escalations: ${requested} requested, ${approved} approved, ${denied} denied, ${timedOut} timed out`);
14059
- }
14060
- if (view.autonomyEnforcement !== void 0) {
14061
- const { grade, autonomy, externalMode, dangerousBypass } = view.autonomyEnforcement;
14062
- const mode = externalMode !== void 0 ? ` mode=${externalMode}` : "";
14063
- const bypass = dangerousBypass === true ? " dangerousBypass=true" : "";
14064
- lines.push(`autonomy enforcement: ${grade} autonomy=${autonomy}${mode}${bypass}`);
14065
- }
14066
- return lines;
13368
+ function isFinishContractEvidenceKind(value) {
13369
+ return value === "validation_command" || value === "protected_artifact" || value === "dispatch_receipt";
14067
13370
  }
14068
- function provenanceCompactSuffix(view) {
14069
- const parts = [];
14070
- if (view.pipeline !== void 0) {
14071
- const { fromRunId, position, inputBytes, inputTruncated } = view.pipeline;
14072
- const from = fromRunId ?? "unknown";
14073
- parts.push(`pipeline=step${position} from=${from} in=${inputBytes}b${inputTruncated ? " truncated" : ""}`);
14074
- }
14075
- if (view.personaOverride !== void 0) {
14076
- parts.push(`persona=${formatPersonaHashPrefix(view.personaOverride.promptHash)}`);
14077
- }
14078
- if (view.escalation !== void 0) {
14079
- const { requested, approved, denied, timedOut } = view.escalation;
14080
- parts.push(`escalations=${requested}req/${approved}appr/${denied}deny/${timedOut}timeout`);
14081
- }
14082
- if (view.autonomyEnforcement !== void 0) {
14083
- const { grade, autonomy, externalMode, dangerousBypass } = view.autonomyEnforcement;
14084
- const mode = externalMode !== void 0 ? `/${externalMode}` : "";
14085
- const bypass = dangerousBypass === true ? "/bypass" : "";
14086
- parts.push(`enforcement=${grade}:${autonomy}${mode}${bypass}`);
14087
- }
14088
- return parts.length === 0 ? "" : ` ${parts.join(" ")}`;
13371
+ function readOptionalString(value) {
13372
+ return typeof value === "string" && value.trim().length > 0 ? value : null;
14089
13373
  }
14090
13374
 
14091
13375
  // src/domains/evidence/store.ts
14092
13376
  init_esm_shims();
14093
- import { readdir as readdir2, readFile as readFile2 } from "node:fs/promises";
14094
- import { join as join18 } from "node:path";
13377
+ import { readdir, readFile } from "node:fs/promises";
13378
+ import { join as join15 } from "node:path";
14095
13379
  var EVIDENCE_FILES = [
14096
13380
  "overview.json",
14097
13381
  "transcript.md",
@@ -14101,16 +13385,17 @@ var EVIDENCE_FILES = [
14101
13385
  "audit-linked.jsonl",
14102
13386
  "receipt.json",
14103
13387
  "gate-decisions.json",
13388
+ "trust-status.json",
14104
13389
  "protected-artifacts.json",
14105
13390
  "findings.json",
14106
13391
  "findings.md"
14107
13392
  ];
14108
13393
  function evidenceRoot(dataDir) {
14109
- return join18(dataDir, "evidence");
13394
+ return join15(dataDir, "evidence");
14110
13395
  }
14111
13396
  function evidenceDirectory(dataDir, evidenceId) {
14112
13397
  assertSafeId(evidenceId, "evidence");
14113
- return join18(evidenceRoot(dataDir), evidenceId);
13398
+ return join15(evidenceRoot(dataDir), evidenceId);
14114
13399
  }
14115
13400
  var EvidenceNotFoundError = class extends Error {
14116
13401
  constructor(evidenceId) {
@@ -14126,7 +13411,7 @@ function isMissingFile(error) {
14126
13411
  async function loadEvidenceOverview(dataDir, evidenceId) {
14127
13412
  let raw;
14128
13413
  try {
14129
- raw = await readFile2(join18(evidenceDirectory(dataDir, evidenceId), "overview.json"), "utf8");
13414
+ raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "overview.json"), "utf8");
14130
13415
  } catch (error) {
14131
13416
  if (isMissingFile(error)) throw new EvidenceNotFoundError(evidenceId);
14132
13417
  throw error;
@@ -14138,19 +13423,52 @@ async function inspectEvidence(dataDir, evidenceId) {
14138
13423
  const overview = await loadEvidenceOverview(dataDir, evidenceId);
14139
13424
  let findingsRaw;
14140
13425
  try {
14141
- findingsRaw = await readFile2(join18(evidenceDirectory(dataDir, evidenceId), "findings.json"), "utf8");
13426
+ findingsRaw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "findings.json"), "utf8");
14142
13427
  } catch (error) {
14143
13428
  if (isMissingFile(error)) throw new Error(`evidence artifact ${evidenceId} is missing findings.json`);
14144
13429
  throw error;
14145
13430
  }
14146
13431
  const findingsParsed = parseJson(findingsRaw, `${evidenceId}/findings.json`);
14147
13432
  const findings = parseFindingsFile(findingsParsed, `${evidenceId}/findings.json`);
14148
- return { overview, findings };
13433
+ return { overview, findings, trustStatus: await loadEvidenceTrustStatus(dataDir, evidenceId) };
13434
+ }
13435
+ async function loadEvidenceTrustStatus(dataDir, evidenceId) {
13436
+ let raw;
13437
+ try {
13438
+ raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "trust-status.json"), "utf8");
13439
+ } catch (error) {
13440
+ if (isMissingFile(error)) {
13441
+ return { version: 1, evidenceId, projection: "historical_format", runs: [] };
13442
+ }
13443
+ throw error;
13444
+ }
13445
+ const source = `${evidenceId}/trust-status.json`;
13446
+ const parsed = parseJson(raw, source);
13447
+ if (!isRecord11(parsed)) throw new Error(`${source}: expected object`);
13448
+ if (parsed.version !== 1) throw new Error(`${source}: expected version 1`);
13449
+ if (readString(parsed, source, "evidenceId") !== evidenceId) {
13450
+ throw new Error(`${source}.evidenceId: expected ${evidenceId}`);
13451
+ }
13452
+ if (parsed.projection !== "canonical") throw new Error(`${source}.projection: expected canonical`);
13453
+ if (!Array.isArray(parsed.runs)) throw new Error(`${source}.runs: expected array`);
13454
+ return {
13455
+ version: 1,
13456
+ evidenceId,
13457
+ projection: "canonical",
13458
+ runs: parsed.runs.map((entry, index) => {
13459
+ const entrySource = `${source}.runs[${index}]`;
13460
+ if (!isRecord11(entry)) throw new Error(`${entrySource}: expected object`);
13461
+ return {
13462
+ runId: readString(entry, entrySource, "runId"),
13463
+ status: normalizeTrustStatus(entry.status)
13464
+ };
13465
+ })
13466
+ };
14149
13467
  }
14150
13468
  async function loadEvidenceRunProvenance(dataDir, evidenceId) {
14151
13469
  let raw;
14152
13470
  try {
14153
- raw = await readFile2(join18(evidenceDirectory(dataDir, evidenceId), "receipt.json"), "utf8");
13471
+ raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "receipt.json"), "utf8");
14154
13472
  } catch (error) {
14155
13473
  const err = error;
14156
13474
  if (err.code === "ENOENT") return [];
@@ -14169,14 +13487,14 @@ async function loadEvidenceRunProvenance(dataDir, evidenceId) {
14169
13487
  async function listEvidenceOverviews(dataDir) {
14170
13488
  let entries;
14171
13489
  try {
14172
- entries = await readdir2(evidenceRoot(dataDir));
13490
+ entries = await readdir(evidenceRoot(dataDir));
14173
13491
  } catch (error) {
14174
13492
  const err = error;
14175
13493
  if (err.code === "ENOENT") return [];
14176
13494
  throw error;
14177
13495
  }
14178
13496
  const overviews = [];
14179
- for (const entry of entries.sort(compareStrings4)) {
13497
+ for (const entry of entries.sort(compareCodepoints)) {
14180
13498
  try {
14181
13499
  overviews.push(await loadEvidenceOverview(dataDir, entry));
14182
13500
  } catch {
@@ -14313,26 +13631,10 @@ function parseJson(raw, source) {
14313
13631
  function isRecord11(value) {
14314
13632
  return typeof value === "object" && value !== null && !Array.isArray(value);
14315
13633
  }
14316
- function compareStrings4(a, b) {
14317
- return a.localeCompare(b);
14318
- }
14319
13634
  function findingsFile(evidenceId, findings) {
14320
13635
  return { version: 1, evidenceId, findings };
14321
13636
  }
14322
13637
 
14323
- // src/domains/evidence/types.ts
14324
- init_esm_shims();
14325
- var EVIDENCE_VERSION = 1;
14326
- var FAILURE_CAUSE_TAG_ORDER = [
14327
- "timeout",
14328
- "auth-failure",
14329
- "missing-dependency",
14330
- "build-failure",
14331
- "test-failure",
14332
- "blocked-tool"
14333
- ];
14334
- var FAILURE_CAUSE_TAGS = new Set(FAILURE_CAUSE_TAG_ORDER);
14335
-
14336
13638
  // src/domains/evidence/build.ts
14337
13639
  var MAX_TASK_CHARS = 500;
14338
13640
  var TRANSCRIPT_TEXT_MAX_CHARS = 500;
@@ -14376,7 +13678,15 @@ async function buildEvidence(options) {
14376
13678
  const auditLinks = await linkAuditRows(options.stateDir, source, runSources, sessionLinks);
14377
13679
  const toolEventRows = toolEvents(runSources, sessionLinks, auditLinks);
14378
13680
  const protectedArtifactsRaw = protectedArtifactsFile(sessionLinks);
14379
- const findings = buildFindings(runSources, sessionLinks, auditLinks, protectedArtifactsRaw);
13681
+ const validationEvidence = validationEvidenceByRun(sessionLinks.entries, runSources);
13682
+ const trustStatusRaw = buildEvidenceTrustStatusFile({
13683
+ evidenceId,
13684
+ runSources,
13685
+ gateDecisions: gateDecisions.decisions,
13686
+ auditRows: auditLinks.rows,
13687
+ validationEvidence
13688
+ });
13689
+ const findings = buildFindings(runSources, trustStatusRaw, sessionLinks, auditLinks, protectedArtifactsRaw);
14380
13690
  const tally = createRedactionTally();
14381
13691
  const redactedRunSources = runSources.map((item) => ({
14382
13692
  ...item,
@@ -14393,6 +13703,7 @@ async function buildEvidence(options) {
14393
13703
  readErrors: auditLinks.readErrors
14394
13704
  };
14395
13705
  const protectedArtifacts = redactSecretsDeep(protectedArtifactsRaw, tally);
13706
+ const trustStatus = redactSecretsDeep(trustStatusRaw, tally);
14396
13707
  const overview = buildOverview(
14397
13708
  evidenceId,
14398
13709
  source,
@@ -14414,16 +13725,17 @@ async function buildEvidence(options) {
14414
13725
  redactedAuditLinks,
14415
13726
  redactedToolEvents,
14416
13727
  gateDecisions,
13728
+ trustStatus,
14417
13729
  protectedArtifacts,
14418
13730
  transcript
14419
13731
  );
14420
- return { evidenceId, directory, overview: finalOverview, findings };
13732
+ return { evidenceId, directory, overview: finalOverview, findings, trustStatus };
14421
13733
  }
14422
13734
  function buildOverview(evidenceId, source, runSources, findings, sessionLinks, auditLinks, toolEventRows, protectedArtifacts) {
14423
13735
  const envelopes = runSources.map((item) => item.envelope);
14424
13736
  const receipts = runSources.flatMap((item) => item.receipt === null ? [] : [item.receipt]);
14425
13737
  const toolStats = receipts.flatMap((receipt) => receipt.toolStats);
14426
- const runIds = envelopes.map((envelope) => envelope.id).sort(compareStrings5);
13738
+ const runIds = envelopes.map((envelope) => envelope.id).sort(compareCodepoints);
14427
13739
  const sessionIds = uniqueStrings(
14428
13740
  envelopes.flatMap((envelope) => envelope.sessionId === null ? [] : [envelope.sessionId])
14429
13741
  );
@@ -14468,15 +13780,17 @@ function buildOverview(evidenceId, source, runSources, findings, sessionLinks, a
14468
13780
  files: [...EVIDENCE_FILES]
14469
13781
  };
14470
13782
  }
14471
- function buildFindings(runSources, sessionLinks, auditLinks, protectedArtifacts) {
13783
+ function buildFindings(runSources, trustStatus, sessionLinks, auditLinks, protectedArtifacts) {
14472
13784
  const findings = [];
14473
- const validationRunIds = validationEvidenceRunIds(sessionLinks.entries, runSources, auditLinks.rows);
13785
+ const trustByRun = new Map(trustStatus.runs.map((entry) => [entry.runId, entry.status]));
14474
13786
  for (const source of runSources) {
13787
+ const status = trustByRun.get(source.envelope.id);
13788
+ if (status === void 0) throw new Error(`canonical trust status missing for run ${source.envelope.id}`);
14475
13789
  if (source.receiptError !== null) {
14476
13790
  const tag = source.receiptIntegrityFailed ? "receipt-integrity" : "unknown";
14477
13791
  findings.push(finding(findings.length, "warn", tag, source.envelope.id, source.receiptError));
14478
13792
  }
14479
- if (isSuccessfulRun(source) && !validationRunIds.has(source.envelope.id)) {
13793
+ if (isSuccessfulRun(source) && (status.validationGrounding.state === "absent" || status.validationGrounding.state === "unknown")) {
14480
13794
  findings.push(
14481
13795
  finding(
14482
13796
  findings.length,
@@ -14487,10 +13801,21 @@ function buildFindings(runSources, sessionLinks, auditLinks, protectedArtifacts)
14487
13801
  )
14488
13802
  );
14489
13803
  }
13804
+ if (status.validationGrounding.state === "ungrounded") {
13805
+ findings.push(
13806
+ finding(
13807
+ findings.length,
13808
+ "warn",
13809
+ "proxy-validation",
13810
+ source.envelope.id,
13811
+ "run claimed validation that was not grounded in an observed execution"
13812
+ )
13813
+ );
13814
+ }
14490
13815
  if (source.envelope.cwd.trim().length === 0) {
14491
13816
  findings.push(finding(findings.length, "warn", "cwd-missing", source.envelope.id, "run ledger cwd is empty"));
14492
13817
  }
14493
- const receipt = source.receipt;
13818
+ const receipt = authenticatedReceipt(source);
14494
13819
  const blocked = receipt?.toolStats.reduce((total, stat) => total + stat.blocked, 0) ?? 0;
14495
13820
  if (blocked > 0) {
14496
13821
  findings.push(
@@ -14509,12 +13834,11 @@ function buildFindings(runSources, sessionLinks, auditLinks, protectedArtifacts)
14509
13834
  )
14510
13835
  );
14511
13836
  }
14512
- const autonomyEnforcement = receipt?.autonomyEnforcement;
14513
- if (autonomyEnforcement?.dangerousBypass === true) {
14514
- const message = autonomyEnforcement.externalMode === "agent-managed" ? "run used external agent-managed governance; Clio safety blocks were not enforced" : "run executed with external permission bypass (CLIO_CODER_ALLOW_EXTERNAL_FULL_ACCESS=1); Clio safety blocks were not enforced";
13837
+ if (status.autonomyEnforcement.state === "bypassed") {
13838
+ const message = status.autonomyEnforcement.authority.id === "agent-managed" ? "run used external agent-managed governance; Clio safety blocks were not enforced" : "run executed with external permission bypass (CLIO_CODER_ALLOW_EXTERNAL_FULL_ACCESS=1); Clio safety blocks were not enforced";
14515
13839
  findings.push(finding(findings.length, "warn", "external-bypass", source.envelope.id, message));
14516
- } else if (autonomyEnforcement?.grade === "approximated") {
14517
- const mode = autonomyEnforcement.externalMode ? ` via ${autonomyEnforcement.externalMode}` : "";
13840
+ } else if (status.autonomyEnforcement.state === "approximated") {
13841
+ const mode = status.autonomyEnforcement.authority.id === "external-runtime" ? "" : ` via ${status.autonomyEnforcement.authority.id}`;
14518
13842
  findings.push(
14519
13843
  finding(
14520
13844
  findings.length,
@@ -14601,19 +13925,22 @@ function buildFindings(runSources, sessionLinks, auditLinks, protectedArtifacts)
14601
13925
  }
14602
13926
  return findings;
14603
13927
  }
14604
- function validationEvidenceRunIds(entries, runSources, auditRows) {
14605
- const runIds = /* @__PURE__ */ new Set();
14606
- const sourceRunIds = new Set(runSources.map((source) => source.envelope.id));
13928
+ function validationEvidenceByRun(entries, runSources) {
13929
+ const evidence = /* @__PURE__ */ new Map();
14607
13930
  const calls = /* @__PURE__ */ new Map();
14608
13931
  for (const linked of entries) {
14609
13932
  const runId = validationRunIdFor(linked, runSources);
14610
13933
  const entry = linked.entry;
14611
13934
  if (entry.kind === "bashExecution") {
14612
- if (runId !== null && isSuccessfulValidationBashExecution(entry)) runIds.add(runId);
13935
+ if (runId !== null && isSuccessfulValidationBashExecution(entry)) {
13936
+ addValidationEvidence(evidence, runId, { kind: "session_entry", id: entry.turnId });
13937
+ }
14613
13938
  continue;
14614
13939
  }
14615
13940
  if (entry.kind === "protectedArtifact") {
14616
- if (runId !== null && isValidationProtectedArtifact(entry)) runIds.add(runId);
13941
+ if (runId !== null && isValidationProtectedArtifact(entry)) {
13942
+ addValidationEvidence(evidence, runId, { kind: "session_entry", id: entry.turnId });
13943
+ }
14617
13944
  continue;
14618
13945
  }
14619
13946
  if (entry.kind !== "message") continue;
@@ -14626,16 +13953,16 @@ function validationEvidenceRunIds(entries, runSources, auditRows) {
14626
13953
  const result = extractSessionToolResult(entry, linked);
14627
13954
  if (result.id === null || !isSuccessfulSessionToolResult(result)) continue;
14628
13955
  const candidate = calls.get(result.id);
14629
- if (candidate?.runId !== null && candidate?.runId !== void 0) runIds.add(candidate.runId);
14630
- }
14631
- for (const linked of auditRows) {
14632
- if (linked.auditKind !== "completion_contract") continue;
14633
- if (linked.runId === null || !sourceRunIds.has(linked.runId)) continue;
14634
- if (readOptionalString2(linked.row.decision) !== "ok") continue;
14635
- if (readOptionalString2(linked.row.reason) !== "validation_evidence") continue;
14636
- runIds.add(linked.runId);
13956
+ if (candidate?.runId !== null && candidate?.runId !== void 0) {
13957
+ addValidationEvidence(evidence, candidate.runId, candidate.artifact);
13958
+ }
14637
13959
  }
14638
- return runIds;
13960
+ return evidence;
13961
+ }
13962
+ function addValidationEvidence(evidence, runId, reference) {
13963
+ const current = evidence.get(runId) ?? [];
13964
+ current.push(reference);
13965
+ evidence.set(runId, current);
14639
13966
  }
14640
13967
  function validationRunIdFor(linked, runSources) {
14641
13968
  if (linked.link.runId !== null) return linked.link.runId;
@@ -14643,11 +13970,15 @@ function validationRunIdFor(linked, runSources) {
14643
13970
  return runSources[0]?.envelope.id ?? null;
14644
13971
  }
14645
13972
  function isSuccessfulRun(source) {
14646
- const outcome = source.receipt?.outcome ?? source.envelope.outcome ?? null;
13973
+ const receipt = authenticatedReceipt(source);
13974
+ const outcome = receipt?.outcome ?? source.envelope.outcome ?? null;
14647
13975
  if (outcome !== null) return outcome === "succeeded";
14648
- const exitCode = source.receipt?.exitCode ?? source.envelope.exitCode;
13976
+ const exitCode = receipt?.exitCode ?? source.envelope.exitCode;
14649
13977
  return source.envelope.status === "completed" && exitCode === 0;
14650
13978
  }
13979
+ function authenticatedReceipt(source) {
13980
+ return source.receipt !== null && source.receiptError === null && !source.receiptIntegrityFailed ? source.receipt : null;
13981
+ }
14651
13982
  function isSuccessfulValidationBashExecution(entry) {
14652
13983
  if (entry.cancelled || entry.exitCode !== 0) return false;
14653
13984
  return detectValidationCommand(entry.command).kind === "validation";
@@ -14662,7 +13993,8 @@ function validationToolCallCandidate(entry, linked, runSources) {
14662
13993
  if (validationToolCallSummary(call.tool, call.args) === null) return null;
14663
13994
  return {
14664
13995
  toolCallId: call.id,
14665
- runId: validationRunIdFor(linked, runSources)
13996
+ runId: validationRunIdFor(linked, runSources),
13997
+ artifact: { kind: "session_entry", id: entry.turnId }
14666
13998
  };
14667
13999
  }
14668
14000
  function validationToolCallSummary(toolName, args) {
@@ -14680,8 +14012,10 @@ function validationToolCallSummary(toolName, args) {
14680
14012
  const target = readOptionalString2(argRecord?.path) ?? "artifact";
14681
14013
  return `verify frontend ${target}`;
14682
14014
  }
14683
- if (check === null || !isVerificationScriptName(check)) return null;
14684
- return `npm run ${check}`;
14015
+ if (check === null) return null;
14016
+ if (isVerificationScriptName(check)) return `npm run ${check}`;
14017
+ if (isProjectVerifierCheckId(check)) return `verify ${check}`;
14018
+ return null;
14685
14019
  }
14686
14020
  return null;
14687
14021
  }
@@ -14700,23 +14034,24 @@ function finding(index, severity, tag, runId, message) {
14700
14034
  message
14701
14035
  };
14702
14036
  }
14703
- async function writeEvidenceFiles(directory, overview, runSources, findings, sessionLinks, auditLinks, toolEventRows, gateDecisions, protectedArtifacts, transcript) {
14037
+ async function writeEvidenceFiles(directory, overview, runSources, findings, sessionLinks, auditLinks, toolEventRows, gateDecisions, trustStatus, protectedArtifacts, transcript) {
14704
14038
  await mkdir(directory, { recursive: true });
14705
- await writeJson(join19(directory, "overview.json"), overview);
14039
+ await writeJson(join16(directory, "overview.json"), overview);
14706
14040
  await writeFile(
14707
- join19(directory, "transcript.md"),
14041
+ join16(directory, "transcript.md"),
14708
14042
  transcript ?? renderTranscript(overview, runSources, sessionLinks),
14709
14043
  "utf8"
14710
14044
  );
14711
- await writeJsonl(join19(directory, "trace.raw.jsonl"), rawTraceRows(runSources));
14712
- await writeJsonl(join19(directory, "trace.cleaned.jsonl"), cleanedTraceRows(runSources, findings, toolEventRows));
14713
- await writeJsonl(join19(directory, "tool-events.jsonl"), toolEventRows);
14714
- await writeJsonl(join19(directory, "audit-linked.jsonl"), auditLinks.rows);
14715
- await writeJson(join19(directory, "receipt.json"), receiptsFile(runSources));
14716
- await writeJson(join19(directory, "gate-decisions.json"), gateDecisions);
14717
- await writeJson(join19(directory, "protected-artifacts.json"), protectedArtifacts);
14718
- await writeJson(join19(directory, "findings.json"), findingsFile(overview.evidenceId, [...findings]));
14719
- await writeFile(join19(directory, "findings.md"), renderFindings(findings), "utf8");
14045
+ await writeJsonl(join16(directory, "trace.raw.jsonl"), rawTraceRows(runSources));
14046
+ await writeJsonl(join16(directory, "trace.cleaned.jsonl"), cleanedTraceRows(runSources, findings, toolEventRows));
14047
+ await writeJsonl(join16(directory, "tool-events.jsonl"), toolEventRows);
14048
+ await writeJsonl(join16(directory, "audit-linked.jsonl"), auditLinks.rows);
14049
+ await writeJson(join16(directory, "receipt.json"), receiptsFile(runSources));
14050
+ await writeJson(join16(directory, "gate-decisions.json"), gateDecisions);
14051
+ await writeJson(join16(directory, "trust-status.json"), trustStatus);
14052
+ await writeJson(join16(directory, "protected-artifacts.json"), protectedArtifacts);
14053
+ await writeJson(join16(directory, "findings.json"), findingsFile(overview.evidenceId, [...findings]));
14054
+ await writeFile(join16(directory, "findings.md"), renderFindings(findings), "utf8");
14720
14055
  }
14721
14056
  function rawTraceRows(runSources) {
14722
14057
  const rows = [];
@@ -14835,7 +14170,7 @@ function linkSessionEntry(entry, windows) {
14835
14170
  if (stamped !== null) {
14836
14171
  return { runId: stamped, kind: "entry-run-id", confidence: "exact", candidateRunIds: [stamped] };
14837
14172
  }
14838
- const candidates = windows.filter((window) => timestampInRunWindow(entry.timestamp, window)).map((window) => window.runId).sort(compareStrings5);
14173
+ const candidates = windows.filter((window) => timestampInRunWindow(entry.timestamp, window)).map((window) => window.runId).sort(compareCodepoints);
14839
14174
  const only = candidates.length === 1 ? candidates[0] : void 0;
14840
14175
  if (only !== void 0) {
14841
14176
  return { runId: only, kind: "timestamp-window", confidence: "best-effort", candidateRunIds: candidates };
@@ -14867,7 +14202,7 @@ function attributionWindows(ledger, runSources, sessionIds) {
14867
14202
  if (windows.has(id) || !linkedSessions.has(sessionId)) continue;
14868
14203
  windows.set(id, { runId: id, startedAt, endedAt: readOptionalString2(row.endedAt) });
14869
14204
  }
14870
- return [...windows.values()].sort((left, right) => compareStrings5(left.runId, right.runId));
14205
+ return [...windows.values()].sort((left, right) => compareCodepoints(left.runId, right.runId));
14871
14206
  }
14872
14207
  function evidenceRunLink(link) {
14873
14208
  return {
@@ -14884,11 +14219,11 @@ function timestampInRunWindow(timestamp, envelope) {
14884
14219
  return value >= start && value <= end;
14885
14220
  }
14886
14221
  function compareLinkedSessionEntries(a, b) {
14887
- const byTimestamp = compareStrings5(a.entry.timestamp, b.entry.timestamp);
14222
+ const byTimestamp = compareCodepoints(a.entry.timestamp, b.entry.timestamp);
14888
14223
  if (byTimestamp !== 0) return byTimestamp;
14889
- const bySession = compareStrings5(a.sessionId, b.sessionId);
14224
+ const bySession = compareCodepoints(a.sessionId, b.sessionId);
14890
14225
  if (bySession !== 0) return bySession;
14891
- return compareStrings5(a.entry.turnId, b.entry.turnId);
14226
+ return compareCodepoints(a.entry.turnId, b.entry.turnId);
14892
14227
  }
14893
14228
  function sessionToolEvents(entries) {
14894
14229
  const calls = /* @__PURE__ */ new Map();
@@ -15002,9 +14337,9 @@ function extractSessionToolResult(entry, linked) {
15002
14337
  };
15003
14338
  }
15004
14339
  function compareSessionToolCalls(a, b) {
15005
- const byTimestamp = compareStrings5(a.timestamp, b.timestamp);
14340
+ const byTimestamp = compareCodepoints(a.timestamp, b.timestamp);
15006
14341
  if (byTimestamp !== 0) return byTimestamp;
15007
- return compareStrings5(a.id, b.id);
14342
+ return compareCodepoints(a.id, b.id);
15008
14343
  }
15009
14344
  async function linkAuditRows(stateDir, source, runSources, sessionLinks) {
15010
14345
  const auditRows = await readAuditRows(stateDir);
@@ -15089,7 +14424,7 @@ function bestEffortAuditLink(audit, source, runSources, sessionIds) {
15089
14424
  linkKind: "ambiguous-timestamp-tool",
15090
14425
  confidence: "best-effort",
15091
14426
  reasons: ["audit timestamp and tool matched multiple runs in this session"],
15092
- candidateRunIds: candidates.map((item) => item.envelope.id).sort(compareStrings5)
14427
+ candidateRunIds: candidates.map((item) => item.envelope.id).sort(compareCodepoints)
15093
14428
  };
15094
14429
  }
15095
14430
  if (source.kind === "session" && sessionIds.has(source.sessionId)) {
@@ -15156,12 +14491,12 @@ function auditToolEvents(rows) {
15156
14491
  function compareAuditLinkedRows(a, b) {
15157
14492
  const byTs = compareNullableStrings(a.ts, b.ts);
15158
14493
  if (byTs !== 0) return byTs;
15159
- const byKind = compareStrings5(a.auditKind, b.auditKind);
14494
+ const byKind = compareCodepoints(a.auditKind, b.auditKind);
15160
14495
  if (byKind !== 0) return byKind;
15161
14496
  const aCorrelation = readOptionalString2(a.row.correlationId) ?? "";
15162
14497
  const bCorrelation = readOptionalString2(b.row.correlationId) ?? "";
15163
- if (aCorrelation !== bCorrelation) return compareStrings5(aCorrelation, bCorrelation);
15164
- return JSON.stringify(a.row).localeCompare(JSON.stringify(b.row));
14498
+ if (aCorrelation !== bCorrelation) return compareCodepoints(aCorrelation, bCorrelation);
14499
+ return compareCodepoints(JSON.stringify(a.row), JSON.stringify(b.row));
15165
14500
  }
15166
14501
  function receiptsFile(runSources) {
15167
14502
  return {
@@ -15198,7 +14533,7 @@ function protectedArtifactsFile(sessionLinks) {
15198
14533
  };
15199
14534
  }
15200
14535
  function compareProtectedArtifactEvents(left, right) {
15201
- return compareStrings5(left.timestamp, right.timestamp) || compareStrings5(left.sessionId, right.sessionId) || compareStrings5(left.turnId, right.turnId) || compareStrings5(left.artifact.path, right.artifact.path);
14536
+ return compareCodepoints(left.timestamp, right.timestamp) || compareCodepoints(left.sessionId, right.sessionId) || compareCodepoints(left.turnId, right.turnId) || compareCodepoints(left.artifact.path, right.artifact.path);
15202
14537
  }
15203
14538
  function renderTranscript(overview, runSources, sessionLinks) {
15204
14539
  const lines = [
@@ -15259,7 +14594,7 @@ function renderSessionTranscriptEntry(linked) {
15259
14594
  const error = result.isError ? " error=true" : "";
15260
14595
  return [`${prefix} tool_result ${result.tool}${id}${error}: ${previewUnknown(result.result)}`];
15261
14596
  }
15262
- const text = collapseWhitespace2(extractTextFromPayload(entry.payload));
14597
+ const text = collapseWhitespace(extractTextFromPayload(entry.payload));
15263
14598
  const rendered = text.length > 0 ? truncateText(text, TRANSCRIPT_TEXT_MAX_CHARS) : previewUnknown(entry.payload);
15264
14599
  return [`${prefix} ${entry.role}: ${rendered}`];
15265
14600
  }
@@ -15344,6 +14679,18 @@ function renderSessionTranscriptEntry(linked) {
15344
14679
  ];
15345
14680
  }
15346
14681
  if (entry.kind === "custom") return [`${prefix} custom:${entry.customType} ${previewUnknown(entry.data)}`];
14682
+ if (entry.kind === "contextEviction") {
14683
+ const pressure = entry.pressureBefore === null ? "" : ` pressure=${entry.pressureBefore.toFixed(3)}`;
14684
+ return [
14685
+ `${prefix} contextEviction policy=${entry.policyId} trigger=${entry.trigger} items=${entry.evicted.length} tokens=${entry.tokensBefore}->${entry.tokensAfter}${pressure}`,
14686
+ ...entry.evicted.map(
14687
+ (item) => ` evicted ref=${item.ref.entry} reason=${item.reason}${item.by === void 0 ? "" : ` by=${item.by}`} freed=${item.tokensFreed}`
14688
+ )
14689
+ ];
14690
+ }
14691
+ if (entry.kind === "contextRecall") {
14692
+ return [`${prefix} contextRecall ref=${entry.ref.entry} trigger=${entry.trigger} tokens=${entry.tokensReadmitted}`];
14693
+ }
15347
14694
  const _exhaustive = entry;
15348
14695
  return [`${prefix} ${String(_exhaustive)}`];
15349
14696
  }
@@ -15359,10 +14706,10 @@ function renderFindings(findings) {
15359
14706
  `;
15360
14707
  }
15361
14708
  async function readRunLedger(stateDir) {
15362
- const target = join19(stateDir, "runs.json");
14709
+ const target = join16(stateDir, "runs.json");
15363
14710
  let raw;
15364
14711
  try {
15365
- raw = await readFile3(target, "utf8");
14712
+ raw = await readFile2(target, "utf8");
15366
14713
  } catch (error) {
15367
14714
  const err = error;
15368
14715
  if (err.code === "ENOENT") throw new Error("run ledger not found");
@@ -15380,10 +14727,10 @@ function selectRunEnvelopes(ledger, source) {
15380
14727
  });
15381
14728
  }
15382
14729
  async function readReceipt(stateDir, envelope) {
15383
- const receiptPath = envelope.receiptPath ?? join19(stateDir, "receipts", `${envelope.id}.json`);
14730
+ const receiptPath = envelope.receiptPath ?? join16(stateDir, "receipts", `${envelope.id}.json`);
15384
14731
  let raw;
15385
14732
  try {
15386
- raw = await readFile3(receiptPath, "utf8");
14733
+ raw = await readFile2(receiptPath, "utf8");
15387
14734
  } catch (error) {
15388
14735
  const err = error;
15389
14736
  if (err.code === "ENOENT") {
@@ -15391,9 +14738,18 @@ async function readReceipt(stateDir, envelope) {
15391
14738
  }
15392
14739
  return { receipt: null, error: `receipt read error: ${err.message ?? String(err)}`, integrityFailed: false };
15393
14740
  }
15394
- const parsed = parseJson2(raw, receiptPath);
15395
- const receipt = parseRunReceipt(parsed, receiptPath);
15396
- const integrity = verifyReceiptIntegrity(receipt, envelope);
14741
+ let receipt;
14742
+ try {
14743
+ const parsed = parseJson2(raw, receiptPath);
14744
+ receipt = parseRunReceipt(parsed, receiptPath);
14745
+ } catch (error) {
14746
+ return {
14747
+ receipt: null,
14748
+ error: `receipt invalid: ${error instanceof Error ? error.message : String(error)}`,
14749
+ integrityFailed: true
14750
+ };
14751
+ }
14752
+ const integrity = inspectRunReceiptTrustStatus(receipt, envelope).integrity;
15397
14753
  if (!integrity.ok) {
15398
14754
  return { receipt, error: `receipt integrity: ${integrity.reason}`, integrityFailed: true };
15399
14755
  }
@@ -15582,15 +14938,15 @@ function extractTextFromPayload(payload) {
15582
14938
  }
15583
14939
  function previewUnknown(value) {
15584
14940
  if (value === void 0) return "";
15585
- if (typeof value === "string") return truncateText(collapseWhitespace2(value), TOOL_PREVIEW_MAX_CHARS);
14941
+ if (typeof value === "string") return truncateText(collapseWhitespace(value), TOOL_PREVIEW_MAX_CHARS);
15586
14942
  try {
15587
14943
  const text = JSON.stringify(value);
15588
- return text === void 0 ? "" : truncateText(collapseWhitespace2(text), TOOL_PREVIEW_MAX_CHARS);
14944
+ return text === void 0 ? "" : truncateText(collapseWhitespace(text), TOOL_PREVIEW_MAX_CHARS);
15589
14945
  } catch {
15590
- return truncateText(collapseWhitespace2(String(value)), TOOL_PREVIEW_MAX_CHARS);
14946
+ return truncateText(collapseWhitespace(String(value)), TOOL_PREVIEW_MAX_CHARS);
15591
14947
  }
15592
14948
  }
15593
- function collapseWhitespace2(text) {
14949
+ function collapseWhitespace(text) {
15594
14950
  return text.replace(/\s+/g, " ").trim();
15595
14951
  }
15596
14952
  async function writeJson(path2, value) {
@@ -15609,34 +14965,31 @@ function durationMs(startedAt, endedAt) {
15609
14965
  }
15610
14966
  function earliest(values) {
15611
14967
  if (values.length === 0) return null;
15612
- return [...values].sort(compareStrings5)[0] ?? null;
14968
+ return [...values].sort(compareCodepoints)[0] ?? null;
15613
14969
  }
15614
14970
  function latest(values) {
15615
14971
  if (values.length === 0) return null;
15616
- return [...values].sort(compareStrings5).at(-1) ?? null;
14972
+ return [...values].sort(compareCodepoints).at(-1) ?? null;
15617
14973
  }
15618
14974
  function uniqueStrings(values) {
15619
- return [...new Set(values)].sort(compareStrings5);
14975
+ return [...new Set(values)].sort(compareCodepoints);
15620
14976
  }
15621
14977
  function uniqueTags(values) {
15622
- return [...new Set(values)].sort(compareStrings5);
15623
- }
15624
- function compareStrings5(a, b) {
15625
- return a.localeCompare(b);
14978
+ return [...new Set(values)].sort(compareCodepoints);
15626
14979
  }
15627
14980
  function compareNullableStrings(a, b) {
15628
14981
  if (a === b) return 0;
15629
14982
  if (a === null) return 1;
15630
14983
  if (b === null) return -1;
15631
- return compareStrings5(a, b);
14984
+ return compareCodepoints(a, b);
15632
14985
  }
15633
14986
  function compareRuns(a, b) {
15634
- const byStart = compareStrings5(a.startedAt, b.startedAt);
14987
+ const byStart = compareCodepoints(a.startedAt, b.startedAt);
15635
14988
  if (byStart !== 0) return byStart;
15636
- return compareStrings5(a.id, b.id);
14989
+ return compareCodepoints(a.id, b.id);
15637
14990
  }
15638
14991
  function compareToolStats(a, b) {
15639
- return compareStrings5(a.tool, b.tool);
14992
+ return compareCodepoints(a.tool, b.tool);
15640
14993
  }
15641
14994
  function compareEvidenceToolEvents(a, b) {
15642
14995
  const byTimestamp = compareNullableStrings(a.timestamp ?? null, b.timestamp ?? null);
@@ -15645,7 +14998,7 @@ function compareEvidenceToolEvents(a, b) {
15645
14998
  if (byRun !== 0) return byRun;
15646
14999
  const bySession = compareNullableStrings(a.sessionId, b.sessionId);
15647
15000
  if (bySession !== 0) return bySession;
15648
- const byTool = compareStrings5(a.tool, b.tool);
15001
+ const byTool = compareCodepoints(a.tool, b.tool);
15649
15002
  if (byTool !== 0) return byTool;
15650
15003
  return compareNullableStrings(a.toolCallId ?? null, b.toolCallId ?? null);
15651
15004
  }
@@ -15661,8 +15014,8 @@ function sanitizeEvidenceId(value) {
15661
15014
 
15662
15015
  // src/domains/evidence/eval.ts
15663
15016
  init_esm_shims();
15664
- import { mkdir as mkdir2, readdir as readdir3, readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
15665
- import { join as join20 } from "node:path";
15017
+ import { mkdir as mkdir2, readdir as readdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
15018
+ import { join as join17 } from "node:path";
15666
15019
 
15667
15020
  // src/domains/eval/index.ts
15668
15021
  init_esm_shims();
@@ -15712,12 +15065,13 @@ var EVAL_EVIDENCE_FILES = [
15712
15065
  "audit-linked.jsonl",
15713
15066
  "receipt.json",
15714
15067
  "gate-decisions.json",
15068
+ "trust-status.json",
15715
15069
  "protected-artifacts.json",
15716
15070
  "eval-result.json",
15717
15071
  "findings.json",
15718
15072
  "findings.md"
15719
15073
  ];
15720
- var PREVIEW_MAX_CHARS2 = 240;
15074
+ var PREVIEW_MAX_CHARS = 240;
15721
15075
  async function buildEvalEvidence(options) {
15722
15076
  if (options.evalId !== void 0 && options.artifact !== void 0) {
15723
15077
  throw new Error("build eval evidence accepts either evalId or artifact, not both");
@@ -15740,8 +15094,23 @@ async function buildEvalEvidence(options) {
15740
15094
  options.stateDir
15741
15095
  ).map((entry) => entry.artifact)
15742
15096
  };
15743
- await writeEvalEvidenceFiles(directory, artifact, overview, findings, toolEventRows, linkedRuns, gateDecisions);
15744
- return { evidenceId, directory, overview, findings };
15097
+ const trustStatus = buildEvidenceTrustStatusFile({
15098
+ evidenceId,
15099
+ runSources: linkedRuns.runSources,
15100
+ gateDecisions: gateDecisions.decisions,
15101
+ auditRows: linkedRuns.auditRows
15102
+ });
15103
+ await writeEvalEvidenceFiles(
15104
+ directory,
15105
+ artifact,
15106
+ overview,
15107
+ findings,
15108
+ toolEventRows,
15109
+ linkedRuns,
15110
+ gateDecisions,
15111
+ trustStatus
15112
+ );
15113
+ return { evidenceId, directory, overview, findings, trustStatus };
15745
15114
  }
15746
15115
  function evalEvidenceId(evalId) {
15747
15116
  return `eval-${sanitizeEvidenceId2(evalId)}`;
@@ -15756,7 +15125,7 @@ function evalOverview(evidenceId, artifact, findings, toolEventRows, linkedRuns,
15756
15125
  evidenceId,
15757
15126
  source: { kind: "eval", evalId: artifact.evalId },
15758
15127
  generatedAt: artifact.endedAt,
15759
- runIds: envelopes.length > 0 ? uniqueStrings2(envelopes.map((envelope) => envelope.id)) : artifact.results.map((result) => result.runId).sort(compareStrings6),
15128
+ runIds: envelopes.length > 0 ? uniqueStrings2(envelopes.map((envelope) => envelope.id)) : artifact.results.map((result) => result.runId).sort(compareCodepoints),
15760
15129
  sessionId: uniqueStrings2(envelopes.flatMap((envelope) => envelope.sessionId === null ? [] : [envelope.sessionId]))[0] ?? null,
15761
15130
  statuses: envelopes.length > 0 ? uniqueStrings2(envelopes.map((envelope) => envelope.status)) : uniqueStrings2(artifact.results.map((result) => result.pass ? "passed" : "failed")),
15762
15131
  startedAt: artifact.startedAt,
@@ -15843,7 +15212,7 @@ function evalToolEvents(artifact) {
15843
15212
  }
15844
15213
  return events.sort(compareEvidenceToolEvents2);
15845
15214
  }
15846
- async function writeEvalEvidenceFiles(directory, artifact, overview, findings, toolEventRows, linkedRuns, gateDecisions) {
15215
+ async function writeEvalEvidenceFiles(directory, artifact, overview, findings, toolEventRows, linkedRuns, gateDecisions, trustStatus) {
15847
15216
  const emptyProtected = { version: EVIDENCE_VERSION, artifacts: [], events: [] };
15848
15217
  const receiptsFile2 = {
15849
15218
  version: EVIDENCE_VERSION,
@@ -15851,18 +15220,19 @@ async function writeEvalEvidenceFiles(directory, artifact, overview, findings, t
15851
15220
  };
15852
15221
  const redactedArtifact = redactArtifactForStorage(artifact);
15853
15222
  await mkdir2(directory, { recursive: true });
15854
- await writeJson2(join20(directory, "overview.json"), overview);
15855
- await writeFile2(join20(directory, "transcript.md"), renderEvalTranscript(redactedArtifact, overview), "utf8");
15856
- await writeJsonl2(join20(directory, "trace.raw.jsonl"), rawEvalTraceRows(redactedArtifact));
15857
- await writeJsonl2(join20(directory, "trace.cleaned.jsonl"), cleanedEvalTraceRows(redactedArtifact, findings));
15858
- await writeJsonl2(join20(directory, "tool-events.jsonl"), redactArtifactForStorage(toolEventRows));
15859
- await writeJsonl2(join20(directory, "audit-linked.jsonl"), linkedRuns.auditRows);
15860
- await writeJson2(join20(directory, "receipt.json"), receiptsFile2);
15861
- await writeJson2(join20(directory, "gate-decisions.json"), gateDecisions);
15862
- await writeJson2(join20(directory, "protected-artifacts.json"), emptyProtected);
15863
- await writeJson2(join20(directory, "eval-result.json"), redactedArtifact);
15864
- await writeJson2(join20(directory, "findings.json"), findingsFile(overview.evidenceId, [...findings]));
15865
- await writeFile2(join20(directory, "findings.md"), renderFindings2(findings), "utf8");
15223
+ await writeJson2(join17(directory, "overview.json"), overview);
15224
+ await writeFile2(join17(directory, "transcript.md"), renderEvalTranscript(redactedArtifact, overview), "utf8");
15225
+ await writeJsonl2(join17(directory, "trace.raw.jsonl"), rawEvalTraceRows(redactedArtifact));
15226
+ await writeJsonl2(join17(directory, "trace.cleaned.jsonl"), cleanedEvalTraceRows(redactedArtifact, findings));
15227
+ await writeJsonl2(join17(directory, "tool-events.jsonl"), redactArtifactForStorage(toolEventRows));
15228
+ await writeJsonl2(join17(directory, "audit-linked.jsonl"), linkedRuns.auditRows);
15229
+ await writeJson2(join17(directory, "receipt.json"), receiptsFile2);
15230
+ await writeJson2(join17(directory, "gate-decisions.json"), gateDecisions);
15231
+ await writeJson2(join17(directory, "trust-status.json"), trustStatus);
15232
+ await writeJson2(join17(directory, "protected-artifacts.json"), emptyProtected);
15233
+ await writeJson2(join17(directory, "eval-result.json"), redactedArtifact);
15234
+ await writeJson2(join17(directory, "findings.json"), findingsFile(overview.evidenceId, [...findings]));
15235
+ await writeFile2(join17(directory, "findings.md"), renderFindings2(findings), "utf8");
15866
15236
  }
15867
15237
  function rawEvalTraceRows(artifact) {
15868
15238
  return artifact.results.map((result) => ({
@@ -15971,22 +15341,22 @@ async function writeJsonl2(path2, rows) {
15971
15341
  }
15972
15342
  function commandPreview(command) {
15973
15343
  const text = command.stderr.length > 0 ? command.stderr : command.stdout;
15974
- return truncateText2(text, PREVIEW_MAX_CHARS2);
15344
+ return truncateText2(text, PREVIEW_MAX_CHARS);
15975
15345
  }
15976
15346
  function truncateText2(value, maxChars) {
15977
15347
  if (value.length <= maxChars) return value;
15978
15348
  return `${value.slice(0, Math.max(0, maxChars - 1))}\u2026`;
15979
15349
  }
15980
15350
  function uniqueStrings2(values) {
15981
- return [...new Set(values)].sort(compareStrings6);
15351
+ return [...new Set(values)].sort(compareCodepoints);
15982
15352
  }
15983
15353
  function uniqueTags2(values) {
15984
- return [...new Set(values)].sort(compareStrings6);
15354
+ return [...new Set(values)].sort(compareCodepoints);
15985
15355
  }
15986
15356
  function compareEvidenceToolEvents2(a, b) {
15987
15357
  const byRun = compareNullableStrings2(a.runId, b.runId);
15988
15358
  if (byRun !== 0) return byRun;
15989
- const byTool = compareStrings6(a.tool, b.tool);
15359
+ const byTool = compareCodepoints(a.tool, b.tool);
15990
15360
  if (byTool !== 0) return byTool;
15991
15361
  const byArgs = compareNullableStrings2(a.argsPreview ?? null, b.argsPreview ?? null);
15992
15362
  if (byArgs !== 0) return byArgs;
@@ -16013,7 +15383,7 @@ async function linkEvalRuns(stateDir, artifact) {
16013
15383
  }
16014
15384
  async function readRunLedger2(stateDir) {
16015
15385
  try {
16016
- const raw = await readFile4(join20(stateDir, "runs.json"), "utf8");
15386
+ const raw = await readFile3(join17(stateDir, "runs.json"), "utf8");
16017
15387
  const parsed = JSON.parse(raw);
16018
15388
  return Array.isArray(parsed) ? parsed.filter(isRecord13) : [];
16019
15389
  } catch {
@@ -16024,9 +15394,9 @@ function evalRunMatches(artifact, envelope) {
16024
15394
  return artifact.results.some((result) => result.runId === envelope.id);
16025
15395
  }
16026
15396
  async function readReceiptForRun(stateDir, envelope) {
16027
- const path2 = envelope.receiptPath ?? join20(stateDir, "receipts", `${envelope.id}.json`);
15397
+ const path2 = envelope.receiptPath ?? join17(stateDir, "receipts", `${envelope.id}.json`);
16028
15398
  try {
16029
- const parsed = JSON.parse(await readFile4(path2, "utf8"));
15399
+ const parsed = JSON.parse(await readFile3(path2, "utf8"));
16030
15400
  return isRecord13(parsed) ? parsed : null;
16031
15401
  } catch {
16032
15402
  return null;
@@ -16038,7 +15408,7 @@ async function countSessionEntries(stateDir, sessionIds) {
16038
15408
  const path2 = await findSessionLedgerPath(stateDir, sessionId);
16039
15409
  if (path2 === null) continue;
16040
15410
  try {
16041
- const raw = await readFile4(path2, "utf8");
15411
+ const raw = await readFile3(path2, "utf8");
16042
15412
  count += raw.split("\n").filter((line) => line.trim().length > 0).filter((line) => {
16043
15413
  try {
16044
15414
  const parsed = JSON.parse(line);
@@ -16053,17 +15423,17 @@ async function countSessionEntries(stateDir, sessionIds) {
16053
15423
  return count;
16054
15424
  }
16055
15425
  async function findSessionLedgerPath(stateDir, sessionId) {
16056
- const root = join20(stateDir, "sessions");
15426
+ const root = join17(stateDir, "sessions");
16057
15427
  let cwdHashes;
16058
15428
  try {
16059
- cwdHashes = await readdir3(root);
15429
+ cwdHashes = await readdir2(root);
16060
15430
  } catch {
16061
15431
  return null;
16062
15432
  }
16063
- for (const cwdHash2 of cwdHashes) {
16064
- const path2 = join20(root, cwdHash2, sessionId, "current.jsonl");
15433
+ for (const cwdHash of cwdHashes) {
15434
+ const path2 = join17(root, cwdHash, sessionId, "current.jsonl");
16065
15435
  try {
16066
- await readFile4(path2, "utf8");
15436
+ await readFile3(path2, "utf8");
16067
15437
  return path2;
16068
15438
  } catch {
16069
15439
  }
@@ -16071,16 +15441,16 @@ async function findSessionLedgerPath(stateDir, sessionId) {
16071
15441
  return null;
16072
15442
  }
16073
15443
  async function linkedEvalAuditRows(stateDir, runIds, artifact) {
16074
- const root = join20(stateDir, "audit");
15444
+ const root = join17(stateDir, "audit");
16075
15445
  let files;
16076
15446
  try {
16077
- files = await readdir3(root);
15447
+ files = await readdir2(root);
16078
15448
  } catch {
16079
15449
  return [];
16080
15450
  }
16081
15451
  const rows = [];
16082
- for (const file of files.filter((name) => name.endsWith(".jsonl")).sort(compareStrings6)) {
16083
- const raw = await readFile4(join20(root, file), "utf8").catch(() => "");
15452
+ for (const file of files.filter((name) => name.endsWith(".jsonl")).sort(compareCodepoints)) {
15453
+ const raw = await readFile3(join17(root, file), "utf8").catch(() => "");
16084
15454
  const lines = raw.split("\n");
16085
15455
  for (let index = 0; index < lines.length; index += 1) {
16086
15456
  const line = lines[index];
@@ -16144,27 +15514,24 @@ function timestampInEvalWindow(timestamp, artifact) {
16144
15514
  return Number.isFinite(value) && Number.isFinite(start) && Number.isFinite(end) && value >= start && value <= end;
16145
15515
  }
16146
15516
  function compareRunEnvelopes(a, b) {
16147
- return compareStrings6(a.startedAt, b.startedAt) || compareStrings6(a.id, b.id);
15517
+ return compareCodepoints(a.startedAt, b.startedAt) || compareCodepoints(a.id, b.id);
16148
15518
  }
16149
15519
  function compareAuditRows(a, b) {
16150
- return compareNullableStrings2(a.ts, b.ts) || compareNullableStrings2(a.runId, b.runId) || JSON.stringify(a.row).localeCompare(JSON.stringify(b.row));
15520
+ return compareNullableStrings2(a.ts, b.ts) || compareNullableStrings2(a.runId, b.runId) || compareCodepoints(JSON.stringify(a.row), JSON.stringify(b.row));
16151
15521
  }
16152
15522
  function compareToolStats2(a, b) {
16153
- return compareStrings6(a.tool, b.tool);
15523
+ return compareCodepoints(a.tool, b.tool);
16154
15524
  }
16155
15525
  function compareNullableStrings2(a, b) {
16156
15526
  if (a === b) return 0;
16157
15527
  if (a === null) return -1;
16158
15528
  if (b === null) return 1;
16159
- return compareStrings6(a, b);
15529
+ return compareCodepoints(a, b);
16160
15530
  }
16161
15531
  function sanitizeEvidenceId2(value) {
16162
15532
  const sanitized = value.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
16163
15533
  return sanitized.length === 0 ? "unknown" : sanitized;
16164
15534
  }
16165
- function compareStrings6(a, b) {
16166
- return a.localeCompare(b);
16167
- }
16168
15535
  function isRecord13(value) {
16169
15536
  return typeof value === "object" && value !== null && !Array.isArray(value);
16170
15537
  }
@@ -16380,26 +15747,19 @@ export {
16380
15747
  createWriteBoundaryEnforcer,
16381
15748
  DispatchDomainModule,
16382
15749
  createDispatchDomainModule,
16383
- collectSessionEntries,
16384
- filterEntriesToActivePath,
16385
- readAuditRows,
16386
- parseSessionEntries,
16387
- listSessionLedgerRefs,
16388
- protectedArtifactEntryFromArtifact,
16389
- protectedArtifactStateFromSessionEntries,
16390
- ledgerUsageCalls,
16391
- SessionDomainModule,
16392
15750
  extractRunProvenance,
16393
15751
  provenanceTranscriptLines,
16394
15752
  provenanceCompactSuffix,
15753
+ adaptRunReceiptTrustStatus,
15754
+ inspectRunReceiptTrustStatus,
15755
+ FAILURE_CAUSE_TAGS,
16395
15756
  evidenceDirectory,
16396
15757
  EvidenceNotFoundError,
16397
15758
  inspectEvidence,
16398
15759
  loadEvidenceRunProvenance,
16399
15760
  listEvidenceOverviews,
16400
- FAILURE_CAUSE_TAGS,
16401
15761
  buildEvidence,
16402
15762
  summarizeEvalResults,
16403
15763
  buildEvalEvidence
16404
15764
  };
16405
- //# sourceMappingURL=chunk-6EJV5X2W.js.map
15765
+ //# sourceMappingURL=chunk-QQL5RT5M.js.map