@iowarp/clio-coder 0.5.0 → 0.5.2

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 (312) hide show
  1. package/.claude-plugin/marketplace.json +4 -4
  2. package/CHANGELOG.md +35 -0
  3. package/CONTRIBUTING.md +9 -0
  4. package/README.md +12 -9
  5. package/ROADMAP.md +30 -5
  6. package/dist/{acp-KS7ARGV6.js → acp-F6PGOFZ4.js} +2 -2
  7. package/dist/{agents-YOGJ2YEJ.js → agents-ZHP4R6EX.js} +22 -21
  8. package/dist/assets/codewiki.json +1 -1
  9. package/dist/{auth-CEDCO6O6.js → auth-N75U2H3Z.js} +4 -4
  10. package/dist/{chunk-D3KWFOUT.js → chunk-23UIXH6Z.js} +3 -3
  11. package/dist/{chunk-ZR5YA6ZF.js → chunk-36XVK5P5.js} +5 -5
  12. package/dist/{chunk-AVSR2HKI.js → chunk-3DZ4LPLS.js} +6 -6
  13. package/dist/{chunk-LYJJ6546.js → chunk-3GSPCWFX.js} +12 -12
  14. package/dist/{chunk-CRHPCPZP.js → chunk-4KC4CHKJ.js} +2 -2
  15. package/dist/{chunk-4VDHLCF5.js → chunk-4WJBWKMI.js} +2 -2
  16. package/dist/{chunk-KBUTSJSR.js → chunk-4XBYHXGK.js} +2 -2
  17. package/dist/{chunk-6W75D37F.js → chunk-53P775GE.js} +6 -3
  18. package/dist/{chunk-XZWSP67B.js → chunk-5APYAXCB.js} +2 -2
  19. package/dist/{chunk-D65E25JG.js → chunk-67HPYNTJ.js} +2 -2
  20. package/dist/{chunk-5JQR5B4D.js → chunk-6KV4KCQZ.js} +4 -4
  21. package/dist/{chunk-V4XJWDHR.js → chunk-6UKFRTXI.js} +2 -1
  22. package/dist/{chunk-NDPF2N2L.js → chunk-7DW7CJW2.js} +2 -2
  23. package/dist/{chunk-5KQEUIWM.js → chunk-7LUEQODV.js} +4 -4
  24. package/dist/{chunk-LNOXCGN2.js → chunk-7UFDIOBT.js} +3 -3
  25. package/dist/{chunk-DXSETN72.js → chunk-7WUGNN43.js} +2 -2
  26. package/dist/{chunk-V35KZDUZ.js → chunk-AA3GRZWS.js} +2 -2
  27. package/dist/{chunk-X4CEFOSG.js → chunk-ADO3OQIC.js} +4 -4
  28. package/dist/{chunk-UX2L5CUD.js → chunk-AI36V3ON.js} +3 -3
  29. package/dist/{chunk-B7GY6QER.js → chunk-B26OUMJW.js} +2 -2
  30. package/dist/{chunk-LAR7DX5E.js → chunk-B5TASTCK.js} +153 -62
  31. package/dist/{chunk-TGWZXJ7L.js → chunk-BEMQK5Q7.js} +92 -84
  32. package/dist/{chunk-RNDCROSG.js → chunk-CNXU7TR2.js} +3 -3
  33. package/dist/{chunk-3JLTRPN7.js → chunk-CVMUXT64.js} +35 -66
  34. package/dist/{chunk-733ZBT5P.js → chunk-E74MJF6G.js} +4 -4
  35. package/dist/{chunk-T2MDZES3.js → chunk-EBMTBE76.js} +3 -3
  36. package/dist/{chunk-OZ76TLGU.js → chunk-EEITU7S6.js} +2 -2
  37. package/dist/{chunk-GRHOXDKB.js → chunk-ELDJWJKM.js} +97 -14
  38. package/dist/{chunk-GCQFN7YI.js → chunk-EMYEQLWO.js} +2 -2
  39. package/dist/{chunk-LTWH2ACR.js → chunk-EQPFEDFV.js} +222 -127
  40. package/dist/{chunk-TDGYTWM6.js → chunk-F4I3H56H.js} +2 -2
  41. package/dist/chunk-F6KCJO3U.js +523 -0
  42. package/dist/{chunk-FGSQHUCK.js → chunk-F6VKWTTY.js} +5 -5
  43. package/dist/{chunk-UJD5MPP6.js → chunk-FLNXQQ5B.js} +2 -2
  44. package/dist/{chunk-EX57VVWW.js → chunk-FOSRJ2VZ.js} +4 -4
  45. package/dist/{chunk-ZARZ4POR.js → chunk-G5ZDQQE3.js} +3 -3
  46. package/dist/{chunk-HQVN7G4F.js → chunk-G62JBPXN.js} +7 -7
  47. package/dist/{chunk-ZJPORZTC.js → chunk-GIAI7A2K.js} +2 -2
  48. package/dist/chunk-GPTR6OTU.js +2551 -0
  49. package/dist/{chunk-EZD2BXGP.js → chunk-GUFQPTQK.js} +2 -2
  50. package/dist/{chunk-OPD7GL6F.js → chunk-H6FQVNZC.js} +8 -7
  51. package/dist/chunk-H7REJ7L5.js +80 -0
  52. package/dist/{chunk-EYTLV3W3.js → chunk-HTWTORF7.js} +2 -2
  53. package/dist/{chunk-DF6PI6GN.js → chunk-I6UKQPGS.js} +3 -3
  54. package/dist/{chunk-ISHUS7HC.js → chunk-JRW236JT.js} +3 -3
  55. package/dist/{chunk-DE2LU267.js → chunk-KKAJGT3B.js} +3 -2
  56. package/dist/{chunk-OV62D6KO.js → chunk-KQMYL5GR.js} +3 -3
  57. package/dist/{chunk-QDUUOZ3S.js → chunk-KWMFC7FN.js} +3 -3
  58. package/dist/{chunk-R7FGRZNF.js → chunk-LXYHCCIZ.js} +9 -9
  59. package/dist/{chunk-NFSK2VNU.js → chunk-LZMTVVN4.js} +2 -2
  60. package/dist/{chunk-62UK7AGW.js → chunk-M5PMRZSR.js} +397 -44
  61. package/dist/chunk-MMZMM6SW.js +131 -0
  62. package/dist/{chunk-FFYTC2KQ.js → chunk-MNABNEBX.js} +2 -2
  63. package/dist/{chunk-XMDBTYCH.js → chunk-N3CWOGVF.js} +3 -3
  64. package/dist/{chunk-VYRQHORQ.js → chunk-NMQSO6Z6.js} +4 -3
  65. package/dist/{chunk-R2UUNSNQ.js → chunk-O3ZAF7UY.js} +18 -5
  66. package/dist/{chunk-4SYHGVDE.js → chunk-OQNCLZI4.js} +4 -4
  67. package/dist/{chunk-EG4ARXPC.js → chunk-OX6QTA4N.js} +3 -3
  68. package/dist/{chunk-P4GNZPXO.js → chunk-OYUS3UZP.js} +2 -2
  69. package/dist/{chunk-OQ2EOAHA.js → chunk-PF36KOGI.js} +291 -112
  70. package/dist/{chunk-55RMDDFM.js → chunk-PGQG7ZMW.js} +2 -2
  71. package/dist/{chunk-CBAQPTDU.js → chunk-PIU6BXXW.js} +2 -2
  72. package/dist/{chunk-EKV4UBCM.js → chunk-PZBQUJ2F.js} +2 -2
  73. package/dist/{chunk-7RET77VB.js → chunk-Q2HKY32Y.js} +2 -2
  74. package/dist/{chunk-U6YTUVOX.js → chunk-Q4RMNWMZ.js} +4 -4
  75. package/dist/chunk-Q6FRR3AQ.js +48 -0
  76. package/dist/{chunk-6RJMYYIE.js → chunk-QJSIAJBY.js} +3 -3
  77. package/dist/{chunk-DOUISWEE.js → chunk-QOJ4ERMU.js} +5 -5
  78. package/dist/{chunk-IFPDAD7R.js → chunk-RWSRKXLT.js} +3 -3
  79. package/dist/{chunk-T33IYTZM.js → chunk-SAASVMIY.js} +3 -3
  80. package/dist/{chunk-2DTIWSAW.js → chunk-SEQDH6JC.js} +3 -3
  81. package/dist/{chunk-BRCOSE7O.js → chunk-SZUO5BSE.js} +2 -2
  82. package/dist/{chunk-HOEDA42N.js → chunk-T7HZ7KJF.js} +2 -2
  83. package/dist/{chunk-OJXOA6YU.js → chunk-TL6LNERH.js} +2 -2
  84. package/dist/{chunk-UCINIRHW.js → chunk-TPCZXWLT.js} +3 -3
  85. package/dist/{chunk-ZUKUCZYZ.js → chunk-TQ2KTH4A.js} +2 -2
  86. package/dist/{chunk-4WOOTKFD.js → chunk-U3FETNQB.js} +341 -20
  87. package/dist/{chunk-5B3RTYAK.js → chunk-UGDSB4AN.js} +2 -2
  88. package/dist/{chunk-VKHLUZNO.js → chunk-UZ7YBL43.js} +3 -3
  89. package/dist/{chunk-QNUQ7K7D.js → chunk-VKMSEO7Y.js} +4 -4
  90. package/dist/{chunk-IN7DGBVS.js → chunk-VLX5VZ35.js} +5 -5
  91. package/dist/{chunk-SJGS3GDI.js → chunk-WAGBMMNX.js} +5 -5
  92. package/dist/{chunk-BFOSV5EZ.js → chunk-WX2YCH7F.js} +2 -2
  93. package/dist/{chunk-3LT34CAM.js → chunk-XBIGUILU.js} +32 -17
  94. package/dist/{chunk-XDHUDE5K.js → chunk-XKYBFRWR.js} +5 -5
  95. package/dist/{chunk-U5QU5ZOD.js → chunk-XYPWFSU5.js} +3 -3
  96. package/dist/{chunk-YBUECLAF.js → chunk-YEJQDODA.js} +2 -2
  97. package/dist/{chunk-YQ6XEFVK.js → chunk-Z74OGONW.js} +39 -7
  98. package/dist/{chunk-I4ELN5BX.js → chunk-ZTNOEJRI.js} +2 -2
  99. package/dist/cli/index.js +26 -26
  100. package/dist/{clio-K2PBVCEM.js → clio-4IKFE25F.js} +2 -2
  101. package/dist/{clio-context-tools-GR4OHFSO.js → clio-context-tools-OHJXYX4R.js} +25 -23
  102. package/dist/{code-nav-4X3OI6DK.js → code-nav-XPM3MY5I.js} +7 -7
  103. package/dist/{config-Q5J7UBAB.js → config-343YS25T.js} +43 -41
  104. package/dist/{config-graph-P3555574.js → config-graph-WI263KDX.js} +43 -41
  105. package/dist/{configure-KIJ32ZO6.js → configure-GZDG4HER.js} +21 -21
  106. package/dist/{context-LFBQOSXT.js → context-4OFO7N7Y.js} +12 -12
  107. package/dist/{context-WBH3KSVR.js → context-JLK2RLOG.js} +42 -40
  108. package/dist/{context-NNLBES2Y.js → context-O6DIWCF6.js} +23 -21
  109. package/dist/{context-clear-YOHMQ6SQ.js → context-clear-MR7KOGQI.js} +42 -40
  110. package/dist/{context-working-set-MRAEVDNV.js → context-working-set-YZAD3KWO.js} +14 -13
  111. package/dist/{data-tool-JJPBGMQJ.js → data-tool-EKD7DFHG.js} +7 -7
  112. package/dist/{detail-RHJOTGN4.js → detail-YZPHFEVJ.js} +43 -41
  113. package/dist/{dispatch-runner-NC7PYNIO.js → dispatch-runner-VKVXVTWJ.js} +44 -42
  114. package/dist/{doctor-S5KZ2GTN.js → doctor-53AVQXAO.js} +17 -16
  115. package/dist/{doctor-deep-2EJQSHIZ.js → doctor-deep-BLRB2NCG.js} +5 -5
  116. package/dist/{eval-3D6M36N7.js → eval-P3BQSLQE.js} +21 -20
  117. package/dist/{evidence-XNVPPLVK.js → evidence-6LLI6SZH.js} +44 -42
  118. package/dist/{evidence-6IYN52ET.js → evidence-HTN3JLUO.js} +42 -40
  119. package/dist/{evidence-JVECPI3F.js → evidence-NJRE3R5H.js} +42 -40
  120. package/dist/{evolve-TLPUDJDM.js → evolve-WWZHJVJP.js} +42 -40
  121. package/dist/{fleet-WKVBF5SZ.js → fleet-GGZ4BVJE.js} +64 -62
  122. package/dist/{fleet-6RJWIOEO.js → fleet-QG3IIWWM.js} +44 -42
  123. package/dist/{fleet-commands-L6WFT7KZ.js → fleet-commands-J2ZIKISQ.js} +7 -7
  124. package/dist/{fleet-decisions-BTQMWU5A.js → fleet-decisions-Y2Q7375Q.js} +8 -8
  125. package/dist/{fleet-graph-553DZ67Q.js → fleet-graph-TCBCCCBP.js} +11 -11
  126. package/dist/{fleet-inspect-236FZPRB.js → fleet-inspect-KOLKBC56.js} +44 -42
  127. package/dist/{fleet-preflight-NZQHABWO.js → fleet-preflight-44UNCC4Y.js} +27 -25
  128. package/dist/{fleet-validate-7NLAE26R.js → fleet-validate-K2FXRZVA.js} +13 -13
  129. package/dist/{fleet-verify-E3RO6A5W.js → fleet-verify-AS444WDW.js} +42 -40
  130. package/dist/{fleet-view-KMZQY7YJ.js → fleet-view-X4JU4J6O.js} +43 -41
  131. package/dist/gui/ops-worker.js +9 -9
  132. package/dist/gui/reads-worker.js +9 -8
  133. package/dist/{init-DV5B6HQG.js → init-VSOWFHVL.js} +54 -52
  134. package/dist/{interactive-OXGYZYAS.js → interactive-JRCBENLZ.js} +1733 -577
  135. package/dist/{interop-J7UOBOSF.js → interop-JR6BCY7R.js} +10 -10
  136. package/dist/{inventory-OEGIL6PY.js → inventory-3JUGLVJI.js} +43 -41
  137. package/dist/{library-ROZAMUIL.js → library-7BOH3Y7N.js} +15 -15
  138. package/dist/{library-B3UPGY4V.js → library-7PFONXUI.js} +9 -9
  139. package/dist/{library-MXQA5DLT.js → library-TUYZMFIA.js} +7 -7
  140. package/dist/{library-import-2LTWOVBD.js → library-import-TJVXKLDK.js} +10 -10
  141. package/dist/{library-inventory-LJ3XHLWO.js → library-inventory-MD3AYTP4.js} +9 -9
  142. package/dist/{library-validation-DARHHUNW.js → library-validation-ZDLITEA3.js} +7 -7
  143. package/dist/{mcp-2GSPYQ54.js → mcp-EFCWUPUR.js} +3 -3
  144. package/dist/{memory-J3STUUIK.js → memory-Q2YVOKK5.js} +42 -40
  145. package/dist/{models-Y3GMFJ2V.js → models-M7BOCW7F.js} +17 -16
  146. package/dist/{monitor-LHNH577J.js → monitor-2HD3MC67.js} +47 -45
  147. package/dist/{orchestrator-DTAPXULA.js → orchestrator-OUW3ZN6Y.js} +1894 -226
  148. package/dist/{panes-A743ONZ5.js → panes-TTPPSYCL.js} +3 -3
  149. package/dist/{preload-OJBMAIXF.js → preload-A47C2NUF.js} +42 -40
  150. package/dist/{providers-CMETPZNS.js → providers-T43W7EL4.js} +4 -4
  151. package/dist/{resources-FY6XYFN2.js → resources-TP6X2V6W.js} +20 -11
  152. package/dist/{run-H64MEVTA.js → run-LDSBPMCS.js} +61 -59
  153. package/dist/{share-CAFMMQLM.js → share-URHKKMHR.js} +9 -9
  154. package/dist/{skills-ERKQUC7L.js → skills-E477MOOO.js} +13 -11
  155. package/dist/{skills-eval-CQ23MYQK.js → skills-eval-AIBR2L7H.js} +583 -93
  156. package/dist/{skills-inventory-TVUYJDVN.js → skills-inventory-HLMKY3R5.js} +13 -11
  157. package/dist/{slash-commands-ROG3KIFJ.js → slash-commands-LIIZKA5Y.js} +28 -26
  158. package/dist/{startup-background-KDWCQMWT.js → startup-background-JR2KDK6R.js} +43 -41
  159. package/dist/{steer-KKYXJSH4.js → steer-D7RTAPCM.js} +3 -3
  160. package/dist/{system-ZDW44ZGX.js → system-X2P5N4IY.js} +14 -13
  161. package/dist/{targets-AJWA6E7Z.js → targets-VFFAKUFM.js} +25 -24
  162. package/dist/{tasks-6L2JJRC5.js → tasks-ERAWZA22.js} +6 -6
  163. package/dist/{terminal-lease-YFUSDPAD.js → terminal-lease-V2N2BIKQ.js} +2 -2
  164. package/dist/{trace-LA5MVR4Y.js → trace-MA5BT7XY.js} +3 -3
  165. package/dist/{usage-XSILDHKF.js → usage-WYFY2L6M.js} +50 -48
  166. package/dist/{verifiers-ECA5GIHL.js → verifiers-TYIW2XKF.js} +7 -7
  167. package/dist/{verify-R6QQCCEB.js → verify-242UFYTP.js} +6 -6
  168. package/dist/{web-fetch-PVZNMBOB.js → web-fetch-LRAGYU6Y.js} +3 -3
  169. package/dist/{wiki-generate-RP22WP5K.js → wiki-generate-OFKOX2T6.js} +53 -51
  170. package/dist/worker/entry.js +31 -29
  171. package/docs/architecture/architecture.md +1 -0
  172. package/docs/architecture/context-engine.md +4 -2
  173. package/docs/architecture/observability.md +6 -4
  174. package/docs/architecture/prompt-envelope-and-tools.md +1 -1
  175. package/docs/architecture/session-lifecycle.md +1 -1
  176. package/docs/architecture/tui-design.md +12 -9
  177. package/docs/gui/parity/02-slash-and-surfaces.md +1 -1
  178. package/docs/guide/commands-and-modes.md +91 -5
  179. package/docs/guide/configuration-and-targets.md +2 -2
  180. package/docs/guide/context-continuity.md +49 -0
  181. package/docs/guide/proactive-memory.md +6 -3
  182. package/library/registry.yaml +292 -32
  183. package/library/skills/README.md +27 -2
  184. package/library/skills/context/context-handoff/SKILL.md +10 -4
  185. package/library/skills/meta/clio-coder-dev/SKILL.md +92 -88
  186. package/library/skills/meta/clio-coder-dev/evals.md +51 -46
  187. package/library/skills/meta/clio-coder-dev/plugin.json +2 -2
  188. package/library/skills/meta/clio-coder-dev/references/change-map.md +49 -0
  189. package/library/skills/meta/clio-coder-test/SKILL.md +89 -142
  190. package/library/skills/meta/clio-coder-test/evals.md +58 -62
  191. package/library/skills/meta/clio-coder-test/plugin.json +2 -2
  192. package/library/skills/meta/clio-coder-test/references/harness.md +3 -3
  193. package/library/skills/meta/clio-coder-test/references/lifecycle-validation.md +30 -0
  194. package/library/skills/meta/clio-coder-test/references/test-map.md +60 -89
  195. package/library/skills/registry.yaml +5 -5
  196. package/library/skills/skill-marketplace.json +12 -14
  197. package/package.json +1 -1
  198. package/src/cli/skills-eval.ts +1064 -54
  199. package/src/cli/usage.ts +2 -2
  200. package/src/core/clio-repo.ts +3 -0
  201. package/src/core/tool-names.ts +1 -0
  202. package/src/domains/context/budget/inspection.ts +9 -0
  203. package/src/domains/context/budget/live-view.ts +418 -0
  204. package/src/domains/context/budget/pressure.ts +393 -0
  205. package/src/domains/context/budget/request-fit.ts +15 -0
  206. package/src/domains/evidence/build.ts +24 -0
  207. package/src/domains/gateway/mcp/client.ts +1 -1
  208. package/src/domains/memory/commit-state.ts +160 -0
  209. package/src/domains/memory/operations.ts +18 -10
  210. package/src/domains/memory/prompt-cache.ts +95 -0
  211. package/src/domains/memory/prompt-section.ts +50 -7
  212. package/src/domains/memory/relevance.ts +93 -0
  213. package/src/domains/memory/restoration.ts +78 -0
  214. package/src/domains/memory/store.ts +39 -1
  215. package/src/domains/middleware/memory-intervention.ts +116 -24
  216. package/src/domains/observability/background-memory-usage.ts +1 -1
  217. package/src/domains/observability/cost.ts +3 -3
  218. package/src/domains/observability/extension.ts +1 -1
  219. package/src/domains/observability/metrics.ts +1 -1
  220. package/src/domains/prompts/compiler.ts +1 -1
  221. package/src/domains/prompts/extension.ts +38 -1
  222. package/src/domains/quota/anthropic-max-provider.ts +134 -0
  223. package/src/domains/quota/anthropic-usage.ts +220 -0
  224. package/src/domains/quota/antigravity-provider.ts +339 -0
  225. package/src/domains/quota/cache.ts +87 -0
  226. package/src/domains/quota/claude-code-provider.ts +169 -0
  227. package/src/domains/quota/codex-provider.ts +237 -0
  228. package/src/domains/quota/presentation.ts +240 -0
  229. package/src/domains/quota/registry.ts +23 -0
  230. package/src/domains/quota/service.ts +93 -0
  231. package/src/domains/quota/summary-feed.ts +86 -0
  232. package/src/domains/quota/types.ts +84 -0
  233. package/src/domains/resources/index.ts +11 -0
  234. package/src/domains/resources/skills/catalog-view.ts +571 -0
  235. package/src/domains/resources/skills/lexical-match.ts +136 -0
  236. package/src/domains/resources/skills/loader.ts +38 -0
  237. package/src/domains/resources/skills/promotion.ts +1 -55
  238. package/src/domains/resources/skills/provenance-pin.ts +50 -20
  239. package/src/domains/safety/action-classifier.ts +1 -0
  240. package/src/domains/session/compaction/branch-summary.ts +4 -1
  241. package/src/domains/session/compaction/compact.ts +18 -2
  242. package/src/domains/session/compaction/cut-point.ts +20 -1
  243. package/src/domains/session/compaction/tokens.ts +48 -3
  244. package/src/domains/session/context-accounting.ts +8 -1
  245. package/src/domains/session/continuity/carry.ts +59 -0
  246. package/src/domains/session/continuity/contract.ts +592 -0
  247. package/src/domains/session/continuity/evidence.ts +290 -0
  248. package/src/domains/session/continuity/fold.ts +1075 -0
  249. package/src/domains/session/continuity/note.ts +79 -0
  250. package/src/domains/session/continuity/operator-request.ts +104 -0
  251. package/src/domains/session/continuity/persistence.ts +408 -0
  252. package/src/domains/session/continuity/ports.ts +231 -0
  253. package/src/domains/session/continuity/projection.ts +538 -0
  254. package/src/domains/session/continuity/validate.ts +352 -0
  255. package/src/domains/session/entries.ts +50 -3
  256. package/src/domains/session/index.ts +48 -0
  257. package/src/domains/session/migrations/index.ts +7 -3
  258. package/src/domains/session/tree/fork.ts +15 -1
  259. package/src/domains/session/usage.ts +2 -2
  260. package/src/engine/acp/commands.ts +1 -1
  261. package/src/engine/agent.ts +133 -9
  262. package/src/engine/session.ts +13 -6
  263. package/src/entry/orchestrator.ts +116 -33
  264. package/src/interactive/chat-loop-messages.ts +2 -2
  265. package/src/interactive/chat-loop.ts +219 -63
  266. package/src/interactive/chat-renderer.ts +99 -8
  267. package/src/interactive/context-overlay.ts +24 -3
  268. package/src/interactive/continuity-controller.ts +526 -0
  269. package/src/interactive/dispatch-board.ts +21 -3
  270. package/src/interactive/footer/dashboard.ts +25 -1
  271. package/src/interactive/footer/key-hints.ts +2 -2
  272. package/src/interactive/footer/pages.ts +70 -27
  273. package/src/interactive/footer/widgets.ts +32 -7
  274. package/src/interactive/footer-panel.ts +1 -1
  275. package/src/interactive/interactive-application.ts +7 -2
  276. package/src/interactive/interactive-input-runtime.ts +2 -2
  277. package/src/interactive/interactive-presentation.ts +15 -0
  278. package/src/interactive/interactive-slash-runtime.ts +45 -8
  279. package/src/interactive/interactive-tickers.ts +7 -1
  280. package/src/interactive/model-session-replay.ts +130 -3
  281. package/src/interactive/output-reserve.ts +35 -0
  282. package/src/interactive/overlay-general-openers.ts +12 -8
  283. package/src/interactive/overlay-key-routing.ts +6 -9
  284. package/src/interactive/overlay-lifecycle.ts +10 -6
  285. package/src/interactive/overlay-session-lifecycle.ts +21 -14
  286. package/src/interactive/quota-view.ts +229 -0
  287. package/src/interactive/session-last-turn.ts +1 -1
  288. package/src/interactive/session-transcript.ts +2 -1
  289. package/src/interactive/session-usage-reseed.ts +2 -2
  290. package/src/interactive/side-question.ts +2 -2
  291. package/src/interactive/slash-commands.ts +28 -9
  292. package/src/interactive/turn-context.ts +686 -63
  293. package/src/interactive/turn-middleware.ts +39 -6
  294. package/src/interactive/turn-persistence.ts +15 -2
  295. package/src/interactive/turn-prewarm.ts +1 -1
  296. package/src/interactive/turn-runtime.ts +48 -5
  297. package/src/interactive/{cost-overlay.ts → usage-overlay.ts} +121 -33
  298. package/src/interactive/welcome-dashboard.ts +26 -3
  299. package/src/tools/agent-tools.ts +3 -1
  300. package/src/tools/bootstrap.ts +6 -0
  301. package/src/tools/builtin-tool-catalog.ts +9 -0
  302. package/src/tools/context/index.ts +148 -113
  303. package/src/tools/context/surface.ts +11 -7
  304. package/src/tools/core-bootstrap.ts +4 -0
  305. package/src/tools/observation.ts +8 -2
  306. package/src/tools/policy.ts +3 -0
  307. package/src/tools/self-compact.ts +31 -0
  308. package/src/tools/surface.ts +1 -0
  309. package/src/tools/tasks.ts +1 -1
  310. package/dist/chunk-CTFPFW3H.js +0 -44
  311. package/dist/chunk-EOJPDNUP.js +0 -1325
  312. package/dist/chunk-I4Y4WKZR.js +0 -386
