harnery 0.34.1 → 0.36.0

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 (692) hide show
  1. package/dist/commander.d.ts +30 -5
  2. package/dist/commander.d.ts.map +1 -1
  3. package/dist/commander.js +124 -94
  4. package/dist/commands/agents.d.ts +37 -6
  5. package/dist/commands/agents.d.ts.map +1 -1
  6. package/dist/commands/agents.js +466 -371
  7. package/dist/commands/backup.d.ts.map +1 -1
  8. package/dist/commands/backup.js +10 -10
  9. package/dist/commands/browse-session.d.ts.map +1 -1
  10. package/dist/commands/browse-session.js +12 -0
  11. package/dist/commands/browse.d.ts +1 -1
  12. package/dist/commands/browse.d.ts.map +1 -1
  13. package/dist/commands/browse.js +31 -6
  14. package/dist/commands/conversations.d.ts +10 -0
  15. package/dist/commands/conversations.d.ts.map +1 -0
  16. package/dist/commands/conversations.js +201 -0
  17. package/dist/commands/decision.d.ts.map +1 -1
  18. package/dist/commands/decision.js +2 -2
  19. package/dist/commands/deinit.d.ts.map +1 -1
  20. package/dist/commands/deinit.js +5 -0
  21. package/dist/commands/docs.d.ts.map +1 -1
  22. package/dist/commands/docs.js +13 -2
  23. package/dist/commands/doctor.d.ts +5 -0
  24. package/dist/commands/doctor.d.ts.map +1 -1
  25. package/dist/commands/doctor.js +51 -7
  26. package/dist/commands/events.d.ts.map +1 -1
  27. package/dist/commands/events.js +18 -1
  28. package/dist/commands/fetch.js +6 -5
  29. package/dist/commands/files.d.ts +22 -0
  30. package/dist/commands/files.d.ts.map +1 -0
  31. package/dist/commands/files.js +113 -0
  32. package/dist/commands/governor.js +14 -12
  33. package/dist/commands/inbox.d.ts +5 -0
  34. package/dist/commands/inbox.d.ts.map +1 -0
  35. package/dist/commands/inbox.js +57 -0
  36. package/dist/commands/init.d.ts +4 -5
  37. package/dist/commands/init.d.ts.map +1 -1
  38. package/dist/commands/init.js +63 -13
  39. package/dist/commands/ledger-v3.d.ts.map +1 -1
  40. package/dist/commands/ledger-v3.js +347 -1
  41. package/dist/commands/logs.d.ts +4 -0
  42. package/dist/commands/logs.d.ts.map +1 -0
  43. package/dist/commands/logs.js +169 -0
  44. package/dist/commands/messages.d.ts +5 -0
  45. package/dist/commands/messages.d.ts.map +1 -0
  46. package/dist/commands/messages.js +45 -0
  47. package/dist/commands/outline.d.ts +1 -1
  48. package/dist/commands/outline.d.ts.map +1 -1
  49. package/dist/commands/outline.js +2 -2
  50. package/dist/commands/presence.d.ts.map +1 -1
  51. package/dist/commands/presence.js +2 -2
  52. package/dist/commands/read.d.ts +1 -1
  53. package/dist/commands/read.d.ts.map +1 -1
  54. package/dist/commands/read.js +2 -2
  55. package/dist/commands/semantic.d.ts +4 -0
  56. package/dist/commands/semantic.d.ts.map +1 -0
  57. package/dist/commands/semantic.js +199 -0
  58. package/dist/commands/storage.d.ts +4 -0
  59. package/dist/commands/storage.d.ts.map +1 -0
  60. package/dist/commands/storage.js +238 -0
  61. package/dist/commands/tunnel.d.ts +5 -1
  62. package/dist/commands/tunnel.d.ts.map +1 -1
  63. package/dist/commands/tunnel.js +44 -31
  64. package/dist/commands/web.d.ts +3 -0
  65. package/dist/commands/web.d.ts.map +1 -1
  66. package/dist/commands/web.js +84 -7
  67. package/dist/commands/work.js +3 -3
  68. package/dist/commands/workflow.js +13 -13
  69. package/dist/core/adapters/profiles.d.ts +1 -1
  70. package/dist/core/agents/canonical-emit.d.ts +3 -0
  71. package/dist/core/agents/canonical-emit.d.ts.map +1 -1
  72. package/dist/core/agents/canonical-emit.js +12 -0
  73. package/dist/core/agents/claim-path.d.ts +11 -0
  74. package/dist/core/agents/claim-path.d.ts.map +1 -0
  75. package/dist/core/agents/claim-path.js +22 -0
  76. package/dist/core/agents/cli.js +209 -39
  77. package/dist/core/agents/coord-client.d.ts +29 -3
  78. package/dist/core/agents/coord-client.d.ts.map +1 -1
  79. package/dist/core/agents/coord-client.js +88 -9
  80. package/dist/core/agents/live-authority-v3.d.ts +47 -1
  81. package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
  82. package/dist/core/agents/live-authority-v3.js +245 -13
  83. package/dist/core/agents/live-lifecycle-v3.js +9 -4
  84. package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
  85. package/dist/core/agents/live-observation-v3.js +8 -3
  86. package/dist/core/agents/render/prompt-context.d.ts +9 -3
  87. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  88. package/dist/core/agents/render/prompt-context.js +36 -17
  89. package/dist/core/agents/rules/stop-hook.d.ts +2 -0
  90. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  91. package/dist/core/agents/rules/stop-hook.js +115 -22
  92. package/dist/core/agents/rules/verdict.d.ts +1 -0
  93. package/dist/core/agents/rules/verdict.d.ts.map +1 -1
  94. package/dist/core/agents/session-events.d.ts.map +1 -1
  95. package/dist/core/agents/session-events.js +4 -0
  96. package/dist/core/agents/session-finalization-state-v3.js +1 -1
  97. package/dist/core/agents/session-finalizer-v3.js +5 -1
  98. package/dist/core/agents/session-name-display.d.ts +1 -0
  99. package/dist/core/agents/session-name-display.d.ts.map +1 -1
  100. package/dist/core/agents/session-name-display.js +8 -1
  101. package/dist/core/agents/state/activity-log.d.ts +3 -0
  102. package/dist/core/agents/state/activity-log.d.ts.map +1 -1
  103. package/dist/core/agents/state/activity-log.js +6 -3
  104. package/dist/core/agents/state/heartbeat-reader.d.ts +46 -0
  105. package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -0
  106. package/dist/core/agents/state/heartbeat-reader.js +25 -0
  107. package/dist/core/agents/state/heartbeat-writer.d.ts +9 -48
  108. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  109. package/dist/core/agents/state/heartbeat-writer.js +34 -34
  110. package/dist/core/agents/state/live-coordination-view.d.ts +6 -8
  111. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
  112. package/dist/core/agents/state/live-coordination-view.js +16 -67
  113. package/dist/core/agents/state/live-coordination-writer.d.ts +12 -0
  114. package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -0
  115. package/dist/core/agents/state/live-coordination-writer.js +92 -0
  116. package/dist/core/agents/state/names.d.ts +9 -1
  117. package/dist/core/agents/state/names.d.ts.map +1 -1
  118. package/dist/core/agents/state/names.js +190 -182
  119. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  120. package/dist/core/agents/state/stale-sweep.js +23 -5
  121. package/dist/core/artifacts/constants.d.ts +5 -0
  122. package/dist/core/artifacts/constants.d.ts.map +1 -0
  123. package/dist/core/artifacts/constants.js +4 -0
  124. package/dist/core/artifacts/index.d.ts +24 -3
  125. package/dist/core/artifacts/index.d.ts.map +1 -1
  126. package/dist/core/artifacts/index.js +96 -8
  127. package/dist/core/config.d.ts +62 -4
  128. package/dist/core/config.d.ts.map +1 -1
  129. package/dist/core/config.js +98 -4
  130. package/dist/core/conversations/archive.d.ts +49 -0
  131. package/dist/core/conversations/archive.d.ts.map +1 -0
  132. package/dist/core/conversations/archive.js +136 -0
  133. package/dist/core/conversations/catalog.d.ts +10 -0
  134. package/dist/core/conversations/catalog.d.ts.map +1 -0
  135. package/dist/core/conversations/catalog.js +72 -0
  136. package/dist/core/conversations/context-pack.d.ts +6 -0
  137. package/dist/core/conversations/context-pack.d.ts.map +1 -0
  138. package/dist/core/conversations/context-pack.js +60 -0
  139. package/dist/core/conversations/contract.d.ts +155 -0
  140. package/dist/core/conversations/contract.d.ts.map +1 -0
  141. package/dist/core/conversations/contract.js +1 -0
  142. package/dist/core/conversations/evaluation.d.ts +16 -0
  143. package/dist/core/conversations/evaluation.d.ts.map +1 -0
  144. package/dist/core/conversations/evaluation.js +9 -0
  145. package/dist/core/conversations/index.d.ts +10 -0
  146. package/dist/core/conversations/index.d.ts.map +1 -0
  147. package/dist/core/conversations/index.js +9 -0
  148. package/dist/core/conversations/lifecycle.d.ts +28 -0
  149. package/dist/core/conversations/lifecycle.d.ts.map +1 -0
  150. package/dist/core/conversations/lifecycle.js +29 -0
  151. package/dist/core/conversations/normalize.d.ts +14 -0
  152. package/dist/core/conversations/normalize.d.ts.map +1 -0
  153. package/dist/core/conversations/normalize.js +82 -0
  154. package/dist/core/conversations/query.d.ts +8 -0
  155. package/dist/core/conversations/query.d.ts.map +1 -0
  156. package/dist/core/conversations/query.js +280 -0
  157. package/dist/core/conversations/search-index.d.ts +9 -0
  158. package/dist/core/conversations/search-index.d.ts.map +1 -0
  159. package/dist/core/conversations/search-index.js +29 -0
  160. package/dist/core/events/legacy-storage/canary.d.ts +18 -0
  161. package/dist/core/events/legacy-storage/canary.d.ts.map +1 -0
  162. package/dist/core/events/legacy-storage/canary.js +150 -0
  163. package/dist/core/events/legacy-storage/fence.d.ts +15 -0
  164. package/dist/core/events/legacy-storage/fence.d.ts.map +1 -0
  165. package/dist/core/events/legacy-storage/fence.js +115 -0
  166. package/dist/core/events/legacy-storage/index.d.ts +6 -0
  167. package/dist/core/events/legacy-storage/index.d.ts.map +1 -0
  168. package/dist/core/events/legacy-storage/index.js +5 -0
  169. package/dist/core/events/legacy-storage/inventory.d.ts +10 -0
  170. package/dist/core/events/legacy-storage/inventory.d.ts.map +1 -0
  171. package/dist/core/events/legacy-storage/inventory.js +40 -0
  172. package/dist/core/events/legacy-storage/manifest.d.ts +23 -0
  173. package/dist/core/events/legacy-storage/manifest.d.ts.map +1 -0
  174. package/dist/core/events/legacy-storage/manifest.js +108 -0
  175. package/dist/core/events/legacy-storage/reader.d.ts +15 -0
  176. package/dist/core/events/legacy-storage/reader.d.ts.map +1 -0
  177. package/dist/core/events/legacy-storage/reader.js +154 -0
  178. package/dist/core/events/v3/authority-outbox.d.ts +7 -2
  179. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
  180. package/dist/core/events/v3/authority-outbox.js +16 -3
  181. package/dist/core/events/v3/base-contract.d.ts +851 -16
  182. package/dist/core/events/v3/base-contract.d.ts.map +1 -1
  183. package/dist/core/events/v3/base-contract.js +50 -7
  184. package/dist/core/events/v3/bootstrap.d.ts +39 -0
  185. package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
  186. package/dist/core/events/v3/bootstrap.js +167 -3
  187. package/dist/core/events/v3/capabilities.d.ts +11 -0
  188. package/dist/core/events/v3/capabilities.d.ts.map +1 -1
  189. package/dist/core/events/v3/capabilities.js +26 -3
  190. package/dist/core/events/v3/control-witness.d.ts +44 -0
  191. package/dist/core/events/v3/control-witness.d.ts.map +1 -0
  192. package/dist/core/events/v3/control-witness.js +233 -0
  193. package/dist/core/events/v3/control-writer.d.ts +4 -0
  194. package/dist/core/events/v3/control-writer.d.ts.map +1 -0
  195. package/dist/core/events/v3/control-writer.js +16 -0
  196. package/dist/core/events/v3/control.d.ts +8 -2
  197. package/dist/core/events/v3/control.d.ts.map +1 -1
  198. package/dist/core/events/v3/control.js +46 -18
  199. package/dist/core/events/v3/coordination-transaction-recovery.d.ts +42 -0
  200. package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -0
  201. package/dist/core/events/v3/coordination-transaction-recovery.js +342 -0
  202. package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
  203. package/dist/core/events/v3/coordination-view.js +16 -1
  204. package/dist/core/events/v3/generated.d.ts +1 -1
  205. package/dist/core/events/v3/generated.js +1 -1
  206. package/dist/core/events/v3/index.d.ts +8 -5
  207. package/dist/core/events/v3/index.d.ts.map +1 -1
  208. package/dist/core/events/v3/index.js +7 -4
  209. package/dist/core/events/v3/latency.d.ts +31 -1
  210. package/dist/core/events/v3/latency.d.ts.map +1 -1
  211. package/dist/core/events/v3/latency.js +127 -3
  212. package/dist/core/events/v3/live-route-observer.d.ts +31 -0
  213. package/dist/core/events/v3/live-route-observer.d.ts.map +1 -0
  214. package/dist/core/events/v3/live-route-observer.js +58 -0
  215. package/dist/core/events/v3/live-routing.d.ts +42 -20
  216. package/dist/core/events/v3/live-routing.d.ts.map +1 -1
  217. package/dist/core/events/v3/live-routing.js +153 -41
  218. package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
  219. package/dist/core/events/v3/producers/command-recorder.js +10 -1
  220. package/dist/core/events/v3/producers/coordination-recorder.d.ts +11 -1
  221. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  222. package/dist/core/events/v3/producers/coordination-recorder.js +90 -13
  223. package/dist/core/events/v3/producers/diagnostic-summaries.d.ts +129 -0
  224. package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -0
  225. package/dist/core/events/v3/producers/diagnostic-summaries.js +499 -0
  226. package/dist/core/events/v3/producers/hook-base.d.ts +17 -1
  227. package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
  228. package/dist/core/events/v3/producers/hook-base.js +83 -2
  229. package/dist/core/events/v3/producers/intake.d.ts +13 -0
  230. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  231. package/dist/core/events/v3/producers/intake.js +36 -2
  232. package/dist/core/events/v3/producers/producer-state-observer.d.ts +8 -0
  233. package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -0
  234. package/dist/core/events/v3/producers/producer-state-observer.js +45 -0
  235. package/dist/core/events/v3/producers/recorder.d.ts +117 -1
  236. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  237. package/dist/core/events/v3/producers/recorder.js +992 -27
  238. package/dist/core/events/v3/reader.d.ts +51 -0
  239. package/dist/core/events/v3/reader.d.ts.map +1 -1
  240. package/dist/core/events/v3/reader.js +181 -1
  241. package/dist/core/events/v3/rotation-config.d.ts +9 -0
  242. package/dist/core/events/v3/rotation-config.d.ts.map +1 -0
  243. package/dist/core/events/v3/rotation-config.js +91 -0
  244. package/dist/core/events/v3/runtime-build.d.ts +11 -0
  245. package/dist/core/events/v3/runtime-build.d.ts.map +1 -0
  246. package/dist/core/events/v3/runtime-build.js +39 -0
  247. package/dist/core/events/v3/runtime-identity.d.ts +5 -0
  248. package/dist/core/events/v3/runtime-identity.d.ts.map +1 -0
  249. package/dist/core/events/v3/runtime-identity.js +18 -0
  250. package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +52 -0
  251. package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -0
  252. package/dist/core/events/v3/runtime-telemetry-capabilities.js +54 -0
  253. package/dist/core/events/v3/support-storage/classify.d.ts +46 -0
  254. package/dist/core/events/v3/support-storage/classify.d.ts.map +1 -0
  255. package/dist/core/events/v3/support-storage/classify.js +149 -0
  256. package/dist/core/events/v3/support-storage/eligibility.d.ts +29 -0
  257. package/dist/core/events/v3/support-storage/eligibility.d.ts.map +1 -0
  258. package/dist/core/events/v3/support-storage/eligibility.js +35 -0
  259. package/dist/core/events/v3/support-storage/index.d.ts +10 -0
  260. package/dist/core/events/v3/support-storage/index.d.ts.map +1 -0
  261. package/dist/core/events/v3/support-storage/index.js +9 -0
  262. package/dist/core/events/v3/support-storage/inventory.d.ts +30 -0
  263. package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -0
  264. package/dist/core/events/v3/support-storage/inventory.js +94 -0
  265. package/dist/core/events/v3/support-storage/logical-authority.d.ts +14 -0
  266. package/dist/core/events/v3/support-storage/logical-authority.d.ts.map +1 -0
  267. package/dist/core/events/v3/support-storage/logical-authority.js +104 -0
  268. package/dist/core/events/v3/support-storage/maintenance.d.ts +98 -0
  269. package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -0
  270. package/dist/core/events/v3/support-storage/maintenance.js +352 -0
  271. package/dist/core/events/v3/support-storage/pack-contract.d.ts +59 -0
  272. package/dist/core/events/v3/support-storage/pack-contract.d.ts.map +1 -0
  273. package/dist/core/events/v3/support-storage/pack-contract.js +249 -0
  274. package/dist/core/events/v3/support-storage/pack-reader.d.ts +34 -0
  275. package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -0
  276. package/dist/core/events/v3/support-storage/pack-reader.js +258 -0
  277. package/dist/core/events/v3/support-storage/pack-writer.d.ts +30 -0
  278. package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -0
  279. package/dist/core/events/v3/support-storage/pack-writer.js +268 -0
  280. package/dist/core/events/v3/support-storage/recovery.d.ts +15 -0
  281. package/dist/core/events/v3/support-storage/recovery.d.ts.map +1 -0
  282. package/dist/core/events/v3/support-storage/recovery.js +22 -0
  283. package/dist/core/events/v3/turn-telemetry.d.ts +21 -6
  284. package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
  285. package/dist/core/events/v3/turn-telemetry.js +32 -2
  286. package/dist/core/events/v3/writer.d.ts +13 -1
  287. package/dist/core/events/v3/writer.d.ts.map +1 -1
  288. package/dist/core/events/v3/writer.js +126 -12
  289. package/dist/core/governor/plan-read.d.ts.map +1 -1
  290. package/dist/core/governor/plan-read.js +5 -21
  291. package/dist/core/governor/planning.js +6 -8
  292. package/dist/core/governor/service-read.d.ts +12 -0
  293. package/dist/core/governor/service-read.d.ts.map +1 -1
  294. package/dist/core/governor/service-read.js +266 -2
  295. package/dist/core/governor/service.d.ts +1 -0
  296. package/dist/core/governor/service.d.ts.map +1 -1
  297. package/dist/core/governor/service.js +53 -18
  298. package/dist/core/guard/evidence-v3.d.ts.map +1 -1
  299. package/dist/core/guard/evidence-v3.js +2 -0
  300. package/dist/core/hooks/adapter/events.d.ts.map +1 -1
  301. package/dist/core/hooks/adapter/events.js +1 -0
  302. package/dist/core/hooks/adapter/output.d.ts +4 -2
  303. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  304. package/dist/core/hooks/adapter/output.js +13 -5
  305. package/dist/core/hooks/adapter/parse.d.ts +3 -0
  306. package/dist/core/hooks/adapter/parse.d.ts.map +1 -1
  307. package/dist/core/hooks/adapter/parse.js +14 -0
  308. package/dist/core/hooks/adapter/runtime-telemetry.d.ts +142 -0
  309. package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -0
  310. package/dist/core/hooks/adapter/runtime-telemetry.js +869 -0
  311. package/dist/core/hooks/cli.js +318 -61
  312. package/dist/core/hooks/effects/image-capture.d.ts +1 -1
  313. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  314. package/dist/core/hooks/effects/image-capture.js +4 -2
  315. package/dist/core/hooks/remediation-cap.d.ts +39 -0
  316. package/dist/core/hooks/remediation-cap.d.ts.map +1 -0
  317. package/dist/core/hooks/remediation-cap.js +63 -0
  318. package/dist/core/hooks/resolve/coord-root.d.ts +22 -9
  319. package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
  320. package/dist/core/hooks/resolve/coord-root.js +92 -11
  321. package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
  322. package/dist/core/hooks/resolve/owner.js +5 -0
  323. package/dist/core/hooks/resolve/transcript.d.ts +33 -9
  324. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  325. package/dist/core/hooks/resolve/transcript.js +33 -10
  326. package/dist/core/inbox/contract.d.ts +64 -0
  327. package/dist/core/inbox/contract.d.ts.map +1 -0
  328. package/dist/core/inbox/contract.js +13 -0
  329. package/dist/core/inbox/index.d.ts +5 -0
  330. package/dist/core/inbox/index.d.ts.map +1 -0
  331. package/dist/core/inbox/index.js +4 -0
  332. package/dist/core/inbox/lifecycle.d.ts +22 -0
  333. package/dist/core/inbox/lifecycle.d.ts.map +1 -0
  334. package/dist/core/inbox/lifecycle.js +41 -0
  335. package/dist/core/inbox/service.d.ts +36 -0
  336. package/dist/core/inbox/service.d.ts.map +1 -0
  337. package/dist/core/inbox/service.js +210 -0
  338. package/dist/core/inbox/watcher.d.ts +7 -0
  339. package/dist/core/inbox/watcher.d.ts.map +1 -0
  340. package/dist/core/inbox/watcher.js +26 -0
  341. package/dist/core/presence/codec-digest.d.ts.map +1 -1
  342. package/dist/core/presence/codec-digest.js +14 -3
  343. package/dist/core/presence/relay-client.d.ts +1 -0
  344. package/dist/core/presence/relay-client.d.ts.map +1 -1
  345. package/dist/core/presence/relay-client.js +52 -8
  346. package/dist/core/semantic/adapters.d.ts +37 -0
  347. package/dist/core/semantic/adapters.d.ts.map +1 -0
  348. package/dist/core/semantic/adapters.js +360 -0
  349. package/dist/core/semantic/contract.d.ts +1072 -0
  350. package/dist/core/semantic/contract.d.ts.map +1 -0
  351. package/dist/core/semantic/contract.js +331 -0
  352. package/dist/core/semantic/evidence.d.ts +11 -0
  353. package/dist/core/semantic/evidence.d.ts.map +1 -0
  354. package/dist/core/semantic/evidence.js +262 -0
  355. package/dist/core/semantic/index.d.ts +14 -0
  356. package/dist/core/semantic/index.d.ts.map +1 -0
  357. package/dist/core/semantic/index.js +13 -0
  358. package/dist/core/semantic/once.d.ts +38 -0
  359. package/dist/core/semantic/once.d.ts.map +1 -0
  360. package/dist/core/semantic/once.js +364 -0
  361. package/dist/core/semantic/prompt.d.ts +12 -0
  362. package/dist/core/semantic/prompt.d.ts.map +1 -0
  363. package/dist/core/semantic/prompt.js +83 -0
  364. package/dist/core/semantic/review.d.ts +144 -0
  365. package/dist/core/semantic/review.d.ts.map +1 -0
  366. package/dist/core/semantic/review.js +544 -0
  367. package/dist/core/semantic/routes.d.ts +10 -0
  368. package/dist/core/semantic/routes.d.ts.map +1 -0
  369. package/dist/core/semantic/routes.js +21 -0
  370. package/dist/core/semantic/scheduler.d.ts +27 -0
  371. package/dist/core/semantic/scheduler.d.ts.map +1 -0
  372. package/dist/core/semantic/scheduler.js +91 -0
  373. package/dist/core/semantic/service-status.d.ts +51 -0
  374. package/dist/core/semantic/service-status.d.ts.map +1 -0
  375. package/dist/core/semantic/service-status.js +140 -0
  376. package/dist/core/semantic/service.d.ts +52 -0
  377. package/dist/core/semantic/service.d.ts.map +1 -0
  378. package/dist/core/semantic/service.js +559 -0
  379. package/dist/core/semantic/soak.d.ts +75 -0
  380. package/dist/core/semantic/soak.d.ts.map +1 -0
  381. package/dist/core/semantic/soak.js +476 -0
  382. package/dist/core/semantic/storage.d.ts +81 -0
  383. package/dist/core/semantic/storage.d.ts.map +1 -0
  384. package/dist/core/semantic/storage.js +180 -0
  385. package/dist/core/semantic/usage.d.ts +43 -0
  386. package/dist/core/semantic/usage.d.ts.map +1 -0
  387. package/dist/core/semantic/usage.js +193 -0
  388. package/dist/core/semantic/validate.d.ts +18 -0
  389. package/dist/core/semantic/validate.d.ts.map +1 -0
  390. package/dist/core/semantic/validate.js +207 -0
  391. package/dist/core/storage/buffer.d.ts +28 -0
  392. package/dist/core/storage/buffer.d.ts.map +1 -0
  393. package/dist/core/storage/buffer.js +101 -0
  394. package/dist/core/storage/builtins.d.ts +3 -0
  395. package/dist/core/storage/builtins.d.ts.map +1 -0
  396. package/dist/core/storage/builtins.js +683 -0
  397. package/dist/core/storage/catalog.d.ts +19 -0
  398. package/dist/core/storage/catalog.d.ts.map +1 -0
  399. package/dist/core/storage/catalog.js +365 -0
  400. package/dist/core/storage/config.d.ts +16 -0
  401. package/dist/core/storage/config.d.ts.map +1 -0
  402. package/dist/core/storage/config.js +311 -0
  403. package/dist/core/storage/contract.d.ts +275 -0
  404. package/dist/core/storage/contract.d.ts.map +1 -0
  405. package/dist/core/storage/contract.js +3 -0
  406. package/dist/core/storage/durable-history.d.ts +36 -0
  407. package/dist/core/storage/durable-history.d.ts.map +1 -0
  408. package/dist/core/storage/durable-history.js +606 -0
  409. package/dist/core/storage/health.d.ts +4 -0
  410. package/dist/core/storage/health.d.ts.map +1 -0
  411. package/dist/core/storage/health.js +65 -0
  412. package/dist/core/storage/index.d.ts +16 -0
  413. package/dist/core/storage/index.d.ts.map +1 -0
  414. package/dist/core/storage/index.js +15 -0
  415. package/dist/core/storage/inventory.d.ts +25 -0
  416. package/dist/core/storage/inventory.d.ts.map +1 -0
  417. package/dist/core/storage/inventory.js +666 -0
  418. package/dist/core/storage/jsonl.d.ts +52 -0
  419. package/dist/core/storage/jsonl.d.ts.map +1 -0
  420. package/dist/core/storage/jsonl.js +156 -0
  421. package/dist/core/storage/log-retention.d.ts +52 -0
  422. package/dist/core/storage/log-retention.d.ts.map +1 -0
  423. package/dist/core/storage/log-retention.js +419 -0
  424. package/dist/core/storage/logger.d.ts +82 -0
  425. package/dist/core/storage/logger.d.ts.map +1 -0
  426. package/dist/core/storage/logger.js +411 -0
  427. package/dist/core/storage/maintenance-providers.d.ts +26 -0
  428. package/dist/core/storage/maintenance-providers.d.ts.map +1 -0
  429. package/dist/core/storage/maintenance-providers.js +141 -0
  430. package/dist/core/storage/maintenance.d.ts +125 -0
  431. package/dist/core/storage/maintenance.d.ts.map +1 -0
  432. package/dist/core/storage/maintenance.js +609 -0
  433. package/dist/core/storage/metrics.d.ts +60 -0
  434. package/dist/core/storage/metrics.d.ts.map +1 -0
  435. package/dist/core/storage/metrics.js +134 -0
  436. package/dist/core/storage/policy.d.ts +7 -0
  437. package/dist/core/storage/policy.d.ts.map +1 -0
  438. package/dist/core/storage/policy.js +110 -0
  439. package/dist/core/storage/process-log.d.ts +38 -0
  440. package/dist/core/storage/process-log.d.ts.map +1 -0
  441. package/dist/core/storage/process-log.js +165 -0
  442. package/dist/core/storage/query.d.ts +34 -0
  443. package/dist/core/storage/query.d.ts.map +1 -0
  444. package/dist/core/storage/query.js +295 -0
  445. package/dist/core/storage/receipts.d.ts +23 -0
  446. package/dist/core/storage/receipts.d.ts.map +1 -0
  447. package/dist/core/storage/receipts.js +117 -0
  448. package/dist/core/storage/segments.d.ts +84 -0
  449. package/dist/core/storage/segments.d.ts.map +1 -0
  450. package/dist/core/storage/segments.js +542 -0
  451. package/dist/core/storage/sink-graph.d.ts +65 -0
  452. package/dist/core/storage/sink-graph.d.ts.map +1 -0
  453. package/dist/core/storage/sink-graph.js +213 -0
  454. package/dist/core/storage/storm-control.d.ts +23 -0
  455. package/dist/core/storage/storm-control.d.ts.map +1 -0
  456. package/dist/core/storage/storm-control.js +59 -0
  457. package/dist/core/work/state.d.ts.map +1 -1
  458. package/dist/core/work/state.js +10 -14
  459. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  460. package/dist/core/workflow/live-session-v3.js +2 -1
  461. package/dist/index.d.ts +2 -0
  462. package/dist/index.d.ts.map +1 -1
  463. package/dist/index.js +2 -0
  464. package/dist/lazy-commands.d.ts +26 -0
  465. package/dist/lazy-commands.d.ts.map +1 -0
  466. package/dist/lazy-commands.js +210 -0
  467. package/dist/lib/browser/client.d.ts +11 -0
  468. package/dist/lib/browser/client.d.ts.map +1 -1
  469. package/dist/lib/browser/client.js +13 -0
  470. package/dist/lib/browser/index.d.ts +1 -0
  471. package/dist/lib/browser/index.d.ts.map +1 -1
  472. package/dist/lib/browser/standalone-html.d.ts +25 -0
  473. package/dist/lib/browser/standalone-html.d.ts.map +1 -0
  474. package/dist/lib/browser/standalone-html.js +284 -0
  475. package/dist/lib/docs-lint.d.ts +2 -0
  476. package/dist/lib/docs-lint.d.ts.map +1 -1
  477. package/dist/lib/docs-lint.js +45 -80
  478. package/dist/lib/docs-metadata-audit.d.ts +3 -0
  479. package/dist/lib/docs-metadata-audit.d.ts.map +1 -1
  480. package/dist/lib/docs-metadata-audit.js +13 -23
  481. package/dist/lib/docs-metadata-sync.d.ts +1 -0
  482. package/dist/lib/docs-metadata-sync.d.ts.map +1 -1
  483. package/dist/lib/docs-metadata-sync.js +28 -10
  484. package/dist/lib/docs-repository-view.d.ts +22 -0
  485. package/dist/lib/docs-repository-view.d.ts.map +1 -0
  486. package/dist/lib/docs-repository-view.js +185 -0
  487. package/dist/lib/http/client.d.ts +11 -5
  488. package/dist/lib/http/client.d.ts.map +1 -1
  489. package/dist/lib/http/client.js +22 -4
  490. package/dist/lib/http/index.d.ts +1 -1
  491. package/dist/lib/http/index.d.ts.map +1 -1
  492. package/dist/lib/http/index.js +1 -1
  493. package/dist/lib/indexer-exclusions.d.ts +27 -0
  494. package/dist/lib/indexer-exclusions.d.ts.map +1 -0
  495. package/dist/lib/indexer-exclusions.js +176 -0
  496. package/dist/lib/instructions/apply.d.ts.map +1 -1
  497. package/dist/lib/instructions/apply.js +1 -0
  498. package/dist/lib/instructions/templates.d.ts +2 -0
  499. package/dist/lib/instructions/templates.d.ts.map +1 -1
  500. package/dist/lib/instructions/templates.js +149 -4
  501. package/dist/lib/local-file-url.d.ts +9 -0
  502. package/dist/lib/local-file-url.d.ts.map +1 -0
  503. package/dist/lib/local-file-url.js +20 -0
  504. package/dist/lib/web-performance.d.ts +118 -0
  505. package/dist/lib/web-performance.d.ts.map +1 -0
  506. package/dist/lib/web-performance.js +192 -0
  507. package/package.json +34 -2
  508. package/schemas/config.schema.json +58 -0
  509. package/schemas/event-v3.schema.json +3073 -581
  510. package/src/commander.ts +462 -93
  511. package/src/commands/agents.ts +617 -355
  512. package/src/commands/backup.ts +18 -14
  513. package/src/commands/browse-session.ts +12 -0
  514. package/src/commands/browse.ts +31 -9
  515. package/src/commands/conversations.ts +279 -0
  516. package/src/commands/decision.ts +8 -2
  517. package/src/commands/deinit.ts +6 -0
  518. package/src/commands/docs.ts +25 -6
  519. package/src/commands/doctor.ts +75 -9
  520. package/src/commands/events.ts +21 -1
  521. package/src/commands/fetch.ts +7 -6
  522. package/src/commands/files.ts +143 -0
  523. package/src/commands/governor.ts +13 -12
  524. package/src/commands/inbox.ts +61 -0
  525. package/src/commands/init.ts +78 -16
  526. package/src/commands/ledger-v3.ts +421 -1
  527. package/src/commands/logs.ts +224 -0
  528. package/src/commands/messages.ts +61 -0
  529. package/src/commands/outline.ts +6 -2
  530. package/src/commands/presence.ts +7 -2
  531. package/src/commands/read.ts +6 -2
  532. package/src/commands/semantic.ts +244 -0
  533. package/src/commands/storage.ts +310 -0
  534. package/src/commands/tunnel.ts +66 -52
  535. package/src/commands/web.ts +92 -7
  536. package/src/commands/work.ts +3 -3
  537. package/src/commands/workflow.ts +13 -13
  538. package/src/core/agents/canonical-emit.ts +15 -0
  539. package/src/core/agents/claim-path.ts +23 -0
  540. package/src/core/agents/cli.ts +259 -53
  541. package/src/core/agents/coord-client.ts +92 -8
  542. package/src/core/agents/live-authority-v3.ts +342 -14
  543. package/src/core/agents/live-lifecycle-v3.ts +14 -4
  544. package/src/core/agents/live-observation-v3.ts +13 -3
  545. package/src/core/agents/render/prompt-context.ts +40 -16
  546. package/src/core/agents/rules/stop-hook.ts +129 -25
  547. package/src/core/agents/rules/verdict.ts +1 -0
  548. package/src/core/agents/session-events.ts +4 -0
  549. package/src/core/agents/session-finalization-state-v3.ts +1 -1
  550. package/src/core/agents/session-finalizer-v3.ts +4 -1
  551. package/src/core/agents/session-name-display.ts +9 -1
  552. package/src/core/agents/state/activity-log.ts +7 -2
  553. package/src/core/agents/state/heartbeat-reader.ts +69 -0
  554. package/src/core/agents/state/heartbeat-writer.ts +47 -84
  555. package/src/core/agents/state/live-coordination-view.ts +17 -81
  556. package/src/core/agents/state/live-coordination-writer.ts +141 -0
  557. package/src/core/agents/state/names.ts +190 -182
  558. package/src/core/agents/state/stale-sweep.ts +25 -5
  559. package/src/core/artifacts/constants.ts +4 -0
  560. package/src/core/artifacts/index.ts +113 -8
  561. package/src/core/config.ts +126 -5
  562. package/src/core/conversations/archive.ts +237 -0
  563. package/src/core/conversations/catalog.ts +79 -0
  564. package/src/core/conversations/context-pack.ts +72 -0
  565. package/src/core/conversations/contract.ts +178 -0
  566. package/src/core/conversations/evaluation.ts +30 -0
  567. package/src/core/conversations/index.ts +9 -0
  568. package/src/core/conversations/lifecycle.ts +63 -0
  569. package/src/core/conversations/normalize.ts +105 -0
  570. package/src/core/conversations/query.ts +318 -0
  571. package/src/core/conversations/search-index.ts +48 -0
  572. package/src/core/events/legacy-storage/canary.ts +177 -0
  573. package/src/core/events/legacy-storage/fence.ts +129 -0
  574. package/src/core/events/legacy-storage/index.ts +5 -0
  575. package/src/core/events/legacy-storage/inventory.ts +51 -0
  576. package/src/core/events/legacy-storage/manifest.ts +136 -0
  577. package/src/core/events/legacy-storage/reader.ts +178 -0
  578. package/src/core/events/v3/authority-outbox.ts +22 -1
  579. package/src/core/events/v3/base-contract.ts +56 -7
  580. package/src/core/events/v3/bootstrap.ts +195 -2
  581. package/src/core/events/v3/capabilities.ts +37 -3
  582. package/src/core/events/v3/control-witness.ts +339 -0
  583. package/src/core/events/v3/control-writer.ts +16 -0
  584. package/src/core/events/v3/control.ts +54 -18
  585. package/src/core/events/v3/coordination-transaction-recovery.ts +477 -0
  586. package/src/core/events/v3/coordination-view.ts +17 -1
  587. package/src/core/events/v3/generated.ts +1 -1
  588. package/src/core/events/v3/index.ts +26 -2
  589. package/src/core/events/v3/latency.ts +213 -2
  590. package/src/core/events/v3/live-route-observer.ts +80 -0
  591. package/src/core/events/v3/live-routing.ts +182 -45
  592. package/src/core/events/v3/producers/command-recorder.ts +10 -1
  593. package/src/core/events/v3/producers/coordination-recorder.ts +112 -15
  594. package/src/core/events/v3/producers/diagnostic-summaries.ts +593 -0
  595. package/src/core/events/v3/producers/hook-base.ts +116 -2
  596. package/src/core/events/v3/producers/intake.ts +48 -2
  597. package/src/core/events/v3/producers/producer-state-observer.ts +52 -0
  598. package/src/core/events/v3/producers/recorder.ts +1403 -30
  599. package/src/core/events/v3/reader.ts +243 -2
  600. package/src/core/events/v3/rotation-config.ts +98 -0
  601. package/src/core/events/v3/runtime-build.ts +41 -0
  602. package/src/core/events/v3/runtime-identity.ts +16 -0
  603. package/src/core/events/v3/runtime-telemetry-capabilities.ts +143 -0
  604. package/src/core/events/v3/support-storage/classify.ts +209 -0
  605. package/src/core/events/v3/support-storage/eligibility.ts +58 -0
  606. package/src/core/events/v3/support-storage/index.ts +9 -0
  607. package/src/core/events/v3/support-storage/inventory.ts +135 -0
  608. package/src/core/events/v3/support-storage/logical-authority.ts +117 -0
  609. package/src/core/events/v3/support-storage/maintenance.ts +501 -0
  610. package/src/core/events/v3/support-storage/pack-contract.ts +337 -0
  611. package/src/core/events/v3/support-storage/pack-reader.ts +346 -0
  612. package/src/core/events/v3/support-storage/pack-writer.ts +352 -0
  613. package/src/core/events/v3/support-storage/recovery.ts +43 -0
  614. package/src/core/events/v3/turn-telemetry.ts +66 -5
  615. package/src/core/events/v3/writer.ts +168 -16
  616. package/src/core/governor/plan-read.ts +5 -18
  617. package/src/core/governor/planning.ts +5 -8
  618. package/src/core/governor/service-read.ts +320 -2
  619. package/src/core/governor/service.ts +49 -22
  620. package/src/core/guard/evidence-v3.ts +1 -0
  621. package/src/core/hooks/adapter/events.ts +1 -0
  622. package/src/core/hooks/adapter/output.ts +12 -5
  623. package/src/core/hooks/adapter/parse.ts +16 -0
  624. package/src/core/hooks/adapter/runtime-telemetry.ts +1200 -0
  625. package/src/core/hooks/cli.ts +342 -64
  626. package/src/core/hooks/effects/image-capture.ts +4 -1
  627. package/src/core/hooks/remediation-cap.ts +83 -0
  628. package/src/core/hooks/resolve/coord-root.ts +91 -11
  629. package/src/core/hooks/resolve/owner.ts +4 -0
  630. package/src/core/hooks/resolve/transcript.ts +55 -11
  631. package/src/core/inbox/contract.ts +81 -0
  632. package/src/core/inbox/index.ts +4 -0
  633. package/src/core/inbox/lifecycle.ts +104 -0
  634. package/src/core/inbox/service.ts +305 -0
  635. package/src/core/inbox/watcher.ts +36 -0
  636. package/src/core/presence/codec-digest.ts +15 -9
  637. package/src/core/presence/relay-client.ts +55 -7
  638. package/src/core/semantic/adapters.ts +452 -0
  639. package/src/core/semantic/contract.ts +430 -0
  640. package/src/core/semantic/evidence.ts +336 -0
  641. package/src/core/semantic/index.ts +201 -0
  642. package/src/core/semantic/once.ts +496 -0
  643. package/src/core/semantic/prompt.ts +96 -0
  644. package/src/core/semantic/review.ts +803 -0
  645. package/src/core/semantic/routes.ts +30 -0
  646. package/src/core/semantic/scheduler.ts +151 -0
  647. package/src/core/semantic/service-status.ts +212 -0
  648. package/src/core/semantic/service.ts +681 -0
  649. package/src/core/semantic/soak.ts +638 -0
  650. package/src/core/semantic/storage.ts +300 -0
  651. package/src/core/semantic/usage.ts +272 -0
  652. package/src/core/semantic/validate.ts +243 -0
  653. package/src/core/storage/buffer.ts +124 -0
  654. package/src/core/storage/builtins.ts +916 -0
  655. package/src/core/storage/catalog.ts +467 -0
  656. package/src/core/storage/config.ts +423 -0
  657. package/src/core/storage/contract.ts +342 -0
  658. package/src/core/storage/durable-history.ts +738 -0
  659. package/src/core/storage/health.ts +76 -0
  660. package/src/core/storage/index.ts +15 -0
  661. package/src/core/storage/inventory.ts +859 -0
  662. package/src/core/storage/jsonl.ts +213 -0
  663. package/src/core/storage/log-retention.ts +555 -0
  664. package/src/core/storage/logger.ts +546 -0
  665. package/src/core/storage/maintenance-providers.ts +200 -0
  666. package/src/core/storage/maintenance.ts +929 -0
  667. package/src/core/storage/metrics.ts +199 -0
  668. package/src/core/storage/policy.ts +141 -0
  669. package/src/core/storage/process-log.ts +203 -0
  670. package/src/core/storage/query.ts +360 -0
  671. package/src/core/storage/receipts.ts +162 -0
  672. package/src/core/storage/segments.ts +721 -0
  673. package/src/core/storage/sink-graph.ts +343 -0
  674. package/src/core/storage/storm-control.ts +91 -0
  675. package/src/core/work/state.ts +12 -21
  676. package/src/core/workflow/live-session-v3.ts +2 -4
  677. package/src/index.ts +2 -0
  678. package/src/lazy-commands.ts +294 -0
  679. package/src/lib/browser/client.ts +21 -0
  680. package/src/lib/browser/index.ts +4 -0
  681. package/src/lib/browser/standalone-html.ts +312 -0
  682. package/src/lib/docs-lint.ts +58 -77
  683. package/src/lib/docs-metadata-audit.ts +26 -21
  684. package/src/lib/docs-metadata-sync.ts +32 -9
  685. package/src/lib/docs-repository-view.ts +220 -0
  686. package/src/lib/http/client.ts +44 -8
  687. package/src/lib/http/index.ts +6 -1
  688. package/src/lib/indexer-exclusions.ts +173 -0
  689. package/src/lib/instructions/apply.ts +1 -0
  690. package/src/lib/instructions/templates.ts +154 -4
  691. package/src/lib/local-file-url.ts +31 -0
  692. package/src/lib/web-performance.ts +335 -0