@@ -0,0 +1,592 @@
1
+ /**
2
+ * Durable session continuity: the typed core.
3
+ *
4
+ * These are the record shapes, fold inputs/results, and injected persistence
5
+ * ports for CONTRACTS.md §§2–8. Nothing here is registered in the live
6
+ * `SessionEntry` union yet and no session is stamped v5: packet 02B does that
7
+ * once readers, replay, fork and export can all interpret the records. Until
8
+ * then these types describe records the core can build and validate, not
9
+ * records the product writes.
10
+ *
11
+ * The module imports `BaseSessionEntry` as a type only. A value import from
12
+ * `entries.ts` would create the reverse cycle 02B needs to avoid when
13
+ * `entries.ts` starts calling these validators, so envelope checking is done
14
+ * locally by `validate.ts`.
15
+ *
16
+ * Nothing in the pure half of this domain (contract, note, validate, fold,
17
+ * carry) reads a clock, mints an ID, touches disk, or calls a model. Time,
18
+ * authority, already-allocated identifiers and persistence are supplied by the
19
+ * caller. Preparation and composition mint identity; recovery only reuses it.
20
+ */
21
+
22
+ import type { BaseSessionEntry } from "../entries.js";
23
+
24
+ export const HANDOFF_SCHEMA_VERSION = 1;
25
+ export const HANDOFF_NOTE_MAX_BYTES = 8192;
26
+
27
+ /**
28
+ * Bound on any single automatic handoff window, from §7. A persisted deadline
29
+ * is clamped to this ceiling on reload so a wrong or hostile recorded value
30
+ * cannot grant unbounded automatic execution.
31
+ */
32
+ export const HANDOFF_MAX_WINDOW_MS = 900_000;
33
+
34
+ /** What a reduction actually did. `no_material` is never a commit outcome. */
35
+ export type ContinuityOutcome = "summarized" | "evicted" | "continuity_only";
36
+
37
+ export type HandoffFailureReason =
38
+ | "invalid_note"
39
+ | "note_exceeds_replay_budget"
40
+ | "budget_unsafe_no_material"
41
+ | "durability_unresolved"
42
+ | "state_root_removed"
43
+ | "origin_changed"
44
+ | "provider_failed"
45
+ | "attempts_exhausted"
46
+ | "deadline_exceeded";
47
+
48
+ export type HandoffPauseReason = "operator_cancelled" | "origin_changed" | "delivery_uncertain";
49
+
50
+ /**
51
+ * Identity minted once at admitted preparation and never replaced. Recovery
52
+ * reuses every field, including `commitEntryId`, so a commit that went missing
53
+ * is rebuilt under the identity the original reserved rather than a new one.
54
+ */
55
+ export interface HandoffIdentity {
56
+ handoffId: string;
57
+ preparedEntryId: string;
58
+ commitId: string;
59
+ /** Reserved before any summary append so a missing commit is reconstructible. */
60
+ commitEntryId: string;
61
+ originSessionId: string;
62
+ /** The originally selected message leaf. Immutable; not the live selection. */
63
+ branchAnchorTurnId: string | null;
64
+ initiatingTurnId: string;
65
+ toolCallId: string;
66
+ /** Opaque live-budget revision from packet 01. Persistence never interprets it. */
67
+ sourceRevision: string;
68
+ }
69
+
70
+ export interface HandoffPolicy {
71
+ preparedAtMs: number;
72
+ /** Absolute, finite, positive. Never reset on reload. */
73
+ automaticDeadlineAtMs: number;
74
+ maxAttempts: number;
75
+ maxSummaryCallsPerAttempt: number;
76
+ additionalSummaryRetriesPerCall: number;
77
+ maxSummaryStreamInvocations: number;
78
+ flushRetryLimit: number;
79
+ }
80
+
81
+ /**
82
+ * The frozen §2/§7 ceilings. A persisted policy is validated against these, so
83
+ * a record that claims three attempts or a summary-retry loop cannot widen the
84
+ * automatic budget merely by being on disk. Runtime stream counting is packet
85
+ * 03's job; this is the durable bound it starts from.
86
+ */
87
+ export const HANDOFF_POLICY_LIMITS = Object.freeze({
88
+ maxAttempts: 2,
89
+ maxSummaryCallsPerAttempt: 2,
90
+ additionalSummaryRetriesPerCall: 0,
91
+ maxSummaryStreamInvocations: 4,
92
+ flushRetryLimit: 3,
93
+ });
94
+
95
+ /** Barrier retries after the first attempt, from `HandoffPolicy.flushRetryLimit`. */
96
+ export const HANDOFF_MAX_FLUSH_RETRIES = 3;
97
+
98
+ /**
99
+ * An admitted note, stored as exactly the bytes that were submitted.
100
+ *
101
+ * The note is **agent-authored**: it is the text the model supplied as the
102
+ * `self_compact` argument, not operator-written prose. Replay and export must
103
+ * preserve that authorship and never present it as an operator turn. `note` is
104
+ * never trimmed, normalized, truncated or regenerated; `noteSha256` is over its
105
+ * UTF-8 encoding and `noteBytes` is that encoding's length.
106
+ */
107
+ export interface AcceptedNote {
108
+ note: string;
109
+ noteBytes: number;
110
+ noteSha256: string;
111
+ }
112
+
113
+ /**
114
+ * Position in the transaction chain. `entryId` equals the envelope's `turnId`;
115
+ * `prevEntryId` is the transaction predecessor, which is deliberately not the
116
+ * structural `parentTurnId`.
117
+ */
118
+ export interface TransitionLink {
119
+ entryId: string;
120
+ prevEntryId: string | null;
121
+ /** prepared = 0; each accepted successor = predecessor + 1. */
122
+ sequence: number;
123
+ /** 0 initially; incremented only when a `reducing` event is accepted. */
124
+ attempt: number;
125
+ }
126
+
127
+ /**
128
+ * The durable authority a `resumed` event cites.
129
+ *
130
+ * `operatorRequestEntryId` names a **control-request record**, not a
131
+ * conversation turn. Clio's `/context compact [instructions]` and the other
132
+ * control commands are display-only today and `/resume` opens session
133
+ * navigation, so there is no operator message turn that means "resume this
134
+ * handoff". The feasible carrier is a typed `CustomEntry<T>` control record;
135
+ * reading and writing it is 02B/03/05 wiring, and nothing here fabricates a
136
+ * message entry to stand in for it.
137
+ */
138
+ export interface HandoffResumeAuthority {
139
+ operatorRequestEntryId: string;
140
+ pausedOrFailedEntryId: string;
141
+ action: "reduce" | "deliver";
142
+ automaticDeadlineAtMs: number;
143
+ }
144
+
145
+ export type HandoffEvent =
146
+ | { phase: "prepared"; accepted: AcceptedNote; policy: HandoffPolicy }
147
+ | { phase: "reducing"; resumeRef?: string }
148
+ | { phase: "delivered"; deliveryId: string; continuationTurnId: string; resumeRef?: string }
149
+ | { phase: "acknowledged"; deliveryId: string; terminalResponseEntryId: string }
150
+ | { phase: "paused"; reason: HandoffPauseReason }
151
+ | { phase: "failed"; reason: HandoffFailureReason }
152
+ | { phase: "resumed"; authority: HandoffResumeAuthority };
153
+
154
+ export type HandoffEventPhase = HandoffEvent["phase"];
155
+
156
+ /** The fold head is an event phase, or `ready` once a valid commit exists. */
157
+ export type ContinuityPhase = HandoffEventPhase | "ready" | "absent";
158
+
159
+ export interface HandoffTransactionEntry extends BaseSessionEntry {
160
+ kind: "handoffTransaction";
161
+ schemaVersion: 1;
162
+ identity: HandoffIdentity;
163
+ transition: TransitionLink;
164
+ event: HandoffEvent;
165
+ }
166
+
167
+ export interface ContinuityCommitData {
168
+ outcome: ContinuityOutcome;
169
+ /** The commit's exact original envelope, retained for reconstruction. */
170
+ entry: { turnId: string; parentTurnId: string | null; timestamp: string };
171
+ transition: TransitionLink;
172
+ /** Required only for `summarized`. */
173
+ summaryRef?: string;
174
+ /** Required only for `evicted`. */
175
+ evictionRef?: string;
176
+ tokensBefore: number;
177
+ tokensAfter: number;
178
+ }
179
+
180
+ /**
181
+ * The latest validated fold head, carried alongside the immutable transaction
182
+ * facts. `activeResume` keeps the newest durable resume permission after its
183
+ * event stops being the head; `delivery` keeps the matching intent through a
184
+ * pause or acknowledgement. Neither authorizes automatic redelivery.
185
+ */
186
+ export interface ContinuityCarriedState {
187
+ transition: TransitionLink;
188
+ event: HandoffEvent | { phase: "ready" };
189
+ activeResume: { entryId: string; authority: HandoffResumeAuthority } | null;
190
+ delivery: { deliveryId: string; continuationTurnId: string } | null;
191
+ }
192
+
193
+ export interface ContinuityCheckpointPayload {
194
+ schemaVersion: 1;
195
+ identity: HandoffIdentity;
196
+ accepted: AcceptedNote;
197
+ policy: HandoffPolicy;
198
+ commit: ContinuityCommitData;
199
+ state: ContinuityCarriedState;
200
+ }
201
+
202
+ export interface ContinuityCommitEntry extends BaseSessionEntry {
203
+ kind: "continuityCommit";
204
+ continuity: ContinuityCheckpointPayload;
205
+ }
206
+
207
+ /**
208
+ * A compaction summary that carries a continuity payload. 02B adds the optional
209
+ * field to `CompactionSummaryEntry` itself; until then the fold recognizes the
210
+ * shape structurally so no live union changes here.
211
+ */
212
+ export interface ContinuityCarryingSummary extends BaseSessionEntry {
213
+ kind: "compactionSummary";
214
+ continuity: ContinuityCheckpointPayload;
215
+ }
216
+
217
+ // ---------------------------------------------------------------------------
218
+ // Note admission
219
+ // ---------------------------------------------------------------------------
220
+
221
+ export type NoteRejectionReason =
222
+ | "not_a_string"
223
+ | "blank"
224
+ | "contains_nul"
225
+ | "not_utf8_round_trip"
226
+ | "exceeds_max_bytes";
227
+
228
+ export type NoteValidation =
229
+ | { ok: true; accepted: AcceptedNote }
230
+ | { ok: false; reason: NoteRejectionReason; noteBytes: number | null };
231
+
232
+ export type AcceptedNoteVerification =
233
+ | { ok: true }
234
+ | { ok: false; reason: "byte_count_mismatch" | "hash_mismatch" | "decoded_text_mismatch" | NoteRejectionReason };
235
+
236
+ // ---------------------------------------------------------------------------
237
+ // Fold inputs
238
+ // ---------------------------------------------------------------------------
239
+
240
+ /**
241
+ * A terminal assistant response the caller has already located and classified.
242
+ * Acknowledgement needs `status: "success"` on the continuation turn that
243
+ * consumed the delivery; empty, errored, aborted or interrupted responses and
244
+ * another turn's response are not acknowledgement (§3.4, §12.4).
245
+ */
246
+ export interface TerminalResponseEvidence {
247
+ entryId: string;
248
+ continuationTurnId: string;
249
+ status: "success" | "empty" | "error" | "aborted" | "interrupted";
250
+ /** Index into `ContinuityFoldInput.entries`; see its note on one coordinate system. */
251
+ position: number;
252
+ }
253
+
254
+ /**
255
+ * A durable **new** operator control request that can authorize one explicit
256
+ * resume, prevalidated by the caller.
257
+ *
258
+ * Every field is part of the binding, because a bare list of entry ids proves
259
+ * only that the operator did something. Authority requires that this request
260
+ * named this handoff, asked for this action, answered this exact paused/failed
261
+ * head, originated in this session, and was recorded after the head it answers.
262
+ * The fold refuses a resume that does not match all of it.
263
+ *
264
+ * The record behind `operatorRequestEntryId` is a typed control-request entry
265
+ * (a `CustomEntry<T>` in the feasible 02B shape), never a fabricated
266
+ * conversation turn.
267
+ */
268
+ export interface OperatorResumeAuthorityEvidence {
269
+ operatorRequestEntryId: string;
270
+ handoffId: string;
271
+ action: "reduce" | "deliver";
272
+ pausedOrFailedEntryId: string;
273
+ /** The session the control request was recorded in. */
274
+ originSessionId: string;
275
+ /** Index into `ContinuityFoldInput.entries`; see its note on one coordinate system. */
276
+ position: number;
277
+ /**
278
+ * When the control request was durably accepted. This is the **only** base a
279
+ * renewed deadline is measured from: deriving a base backwards from the
280
+ * deadline the record itself asks for would let a far-future request renew
281
+ * itself without bound.
282
+ */
283
+ acceptedAtMs: number;
284
+ }
285
+
286
+ /**
287
+ * What the caller's evidence resolver must already have proven, stated here
288
+ * because the fold cannot re-derive it from an opaque id.
289
+ *
290
+ * For `OperatorResumeAuthorityEvidence`: the record is a genuine typed operator
291
+ * control request (§3.1's `CustomEntry` carrier), reached through an operator
292
+ * surface rather than an agent tool, on this session's selected path and within
293
+ * the historical cutoff. For `ContinuityOutcomeEvidence`: the named record is
294
+ * really a summary or eviction of the stated kind, produced by that commit. For
295
+ * `TerminalResponseEvidence`: the named record is a real assistant response for
296
+ * that continuation turn and `status: "success"` means terminal and nonempty.
297
+ *
298
+ * Test-constructed evidence proves the fold's handling of it, never that 02B/03
299
+ * adapters discharge these obligations.
300
+ */
301
+ export type ContinuityEvidenceObligations = never;
302
+
303
+ /**
304
+ * A summary or eviction record bound to the commit that produced it.
305
+ *
306
+ * A record merely existing under the id a commit names is not matching
307
+ * evidence: an unrelated ordinary summary can share neither this handoff nor
308
+ * this commit. The caller supplies the binding it established.
309
+ */
310
+ export interface ContinuityOutcomeEvidence {
311
+ entryId: string;
312
+ outcome: Exclude<ContinuityOutcome, "continuity_only">;
313
+ handoffId: string;
314
+ commitId: string;
315
+ /** Index into `ContinuityFoldInput.entries`; see its note on one coordinate system. */
316
+ position: number;
317
+ }
318
+
319
+ export interface ContinuityFoldEvidence {
320
+ /** Prevalidated resume authority, bound per transaction. */
321
+ resumeAuthorities: ReadonlyArray<OperatorResumeAuthorityEvidence>;
322
+ terminalResponses: ReadonlyArray<TerminalResponseEvidence>;
323
+ /** Summary and eviction records bound to the commits that produced them. */
324
+ outcomeRefs: ReadonlyArray<ContinuityOutcomeEvidence>;
325
+ /**
326
+ * Records the caller could not parse. A nonzero count forbids concluding
327
+ * absence: skipped corrupt records must not turn missing evidence into
328
+ * permission (§6).
329
+ */
330
+ unreadableRecords: number;
331
+ }
332
+
333
+ export interface ContinuityFoldSelection {
334
+ sessionId: string;
335
+ /** Turn ids on the selected path, for branch and initiating-turn applicability. */
336
+ pathTurnIds: ReadonlyArray<string>;
337
+ /**
338
+ * True when this projection is a historical fork cut. Inherited notes are
339
+ * then recallable only, in any phase, and never grant execution ownership.
340
+ */
341
+ historical: boolean;
342
+ }
343
+
344
+ export interface ContinuityFoldInput {
345
+ /**
346
+ * Ordered applicable ledger records; unknown shapes are ignored.
347
+ *
348
+ * This is the **full applicable ledger before the replay cut**, including
349
+ * archive reads where they are needed, which is what makes one coordinate
350
+ * system possible: every evidence `position` is an index into this array, and
351
+ * so is every record position the fold resolves itself. A reference whose
352
+ * record is not here cannot be ordered against anything, and the transaction
353
+ * stays recall-only rather than borrowing another record's position.
354
+ */
355
+ entries: ReadonlyArray<unknown>;
356
+ selection: ContinuityFoldSelection;
357
+ evidence: ContinuityFoldEvidence;
358
+ /** Supplied wall clock in ms. The fold never reads one itself. */
359
+ nowMs: number;
360
+ }
361
+
362
+ // ---------------------------------------------------------------------------
363
+ // Fold results
364
+ // ---------------------------------------------------------------------------
365
+
366
+ export type ContinuityAnomalyKind =
367
+ | "duplicate_conflict"
368
+ | "entry_id_reused"
369
+ | "unbound_outcome_ref"
370
+ | "illegal_transition"
371
+ | "broken_chain"
372
+ | "invalid_attempt"
373
+ | "policy_conflict"
374
+ | "unmatched_resume"
375
+ | "unvalidated_resume_authority"
376
+ | "missing_resume_ref"
377
+ | "missing_commit_ref"
378
+ | "conflicting_carry"
379
+ | "fabricated_carry_extension"
380
+ | "unverified_note"
381
+ | "acknowledgement_unsupported"
382
+ | "malformed_continuity_record"
383
+ | "malformed_record";
384
+
385
+ export interface ContinuityAnomaly {
386
+ kind: ContinuityAnomalyKind;
387
+ entryId: string | null;
388
+ detail: string;
389
+ }
390
+
391
+ export type ContinuityRecallReason =
392
+ | "historical_fork"
393
+ | "conflicting_evidence"
394
+ | "missing_evidence"
395
+ | "attempts_exhausted"
396
+ | "deadline_expired"
397
+ | "clock_ambiguous"
398
+ | "paused"
399
+ | "failed";
400
+
401
+ /**
402
+ * Reconstruction of a commit that a validated carry proves existed. The
403
+ * envelope is the original reserved one, so appending it creates no new
404
+ * identity; `carriedState` is the later head to keep, so appending the old
405
+ * commit at the end of the file cannot regress the fold on reload.
406
+ */
407
+ export interface MissingCommitReconstruction {
408
+ entry: ContinuityCommitEntry;
409
+ carriedState: ContinuityCarriedState;
410
+ }
411
+
412
+ export type ContinuityRecoveryAction =
413
+ | { kind: "none" }
414
+ | { kind: "recall_only"; reason: ContinuityRecallReason }
415
+ | { kind: "reconstruct_commit"; reconstruction: MissingCommitReconstruction }
416
+ | { kind: "pause"; reason: HandoffPauseReason }
417
+ | { kind: "fail"; reason: HandoffFailureReason };
418
+
419
+ /**
420
+ * Whether this projection may act on the transaction at all. `recall_only`
421
+ * means the note can be shown and nothing else; it is the standing answer for
422
+ * an inherited historical note and for any evidence the fold could not verify.
423
+ */
424
+ export type ContinuityAuthority = "none" | "recall_only" | "execution";
425
+
426
+ /**
427
+ * A transaction from an earlier compaction cycle on the same path.
428
+ *
429
+ * Repeated `self_compact` cycles leave several completed transactions in one
430
+ * ledger. They are history, not rivals: a prior handoff is neither a
431
+ * conflicting identity for the selected one nor a source of authority for it.
432
+ * Its note stays recallable, which is all the projection needs.
433
+ */
434
+ export interface ContinuityPriorHandoff {
435
+ handoffId: string;
436
+ commitId: string;
437
+ phase: ContinuityPhase;
438
+ accepted: AcceptedNote | null;
439
+ outcome: ContinuityOutcome | null;
440
+ }
441
+
442
+ export interface ContinuityFoldResult {
443
+ phase: ContinuityPhase;
444
+ authority: ContinuityAuthority;
445
+ identity: HandoffIdentity | null;
446
+ accepted: AcceptedNote | null;
447
+ policy: HandoffPolicy | null;
448
+ commit: ContinuityCommitData | null;
449
+ state: ContinuityCarriedState | null;
450
+ /** Attempts already journaled. Never refunded by a pause or a resume. */
451
+ attemptsSpent: number;
452
+ /** The deadline in force, after clamping and any validated resume. */
453
+ effectiveDeadlineAtMs: number | null;
454
+ /** Set when a validated carry proves a commit that is absent from the input. */
455
+ missingCommit: MissingCommitReconstruction | null;
456
+ /**
457
+ * True when every record and reference this fold relied on validated.
458
+ * A historical inherited note is `validated` and still recall-only; a chain
459
+ * with conflicting copies is neither. Only a validated fold may be projected
460
+ * into a new carry or a reconstruction.
461
+ */
462
+ validated: boolean;
463
+ anomalies: ReadonlyArray<ContinuityAnomaly>;
464
+ /** Proposed only. Inspection never invokes it. */
465
+ action: ContinuityRecoveryAction;
466
+ /**
467
+ * Earlier completed or abandoned transactions on this path, oldest first.
468
+ * Recall projection only.
469
+ */
470
+ priorHandoffs: ReadonlyArray<ContinuityPriorHandoff>;
471
+ skipped: { inapplicable: number; unreadable: number };
472
+ }
473
+
474
+ // ---------------------------------------------------------------------------
475
+ // Persistence ports
476
+ // ---------------------------------------------------------------------------
477
+
478
+ /** A record the group persister may append. Identity is already allocated. */
479
+ export interface ContinuityAppendable {
480
+ kind: string;
481
+ turnId: string;
482
+ [field: string]: unknown;
483
+ }
484
+
485
+ /**
486
+ * Readback is four-valued on purpose. A boolean would let malformed data stand
487
+ * in for proven absence, and only proven absence licenses a re-append.
488
+ */
489
+ export type ContinuityReadback =
490
+ | { status: "matching" }
491
+ | { status: "absent" }
492
+ | { status: "conflicting"; detail?: string }
493
+ | { status: "unresolved"; detail?: string };
494
+
495
+ export interface ContinuityPersistencePorts {
496
+ /** Append one record. A throw proves neither success nor absence. */
497
+ append(entry: ContinuityAppendable): void;
498
+ /**
499
+ * Authoritative lookup for exactly this record.
500
+ *
501
+ * The expected record is passed in rather than a `(kind, id)` pair, because
502
+ * a port given only an id cannot compare payload and would have to answer
503
+ * from the id alone. A stored record with this id but different bytes must
504
+ * return `conflicting`; it must never return `matching`. `unresolved` is the
505
+ * answer whenever the ledger could not be read cleanly, including a
506
+ * malformed line anywhere that could hide this record.
507
+ */
508
+ readExact(expected: ContinuityAppendable): ContinuityReadback;
509
+ /** Synchronous fsync barrier. Absent means an unsupported port, never success. */
510
+ flushAppends?: () => void;
511
+ /** Transcript + tree + meta barrier. Absent means an unsupported port. */
512
+ checkpoint?: (reason: string) => Promise<void>;
513
+ isStateRemoved(): boolean;
514
+ isOriginCurrent(): boolean;
515
+ }
516
+
517
+ export interface ContinuityRetrySchedule {
518
+ /** Barrier retries after the first attempt. */
519
+ limit: number;
520
+ /** Absolute deadline; no retry starts at or after it. */
521
+ deadlineAtMs: number;
522
+ now(): number;
523
+ wait(attempt: number): Promise<void>;
524
+ }
525
+
526
+ export type ContinuityBarrier = { kind: "flush" } | { kind: "checkpoint"; reason: string };
527
+
528
+ /**
529
+ * Progress from a previous partial attempt at this same group.
530
+ *
531
+ * An entry id alone would let a changed payload hide behind an accepted id, so
532
+ * each token carries the digest of the record that was actually accepted. A
533
+ * token whose digest does not match this request's record of the same id is a
534
+ * different request, and the group is refused rather than silently completed.
535
+ */
536
+ export interface ContinuityAcceptedProgress {
537
+ entryId: string;
538
+ payloadDigest: string;
539
+ }
540
+
541
+ export interface ContinuityPersistRequest {
542
+ /** Ordered group. One barrier runs after the complete group. */
543
+ entries: ReadonlyArray<ContinuityAppendable>;
544
+ barrier: ContinuityBarrier;
545
+ /** What a previous attempt at this exact group already got accepted. */
546
+ alreadyAccepted?: ReadonlyArray<ContinuityAcceptedProgress>;
547
+ }
548
+
549
+ export type ContinuityPersistBlockedReason =
550
+ | "append_absent_after_retry"
551
+ | "append_conflicting"
552
+ | "append_unresolved"
553
+ | "barrier_failed"
554
+ | "unsupported_barrier_port"
555
+ | "state_removed"
556
+ | "origin_changed"
557
+ | "invalid_retry_schedule"
558
+ | "deadline_expired"
559
+ | "duplicate_group_entry"
560
+ | "progress_mismatch";
561
+
562
+ export type ContinuityPersistResult =
563
+ | {
564
+ status: "durable";
565
+ accepted: ReadonlyArray<ContinuityAcceptedProgress>;
566
+ barrierAttempts: number;
567
+ /**
568
+ * True only when the barrier is **known** to have completed inside the
569
+ * window: the clock stayed usable and monotonic throughout and had not
570
+ * reached the deadline. A barrier that landed late and one whose clock
571
+ * became unusable are both `false`, because neither confirms anything.
572
+ *
573
+ * The records are persisted either way. `false` is not a persistence
574
+ * failure; it means the caller must re-authorize before dependent
575
+ * execution rather than inherit permission from this call.
576
+ */
577
+ confirmedWithinDeadline: boolean;
578
+ }
579
+ | {
580
+ status: "uncertain";
581
+ reason: ContinuityPersistBlockedReason;
582
+ accepted: ReadonlyArray<ContinuityAcceptedProgress>;
583
+ barrierAttempts: number;
584
+ anomalies: ReadonlyArray<ContinuityAnomaly>;
585
+ };
586
+
587
+ export type ContinuityReconcileResult =
588
+ | { status: "accepted" }
589
+ /** Proven absent, and the re-append under the original id also failed. */
590
+ | { status: "absent"; detail?: string }
591
+ | { status: "conflicting"; detail?: string }
592
+ | { status: "unresolved"; detail?: string };