@@ -17,10 +17,18 @@ import { hostname } from "node:os";
17
17
  import { basename, join, resolve } from "node:path";
18
18
  import type { Adapter } from "../../../adapter.ts";
19
19
  import { extractBashCommand, type ParsedPayload } from "../../../hooks/adapter/parse.ts";
20
+ import {
21
+ discoverCodexSessionTranscript,
22
+ type RuntimeContextTelemetry,
23
+ type RuntimeTelemetryOptions,
24
+ readRuntimeContextTelemetry,
25
+ readRuntimeTuning,
26
+ } from "../../../hooks/adapter/runtime-telemetry.ts";
20
27
  import { fsyncParentDirectory } from "../../../workflow/durable-record.ts";
21
28
  import { acquireNoClobberLease } from "../../../workflow/workspaces/leases.ts";
29
+ import type { RuntimeAttestationV3Base } from "../base-contract.ts";
22
30
  import { buildEventV3 } from "../builder.ts";
23
- import { fingerprintV3, normalizeNativeIdV3 } from "../canonical.ts";
31
+ import { canonicalJsonV3, fingerprintV3, normalizeNativeIdV3 } from "../canonical.ts";
24
32
  import {
25
33
  type AdapterSignalV3,
26
34
  adapterCapabilityProfileDigestV3,
@@ -33,8 +41,19 @@ import { markObservedClockRegressionV3 } from "../clock-order.ts";
33
41
  import type { EventV3 } from "../contract.ts";
34
42
  import { type EventV3WriteMode, readEventV3ControlState } from "../control.ts";
35
43
  import { fingerprintContextV3 } from "../fingerprint-keys.ts";
36
- import { attestationIdV3, clockIdV3, delegationIdV3, generationIdV3, spanIdV3 } from "../ids.ts";
44
+ import {
45
+ attestationIdV3,
46
+ clockIdV3,
47
+ delegationIdV3,
48
+ eventIdV3,
49
+ generationIdV3,
50
+ spanIdV3,
51
+ } from "../ids.ts";
37
52
  import { readLedgerV3 } from "../reader.ts";
53
+ import {
54
+ effectiveRuntimeTelemetryCapabilitiesV3,
55
+ type RuntimeTelemetryCapabilitiesV3,
56
+ } from "../runtime-telemetry-capabilities.ts";
38
57
  import {
39
58
  closeSpanStateV3,
40
59
  type OpenSpanStateV3,
@@ -44,8 +63,10 @@ import {
44
63
  } from "../span-state.ts";
45
64
  import {
46
65
  type ContextMeasurementV3,
66
+ type ContextTelemetryProvenanceV3,
47
67
  extractTurnTelemetryV3,
48
68
  type TelemetryObservationV3,
69
+ type TurnTelemetryV3,
49
70
  } from "../turn-telemetry.ts";
50
71
  import { assertEventV3, validateEventV3 } from "../validate.ts";
51
72
  import {
@@ -74,6 +95,14 @@ const CLOSED_SPAN_TURN_RETENTION = 2;
74
95
  const CLOSED_SPAN_MEMORY_CAP = 512;
75
96
  const CLOSED_TURN_MEMORY_CAP = 16;
76
97
  const SPAN_SOFT_WATERMARK = 128;
98
+ const PENDING_RUNTIME_CONTEXT_CAP = 4;
99
+ const RUNTIME_CONTEXT_RETRY_LIMIT = 2;
100
+ /** Active turns pay for at most one bounded adapter telemetry read per interval. */
101
+ const ACTIVE_RUNTIME_CONTEXT_PROBE_INTERVAL_MS = 15_000;
102
+ /** Codex can flush the terminal row just after Stop; keep this grace bounded and off other hooks. */
103
+ const STOP_RUNTIME_CONTEXT_RETRY_DELAYS_MS = [75, 175] as const;
104
+ /** Finalization is off the interactive hook path; briefly cover Codex's delayed transcript flush. */
105
+ const APPROVED_END_RUNTIME_CONTEXT_RETRY_DELAYS_MS = [0, 250, 250] as const;
77
106
  /**
78
107
  * Adapters whose turn-boundary recovery and mid-flight onboarding are enabled.
79
108
  * Kept in code, outside the digested capability profiles, so tuning recovery
@@ -117,6 +146,29 @@ interface PendingEventV3 {
117
146
  event: EventV3;
118
147
  }
119
148
 
149
+ interface TurnContextTargetV3 {
150
+ terminal_event_id: `evt_${string}`;
151
+ terminal_observed_at: string;
152
+ turn_id: `tid_${string}`;
153
+ run_id?: `run_${string}`;
154
+ workflow_id?: `wf_${string}`;
155
+ workflow_agent_id?: string;
156
+ }
157
+
158
+ interface PendingRuntimeContextV3 extends TurnContextTargetV3 {
159
+ native_session_id: string;
160
+ native_turn_id: string;
161
+ transcript_path?: string;
162
+ runtime_version?: string;
163
+ attempts: number;
164
+ }
165
+
166
+ interface ActiveRuntimeContextProbeV3 {
167
+ turn_id: `tid_${string}`;
168
+ attempted_at: string;
169
+ boundary?: "tool_completed";
170
+ }
171
+
120
172
  interface DelegationStateV3 extends OpenSpanStateV3 {
121
173
  source_id: `hid_${string}`;
122
174
  delegation_id: `del_${string}`;
@@ -135,16 +187,29 @@ export interface HookProducerStateV3 {
135
187
  capability_profile: `cap_${string}`;
136
188
  cursor_mode?: CursorExecutionModeV3;
137
189
  privacy_epoch_id: `pep_${string}`;
190
+ /**
191
+ * Genesis id of the ledger epoch this producer's boot chain lives in. The
192
+ * fingerprint key epoch survives ledger rotation, so this is the field that
193
+ * keeps a state file from being adopted across an epoch boundary (its
194
+ * sequences and causal links only validate inside their own epoch). A state
195
+ * without it predates the field and is never adopted.
196
+ */
197
+ epoch_genesis_id?: `gex_${string}`;
138
198
  boot_id: `boot_${string}`;
139
199
  clock_id: `clk_${string}`;
140
200
  next_sequence: number;
141
201
  current_turn_id?: `tid_${string}`;
202
+ /** Native turn identity retained owner-only for transcript attribution. */
203
+ current_native_turn_id?: string;
142
204
  tool_call_count: number;
143
205
  tool_call_count_turn_id?: `tid_${string}`;
144
206
  last_event_id?: `evt_${string}`;
145
207
  last_monotonic_ns?: string;
146
208
  last_observed_at?: string;
147
209
  started_event_id?: `evt_${string}`;
210
+ /** A derived lifecycle reopen is allowed to exist before the adapter's next
211
+ * native prompt. Retained owner-only until that prompt starts a real turn. */
212
+ session_start_derivation?: "approved_lifecycle_reopen" | "validated_current_session_heal";
148
213
  session_span: OpenSpanStateV3;
149
214
  current_turn_span?: OpenSpanStateV3;
150
215
  terminal: boolean;
@@ -156,6 +221,29 @@ export interface HookProducerStateV3 {
156
221
  turn_harness: TurnHarnessTimingV3;
157
222
  turn_ordinal: number;
158
223
  pending?: PendingEventV3;
224
+ pending_runtime_contexts?: PendingRuntimeContextV3[];
225
+ /** Last bounded active-turn probe; owner-only and used only for cadence. */
226
+ active_runtime_context_probe?: ActiveRuntimeContextProbeV3;
227
+ /** Last emitted runtime source witness; owner-only measurement deduplication. */
228
+ last_context_source_witness?: string;
229
+ /** Verified adapter-native transcript path retained only in owner-only state. */
230
+ runtime_transcript_path?: string;
231
+ /** Tuning carried by the current attestation; {} means attested-none.
232
+ * Absent on pre-upgrade state files, which seed silently on first sight. */
233
+ last_attested_tuning?: { effort?: string; speed?: string };
234
+ /** Model observation carried forward into a refreshed attestation when the
235
+ * change-time transcript read does not pair a model with the new tuning. */
236
+ last_attested_model?: { provider: string; id: string };
237
+ /** Telemetry evidence carried forward verbatim: a tuning change does not
238
+ * alter what telemetry the runtime proved it can deliver. */
239
+ last_attested_telemetry?: RuntimeTelemetryCapabilitiesV3;
240
+ /** Full observations preserve missing and unsupported states when a
241
+ * different attestation channel changes. */
242
+ last_attested_model_observation?: RuntimeAttestationV3Base["model"];
243
+ last_attested_tuning_observation?: RuntimeAttestationV3Base["tuning"];
244
+ /** Turn already probed for Codex tuning while effort is unknown; bounds the
245
+ * rollout forward-scan to one attempt per turn. */
246
+ tuning_probe_turn_id?: `tid_${string}`;
159
247
  }
160
248
 
161
249
  export interface RecordHookSignalV3Input {
@@ -180,7 +268,15 @@ export interface RecordHookSignalV3Input {
180
268
  hook_duration_ms?: number;
181
269
  stop_remediation?: boolean;
182
270
  turn_ritual?: TurnRitualEvidenceV3;
183
- session_start_derivation?: "approved_lifecycle_reopen";
271
+ session_start_derivation?: "approved_lifecycle_reopen" | "validated_current_session_heal";
272
+ delegated_child?: {
273
+ generation_id: `gen_${string}`;
274
+ parent_generation_id: `gen_${string}`;
275
+ delegation_id: `del_${string}`;
276
+ caused_by_event_id: `evt_${string}`;
277
+ };
278
+ /** Optional roots and read budgets for runtime telemetry adapters. */
279
+ runtimeTelemetryOptions?: RuntimeTelemetryOptions;
184
280
  writerOptions?: WriteEventV3Options;
185
281
  }
186
282
 
@@ -310,11 +406,21 @@ function hookSignalGate(
310
406
  }
311
407
 
312
408
  function sessionHashForSignal(
313
- input: Pick<RecordHookSignalV3Input, "coordRoot" | "payload" | "adapter" | "instance_id">,
409
+ input: Pick<
410
+ RecordHookSignalV3Input,
411
+ "coordRoot" | "payload" | "adapter" | "instance_id" | "signal"
412
+ >,
314
413
  context: ReturnType<typeof fingerprintContextV3>,
315
414
  ): `hid_${string}` {
316
- const nativeSession =
317
- input.payload.session_id ?? input.payload.conversation_id ?? input.payload.agent_id;
415
+ const nativeChild = input.payload.subagent_id ?? input.payload.agent_id;
416
+ const childOwnsSignal =
417
+ input.signal !== "sub-agent-start" &&
418
+ input.signal !== "sub-agent-stop" &&
419
+ nativeChild !== undefined &&
420
+ input.instance_id === asLiveInstanceId(nativeChild);
421
+ const nativeSession = childOwnsSignal
422
+ ? nativeChild
423
+ : (input.payload.session_id ?? input.payload.conversation_id ?? input.payload.agent_id);
318
424
  if (nativeSession !== undefined) {
319
425
  return normalizeNativeIdV3(context, `${input.adapter}.session`, nativeSession);
320
426
  }
@@ -360,6 +466,7 @@ function intakeRecord(input: RecordHookSignalV3Input): HookIntakeRecordV3 {
360
466
  : {}),
361
467
  ...(input.stop_remediation !== undefined ? { stop_remediation: input.stop_remediation } : {}),
362
468
  ...(input.turn_ritual ? { turn_ritual: input.turn_ritual } : {}),
469
+ ...(input.delegated_child ? { delegated_child: input.delegated_child } : {}),
363
470
  };
364
471
  }
365
472
 
@@ -386,6 +493,7 @@ function inputForIntakeRecord(
386
493
  ...(record.hook_duration_ms !== undefined ? { hook_duration_ms: record.hook_duration_ms } : {}),
387
494
  ...(record.stop_remediation !== undefined ? { stop_remediation: record.stop_remediation } : {}),
388
495
  ...(record.turn_ritual ? { turn_ritual: record.turn_ritual } : {}),
496
+ ...(record.delegated_child ? { delegated_child: record.delegated_child } : {}),
389
497
  };
390
498
  }
391
499
 
@@ -524,8 +632,23 @@ function processHookSignalLocked(
524
632
  : control.activation.event.event_id;
525
633
  const rootFingerprintContext = fingerprintContextV3(input.coordRoot, rootId, undefined, epochId);
526
634
  const sessionId = `sid_${sessionHash.slice(4)}` as `sid_${string}`;
635
+ const genesisId = control.genesis.event.payload.genesis_id as `gex_${string}`;
636
+ // Every write below carries the epoch fence: an event produced for this
637
+ // epoch is refused (or quarantined from the spool) once the epoch has been
638
+ // replaced, instead of poisoning the successor's authority.
639
+ input = {
640
+ ...input,
641
+ writerOptions: { ...input.writerOptions, expectedGenesisId: genesisId },
642
+ };
527
643
  try {
528
644
  let state = existsSync(path) ? readProducerState(path) : undefined;
645
+ if (state && state.epoch_genesis_id !== genesisId) {
646
+ // A producer state from a replaced epoch (or one that predates the
647
+ // field) is never adopted: its boot sequences and causal links only
648
+ // validate inside the epoch that recorded them. The session re-onboards
649
+ // below exactly as it does after an automatic epoch refresh.
650
+ state = undefined;
651
+ }
529
652
  if (
530
653
  state &&
531
654
  (state.adapter !== input.adapter ||
@@ -551,7 +674,7 @@ function processHookSignalLocked(
551
674
  const pendingSource = state.pending.source_id;
552
675
  const incomingSource = sourceIdForSignal(input, rootFingerprintContext);
553
676
  const pendingEvent = state.pending.event;
554
- const durability = writeEventV3(input.coordRoot, pendingEvent);
677
+ const durability = writeEventV3(input.coordRoot, pendingEvent, input.writerOptions);
555
678
  applyCommittedEvent(state, pendingEvent);
556
679
  state.pending = undefined;
557
680
  publishProducerState(path, state);
@@ -565,10 +688,19 @@ function processHookSignalLocked(
565
688
  if (state && !state.terminal && state.started_event_id) {
566
689
  return { state: "already_started", event_id: state.started_event_id };
567
690
  }
568
- if (input.session_start_derivation && !state?.terminal) {
691
+ if (
692
+ (input.session_start_derivation === "approved_lifecycle_reopen" && !state?.terminal) ||
693
+ (input.session_start_derivation === "validated_current_session_heal" && state?.terminal)
694
+ ) {
569
695
  return { state: "missing_session_start" };
570
696
  }
571
- state = newProducerState(input, sessionId, epochId, boundaryEventId as `evt_${string}`);
697
+ state = newProducerState(
698
+ input,
699
+ sessionId,
700
+ epochId,
701
+ boundaryEventId as `evt_${string}`,
702
+ genesisId,
703
+ );
572
704
  } else if (!state || state.terminal) {
573
705
  // Mid-flight onboarding (ADR 0078): a live session with no producer
574
706
  // state in this epoch (fresh epoch, lost session-start hook) opens a
@@ -595,7 +727,13 @@ function processHookSignalLocked(
595
727
  });
596
728
  return { state: "missing_session_start" };
597
729
  }
598
- state = newProducerState(input, sessionId, epochId, boundaryEventId as `evt_${string}`);
730
+ state = newProducerState(
731
+ input,
732
+ sessionId,
733
+ epochId,
734
+ boundaryEventId as `evt_${string}`,
735
+ genesisId,
736
+ );
599
737
  const cursorPromptBootstrap = isCursorPromptBootstrap(input);
600
738
  const onboarding = buildMidFlightSessionStart(input, state, rootId, cursorPromptBootstrap);
601
739
  commitEventLocked(input, state, path, onboarding);
@@ -605,6 +743,7 @@ function processHookSignalLocked(
605
743
  instance_id: input.instance_id,
606
744
  signal: input.signal,
607
745
  session_hash: sessionHash,
746
+ ...(input.adapter === "codex" ? codexMidFlightDiagnosticContext(input.payload) : {}),
608
747
  });
609
748
  }
610
749
  }
@@ -669,6 +808,9 @@ function processHookSignalLocked(
669
808
  (nativeTid !== undefined && state.current_turn_id === nativeTid));
670
809
 
671
810
  recordTurnHarnessTiming(state, input, !duplicateOpenTurnStart);
811
+ reconcilePendingRuntimeContexts(input, state, path, rootId, fingerprintContext, {
812
+ finalAttempt: input.signal === "session-end",
813
+ });
672
814
 
673
815
  closeResolvedWaits(input, state, path, rootId, fingerprintContext, nativeTid);
674
816
  if (input.signal === "permission-request") {
@@ -736,6 +878,7 @@ function processHookSignalLocked(
736
878
  boot_id: state.boot_id,
737
879
  clock: eventClock,
738
880
  });
881
+ state.current_native_turn_id = input.payload.turn_id;
739
882
  }
740
883
 
741
884
  let sourceId = sourceIdForSignal(input, rootFingerprintContext);
@@ -933,7 +1076,7 @@ function processHookSignalLocked(
933
1076
 
934
1077
  const turnTelemetry =
935
1078
  input.signal === "stop" || input.signal === "stop-failure"
936
- ? extractTurnTelemetryV3(input.adapter, input.payload.raw, eventClock.observed_at)
1079
+ ? turnTelemetryForTerminal(input, state, eventClock.observed_at)
937
1080
  : undefined;
938
1081
  const cursorToolChannelSupport =
939
1082
  input.adapter === "cursor"
@@ -950,6 +1093,9 @@ function processHookSignalLocked(
950
1093
  const toolCallCountScopeMismatch =
951
1094
  (input.signal === "stop" || input.signal === "stop-failure") &&
952
1095
  (!state.current_turn_id || state.tool_call_count_turn_id !== state.current_turn_id);
1096
+ // Before the signal's own event: the tool call or turn that carries the
1097
+ // new effort already ran under it, so it must ride the new attestation.
1098
+ maybeAttestTuningChange(input, state, path, rootId);
953
1099
  const event = normalizeHookEventV3(input.signal, eventInput.payload, {
954
1100
  coordRoot: input.coordRoot,
955
1101
  adapter: input.adapter,
@@ -973,6 +1119,7 @@ function processHookSignalLocked(
973
1119
  platform: input.platform,
974
1120
  bridge: input.bridge,
975
1121
  capability_profile: state.capability_profile,
1122
+ cursor_mode: state.cursor_mode,
976
1123
  fingerprintContext,
977
1124
  turn_id: state.current_turn_id,
978
1125
  span_id: openingSpan?.span_id ?? closingSpan?.span_id,
@@ -1012,12 +1159,58 @@ function processHookSignalLocked(
1012
1159
  if (!event) return { state: "ignored" };
1013
1160
  if (
1014
1161
  input.signal === "session-start" &&
1015
- input.session_start_derivation === "approved_lifecycle_reopen" &&
1162
+ input.delegated_child &&
1163
+ event.event_type === "session.started"
1164
+ ) {
1165
+ event.links = {
1166
+ caused_by: [input.delegated_child.caused_by_event_id],
1167
+ parent_generation_id: input.delegated_child.parent_generation_id,
1168
+ delegation_id: input.delegated_child.delegation_id,
1169
+ };
1170
+ event.provenance = {
1171
+ ...event.provenance,
1172
+ source_event: `${input.adapter}.subagent-start.child-generation`,
1173
+ attestation: "derived",
1174
+ confidence: "high",
1175
+ attribution: {
1176
+ method: "native_payload",
1177
+ state: "verified",
1178
+ subject_instance_id: state.instance_id,
1179
+ },
1180
+ };
1181
+ assertEventV3(event);
1182
+ }
1183
+ if (
1184
+ input.signal === "user-prompt-submit" &&
1185
+ input.delegated_child &&
1186
+ event.event_type === "turn.started"
1187
+ ) {
1188
+ event.links = { caused_by: [input.delegated_child.caused_by_event_id] };
1189
+ event.provenance = {
1190
+ ...event.provenance,
1191
+ source_event: `${input.adapter}.subagent-start.child-turn`,
1192
+ attestation: "derived",
1193
+ confidence: "high",
1194
+ attribution: {
1195
+ method: "native_payload",
1196
+ state: "verified",
1197
+ subject_instance_id: state.instance_id,
1198
+ },
1199
+ };
1200
+ assertEventV3(event);
1201
+ }
1202
+ if (
1203
+ input.signal === "session-start" &&
1204
+ input.session_start_derivation &&
1016
1205
  event.event_type === "session.started"
1017
1206
  ) {
1207
+ const lifecycleReopen = input.session_start_derivation === "approved_lifecycle_reopen";
1208
+ const reason = lifecycleReopen
1209
+ ? "approved_lifecycle_reopen"
1210
+ : "validated_current_session_heal";
1018
1211
  event.provenance = {
1019
1212
  ...event.provenance,
1020
- source_event: `${input.adapter}.approved-lifecycle-reopen`,
1213
+ source_event: `${input.adapter}.${reason.replaceAll("_", "-")}`,
1021
1214
  attestation: "derived",
1022
1215
  confidence: "high",
1023
1216
  attribution: {
@@ -1028,7 +1221,7 @@ function processHookSignalLocked(
1028
1221
  };
1029
1222
  event.payload.resume = {
1030
1223
  state: "unknown",
1031
- reason: "approved_lifecycle_reopen",
1224
+ reason,
1032
1225
  };
1033
1226
  assertEventV3(event);
1034
1227
  }
@@ -1037,7 +1230,20 @@ function processHookSignalLocked(
1037
1230
  span.open_event_id = event.event_id as `evt_${string}`;
1038
1231
  stampSpanTurn(span, event, eventInput, state);
1039
1232
  }
1233
+ // A turn terminal clears current_native_turn_id when it commits. Retain the
1234
+ // native identity long enough to seed a delayed context retry afterward.
1235
+ const nativeTurnIdForContext = input.payload.turn_id ?? state.current_native_turn_id;
1040
1236
  const durability = commitEventLocked(input, state, path, event, sourceId);
1237
+ if (event.event_type === "context.compaction_started" && input.signal === "pre-compact") {
1238
+ maybeCommitNativeHookContextObservation(
1239
+ input,
1240
+ state,
1241
+ path,
1242
+ rootId,
1243
+ fingerprintContext,
1244
+ event,
1245
+ );
1246
+ }
1041
1247
  if (event.event_type === "tool.requested" && sourceId) {
1042
1248
  const explicitWait = explicitNativeWait(input);
1043
1249
  if (explicitWait) {
@@ -1050,8 +1256,35 @@ function processHookSignalLocked(
1050
1256
  if (progressKind) {
1051
1257
  commitProgressObservation(input, state, path, rootId, event, progressKind);
1052
1258
  }
1259
+ if (event.event_type === "tool.completed" && input.signal === "post-tool-use") {
1260
+ maybeCommitActiveRuntimeContextObservation(
1261
+ input,
1262
+ state,
1263
+ path,
1264
+ rootId,
1265
+ fingerprintContext,
1266
+ event,
1267
+ );
1268
+ }
1053
1269
  if (turnTelemetry) {
1054
- commitTurnContextObservation(input, state, path, rootId, event, turnTelemetry.context);
1270
+ const contextTarget = turnContextTarget(event);
1271
+ queuePendingRuntimeContext(
1272
+ input,
1273
+ state,
1274
+ contextTarget,
1275
+ turnTelemetry.context,
1276
+ nativeTurnIdForContext,
1277
+ );
1278
+ commitTurnContextObservation(
1279
+ input,
1280
+ state,
1281
+ path,
1282
+ rootId,
1283
+ fingerprintContext,
1284
+ contextTarget,
1285
+ turnTelemetry.context,
1286
+ turnTelemetry.context_provenance,
1287
+ );
1055
1288
  }
1056
1289
  if (event.event_type === "session.ended") {
1057
1290
  commitCapabilityDriftEvents(input, state, path, rootId);
@@ -1501,10 +1734,60 @@ function commitTurnContextObservation(
1501
1734
  state: HookProducerStateV3,
1502
1735
  path: string,
1503
1736
  rootId: `root_${string}`,
1504
- turnTerminal: EventV3,
1737
+ fingerprintContext: ReturnType<typeof fingerprintContextV3>,
1738
+ target: TurnContextTargetV3 | undefined,
1739
+ measurement: TelemetryObservationV3<ContextMeasurementV3>,
1740
+ contextProvenance?: ContextTelemetryProvenanceV3,
1741
+ observedAt?: string,
1742
+ ): void {
1743
+ if (!target) return;
1744
+ commitContextObservation(
1745
+ input,
1746
+ state,
1747
+ path,
1748
+ rootId,
1749
+ fingerprintContext,
1750
+ {
1751
+ caused_by_event_id: target.terminal_event_id,
1752
+ observed_at: observedAt ?? target.terminal_observed_at,
1753
+ turn_id: target.turn_id,
1754
+ ...(target.run_id ? { run_id: target.run_id } : {}),
1755
+ ...(target.workflow_id ? { workflow_id: target.workflow_id } : {}),
1756
+ ...(target.workflow_agent_id ? { workflow_agent_id: target.workflow_agent_id } : {}),
1757
+ },
1758
+ measurement,
1759
+ contextProvenance,
1760
+ );
1761
+ }
1762
+
1763
+ function commitContextObservation(
1764
+ input: RecordHookSignalV3Input,
1765
+ state: HookProducerStateV3,
1766
+ path: string,
1767
+ rootId: `root_${string}`,
1768
+ fingerprintContext: ReturnType<typeof fingerprintContextV3>,
1769
+ target: {
1770
+ caused_by_event_id: `evt_${string}`;
1771
+ observed_at: string;
1772
+ turn_id: `tid_${string}`;
1773
+ run_id?: `run_${string}`;
1774
+ workflow_id?: `wf_${string}`;
1775
+ workflow_agent_id?: string;
1776
+ },
1505
1777
  measurement: TelemetryObservationV3<ContextMeasurementV3>,
1778
+ contextProvenance?: ContextTelemetryProvenanceV3,
1506
1779
  ): void {
1507
- if (turnTerminal.event_type !== "turn.completed") return;
1780
+ if (
1781
+ measurement.state === "observed" &&
1782
+ contextProvenance?.source_witness &&
1783
+ state.last_context_source_witness === contextProvenance.source_witness
1784
+ ) {
1785
+ publishProducerState(path, state);
1786
+ return;
1787
+ }
1788
+ if (measurement.state === "observed" && contextProvenance?.source_witness) {
1789
+ state.last_context_source_witness = contextProvenance.source_witness;
1790
+ }
1508
1791
  const event = buildEventV3("context.observed", {
1509
1792
  producer: {
1510
1793
  producer_id: input.producer_id,
@@ -1520,36 +1803,859 @@ function commitTurnContextObservation(
1520
1803
  instance_id: state.instance_id,
1521
1804
  session_id: state.session_id,
1522
1805
  generation_id: state.generation_id,
1523
- turn_id: (turnTerminal.scope as { turn_id: `tid_${string}` }).turn_id,
1524
- ...(input.run_id ? { run_id: input.run_id } : {}),
1525
- ...(input.workflow_id ? { workflow_id: input.workflow_id } : {}),
1526
- ...(input.workflow_agent_id ? { workflow_agent_id: input.workflow_agent_id } : {}),
1806
+ turn_id: target.turn_id,
1807
+ ...(target.run_id ? { run_id: target.run_id } : {}),
1808
+ ...(target.workflow_id ? { workflow_id: target.workflow_id } : {}),
1809
+ ...(target.workflow_agent_id ? { workflow_agent_id: target.workflow_agent_id } : {}),
1527
1810
  },
1528
1811
  attestation_id: state.attestation_id,
1529
- links: { caused_by: [turnTerminal.event_id] },
1812
+ links: { caused_by: [target.caused_by_event_id] },
1530
1813
  provenance: {
1531
- source_event: `${input.adapter}.turn-context`,
1814
+ source_event: safeRole(
1815
+ [
1816
+ contextProvenance?.source_event ?? `${input.adapter}.turn-context`,
1817
+ contextProvenance?.runtime_version,
1818
+ ]
1819
+ .filter(Boolean)
1820
+ .join("."),
1821
+ ),
1822
+ attestation: contextProvenance?.attestation ?? "native",
1823
+ confidence: contextProvenance?.confidence ?? "exact",
1824
+ ...(contextProvenance?.source_witness
1825
+ ? {
1826
+ source_record_id: normalizeNativeIdV3(
1827
+ fingerprintContext,
1828
+ `${input.adapter}.runtime-context`,
1829
+ contextProvenance.source_witness,
1830
+ ),
1831
+ }
1832
+ : {}),
1833
+ attribution: {
1834
+ method: "native_payload",
1835
+ state: "verified",
1836
+ subject_instance_id: state.instance_id,
1837
+ },
1838
+ },
1839
+ // The source sample may precede the hook boundary that admits it.
1840
+ // measurement.measured_at preserves the sample clock without creating a
1841
+ // causal wall-clock regression in the producer event chain.
1842
+ observed_at: target.observed_at,
1843
+ monotonic_ns: orderedEventMonotonic(state, input.monotonic_ns),
1844
+ clock_id: state.clock_id,
1845
+ payload: {
1846
+ measurement,
1847
+ },
1848
+ }) as EventV3;
1849
+ commitEventLocked(input, state, path, event);
1850
+ maybeAttestContextCapabilityChange(input, state, path, rootId, measurement, contextProvenance);
1851
+ }
1852
+
1853
+ /**
1854
+ * Admit fresh adapter-native or bounded runtime context while a turn is open.
1855
+ * Tool completions are safe sampling boundaries. Persistent owner-only cadence
1856
+ * state prevents short-lived hook processes from reading on every request,
1857
+ * and the source witness prevents duplicate public events.
1858
+ */
1859
+ function maybeCommitActiveRuntimeContextObservation(
1860
+ input: RecordHookSignalV3Input,
1861
+ state: HookProducerStateV3,
1862
+ path: string,
1863
+ rootId: `root_${string}`,
1864
+ fingerprintContext: ReturnType<typeof fingerprintContextV3>,
1865
+ sourceEvent: EventV3,
1866
+ ): void {
1867
+ if (input.signal !== "post-tool-use" || state.terminal || !state.current_turn_id) {
1868
+ return;
1869
+ }
1870
+ const nativeSessionId = input.payload.session_id ?? input.payload.conversation_id;
1871
+ const nativeTurnId = input.payload.turn_id ?? state.current_native_turn_id;
1872
+ if (!nativeSessionId || (!nativeTurnId && input.adapter !== "cursor")) return;
1873
+
1874
+ const now = Date.now();
1875
+ const configuredInterval = input.runtimeTelemetryOptions?.activeContextProbeIntervalMs;
1876
+ const intervalMs =
1877
+ configuredInterval !== undefined && Number.isFinite(configuredInterval)
1878
+ ? Math.max(0, Math.floor(configuredInterval))
1879
+ : ACTIVE_RUNTIME_CONTEXT_PROBE_INTERVAL_MS;
1880
+ const prior = state.active_runtime_context_probe;
1881
+ const priorAttempt = prior ? Date.parse(prior.attempted_at) : Number.NaN;
1882
+ if (
1883
+ prior?.turn_id === state.current_turn_id &&
1884
+ prior.boundary === "tool_completed" &&
1885
+ Number.isFinite(priorAttempt) &&
1886
+ now - priorAttempt >= 0 &&
1887
+ now - priorAttempt < intervalMs
1888
+ ) {
1889
+ return;
1890
+ }
1891
+ state.active_runtime_context_probe = {
1892
+ turn_id: state.current_turn_id,
1893
+ attempted_at: new Date(now).toISOString(),
1894
+ boundary: "tool_completed",
1895
+ };
1896
+
1897
+ const native = extractTurnTelemetryV3(
1898
+ input.adapter,
1899
+ input.payload.raw,
1900
+ sourceEvent.time.observed_at,
1901
+ ).context;
1902
+ if (native.state === "observed") {
1903
+ commitActiveContextObservation(
1904
+ input,
1905
+ state,
1906
+ path,
1907
+ rootId,
1908
+ fingerprintContext,
1909
+ sourceEvent,
1910
+ native,
1911
+ nativeContextProvenance(input, state, native),
1912
+ );
1913
+ return;
1914
+ }
1915
+ if (input.adapter === "cursor" && state.cursor_mode === "cloud") {
1916
+ publishProducerState(path, state);
1917
+ return;
1918
+ }
1919
+
1920
+ const transcriptPath = runtimeTranscriptPath(input, state);
1921
+ if (!transcriptPath && input.adapter !== "cursor") {
1922
+ publishProducerState(path, state);
1923
+ return;
1924
+ }
1925
+ const runtime = readRuntimeContextTelemetry(
1926
+ {
1927
+ adapter: input.adapter,
1928
+ session_id: nativeSessionId,
1929
+ ...(nativeTurnId ? { turn_id: nativeTurnId } : {}),
1930
+ ...(state.current_turn_span?.opened_at
1931
+ ? { turn_started_at: state.current_turn_span.opened_at }
1932
+ : {}),
1933
+ transcript_path: transcriptPath,
1934
+ observed_at: sourceEvent.time.observed_at,
1935
+ mode: "active_turn",
1936
+ },
1937
+ input.runtimeTelemetryOptions,
1938
+ );
1939
+ if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
1940
+ if (runtime.state !== "observed") {
1941
+ publishProducerState(path, state);
1942
+ return;
1943
+ }
1944
+
1945
+ commitActiveContextObservation(
1946
+ input,
1947
+ state,
1948
+ path,
1949
+ rootId,
1950
+ fingerprintContext,
1951
+ sourceEvent,
1952
+ runtimeContextObservation(runtime),
1953
+ {
1954
+ source_event: runtime.source_event,
1955
+ source_witness: runtime.source_witness,
1956
+ ...(input.adapterVersion ? { runtime_version: input.adapterVersion } : {}),
1957
+ attestation: runtime.attestation,
1958
+ confidence: runtime.confidence,
1959
+ },
1960
+ );
1961
+ }
1962
+
1963
+ function commitActiveContextObservation(
1964
+ input: RecordHookSignalV3Input,
1965
+ state: HookProducerStateV3,
1966
+ path: string,
1967
+ rootId: `root_${string}`,
1968
+ fingerprintContext: ReturnType<typeof fingerprintContextV3>,
1969
+ sourceEvent: EventV3,
1970
+ measurement: TelemetryObservationV3<ContextMeasurementV3>,
1971
+ provenance: ContextTelemetryProvenanceV3,
1972
+ ): void {
1973
+ if (!state.current_turn_id) return;
1974
+ const scope = sourceEvent.scope as {
1975
+ run_id?: `run_${string}`;
1976
+ workflow_id?: `wf_${string}`;
1977
+ workflow_agent_id?: string;
1978
+ };
1979
+ commitContextObservation(
1980
+ input,
1981
+ state,
1982
+ path,
1983
+ rootId,
1984
+ fingerprintContext,
1985
+ {
1986
+ caused_by_event_id: sourceEvent.event_id as `evt_${string}`,
1987
+ observed_at: sourceEvent.time.observed_at,
1988
+ turn_id: state.current_turn_id,
1989
+ ...(scope.run_id ? { run_id: scope.run_id } : {}),
1990
+ ...(scope.workflow_id ? { workflow_id: scope.workflow_id } : {}),
1991
+ ...(scope.workflow_agent_id ? { workflow_agent_id: scope.workflow_agent_id } : {}),
1992
+ },
1993
+ measurement,
1994
+ provenance,
1995
+ );
1996
+ }
1997
+
1998
+ function nativeContextProvenance(
1999
+ input: RecordHookSignalV3Input,
2000
+ state: HookProducerStateV3,
2001
+ measurement: Extract<TelemetryObservationV3<ContextMeasurementV3>, { state: "observed" }>,
2002
+ ): ContextTelemetryProvenanceV3 {
2003
+ const { measured_at: _measuredAt, ...stableValue } = measurement.value;
2004
+ const witness = canonicalJsonV3({
2005
+ adapter: input.adapter,
2006
+ session_id: state.session_id,
2007
+ turn_id: state.current_turn_id,
2008
+ value: stableValue,
2009
+ });
2010
+ return {
2011
+ source_event: `${input.adapter}.native_context`,
2012
+ source_witness: createHash("sha256").update(witness).digest("hex"),
2013
+ ...(input.adapterVersion ? { runtime_version: input.adapterVersion } : {}),
2014
+ attestation: measurement.attestation,
2015
+ confidence: measurement.confidence,
2016
+ };
2017
+ }
2018
+
2019
+ function maybeCommitNativeHookContextObservation(
2020
+ input: RecordHookSignalV3Input,
2021
+ state: HookProducerStateV3,
2022
+ path: string,
2023
+ rootId: `root_${string}`,
2024
+ fingerprintContext: ReturnType<typeof fingerprintContextV3>,
2025
+ sourceEvent: EventV3,
2026
+ ): void {
2027
+ const measurement = extractTurnTelemetryV3(
2028
+ input.adapter,
2029
+ input.payload.raw,
2030
+ sourceEvent.time.observed_at,
2031
+ ).context;
2032
+ if (measurement.state !== "observed") return;
2033
+ commitActiveContextObservation(
2034
+ input,
2035
+ state,
2036
+ path,
2037
+ rootId,
2038
+ fingerprintContext,
2039
+ sourceEvent,
2040
+ measurement,
2041
+ nativeContextProvenance(input, state, measurement),
2042
+ );
2043
+ }
2044
+
2045
+ function maybeAttestContextCapabilityChange(
2046
+ input: RecordHookSignalV3Input,
2047
+ state: HookProducerStateV3,
2048
+ path: string,
2049
+ rootId: `root_${string}`,
2050
+ measurement: TelemetryObservationV3<ContextMeasurementV3>,
2051
+ provenance?: ContextTelemetryProvenanceV3,
2052
+ ): void {
2053
+ const context =
2054
+ measurement.state === "observed"
2055
+ ? {
2056
+ state: "observed" as const,
2057
+ source: provenance?.source_event ?? `${input.adapter}.turn_context`,
2058
+ attestation: provenance?.attestation ?? measurement.attestation,
2059
+ confidence: provenance?.confidence ?? measurement.confidence,
2060
+ completeness:
2061
+ "used_percent" in measurement.value
2062
+ ? ("percentage_only" as const)
2063
+ : (provenance?.attestation ?? measurement.attestation) === "inferred"
2064
+ ? ("inferred" as const)
2065
+ : ("exact" as const),
2066
+ }
2067
+ : measurement.state === "expected_but_missing"
2068
+ ? { state: "partial" as const, reason: measurement.reason }
2069
+ : { state: "unsupported" as const };
2070
+ const telemetry = effectiveRuntimeTelemetryCapabilitiesV3({
2071
+ adapter: input.adapter,
2072
+ ...(state.cursor_mode ? { cursor_mode: state.cursor_mode } : {}),
2073
+ context,
2074
+ canonical_turn_boundaries: true,
2075
+ });
2076
+ if (!state.last_attested_telemetry) return;
2077
+ if (canonicalJsonV3(telemetry) === canonicalJsonV3(state.last_attested_telemetry)) return;
2078
+ if (!state.last_attested_model_observation || !state.last_attested_tuning_observation) return;
2079
+
2080
+ commitRuntimeAttestationChange(input, state, path, rootId, {
2081
+ model: state.last_attested_model_observation,
2082
+ tuning: state.last_attested_tuning_observation,
2083
+ telemetry,
2084
+ reason: "runtime_telemetry_changed",
2085
+ source_event: provenance?.source_event ?? `${input.adapter}.turn_context`,
2086
+ attestation: provenance?.attestation ?? "derived",
2087
+ confidence: provenance?.confidence ?? (measurement.state === "observed" ? "exact" : "high"),
2088
+ });
2089
+ }
2090
+
2091
+ function turnContextTarget(turnTerminal: EventV3): TurnContextTargetV3 | undefined {
2092
+ if (turnTerminal.event_type !== "turn.completed") return undefined;
2093
+ const scope = turnTerminal.scope as {
2094
+ turn_id: `tid_${string}`;
2095
+ run_id?: `run_${string}`;
2096
+ workflow_id?: `wf_${string}`;
2097
+ workflow_agent_id?: string;
2098
+ };
2099
+ return {
2100
+ terminal_event_id: turnTerminal.event_id as `evt_${string}`,
2101
+ terminal_observed_at: turnTerminal.time.observed_at,
2102
+ turn_id: scope.turn_id,
2103
+ ...(scope.run_id ? { run_id: scope.run_id } : {}),
2104
+ ...(scope.workflow_id ? { workflow_id: scope.workflow_id } : {}),
2105
+ ...(scope.workflow_agent_id ? { workflow_agent_id: scope.workflow_agent_id } : {}),
2106
+ };
2107
+ }
2108
+
2109
+ function queuePendingRuntimeContext(
2110
+ input: RecordHookSignalV3Input,
2111
+ state: HookProducerStateV3,
2112
+ target: TurnContextTargetV3 | undefined,
2113
+ measurement: TelemetryObservationV3<ContextMeasurementV3>,
2114
+ nativeTurnId: string | undefined,
2115
+ ): void {
2116
+ if (
2117
+ input.adapter !== "codex" ||
2118
+ !target ||
2119
+ measurement.state !== "expected_but_missing" ||
2120
+ !retryableRuntimeContextReason(measurement.reason)
2121
+ ) {
2122
+ return;
2123
+ }
2124
+ const nativeSessionId = input.payload.session_id ?? input.payload.conversation_id;
2125
+ if (!nativeSessionId || !nativeTurnId) return;
2126
+ const pending: PendingRuntimeContextV3 = {
2127
+ ...target,
2128
+ native_session_id: nativeSessionId,
2129
+ native_turn_id: nativeTurnId,
2130
+ ...((input.payload.transcript_path ?? state.runtime_transcript_path)
2131
+ ? { transcript_path: input.payload.transcript_path ?? state.runtime_transcript_path }
2132
+ : {}),
2133
+ ...(input.adapterVersion ? { runtime_version: input.adapterVersion } : {}),
2134
+ attempts: 0,
2135
+ };
2136
+ state.pending_runtime_contexts = [
2137
+ ...(state.pending_runtime_contexts ?? []).filter(
2138
+ (candidate) => candidate.turn_id !== target.turn_id,
2139
+ ),
2140
+ pending,
2141
+ ].slice(-PENDING_RUNTIME_CONTEXT_CAP);
2142
+ }
2143
+
2144
+ function reconcilePendingRuntimeContexts(
2145
+ input: RecordHookSignalV3Input,
2146
+ state: HookProducerStateV3,
2147
+ path: string,
2148
+ rootId: `root_${string}`,
2149
+ fingerprintContext: ReturnType<typeof fingerprintContextV3>,
2150
+ options: { deferRetryLimit?: boolean; finalAttempt?: boolean } = {},
2151
+ ): void {
2152
+ if (state.adapter !== "codex" || !state.pending_runtime_contexts?.length) return;
2153
+ for (const pending of [...state.pending_runtime_contexts]) {
2154
+ const runtime = readRuntimeContextTelemetry(
2155
+ {
2156
+ adapter: "codex",
2157
+ session_id: pending.native_session_id,
2158
+ turn_id: pending.native_turn_id,
2159
+ transcript_path: pending.transcript_path,
2160
+ mode: "turn",
2161
+ },
2162
+ input.runtimeTelemetryOptions,
2163
+ );
2164
+ if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
2165
+ const queue = state.pending_runtime_contexts;
2166
+ if (!queue) break;
2167
+ const index = queue.findIndex((candidate) => candidate.turn_id === pending.turn_id);
2168
+ if (index < 0) continue;
2169
+ if (runtime.state === "observed") {
2170
+ queue.splice(index, 1);
2171
+ if (queue.length === 0) {
2172
+ state.pending_runtime_contexts = undefined;
2173
+ }
2174
+ commitTurnContextObservation(
2175
+ input,
2176
+ state,
2177
+ path,
2178
+ rootId,
2179
+ fingerprintContext,
2180
+ pending,
2181
+ runtimeContextObservation(runtime),
2182
+ {
2183
+ source_event: runtime.source_event,
2184
+ source_witness: runtime.source_witness,
2185
+ ...(pending.runtime_version ? { runtime_version: pending.runtime_version } : {}),
2186
+ attestation: "derived",
2187
+ confidence: "exact",
2188
+ },
2189
+ signalClock(input).observed_at,
2190
+ );
2191
+ continue;
2192
+ }
2193
+ const attempts = pending.attempts + 1;
2194
+ if (
2195
+ options.finalAttempt ||
2196
+ runtime.state === "unsupported" ||
2197
+ !retryableRuntimeContextReason(runtime.reason) ||
2198
+ (!options.deferRetryLimit && attempts >= RUNTIME_CONTEXT_RETRY_LIMIT)
2199
+ ) {
2200
+ queue.splice(index, 1);
2201
+ } else {
2202
+ queue[index] = { ...pending, attempts };
2203
+ }
2204
+ }
2205
+ if (state.pending_runtime_contexts?.length === 0) {
2206
+ state.pending_runtime_contexts = undefined;
2207
+ }
2208
+ publishProducerState(path, state);
2209
+ }
2210
+
2211
+ function reconcilePendingRuntimeContextsBeforeApprovedEnd(
2212
+ input: RecordApprovedSessionEndV3Input,
2213
+ state: HookProducerStateV3,
2214
+ path: string,
2215
+ rootId: `root_${string}`,
2216
+ fingerprintContext: ReturnType<typeof fingerprintContextV3>,
2217
+ ): void {
2218
+ if (state.adapter !== "codex" || !state.pending_runtime_contexts?.length) return;
2219
+ for (const [index, delayMs] of APPROVED_END_RUNTIME_CONTEXT_RETRY_DELAYS_MS.entries()) {
2220
+ if (delayMs > 0) sleepSync(delayMs);
2221
+ reconcilePendingRuntimeContexts(
2222
+ {
2223
+ coordRoot: input.coordRoot,
2224
+ mode: input.mode,
2225
+ signal: "session-end",
2226
+ payload: { raw: {} },
2227
+ adapter: state.adapter,
2228
+ instance_id: state.instance_id,
2229
+ producer_id: "prd_agent-finalizer",
2230
+ build_id: input.build_id,
2231
+ platform: input.platform,
2232
+ observed_at: new Date().toISOString(),
2233
+ writerOptions: input.writerOptions,
2234
+ },
2235
+ state,
2236
+ path,
2237
+ rootId,
2238
+ fingerprintContext,
2239
+ {
2240
+ deferRetryLimit: true,
2241
+ finalAttempt: index === APPROVED_END_RUNTIME_CONTEXT_RETRY_DELAYS_MS.length - 1,
2242
+ },
2243
+ );
2244
+ if (!state.pending_runtime_contexts?.length) return;
2245
+ }
2246
+ }
2247
+
2248
+ function retryableRuntimeContextReason(reason: string | undefined): boolean {
2249
+ return (
2250
+ reason === "codex_transcript_turn_not_found" ||
2251
+ reason === "codex_transcript_turn_not_terminal" ||
2252
+ reason === "codex_transcript_token_count_missing"
2253
+ );
2254
+ }
2255
+
2256
+ function turnTelemetryForTerminal(
2257
+ input: RecordHookSignalV3Input,
2258
+ state: HookProducerStateV3,
2259
+ observedAt: string,
2260
+ ): TurnTelemetryV3 {
2261
+ const native = extractTurnTelemetryV3(input.adapter, input.payload.raw, observedAt);
2262
+ if (native.context.state === "observed") return native;
2263
+ if (input.adapter === "cursor" && state.cursor_mode === "cloud") {
2264
+ return {
2265
+ ...native,
2266
+ context: { state: "unsupported", capability: "context_usage" },
2267
+ };
2268
+ }
2269
+
2270
+ const request = {
2271
+ adapter: input.adapter,
2272
+ session_id: input.payload.session_id ?? input.payload.conversation_id,
2273
+ turn_id: input.payload.turn_id ?? state.current_native_turn_id,
2274
+ transcript_path: runtimeTranscriptPath(input, state),
2275
+ observed_at: observedAt,
2276
+ mode: "turn" as const,
2277
+ };
2278
+ let runtime = readRuntimeContextTelemetry(request, input.runtimeTelemetryOptions);
2279
+ if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
2280
+ if (
2281
+ input.adapter === "codex" &&
2282
+ runtime.state === "partial" &&
2283
+ retryableRuntimeContextReason(runtime.reason)
2284
+ ) {
2285
+ for (const delayMs of STOP_RUNTIME_CONTEXT_RETRY_DELAYS_MS) {
2286
+ sleepSync(delayMs);
2287
+ runtime = readRuntimeContextTelemetry(request, input.runtimeTelemetryOptions);
2288
+ if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
2289
+ if (runtime.state !== "partial" || !retryableRuntimeContextReason(runtime.reason)) break;
2290
+ }
2291
+ }
2292
+ if (runtime.state === "unsupported") return native;
2293
+ return {
2294
+ ...native,
2295
+ context: runtimeContextObservation(runtime),
2296
+ context_provenance: {
2297
+ source_event:
2298
+ runtime.state === "observed" ? runtime.source_event : `${input.adapter}.runtime_context`,
2299
+ ...(runtime.state === "observed" ? { source_witness: runtime.source_witness } : {}),
2300
+ ...(input.adapterVersion ? { runtime_version: input.adapterVersion } : {}),
2301
+ attestation: runtime.state === "observed" ? runtime.attestation : "derived",
2302
+ confidence: runtime.state === "observed" ? runtime.confidence : "high",
2303
+ },
2304
+ };
2305
+ }
2306
+
2307
+ /**
2308
+ * Resolve Codex's rollout once, retain it in owner-only producer state, and
2309
+ * verify the cached path against the native session before every reuse. Public
2310
+ * events receive only numeric telemetry and an opaque source witness.
2311
+ */
2312
+ function runtimeTranscriptPath(
2313
+ input: RecordHookSignalV3Input,
2314
+ state: HookProducerStateV3,
2315
+ ): string | undefined {
2316
+ if (input.adapter !== "codex") return input.payload.transcript_path;
2317
+ const nativeSessionId = input.payload.session_id ?? input.payload.conversation_id;
2318
+ if (!nativeSessionId) return input.payload.transcript_path;
2319
+
2320
+ const supplied = input.payload.transcript_path;
2321
+ if (supplied) {
2322
+ const verified = discoverCodexSessionTranscript(
2323
+ nativeSessionId,
2324
+ supplied,
2325
+ input.runtimeTelemetryOptions,
2326
+ );
2327
+ if (verified) state.runtime_transcript_path = verified;
2328
+ // Preserve a supplied mismatch so the typed reader reports it honestly.
2329
+ return verified ?? supplied;
2330
+ }
2331
+
2332
+ if (state.runtime_transcript_path) {
2333
+ const verified = discoverCodexSessionTranscript(
2334
+ nativeSessionId,
2335
+ state.runtime_transcript_path,
2336
+ input.runtimeTelemetryOptions,
2337
+ );
2338
+ if (verified) return verified;
2339
+ state.runtime_transcript_path = undefined;
2340
+ }
2341
+
2342
+ const discovered = discoverCodexSessionTranscript(
2343
+ nativeSessionId,
2344
+ undefined,
2345
+ input.runtimeTelemetryOptions,
2346
+ );
2347
+ if (discovered) state.runtime_transcript_path = discovered;
2348
+ return discovered;
2349
+ }
2350
+
2351
+ function runtimeContextObservation(
2352
+ runtime: RuntimeContextTelemetry,
2353
+ ): TelemetryObservationV3<ContextMeasurementV3> {
2354
+ if (runtime.state === "observed") {
2355
+ if ("used_percent" in runtime) {
2356
+ return {
2357
+ state: "observed",
2358
+ value: {
2359
+ used_percent: runtime.used_percent,
2360
+ remaining_percent: Math.max(0, 100 - runtime.used_percent),
2361
+ measured_at: runtime.measured_at,
2362
+ method: runtime.method,
2363
+ },
2364
+ attestation: runtime.attestation,
2365
+ confidence: runtime.confidence,
2366
+ };
2367
+ }
2368
+ return {
2369
+ state: "observed",
2370
+ value: {
2371
+ used_tokens: runtime.used_tokens,
2372
+ limit_tokens: runtime.limit_tokens,
2373
+ remaining_tokens: Math.max(0, runtime.limit_tokens - runtime.used_tokens),
2374
+ measured_at: runtime.measured_at,
2375
+ method: runtime.method,
2376
+ },
2377
+ attestation: runtime.attestation,
2378
+ confidence: runtime.confidence,
2379
+ };
2380
+ }
2381
+ return {
2382
+ state: "expected_but_missing",
2383
+ capability: "context_usage",
2384
+ reason: runtime.reason,
2385
+ };
2386
+ }
2387
+
2388
+ /** Seed the change-detection baseline from a committed session.started. */
2389
+ function seedAttestedTuning(state: HookProducerStateV3, event: { payload: unknown }): void {
2390
+ const attestation = (event.payload as { runtime_attestation?: RuntimeAttestationV3Base })
2391
+ .runtime_attestation;
2392
+ if (!attestation) return;
2393
+ const tuning = attestation.tuning;
2394
+ state.last_attested_tuning =
2395
+ tuning?.state === "observed"
2396
+ ? {
2397
+ ...(tuning.value?.effort ? { effort: tuning.value.effort } : {}),
2398
+ ...(tuning.value?.speed ? { speed: tuning.value.speed } : {}),
2399
+ }
2400
+ : {};
2401
+ const model = attestation.model;
2402
+ if (model.state === "observed") {
2403
+ state.last_attested_model = { provider: model.value.provider, id: model.value.id };
2404
+ }
2405
+ state.last_attested_model_observation = model;
2406
+ state.last_attested_tuning_observation = tuning;
2407
+ state.last_attested_telemetry = attestation.telemetry as RuntimeTelemetryCapabilitiesV3;
2408
+ }
2409
+
2410
+ /**
2411
+ * Emit `session.attestation_changed` when the observed tuning moves.
2412
+ *
2413
+ * Detection channels are deliberately cheap: CC stamps `effort.level` on
2414
+ * every tool hook and Stop (zero I/O), and Codex tuning is read from the
2415
+ * rollout only at turn terminals, where the context enrichment already pays
2416
+ * for a bounded tail read. A pre-upgrade state file (no baseline) seeds
2417
+ * silently so existing sessions do not fire a spurious change on their next
2418
+ * tool event; a fresh session's baseline comes from its session.started.
2419
+ */
2420
+ function maybeAttestTuningChange(
2421
+ input: RecordHookSignalV3Input,
2422
+ state: HookProducerStateV3,
2423
+ path: string,
2424
+ rootId: `root_${string}`,
2425
+ ): void {
2426
+ if (
2427
+ input.signal !== "pre-tool-use" &&
2428
+ input.signal !== "post-tool-use" &&
2429
+ input.signal !== "stop"
2430
+ ) {
2431
+ return;
2432
+ }
2433
+ if (state.terminal) return;
2434
+
2435
+ let candidate: { effort?: string; speed?: string; model?: string } | undefined;
2436
+ let attestationSource: "native" | "derived" = "native";
2437
+ let sourceEvent = `${input.adapter}.effort-payload`;
2438
+ if (input.adapter === "claude-code" || input.adapter === "cursor") {
2439
+ if (!input.payload.effort) return;
2440
+ candidate = { effort: input.payload.effort };
2441
+ } else if (
2442
+ input.adapter === "codex" &&
2443
+ (input.signal === "stop" ||
2444
+ // Early probe: without it, a Codex card shows no effort until the first
2445
+ // turn terminal. One rollout read per turn while effort is unknown.
2446
+ (input.signal === "post-tool-use" &&
2447
+ !state.last_attested_tuning?.effort &&
2448
+ state.current_turn_id !== undefined &&
2449
+ state.tuning_probe_turn_id !== state.current_turn_id))
2450
+ ) {
2451
+ if (input.signal === "post-tool-use") state.tuning_probe_turn_id = state.current_turn_id;
2452
+ const runtime = readRuntimeTuning(
2453
+ {
2454
+ adapter: "codex",
2455
+ session_id: input.payload.session_id ?? input.payload.conversation_id,
2456
+ transcript_path: runtimeTranscriptPath(input, state),
2457
+ },
2458
+ input.runtimeTelemetryOptions,
2459
+ );
2460
+ if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
2461
+ if (runtime.state !== "observed") return;
2462
+ candidate = {
2463
+ ...(runtime.effort ? { effort: runtime.effort } : {}),
2464
+ ...(runtime.speed ? { speed: runtime.speed } : {}),
2465
+ ...(runtime.model ? { model: runtime.model } : {}),
2466
+ };
2467
+ attestationSource = "derived";
2468
+ sourceEvent = runtime.source_event;
2469
+ } else {
2470
+ return;
2471
+ }
2472
+
2473
+ const baseline = state.last_attested_tuning;
2474
+ const next = { effort: candidate.effort, speed: candidate.speed ?? baseline?.speed };
2475
+ if (baseline === undefined || state.last_attested_telemetry === undefined) {
2476
+ // Pre-upgrade state: adopt without emitting; there is no attested prior.
2477
+ state.last_attested_tuning = { ...(next.effort ? { effort: next.effort } : {}) };
2478
+ if (next.speed) state.last_attested_tuning.speed = next.speed;
2479
+ return;
2480
+ }
2481
+ if (baseline.effort === next.effort && (candidate.speed ?? baseline.speed) === baseline.speed) {
2482
+ return;
2483
+ }
2484
+
2485
+ // CC change detection rides the payload; the paired transcript row also
2486
+ // carries speed and the (possibly swapped) model, so refresh from it.
2487
+ if (input.adapter === "claude-code") {
2488
+ const runtime = readRuntimeTuning({
2489
+ adapter: "claude-code",
2490
+ transcript_path: input.payload.transcript_path,
2491
+ });
2492
+ if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
2493
+ if (runtime.state === "observed" && runtime.effort === candidate.effort) {
2494
+ if (runtime.speed) candidate.speed = runtime.speed;
2495
+ if (runtime.model) candidate.model = runtime.model;
2496
+ }
2497
+ }
2498
+
2499
+ const model: RuntimeAttestationV3Base["model"] = candidate.model
2500
+ ? {
2501
+ state: "observed",
2502
+ value: { provider: modelProviderFor(input.adapter), id: safeRole(candidate.model) },
2503
+ attestation: "derived",
2504
+ confidence: "high",
2505
+ }
2506
+ : state.last_attested_model
2507
+ ? {
2508
+ state: "observed",
2509
+ value: state.last_attested_model,
2510
+ attestation: "derived",
2511
+ confidence: "high",
2512
+ }
2513
+ : { state: "expected_but_missing", capability: "model_identity", reason: "not_reported" };
2514
+ const tuning: RuntimeAttestationV3Base["tuning"] =
2515
+ candidate.effort || candidate.speed
2516
+ ? {
2517
+ state: "observed",
2518
+ value: {
2519
+ ...(candidate.effort ? { effort: candidate.effort } : {}),
2520
+ ...(candidate.speed ? { speed: candidate.speed } : {}),
2521
+ },
2522
+ attestation: attestationSource,
2523
+ confidence: "exact",
2524
+ }
2525
+ : { state: "unsupported", capability: "effort_selection" };
2526
+ commitRuntimeAttestationChange(input, state, path, rootId, {
2527
+ model,
2528
+ tuning,
2529
+ telemetry: state.last_attested_telemetry,
2530
+ reason: "runtime_tuning_changed",
2531
+ source_event: sourceEvent,
2532
+ attestation: attestationSource,
2533
+ confidence: attestationSource === "native" ? "exact" : "high",
2534
+ });
2535
+ }
2536
+
2537
+ interface RuntimeAttestationChangeV3 {
2538
+ model: RuntimeAttestationV3Base["model"];
2539
+ tuning: RuntimeAttestationV3Base["tuning"];
2540
+ telemetry: RuntimeTelemetryCapabilitiesV3;
2541
+ reason: string;
2542
+ source_event: string;
2543
+ attestation: "native" | "derived" | "inferred";
2544
+ confidence: "exact" | "high" | "medium" | "low";
2545
+ }
2546
+
2547
+ function commitRuntimeAttestationChange(
2548
+ input: RecordHookSignalV3Input,
2549
+ state: HookProducerStateV3,
2550
+ path: string,
2551
+ rootId: `root_${string}`,
2552
+ change: RuntimeAttestationChangeV3,
2553
+ ): void {
2554
+ const priorAttestationId = state.attestation_id;
2555
+ const nextAttestationId = attestationIdV3();
2556
+ const eventId = eventIdV3();
2557
+ const runtimeAttestation: RuntimeAttestationV3Base = {
2558
+ attestation_id: nextAttestationId,
2559
+ generation_id: state.generation_id,
2560
+ adapter: {
2561
+ state: "observed",
2562
+ value: {
2563
+ id: input.adapter,
2564
+ ...(input.adapterVersion ? { version: input.adapterVersion } : {}),
2565
+ },
1532
2566
  attestation: "native",
1533
2567
  confidence: "exact",
2568
+ },
2569
+ harness: {
2570
+ state: "observed",
2571
+ value: {
2572
+ id: input.adapter,
2573
+ ...(input.harnessVersion ? { version: input.harnessVersion } : {}),
2574
+ },
2575
+ attestation: "native",
2576
+ confidence: "exact",
2577
+ },
2578
+ model: change.model,
2579
+ tuning: change.tuning,
2580
+ telemetry: change.telemetry,
2581
+ capability_profile: state.capability_profile,
2582
+ declared_by_event_id: eventId,
2583
+ };
2584
+ const event = buildEventV3("session.attestation_changed", {
2585
+ event_id: eventId,
2586
+ producer: {
2587
+ producer_id: input.producer_id,
2588
+ boot_id: state.boot_id,
2589
+ sequence: state.next_sequence,
2590
+ component: "agent-hook",
2591
+ build_id: input.build_id,
2592
+ platform: input.platform,
2593
+ ...(input.bridge ? { bridge: input.bridge } : {}),
2594
+ },
2595
+ scope: {
2596
+ root_id: rootId,
2597
+ instance_id: state.instance_id,
2598
+ session_id: state.session_id,
2599
+ generation_id: state.generation_id,
2600
+ ...(input.run_id ? { run_id: input.run_id } : {}),
2601
+ ...(input.workflow_id ? { workflow_id: input.workflow_id } : {}),
2602
+ ...(input.workflow_agent_id ? { workflow_agent_id: input.workflow_agent_id } : {}),
2603
+ },
2604
+ attestation_id: nextAttestationId,
2605
+ links: { caused_by: state.last_event_id ? [state.last_event_id] : [] },
2606
+ provenance: {
2607
+ source_event: safeRole(change.source_event),
2608
+ attestation: change.attestation,
2609
+ confidence: change.confidence,
1534
2610
  attribution: {
1535
2611
  method: "native_payload",
1536
2612
  state: "verified",
1537
2613
  subject_instance_id: state.instance_id,
1538
2614
  },
1539
2615
  },
1540
- observed_at:
1541
- measurement.state === "observed"
1542
- ? measurement.value.measured_at
1543
- : turnTerminal.time.observed_at,
2616
+ observed_at: input.observed_at ?? new Date().toISOString(),
1544
2617
  monotonic_ns: orderedEventMonotonic(state, input.monotonic_ns),
1545
2618
  clock_id: state.clock_id,
1546
2619
  payload: {
1547
- measurement,
2620
+ prior_attestation_id: priorAttestationId,
2621
+ runtime_attestation: runtimeAttestation,
2622
+ reason: change.reason,
1548
2623
  },
1549
2624
  }) as EventV3;
2625
+ // Mutate BEFORE the commit: commitEventLocked publishes the state file, so
2626
+ // post-commit mutations would be dropped by the next signal's fresh read.
2627
+ // A crash between publishes replays the pending event against a state that
2628
+ // already carries the new attestation id, which is the id the event declares.
2629
+ state.attestation_id = nextAttestationId;
2630
+ state.last_attested_model_observation = change.model;
2631
+ state.last_attested_tuning_observation = change.tuning;
2632
+ state.last_attested_telemetry = change.telemetry;
2633
+ state.last_attested_model =
2634
+ change.model.state === "observed" ? { ...change.model.value } : undefined;
2635
+ state.last_attested_tuning = change.tuning.state === "observed" ? { ...change.tuning.value } : {};
1550
2636
  commitEventLocked(input, state, path, event);
1551
2637
  }
1552
2638
 
2639
+ function modelProviderFor(adapter: Adapter): string {
2640
+ if (adapter === "claude-code") return "anthropic";
2641
+ if (adapter === "codex") return "openai";
2642
+ return "cursor";
2643
+ }
2644
+
2645
+ function recordRuntimeTelemetryTiming(state: HookProducerStateV3, durationMs: number): void {
2646
+ const duration = Math.max(0, Math.ceil(durationMs));
2647
+ if (!Number.isSafeInteger(duration)) return;
2648
+ state.turn_harness = {
2649
+ hook_time_ms: state.turn_harness.hook_time_ms + duration,
2650
+ hook_count: state.turn_harness.hook_count + 1,
2651
+ slowest_hook:
2652
+ duration >= state.turn_harness.slowest_hook_ms
2653
+ ? "runtime-context"
2654
+ : state.turn_harness.slowest_hook,
2655
+ slowest_hook_ms: Math.max(duration, state.turn_harness.slowest_hook_ms),
2656
+ };
2657
+ }
2658
+
1553
2659
  function commitCapabilityDriftEvents(
1554
2660
  input: RecordHookSignalV3Input,
1555
2661
  state: HookProducerStateV3,
@@ -1785,6 +2891,40 @@ function isCursorPromptBootstrap(input: RecordHookSignalV3Input): boolean {
1785
2891
  );
1786
2892
  }
1787
2893
 
2894
+ /** Privacy-safe environment and recovery provenance for Codex mid-flight
2895
+ * onboarding. WSLENV values are never recorded, only normalized variable
2896
+ * names, and the native session identifier itself remains fingerprinted. */
2897
+ export function codexMidFlightDiagnosticContext(
2898
+ payload: ParsedPayload,
2899
+ env: NodeJS.ProcessEnv = process.env,
2900
+ ): Record<string, string | boolean> {
2901
+ const wslenv = env.WSLENV?.trim() ?? "";
2902
+ const wslenvNames = [
2903
+ ...new Set(
2904
+ wslenv
2905
+ .split(":")
2906
+ .map((entry) => entry.split("/", 1)[0]?.trim() ?? "")
2907
+ .filter((name) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(name)),
2908
+ ),
2909
+ ]
2910
+ .sort()
2911
+ .join(":")
2912
+ .slice(0, 512);
2913
+ const identityRecoverySource = payload.session_id
2914
+ ? "native_session_id"
2915
+ : payload.conversation_id
2916
+ ? "native_conversation_id"
2917
+ : payload.agent_id
2918
+ ? "native_agent_id"
2919
+ : "unavailable";
2920
+ return {
2921
+ thread_id_present: Boolean(env.CODEX_THREAD_ID?.trim()),
2922
+ wslenv_present: wslenv.length > 0,
2923
+ wslenv_names: wslenvNames,
2924
+ identity_recovery_source: identityRecoverySource,
2925
+ };
2926
+ }
2927
+
1788
2928
  function suppressClosedSpanSignal(
1789
2929
  input: RecordHookSignalV3Input,
1790
2930
  sessionHash: `hid_${string}`,
@@ -1813,6 +2953,13 @@ export function recordApprovedSessionEndV3(
1813
2953
  if (control.state !== input.mode) {
1814
2954
  return { state: "gate_closed", reason: control.state };
1815
2955
  }
2956
+ input = {
2957
+ ...input,
2958
+ writerOptions: {
2959
+ ...input.writerOptions,
2960
+ expectedGenesisId: control.genesis.event.payload.genesis_id as `gex_${string}`,
2961
+ },
2962
+ };
1816
2963
  const matches = listHookProducerStateRecordsV3(input.coordRoot, { includeTerminal: true }).filter(
1817
2964
  ({ state }) =>
1818
2965
  state.instance_id === input.instance_id && state.generation_id === input.generation_id,
@@ -1854,6 +3001,7 @@ export function recordApprovedSessionEndV3(
1854
3001
  state.generation_id,
1855
3002
  state.privacy_epoch_id,
1856
3003
  );
3004
+ reconcilePendingRuntimeContextsBeforeApprovedEnd(input, state, record.path, rootId, context);
1857
3005
  const expected = [
1858
3006
  "session_started",
1859
3007
  "turn_closed",
@@ -1973,6 +3121,13 @@ export function salvageOpenSpansV3(input: SalvageOpenSpansV3Input): SalvageOpenS
1973
3121
  if (control.state !== input.mode) {
1974
3122
  return { state: "gate_closed", reason: control.state };
1975
3123
  }
3124
+ input = {
3125
+ ...input,
3126
+ writerOptions: {
3127
+ ...input.writerOptions,
3128
+ expectedGenesisId: control.genesis.event.payload.genesis_id as `gex_${string}`,
3129
+ },
3130
+ };
1976
3131
  const matches = listHookProducerStateRecordsV3(input.coordRoot).filter(
1977
3132
  ({ state }) =>
1978
3133
  state.instance_id === input.instance_id && state.generation_id === input.generation_id,
@@ -2081,6 +3236,9 @@ export function listHookProducerStateRecordsV3(
2081
3236
  )) {
2082
3237
  const path = join(directory, name);
2083
3238
  const state = readProducerState(path);
3239
+ // Skip authorities left behind by a replaced epoch: their sequences and
3240
+ // causal links belong to the archived ledger, not this one.
3241
+ if (state.epoch_genesis_id !== control.genesis.event.payload.genesis_id) continue;
2084
3242
  if (!options.includeTerminal && state.terminal) continue;
2085
3243
  records.push({ path, modified_at_ms: lstatSync(path).mtimeMs, state });
2086
3244
  }
@@ -2137,7 +3295,101 @@ export function readHookProducerStateV3(
2137
3295
  );
2138
3296
  const sessionHash = normalizeNativeIdV3(context, `${adapter}.session`, nativeSessionId);
2139
3297
  const path = producerStatePath(coordRoot, adapter, sessionHash);
2140
- return existsSync(path) ? readProducerState(path) : undefined;
3298
+ if (!existsSync(path)) return undefined;
3299
+ const state = readProducerState(path);
3300
+ // A state left behind by a replaced epoch is not this epoch's authority.
3301
+ return state.epoch_genesis_id === control.genesis.event.payload.genesis_id ? state : undefined;
3302
+ }
3303
+
3304
+ export interface ReconcilePendingRuntimeContextV3Input {
3305
+ coordRoot: string;
3306
+ mode: EventV3WriteMode;
3307
+ nativeSessionId: string;
3308
+ producer_id: `prd_${string}`;
3309
+ build_id: `build_${string}`;
3310
+ platform: "linux" | "windows" | "macos" | "unknown";
3311
+ finalAttempt?: boolean;
3312
+ runtimeTelemetryOptions?: RuntimeTelemetryOptions;
3313
+ writerOptions?: WriteEventV3Options;
3314
+ }
3315
+
3316
+ export type ReconcilePendingRuntimeContextV3Result =
3317
+ | { state: "gate_closed" }
3318
+ | { state: "missing" }
3319
+ | { state: "busy" }
3320
+ | { state: "not_pending" }
3321
+ | { state: "pending" }
3322
+ | { state: "settled" };
3323
+
3324
+ /**
3325
+ * Retry one Codex session's owner-only context join without replaying its Stop
3326
+ * signal. Codex appends `task_complete` only after the synchronous Stop hook
3327
+ * exits, so this is invoked by a bounded detached worker after that exit.
3328
+ */
3329
+ export function reconcilePendingRuntimeContextV3(
3330
+ input: ReconcilePendingRuntimeContextV3Input,
3331
+ ): ReconcilePendingRuntimeContextV3Result {
3332
+ const control = readEventV3ControlState(input.coordRoot);
3333
+ if (control.state !== input.mode) return { state: "gate_closed" };
3334
+ if (control.state !== "candidate" && control.state !== "active") {
3335
+ return { state: "gate_closed" };
3336
+ }
3337
+ const rootId = control.genesis.event.scope.root_id as `root_${string}`;
3338
+ const rootContext = fingerprintContextV3(
3339
+ input.coordRoot,
3340
+ rootId,
3341
+ undefined,
3342
+ control.genesis.profile.privacy_key_epoch,
3343
+ );
3344
+ const sessionHash = normalizeNativeIdV3(rootContext, "codex.session", input.nativeSessionId);
3345
+ const path = producerStatePath(input.coordRoot, "codex", sessionHash);
3346
+ if (!existsSync(path)) return { state: "missing" };
3347
+ const lease = acquireStateLeaseWithRetry(input.coordRoot, path, STATE_LEASE_RETRY_ATTEMPTS);
3348
+ if (!lease) return { state: "busy" };
3349
+ try {
3350
+ const state = readProducerState(path);
3351
+ if (state.epoch_genesis_id !== control.genesis.event.payload.genesis_id) {
3352
+ // The pending contexts belong to a replaced epoch; its archive already
3353
+ // holds everything this producer durably recorded.
3354
+ return { state: "missing" };
3355
+ }
3356
+ if (state.adapter !== "codex" || !state.pending_runtime_contexts?.length) {
3357
+ return { state: "not_pending" };
3358
+ }
3359
+ const context = fingerprintContextV3(
3360
+ input.coordRoot,
3361
+ rootId,
3362
+ state.generation_id,
3363
+ state.privacy_epoch_id,
3364
+ );
3365
+ reconcilePendingRuntimeContexts(
3366
+ {
3367
+ coordRoot: input.coordRoot,
3368
+ mode: input.mode,
3369
+ signal: "stop",
3370
+ payload: { raw: {}, session_id: input.nativeSessionId },
3371
+ adapter: "codex",
3372
+ instance_id: state.instance_id,
3373
+ producer_id: input.producer_id,
3374
+ build_id: input.build_id,
3375
+ platform: input.platform,
3376
+ observed_at: new Date().toISOString(),
3377
+ runtimeTelemetryOptions: input.runtimeTelemetryOptions,
3378
+ writerOptions: {
3379
+ ...input.writerOptions,
3380
+ expectedGenesisId: control.genesis.event.payload.genesis_id as `gex_${string}`,
3381
+ },
3382
+ },
3383
+ state,
3384
+ path,
3385
+ rootId,
3386
+ context,
3387
+ { deferRetryLimit: true, finalAttempt: input.finalAttempt },
3388
+ );
3389
+ return state.pending_runtime_contexts?.length ? { state: "pending" } : { state: "settled" };
3390
+ } finally {
3391
+ lease.release();
3392
+ }
2141
3393
  }
2142
3394
 
2143
3395
  /** Resolve one terminal producer only when native session and instance identity agree. */
@@ -2175,17 +3427,39 @@ export function readHookProducerStateByInstanceV3(
2175
3427
  /^hid_[a-f0-9]{64}\.json$/.test(entry),
2176
3428
  )) {
2177
3429
  const state = readProducerState(join(directory, name));
3430
+ if (state.epoch_genesis_id !== control.genesis.event.payload.genesis_id) continue;
2178
3431
  if (state.instance_id === instanceId && !state.terminal) matches.push(state);
2179
3432
  }
2180
3433
  }
2181
3434
  return matches.length === 1 ? matches[0] : undefined;
2182
3435
  }
2183
3436
 
3437
+ /**
3438
+ * Join a coordination actor to its hook producer.
3439
+ *
3440
+ * Native subagent commands can retain the parent's session id even after the
3441
+ * child has its own canonical generation. Prefer the native session join, but
3442
+ * when that points at a different instance accept only one exact live
3443
+ * instance match for the same adapter.
3444
+ */
3445
+ export function readJoinableHookProducerStateV3(
3446
+ coordRoot: string,
3447
+ adapter: Adapter,
3448
+ nativeSessionId: string,
3449
+ instanceId: `inst_${string}`,
3450
+ ): HookProducerStateV3 | undefined {
3451
+ const direct = readHookProducerStateV3(coordRoot, adapter, nativeSessionId);
3452
+ if (direct?.instance_id === instanceId && !direct.terminal) return direct;
3453
+ const byInstance = readHookProducerStateByInstanceV3(coordRoot, instanceId);
3454
+ return byInstance?.adapter === adapter && !byInstance.terminal ? byInstance : undefined;
3455
+ }
3456
+
2184
3457
  function newProducerState(
2185
3458
  input: RecordHookSignalV3Input,
2186
3459
  sessionId: `sid_${string}`,
2187
3460
  epochId: `pep_${string}`,
2188
3461
  boundaryEventId: `evt_${string}`,
3462
+ genesisId: `gex_${string}`,
2189
3463
  ): HookProducerStateV3 {
2190
3464
  const bootId = `boot_${randomUUID()}` as const;
2191
3465
  return {
@@ -2194,11 +3468,12 @@ function newProducerState(
2194
3468
  adapter: input.adapter,
2195
3469
  instance_id: input.instance_id,
2196
3470
  session_id: sessionId,
2197
- generation_id: generationIdV3(),
3471
+ generation_id: input.delegated_child?.generation_id ?? generationIdV3(),
2198
3472
  attestation_id: attestationIdV3(),
2199
3473
  capability_profile: adapterCapabilityProfileDigestV3(input.adapter),
2200
3474
  cursor_mode: input.adapter === "cursor" ? (input.payload.cursor_mode ?? "unknown") : undefined,
2201
3475
  privacy_epoch_id: epochId,
3476
+ epoch_genesis_id: genesisId,
2202
3477
  boot_id: bootId,
2203
3478
  clock_id: clockIdV3(),
2204
3479
  next_sequence: 1,
@@ -2209,6 +3484,7 @@ function newProducerState(
2209
3484
  boot_id: bootId,
2210
3485
  clock: signalClock(input),
2211
3486
  }),
3487
+ session_start_derivation: input.session_start_derivation,
2212
3488
  terminal: false,
2213
3489
  spans: [],
2214
3490
  delegations: [],
@@ -2234,10 +3510,12 @@ function applyCommittedEvent(state: HookProducerStateV3, event: EventV3): void {
2234
3510
  if (event.event_type === "session.started") {
2235
3511
  state.started_event_id = event.event_id as `evt_${string}`;
2236
3512
  state.session_span.open_event_id = event.event_id as `evt_${string}`;
3513
+ seedAttestedTuning(state, event);
2237
3514
  }
2238
3515
  if (event.event_type === "turn.started") {
2239
3516
  const nextTurnId = (event.scope as { turn_id: `tid_${string}` }).turn_id;
2240
3517
  state.current_turn_id = nextTurnId;
3518
+ state.session_start_derivation = undefined;
2241
3519
  if (state.tool_call_count_turn_id !== nextTurnId) {
2242
3520
  state.tool_call_count = 0;
2243
3521
  state.tool_call_count_turn_id = nextTurnId;
@@ -2321,6 +3599,7 @@ function applyCommittedEvent(state: HookProducerStateV3, event: EventV3): void {
2321
3599
  }
2322
3600
  }
2323
3601
  state.current_turn_id = undefined;
3602
+ state.current_native_turn_id = undefined;
2324
3603
  state.current_turn_span = undefined;
2325
3604
  state.tool_call_count = 0;
2326
3605
  state.tool_call_count_turn_id = undefined;
@@ -2511,6 +3790,14 @@ function safeRole(value: unknown): string {
2511
3790
  return /^[a-zA-Z0-9]/.test(normalized) ? normalized : "agent";
2512
3791
  }
2513
3792
 
3793
+ function asLiveInstanceId(nativeInstanceId: string): `inst_${string}` {
3794
+ if (/^inst_[a-zA-Z0-9._-]{1,128}$/.test(nativeInstanceId)) {
3795
+ return nativeInstanceId as `inst_${string}`;
3796
+ }
3797
+ if (/^[a-zA-Z0-9._-]{1,128}$/.test(nativeInstanceId)) return `inst_${nativeInstanceId}`;
3798
+ return `inst_${createHash("sha256").update(nativeInstanceId.normalize("NFC")).digest("hex")}`;
3799
+ }
3800
+
2514
3801
  function safeTokenOrUndefined(value: unknown): string | undefined {
2515
3802
  if (typeof value !== "string") return undefined;
2516
3803
  const normalized = value.normalize("NFC");
@@ -2597,8 +3884,15 @@ function readProducerState(path: string): HookProducerStateV3 {
2597
3884
  state.waits ??= [];
2598
3885
  state.closed_turn_ids ??= [];
2599
3886
  state.turn_harness ??= emptyTurnHarnessTiming();
3887
+ if (
3888
+ Array.isArray(state.pending_runtime_contexts) &&
3889
+ state.pending_runtime_contexts.length === 0
3890
+ ) {
3891
+ state.pending_runtime_contexts = undefined;
3892
+ }
2600
3893
  if (state.adapter === "cursor") state.cursor_mode ??= "unknown";
2601
3894
  const allowedKeys = new Set([
3895
+ "active_runtime_context_probe",
2602
3896
  "adapter",
2603
3897
  "attestation_id",
2604
3898
  "boot_id",
@@ -2607,20 +3901,32 @@ function readProducerState(path: string): HookProducerStateV3 {
2607
3901
  "closed_spans",
2608
3902
  "closed_turn_ids",
2609
3903
  "current_turn_id",
3904
+ "current_native_turn_id",
2610
3905
  "current_turn_span",
2611
3906
  "cursor_mode",
2612
3907
  "delegations",
3908
+ "epoch_genesis_id",
2613
3909
  "format",
2614
3910
  "format_version",
2615
3911
  "generation_id",
2616
3912
  "instance_id",
3913
+ "last_attested_model",
3914
+ "last_attested_model_observation",
3915
+ "last_attested_telemetry",
3916
+ "last_attested_tuning",
3917
+ "last_attested_tuning_observation",
3918
+ "last_context_source_witness",
3919
+ "tuning_probe_turn_id",
2617
3920
  "last_event_id",
2618
3921
  "last_monotonic_ns",
2619
3922
  "last_observed_at",
2620
3923
  "next_sequence",
2621
3924
  "pending",
3925
+ "pending_runtime_contexts",
3926
+ "runtime_transcript_path",
2622
3927
  "privacy_epoch_id",
2623
3928
  "session_id",
3929
+ "session_start_derivation",
2624
3930
  "session_span",
2625
3931
  "spans",
2626
3932
  "started_event_id",
@@ -2644,6 +3950,7 @@ function readProducerState(path: string): HookProducerStateV3 {
2644
3950
  !/^att_[0-9a-f-]{36}$/.test(state.attestation_id) ||
2645
3951
  !/^cap_[a-f0-9]{64}$/.test(state.capability_profile) ||
2646
3952
  !/^pep_[a-zA-Z0-9._-]+$/.test(state.privacy_epoch_id) ||
3953
+ (state.epoch_genesis_id !== undefined && !/^gex_[0-9a-f-]{36}$/.test(state.epoch_genesis_id)) ||
2647
3954
  !/^boot_[a-zA-Z0-9._-]+$/.test(state.boot_id) ||
2648
3955
  !/^clk_[0-9a-f-]{36}$/.test(state.clock_id) ||
2649
3956
  !Number.isSafeInteger(state.next_sequence) ||
@@ -2710,11 +4017,32 @@ function readProducerState(path: string): HookProducerStateV3 {
2710
4017
  !Number.isSafeInteger(state.turn_ordinal) ||
2711
4018
  state.turn_ordinal < 0 ||
2712
4019
  (state.current_turn_id !== undefined && !/^tid_[a-f0-9]{64}$/.test(state.current_turn_id)) ||
4020
+ (state.current_native_turn_id !== undefined &&
4021
+ (typeof state.current_native_turn_id !== "string" ||
4022
+ state.current_native_turn_id.length === 0 ||
4023
+ state.current_native_turn_id.length > 512)) ||
2713
4024
  (state.last_event_id !== undefined && !/^evt_[0-9a-f-]{36}$/.test(state.last_event_id)) ||
2714
4025
  (state.last_monotonic_ns !== undefined && !/^\d+$/.test(state.last_monotonic_ns)) ||
2715
4026
  (state.last_observed_at !== undefined &&
2716
4027
  !Number.isFinite(Date.parse(state.last_observed_at))) ||
2717
4028
  (state.started_event_id !== undefined && !/^evt_[0-9a-f-]{36}$/.test(state.started_event_id)) ||
4029
+ (state.session_start_derivation !== undefined &&
4030
+ state.session_start_derivation !== "approved_lifecycle_reopen" &&
4031
+ state.session_start_derivation !== "validated_current_session_heal") ||
4032
+ (state.pending_runtime_contexts !== undefined &&
4033
+ (!Array.isArray(state.pending_runtime_contexts) ||
4034
+ state.pending_runtime_contexts.length === 0 ||
4035
+ state.pending_runtime_contexts.length > PENDING_RUNTIME_CONTEXT_CAP ||
4036
+ state.pending_runtime_contexts.some((pending) => !validPendingRuntimeContext(pending)))) ||
4037
+ (state.active_runtime_context_probe !== undefined &&
4038
+ !validActiveRuntimeContextProbe(state.active_runtime_context_probe)) ||
4039
+ (state.last_context_source_witness !== undefined &&
4040
+ !/^[a-f0-9]{64}$/.test(state.last_context_source_witness)) ||
4041
+ (state.runtime_transcript_path !== undefined &&
4042
+ (typeof state.runtime_transcript_path !== "string" ||
4043
+ state.runtime_transcript_path.length === 0 ||
4044
+ state.runtime_transcript_path.length > 4096 ||
4045
+ state.runtime_transcript_path.includes("\0"))) ||
2718
4046
  (state.pending?.source_id !== undefined &&
2719
4047
  !/^hid_[a-f0-9]{64}$/.test(state.pending.source_id)) ||
2720
4048
  (state.pending && !validateEventV3(state.pending.event).ok)
@@ -2794,6 +4122,51 @@ function validTurnHarnessTiming(value: TurnHarnessTimingV3): boolean {
2794
4122
  );
2795
4123
  }
2796
4124
 
4125
+ function validPendingRuntimeContext(value: unknown): value is PendingRuntimeContextV3 {
4126
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
4127
+ const pending = value as PendingRuntimeContextV3;
4128
+ return (
4129
+ typeof pending.terminal_event_id === "string" &&
4130
+ /^evt_[0-9a-f-]{36}$/.test(pending.terminal_event_id) &&
4131
+ typeof pending.terminal_observed_at === "string" &&
4132
+ Number.isFinite(Date.parse(pending.terminal_observed_at)) &&
4133
+ typeof pending.turn_id === "string" &&
4134
+ /^tid_[a-f0-9]{64}$/.test(pending.turn_id) &&
4135
+ (pending.run_id === undefined || /^run_[0-9a-f-]{36}$/.test(pending.run_id)) &&
4136
+ (pending.workflow_id === undefined || /^wf_[0-9a-f-]{36}$/.test(pending.workflow_id)) &&
4137
+ (pending.workflow_agent_id === undefined ||
4138
+ /^[a-zA-Z0-9][a-zA-Z0-9._:/+-]{0,127}$/.test(pending.workflow_agent_id)) &&
4139
+ typeof pending.native_session_id === "string" &&
4140
+ pending.native_session_id.length > 0 &&
4141
+ pending.native_session_id.length <= 512 &&
4142
+ typeof pending.native_turn_id === "string" &&
4143
+ pending.native_turn_id.length > 0 &&
4144
+ pending.native_turn_id.length <= 512 &&
4145
+ (pending.transcript_path === undefined ||
4146
+ (typeof pending.transcript_path === "string" &&
4147
+ pending.transcript_path.length > 0 &&
4148
+ pending.transcript_path.length <= 4096)) &&
4149
+ (pending.runtime_version === undefined ||
4150
+ (typeof pending.runtime_version === "string" &&
4151
+ /^[a-zA-Z0-9][a-zA-Z0-9._:/+-]{0,127}$/.test(pending.runtime_version))) &&
4152
+ Number.isSafeInteger(pending.attempts) &&
4153
+ pending.attempts >= 0 &&
4154
+ pending.attempts < RUNTIME_CONTEXT_RETRY_LIMIT
4155
+ );
4156
+ }
4157
+
4158
+ function validActiveRuntimeContextProbe(value: unknown): value is ActiveRuntimeContextProbeV3 {
4159
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
4160
+ const probe = value as ActiveRuntimeContextProbeV3;
4161
+ return (
4162
+ typeof probe.turn_id === "string" &&
4163
+ /^tid_[a-f0-9]{64}$/.test(probe.turn_id) &&
4164
+ typeof probe.attempted_at === "string" &&
4165
+ Number.isFinite(Date.parse(probe.attempted_at)) &&
4166
+ (probe.boundary === undefined || probe.boundary === "tool_completed")
4167
+ );
4168
+ }
4169
+
2797
4170
  function pidIsAlive(pid: number): boolean {
2798
4171
  if (!Number.isSafeInteger(pid) || pid < 1) return false;
2799
4172
  try {