@smthrs/harness 0.0.0-stage → 1.0.0-rc.3

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 (476) hide show
  1. package/CHANGELOG.md +387 -0
  2. package/LICENSE +21 -0
  3. package/README.md +138 -2
  4. package/dist/cjs/AgentEvent.d.ts +3092 -0
  5. package/dist/cjs/AgentEvent.d.ts.map +1 -0
  6. package/dist/cjs/AgentEvent.js +1116 -0
  7. package/dist/cjs/AgentEvent.js.map +7 -0
  8. package/dist/cjs/CallLedger.d.ts +378 -0
  9. package/dist/cjs/CallLedger.d.ts.map +1 -0
  10. package/dist/cjs/CallLedger.js +240 -0
  11. package/dist/cjs/CallLedger.js.map +7 -0
  12. package/dist/cjs/Cell.d.ts +774 -0
  13. package/dist/cjs/Cell.d.ts.map +1 -0
  14. package/dist/cjs/Cell.js +431 -0
  15. package/dist/cjs/Cell.js.map +7 -0
  16. package/dist/cjs/CellCalls.d.ts +115 -0
  17. package/dist/cjs/CellCalls.d.ts.map +1 -0
  18. package/dist/cjs/CellCalls.js +98 -0
  19. package/dist/cjs/CellCalls.js.map +7 -0
  20. package/dist/cjs/CellHistory.d.ts +102 -0
  21. package/dist/cjs/CellHistory.d.ts.map +1 -0
  22. package/dist/cjs/CellHistory.js +54 -0
  23. package/dist/cjs/CellHistory.js.map +7 -0
  24. package/dist/cjs/CellTurn.d.ts +1071 -0
  25. package/dist/cjs/CellTurn.d.ts.map +1 -0
  26. package/dist/cjs/CellTurn.js +2618 -0
  27. package/dist/cjs/CellTurn.js.map +7 -0
  28. package/dist/cjs/CellValidation.d.ts +94 -0
  29. package/dist/cjs/CellValidation.d.ts.map +1 -0
  30. package/dist/cjs/CellValidation.js +218 -0
  31. package/dist/cjs/CellValidation.js.map +7 -0
  32. package/dist/cjs/Compaction.d.ts +158 -0
  33. package/dist/cjs/Compaction.d.ts.map +1 -0
  34. package/dist/cjs/Compaction.js +189 -0
  35. package/dist/cjs/Compaction.js.map +7 -0
  36. package/dist/cjs/CompletionClaim.d.ts +801 -0
  37. package/dist/cjs/CompletionClaim.d.ts.map +1 -0
  38. package/dist/cjs/CompletionClaim.js +303 -0
  39. package/dist/cjs/CompletionClaim.js.map +7 -0
  40. package/dist/cjs/ContextWindow.d.ts +435 -0
  41. package/dist/cjs/ContextWindow.d.ts.map +1 -0
  42. package/dist/cjs/ContextWindow.js +319 -0
  43. package/dist/cjs/ContextWindow.js.map +7 -0
  44. package/dist/cjs/EngineLike.d.ts +546 -0
  45. package/dist/cjs/EngineLike.d.ts.map +1 -0
  46. package/dist/cjs/EngineLike.js +114 -0
  47. package/dist/cjs/EngineLike.js.map +7 -0
  48. package/dist/cjs/ExternalTranscript.d.ts +349 -0
  49. package/dist/cjs/ExternalTranscript.d.ts.map +1 -0
  50. package/dist/cjs/ExternalTranscript.js +826 -0
  51. package/dist/cjs/ExternalTranscript.js.map +7 -0
  52. package/dist/cjs/FailedCall.d.ts +132 -0
  53. package/dist/cjs/FailedCall.d.ts.map +1 -0
  54. package/dist/cjs/FailedCall.js +53 -0
  55. package/dist/cjs/FailedCall.js.map +7 -0
  56. package/dist/cjs/FlowBinding.d.ts +289 -0
  57. package/dist/cjs/FlowBinding.d.ts.map +1 -0
  58. package/dist/cjs/FlowBinding.js +251 -0
  59. package/dist/cjs/FlowBinding.js.map +7 -0
  60. package/dist/cjs/HarnessError.d.ts +57 -0
  61. package/dist/cjs/HarnessError.d.ts.map +1 -0
  62. package/dist/cjs/HarnessError.js +75 -0
  63. package/dist/cjs/HarnessError.js.map +7 -0
  64. package/dist/cjs/Judgement.d.ts +289 -0
  65. package/dist/cjs/Judgement.d.ts.map +1 -0
  66. package/dist/cjs/Judgement.js +240 -0
  67. package/dist/cjs/Judgement.js.map +7 -0
  68. package/dist/cjs/Monitor.d.ts +374 -0
  69. package/dist/cjs/Monitor.d.ts.map +1 -0
  70. package/dist/cjs/Monitor.js +233 -0
  71. package/dist/cjs/Monitor.js.map +7 -0
  72. package/dist/cjs/NarrowedCheck.d.ts +523 -0
  73. package/dist/cjs/NarrowedCheck.d.ts.map +1 -0
  74. package/dist/cjs/NarrowedCheck.js +263 -0
  75. package/dist/cjs/NarrowedCheck.js.map +7 -0
  76. package/dist/cjs/Notifications.d.ts +42 -0
  77. package/dist/cjs/Notifications.d.ts.map +1 -0
  78. package/dist/cjs/Notifications.js +177 -0
  79. package/dist/cjs/Notifications.js.map +7 -0
  80. package/dist/cjs/Plan.d.ts +127 -0
  81. package/dist/cjs/Plan.d.ts.map +1 -0
  82. package/dist/cjs/Plan.js +77 -0
  83. package/dist/cjs/Plan.js.map +7 -0
  84. package/dist/cjs/QuickJSSandbox.d.ts +151 -0
  85. package/dist/cjs/QuickJSSandbox.d.ts.map +1 -0
  86. package/dist/cjs/QuickJSSandbox.js +987 -0
  87. package/dist/cjs/QuickJSSandbox.js.map +7 -0
  88. package/dist/cjs/Relevance.d.ts +213 -0
  89. package/dist/cjs/Relevance.d.ts.map +1 -0
  90. package/dist/cjs/Relevance.js +183 -0
  91. package/dist/cjs/Relevance.js.map +7 -0
  92. package/dist/cjs/Sandbox.d.ts +637 -0
  93. package/dist/cjs/Sandbox.d.ts.map +1 -0
  94. package/dist/cjs/Sandbox.js +260 -0
  95. package/dist/cjs/Sandbox.js.map +7 -0
  96. package/dist/cjs/Steering.d.ts +464 -0
  97. package/dist/cjs/Steering.d.ts.map +1 -0
  98. package/dist/cjs/Steering.js +153 -0
  99. package/dist/cjs/Steering.js.map +7 -0
  100. package/dist/cjs/StructuredOutput.d.ts +252 -0
  101. package/dist/cjs/StructuredOutput.d.ts.map +1 -0
  102. package/dist/cjs/StructuredOutput.js +266 -0
  103. package/dist/cjs/StructuredOutput.js.map +7 -0
  104. package/dist/cjs/Sufficiency.d.ts +195 -0
  105. package/dist/cjs/Sufficiency.d.ts.map +1 -0
  106. package/dist/cjs/Sufficiency.js +110 -0
  107. package/dist/cjs/Sufficiency.js.map +7 -0
  108. package/dist/cjs/Supervisor.d.ts +719 -0
  109. package/dist/cjs/Supervisor.d.ts.map +1 -0
  110. package/dist/cjs/Supervisor.js +313 -0
  111. package/dist/cjs/Supervisor.js.map +7 -0
  112. package/dist/cjs/Tokens.d.ts +86 -0
  113. package/dist/cjs/Tokens.d.ts.map +1 -0
  114. package/dist/cjs/Tokens.js +72 -0
  115. package/dist/cjs/Tokens.js.map +7 -0
  116. package/dist/cjs/Transcript.d.ts +171 -0
  117. package/dist/cjs/Transcript.d.ts.map +1 -0
  118. package/dist/cjs/Transcript.js +342 -0
  119. package/dist/cjs/Transcript.js.map +7 -0
  120. package/dist/cjs/TruncatedOutput.d.ts +186 -0
  121. package/dist/cjs/TruncatedOutput.d.ts.map +1 -0
  122. package/dist/cjs/TruncatedOutput.js +143 -0
  123. package/dist/cjs/TruncatedOutput.js.map +7 -0
  124. package/dist/cjs/UnmovedTree.d.ts +113 -0
  125. package/dist/cjs/UnmovedTree.d.ts.map +1 -0
  126. package/dist/cjs/UnmovedTree.js +38 -0
  127. package/dist/cjs/UnmovedTree.js.map +7 -0
  128. package/dist/cjs/UnresolvedFailure.d.ts +196 -0
  129. package/dist/cjs/UnresolvedFailure.d.ts.map +1 -0
  130. package/dist/cjs/UnresolvedFailure.js +77 -0
  131. package/dist/cjs/UnresolvedFailure.js.map +7 -0
  132. package/dist/cjs/VacuousVerification.d.ts +237 -0
  133. package/dist/cjs/VacuousVerification.d.ts.map +1 -0
  134. package/dist/cjs/VacuousVerification.js +91 -0
  135. package/dist/cjs/VacuousVerification.js.map +7 -0
  136. package/dist/cjs/VariablesPanel.d.ts +117 -0
  137. package/dist/cjs/VariablesPanel.d.ts.map +1 -0
  138. package/dist/cjs/VariablesPanel.js +108 -0
  139. package/dist/cjs/VariablesPanel.js.map +7 -0
  140. package/dist/cjs/index.d.ts +172 -0
  141. package/dist/cjs/index.d.ts.map +1 -0
  142. package/dist/cjs/index.js +99 -0
  143. package/dist/cjs/index.js.map +7 -0
  144. package/dist/cjs/internal/bytes.d.ts +36 -0
  145. package/dist/cjs/internal/bytes.d.ts.map +1 -0
  146. package/dist/cjs/internal/bytes.js +57 -0
  147. package/dist/cjs/internal/bytes.js.map +7 -0
  148. package/dist/cjs/internal/cellPrompt.d.ts +122 -0
  149. package/dist/cjs/internal/cellPrompt.d.ts.map +1 -0
  150. package/dist/cjs/internal/cellPrompt.js +146 -0
  151. package/dist/cjs/internal/cellPrompt.js.map +7 -0
  152. package/dist/cjs/internal/compactable.d.ts +44 -0
  153. package/dist/cjs/internal/compactable.d.ts.map +1 -0
  154. package/dist/cjs/internal/compactable.js +56 -0
  155. package/dist/cjs/internal/compactable.js.map +7 -0
  156. package/dist/cjs/internal/compactionMarks.d.ts +278 -0
  157. package/dist/cjs/internal/compactionMarks.d.ts.map +1 -0
  158. package/dist/cjs/internal/compactionMarks.js +212 -0
  159. package/dist/cjs/internal/compactionMarks.js.map +7 -0
  160. package/dist/cjs/internal/demandText.d.ts +95 -0
  161. package/dist/cjs/internal/demandText.d.ts.map +1 -0
  162. package/dist/cjs/internal/demandText.js +70 -0
  163. package/dist/cjs/internal/demandText.js.map +7 -0
  164. package/dist/cjs/internal/elide.d.ts +109 -0
  165. package/dist/cjs/internal/elide.d.ts.map +1 -0
  166. package/dist/cjs/internal/elide.js +59 -0
  167. package/dist/cjs/internal/elide.js.map +7 -0
  168. package/dist/cjs/internal/frame.d.ts +463 -0
  169. package/dist/cjs/internal/frame.d.ts.map +1 -0
  170. package/dist/cjs/internal/frame.js +514 -0
  171. package/dist/cjs/internal/frame.js.map +7 -0
  172. package/dist/cjs/internal/nonNegativeSafeInt.d.ts +20 -0
  173. package/dist/cjs/internal/nonNegativeSafeInt.d.ts.map +1 -0
  174. package/dist/cjs/internal/nonNegativeSafeInt.js +29 -0
  175. package/dist/cjs/internal/nonNegativeSafeInt.js.map +7 -0
  176. package/dist/cjs/internal/paidUsage.d.ts +52 -0
  177. package/dist/cjs/internal/paidUsage.d.ts.map +1 -0
  178. package/dist/cjs/internal/paidUsage.js +70 -0
  179. package/dist/cjs/internal/paidUsage.js.map +7 -0
  180. package/dist/cjs/internal/printChannel.d.ts +233 -0
  181. package/dist/cjs/internal/printChannel.d.ts.map +1 -0
  182. package/dist/cjs/internal/printChannel.js +165 -0
  183. package/dist/cjs/internal/printChannel.js.map +7 -0
  184. package/dist/cjs/internal/printsObservation.d.ts +26 -0
  185. package/dist/cjs/internal/printsObservation.d.ts.map +1 -0
  186. package/dist/cjs/internal/printsObservation.js +27 -0
  187. package/dist/cjs/internal/printsObservation.js.map +7 -0
  188. package/dist/cjs/internal/refusal.d.ts +40 -0
  189. package/dist/cjs/internal/refusal.d.ts.map +1 -0
  190. package/dist/cjs/internal/refusal.js +45 -0
  191. package/dist/cjs/internal/refusal.js.map +7 -0
  192. package/dist/cjs/internal/supervision.d.ts +174 -0
  193. package/dist/cjs/internal/supervision.d.ts.map +1 -0
  194. package/dist/cjs/internal/supervision.js +402 -0
  195. package/dist/cjs/internal/supervision.js.map +7 -0
  196. package/dist/cjs/internal/unfinishedWork.d.ts +99 -0
  197. package/dist/cjs/internal/unfinishedWork.d.ts.map +1 -0
  198. package/dist/cjs/internal/unfinishedWork.js +80 -0
  199. package/dist/cjs/internal/unfinishedWork.js.map +7 -0
  200. package/dist/cjs/internal/unobservedCall.d.ts +112 -0
  201. package/dist/cjs/internal/unobservedCall.d.ts.map +1 -0
  202. package/dist/cjs/internal/unobservedCall.js +345 -0
  203. package/dist/cjs/internal/unobservedCall.js.map +7 -0
  204. package/dist/cjs/internal/untrustedData.d.ts +14 -0
  205. package/dist/cjs/internal/untrustedData.d.ts.map +1 -0
  206. package/dist/cjs/internal/untrustedData.js +30 -0
  207. package/dist/cjs/internal/untrustedData.js.map +7 -0
  208. package/dist/cjs/package.json +1 -0
  209. package/dist/esm/AgentEvent.d.ts +3092 -0
  210. package/dist/esm/AgentEvent.d.ts.map +1 -0
  211. package/dist/esm/AgentEvent.js +1610 -0
  212. package/dist/esm/AgentEvent.js.map +1 -0
  213. package/dist/esm/CallLedger.d.ts +378 -0
  214. package/dist/esm/CallLedger.d.ts.map +1 -0
  215. package/dist/esm/CallLedger.js +506 -0
  216. package/dist/esm/CallLedger.js.map +1 -0
  217. package/dist/esm/Cell.d.ts +774 -0
  218. package/dist/esm/Cell.d.ts.map +1 -0
  219. package/dist/esm/Cell.js +772 -0
  220. package/dist/esm/Cell.js.map +1 -0
  221. package/dist/esm/CellCalls.d.ts +115 -0
  222. package/dist/esm/CellCalls.d.ts.map +1 -0
  223. package/dist/esm/CellCalls.js +97 -0
  224. package/dist/esm/CellCalls.js.map +1 -0
  225. package/dist/esm/CellHistory.d.ts +102 -0
  226. package/dist/esm/CellHistory.d.ts.map +1 -0
  227. package/dist/esm/CellHistory.js +91 -0
  228. package/dist/esm/CellHistory.js.map +1 -0
  229. package/dist/esm/CellTurn.d.ts +1071 -0
  230. package/dist/esm/CellTurn.d.ts.map +1 -0
  231. package/dist/esm/CellTurn.js +3410 -0
  232. package/dist/esm/CellTurn.js.map +1 -0
  233. package/dist/esm/CellValidation.d.ts +94 -0
  234. package/dist/esm/CellValidation.d.ts.map +1 -0
  235. package/dist/esm/CellValidation.js +335 -0
  236. package/dist/esm/CellValidation.js.map +1 -0
  237. package/dist/esm/Compaction.d.ts +158 -0
  238. package/dist/esm/Compaction.d.ts.map +1 -0
  239. package/dist/esm/Compaction.js +216 -0
  240. package/dist/esm/Compaction.js.map +1 -0
  241. package/dist/esm/CompletionClaim.d.ts +801 -0
  242. package/dist/esm/CompletionClaim.d.ts.map +1 -0
  243. package/dist/esm/CompletionClaim.js +833 -0
  244. package/dist/esm/CompletionClaim.js.map +1 -0
  245. package/dist/esm/ContextWindow.d.ts +435 -0
  246. package/dist/esm/ContextWindow.d.ts.map +1 -0
  247. package/dist/esm/ContextWindow.js +427 -0
  248. package/dist/esm/ContextWindow.js.map +1 -0
  249. package/dist/esm/EngineLike.d.ts +546 -0
  250. package/dist/esm/EngineLike.d.ts.map +1 -0
  251. package/dist/esm/EngineLike.js +218 -0
  252. package/dist/esm/EngineLike.js.map +1 -0
  253. package/dist/esm/ExternalTranscript.d.ts +349 -0
  254. package/dist/esm/ExternalTranscript.d.ts.map +1 -0
  255. package/dist/esm/ExternalTranscript.js +987 -0
  256. package/dist/esm/ExternalTranscript.js.map +1 -0
  257. package/dist/esm/FailedCall.d.ts +132 -0
  258. package/dist/esm/FailedCall.d.ts.map +1 -0
  259. package/dist/esm/FailedCall.js +131 -0
  260. package/dist/esm/FailedCall.js.map +1 -0
  261. package/dist/esm/FlowBinding.d.ts +289 -0
  262. package/dist/esm/FlowBinding.d.ts.map +1 -0
  263. package/dist/esm/FlowBinding.js +376 -0
  264. package/dist/esm/FlowBinding.js.map +1 -0
  265. package/dist/esm/HarnessError.d.ts +57 -0
  266. package/dist/esm/HarnessError.d.ts.map +1 -0
  267. package/dist/esm/HarnessError.js +85 -0
  268. package/dist/esm/HarnessError.js.map +1 -0
  269. package/dist/esm/Judgement.d.ts +289 -0
  270. package/dist/esm/Judgement.d.ts.map +1 -0
  271. package/dist/esm/Judgement.js +305 -0
  272. package/dist/esm/Judgement.js.map +1 -0
  273. package/dist/esm/Monitor.d.ts +374 -0
  274. package/dist/esm/Monitor.d.ts.map +1 -0
  275. package/dist/esm/Monitor.js +370 -0
  276. package/dist/esm/Monitor.js.map +1 -0
  277. package/dist/esm/NarrowedCheck.d.ts +523 -0
  278. package/dist/esm/NarrowedCheck.d.ts.map +1 -0
  279. package/dist/esm/NarrowedCheck.js +612 -0
  280. package/dist/esm/NarrowedCheck.js.map +1 -0
  281. package/dist/esm/Notifications.d.ts +42 -0
  282. package/dist/esm/Notifications.d.ts.map +1 -0
  283. package/dist/esm/Notifications.js +215 -0
  284. package/dist/esm/Notifications.js.map +1 -0
  285. package/dist/esm/Plan.d.ts +127 -0
  286. package/dist/esm/Plan.d.ts.map +1 -0
  287. package/dist/esm/Plan.js +97 -0
  288. package/dist/esm/Plan.js.map +1 -0
  289. package/dist/esm/QuickJSSandbox.d.ts +151 -0
  290. package/dist/esm/QuickJSSandbox.d.ts.map +1 -0
  291. package/dist/esm/QuickJSSandbox.js +1364 -0
  292. package/dist/esm/QuickJSSandbox.js.map +1 -0
  293. package/dist/esm/Relevance.d.ts +213 -0
  294. package/dist/esm/Relevance.d.ts.map +1 -0
  295. package/dist/esm/Relevance.js +254 -0
  296. package/dist/esm/Relevance.js.map +1 -0
  297. package/dist/esm/Sandbox.d.ts +637 -0
  298. package/dist/esm/Sandbox.d.ts.map +1 -0
  299. package/dist/esm/Sandbox.js +464 -0
  300. package/dist/esm/Sandbox.js.map +1 -0
  301. package/dist/esm/Steering.d.ts +464 -0
  302. package/dist/esm/Steering.d.ts.map +1 -0
  303. package/dist/esm/Steering.js +193 -0
  304. package/dist/esm/Steering.js.map +1 -0
  305. package/dist/esm/StructuredOutput.d.ts +252 -0
  306. package/dist/esm/StructuredOutput.d.ts.map +1 -0
  307. package/dist/esm/StructuredOutput.js +430 -0
  308. package/dist/esm/StructuredOutput.js.map +1 -0
  309. package/dist/esm/Sufficiency.d.ts +195 -0
  310. package/dist/esm/Sufficiency.d.ts.map +1 -0
  311. package/dist/esm/Sufficiency.js +207 -0
  312. package/dist/esm/Sufficiency.js.map +1 -0
  313. package/dist/esm/Supervisor.d.ts +719 -0
  314. package/dist/esm/Supervisor.d.ts.map +1 -0
  315. package/dist/esm/Supervisor.js +575 -0
  316. package/dist/esm/Supervisor.js.map +1 -0
  317. package/dist/esm/Tokens.d.ts +86 -0
  318. package/dist/esm/Tokens.d.ts.map +1 -0
  319. package/dist/esm/Tokens.js +92 -0
  320. package/dist/esm/Tokens.js.map +1 -0
  321. package/dist/esm/Transcript.d.ts +171 -0
  322. package/dist/esm/Transcript.d.ts.map +1 -0
  323. package/dist/esm/Transcript.js +424 -0
  324. package/dist/esm/Transcript.js.map +1 -0
  325. package/dist/esm/TruncatedOutput.d.ts +186 -0
  326. package/dist/esm/TruncatedOutput.d.ts.map +1 -0
  327. package/dist/esm/TruncatedOutput.js +257 -0
  328. package/dist/esm/TruncatedOutput.js.map +1 -0
  329. package/dist/esm/UnmovedTree.d.ts +113 -0
  330. package/dist/esm/UnmovedTree.d.ts.map +1 -0
  331. package/dist/esm/UnmovedTree.js +90 -0
  332. package/dist/esm/UnmovedTree.js.map +1 -0
  333. package/dist/esm/UnresolvedFailure.d.ts +196 -0
  334. package/dist/esm/UnresolvedFailure.d.ts.map +1 -0
  335. package/dist/esm/UnresolvedFailure.js +218 -0
  336. package/dist/esm/UnresolvedFailure.js.map +1 -0
  337. package/dist/esm/VacuousVerification.d.ts +237 -0
  338. package/dist/esm/VacuousVerification.d.ts.map +1 -0
  339. package/dist/esm/VacuousVerification.js +245 -0
  340. package/dist/esm/VacuousVerification.js.map +1 -0
  341. package/dist/esm/VariablesPanel.d.ts +117 -0
  342. package/dist/esm/VariablesPanel.d.ts.map +1 -0
  343. package/dist/esm/VariablesPanel.js +142 -0
  344. package/dist/esm/VariablesPanel.js.map +1 -0
  345. package/dist/esm/index.d.ts +172 -0
  346. package/dist/esm/index.d.ts.map +1 -0
  347. package/dist/esm/index.js +172 -0
  348. package/dist/esm/index.js.map +1 -0
  349. package/dist/esm/internal/bytes.d.ts +36 -0
  350. package/dist/esm/internal/bytes.d.ts.map +1 -0
  351. package/dist/esm/internal/bytes.js +70 -0
  352. package/dist/esm/internal/bytes.js.map +1 -0
  353. package/dist/esm/internal/cellPrompt.d.ts +122 -0
  354. package/dist/esm/internal/cellPrompt.d.ts.map +1 -0
  355. package/dist/esm/internal/cellPrompt.js +276 -0
  356. package/dist/esm/internal/cellPrompt.js.map +1 -0
  357. package/dist/esm/internal/compactable.d.ts +44 -0
  358. package/dist/esm/internal/compactable.d.ts.map +1 -0
  359. package/dist/esm/internal/compactable.js +71 -0
  360. package/dist/esm/internal/compactable.js.map +1 -0
  361. package/dist/esm/internal/compactionMarks.d.ts +278 -0
  362. package/dist/esm/internal/compactionMarks.d.ts.map +1 -0
  363. package/dist/esm/internal/compactionMarks.js +317 -0
  364. package/dist/esm/internal/compactionMarks.js.map +1 -0
  365. package/dist/esm/internal/demandText.d.ts +95 -0
  366. package/dist/esm/internal/demandText.d.ts.map +1 -0
  367. package/dist/esm/internal/demandText.js +128 -0
  368. package/dist/esm/internal/demandText.js.map +1 -0
  369. package/dist/esm/internal/elide.d.ts +109 -0
  370. package/dist/esm/internal/elide.d.ts.map +1 -0
  371. package/dist/esm/internal/elide.js +123 -0
  372. package/dist/esm/internal/elide.js.map +1 -0
  373. package/dist/esm/internal/frame.d.ts +463 -0
  374. package/dist/esm/internal/frame.d.ts.map +1 -0
  375. package/dist/esm/internal/frame.js +861 -0
  376. package/dist/esm/internal/frame.js.map +1 -0
  377. package/dist/esm/internal/nonNegativeSafeInt.d.ts +20 -0
  378. package/dist/esm/internal/nonNegativeSafeInt.d.ts.map +1 -0
  379. package/dist/esm/internal/nonNegativeSafeInt.js +20 -0
  380. package/dist/esm/internal/nonNegativeSafeInt.js.map +1 -0
  381. package/dist/esm/internal/paidUsage.d.ts +52 -0
  382. package/dist/esm/internal/paidUsage.d.ts.map +1 -0
  383. package/dist/esm/internal/paidUsage.js +72 -0
  384. package/dist/esm/internal/paidUsage.js.map +1 -0
  385. package/dist/esm/internal/printChannel.d.ts +233 -0
  386. package/dist/esm/internal/printChannel.d.ts.map +1 -0
  387. package/dist/esm/internal/printChannel.js +376 -0
  388. package/dist/esm/internal/printChannel.js.map +1 -0
  389. package/dist/esm/internal/printsObservation.d.ts +26 -0
  390. package/dist/esm/internal/printsObservation.d.ts.map +1 -0
  391. package/dist/esm/internal/printsObservation.js +29 -0
  392. package/dist/esm/internal/printsObservation.js.map +1 -0
  393. package/dist/esm/internal/refusal.d.ts +40 -0
  394. package/dist/esm/internal/refusal.d.ts.map +1 -0
  395. package/dist/esm/internal/refusal.js +47 -0
  396. package/dist/esm/internal/refusal.js.map +1 -0
  397. package/dist/esm/internal/supervision.d.ts +174 -0
  398. package/dist/esm/internal/supervision.d.ts.map +1 -0
  399. package/dist/esm/internal/supervision.js +485 -0
  400. package/dist/esm/internal/supervision.js.map +1 -0
  401. package/dist/esm/internal/unfinishedWork.d.ts +99 -0
  402. package/dist/esm/internal/unfinishedWork.d.ts.map +1 -0
  403. package/dist/esm/internal/unfinishedWork.js +85 -0
  404. package/dist/esm/internal/unfinishedWork.js.map +1 -0
  405. package/dist/esm/internal/unobservedCall.d.ts +112 -0
  406. package/dist/esm/internal/unobservedCall.d.ts.map +1 -0
  407. package/dist/esm/internal/unobservedCall.js +501 -0
  408. package/dist/esm/internal/unobservedCall.js.map +1 -0
  409. package/dist/esm/internal/untrustedData.d.ts +14 -0
  410. package/dist/esm/internal/untrustedData.d.ts.map +1 -0
  411. package/dist/esm/internal/untrustedData.js +15 -0
  412. package/dist/esm/internal/untrustedData.js.map +1 -0
  413. package/docs/README.md +129 -0
  414. package/docs/api.md +1869 -0
  415. package/docs/concepts.md +238 -0
  416. package/docs/external-transcripts.md +245 -0
  417. package/docs/guides/bind-flows.md +167 -0
  418. package/docs/guides/drive-the-loop.md +265 -0
  419. package/docs/guides/run-cells.md +262 -0
  420. package/docs/guides/workerd.md +144 -0
  421. package/docs/installation.md +69 -0
  422. package/docs/quickstart.md +121 -0
  423. package/docs/reference.md +954 -0
  424. package/docs/troubleshooting.md +177 -0
  425. package/package.json +463 -3
  426. package/src/AgentEvent.ts +1772 -0
  427. package/src/CallLedger.ts +560 -0
  428. package/src/Cell.ts +926 -0
  429. package/src/CellCalls.ts +198 -0
  430. package/src/CellHistory.ts +128 -0
  431. package/src/CellTurn.ts +4450 -0
  432. package/src/CellValidation.ts +382 -0
  433. package/src/Compaction.ts +330 -0
  434. package/src/CompletionClaim.ts +1013 -0
  435. package/src/ContextWindow.ts +669 -0
  436. package/src/EngineLike.ts +614 -0
  437. package/src/ExternalTranscript.ts +1143 -0
  438. package/src/FailedCall.ts +163 -0
  439. package/src/FlowBinding.ts +603 -0
  440. package/src/HarnessError.ts +98 -0
  441. package/src/Judgement.ts +526 -0
  442. package/src/Monitor.ts +579 -0
  443. package/src/NarrowedCheck.ts +694 -0
  444. package/src/Notifications.ts +262 -0
  445. package/src/Plan.ts +113 -0
  446. package/src/QuickJSSandbox.ts +1557 -0
  447. package/src/Relevance.ts +352 -0
  448. package/src/Sandbox.ts +908 -0
  449. package/src/Steering.ts +405 -0
  450. package/src/StructuredOutput.ts +484 -0
  451. package/src/Sufficiency.ts +247 -0
  452. package/src/Supervisor.ts +798 -0
  453. package/src/Tokens.ts +108 -0
  454. package/src/Transcript.ts +513 -0
  455. package/src/TruncatedOutput.ts +297 -0
  456. package/src/UnmovedTree.ts +121 -0
  457. package/src/UnresolvedFailure.ts +240 -0
  458. package/src/VacuousVerification.ts +280 -0
  459. package/src/VariablesPanel.ts +165 -0
  460. package/src/index.ts +204 -0
  461. package/src/internal/bytes.ts +70 -0
  462. package/src/internal/cellPrompt.ts +337 -0
  463. package/src/internal/compactable.ts +76 -0
  464. package/src/internal/compactionMarks.ts +454 -0
  465. package/src/internal/demandText.ts +145 -0
  466. package/src/internal/elide.ts +130 -0
  467. package/src/internal/frame.ts +1178 -0
  468. package/src/internal/nonNegativeSafeInt.ts +24 -0
  469. package/src/internal/paidUsage.ts +90 -0
  470. package/src/internal/printChannel.ts +434 -0
  471. package/src/internal/printsObservation.ts +31 -0
  472. package/src/internal/refusal.ts +53 -0
  473. package/src/internal/supervision.ts +652 -0
  474. package/src/internal/unfinishedWork.ts +123 -0
  475. package/src/internal/unobservedCall.ts +536 -0
  476. package/src/internal/untrustedData.ts +19 -0
package/docs/api.md ADDED
@@ -0,0 +1,1869 @@
1
+ ---
2
+ title: "API reference"
3
+ description: "The complete @smthrs/harness API: the cell-first controller, the sandbox and engine ports, the cell contract, flow binding, and every error union, with behavior and signatures from source."
4
+ ---
5
+
6
+ `@smthrs/harness` is the built-in agent loop, expressed as pure translation
7
+ plus a small set of service ports. It holds no scheduler, no database, no
8
+ transport and no provider client: `EngineLike` is the port a durable engine
9
+ answers, `Sandbox` is the port a script realm answers, `Steering.Source` is the
10
+ port a notification queue answers, and [`@smthrs/agent`](/api/agent) is the
11
+ assembled production composition over the durable engine.
12
+
13
+ The loop is cell-first. One frame is
14
+
15
+ ```text
16
+ model -> generated cell -> realm evaluation -> individually durable flow calls -> next transition
17
+ ```
18
+
19
+ The model emits fenced `cell` blocks; they run as one program inside a realm
20
+ that outlives the frame; the only authority the program holds is
21
+ `ctx.call(flowName, input)`; and the program states its intent by calling
22
+ `ctx.done(output)`, `ctx.park(reason, message)`, or neither, which continues.
23
+ `Sandbox.replTransition` turns that into the transition the journal records.
24
+
25
+ ## Example
26
+
27
+ ```ts
28
+ import * as Cell from "@smthrs/harness/Cell"
29
+ import * as QuickJSSandbox from "@smthrs/harness/QuickJSSandbox"
30
+ import { Effect } from "effect"
31
+
32
+ const frame = await Effect.runPromise(Effect.scoped(Effect.gen(function*() {
33
+ const realm = yield* (yield* QuickJSSandbox.make).openRealm!({ flows: {} })
34
+ const call = () => Effect.succeed(new Cell.CallResult({ outcome: "success", value: null }))
35
+ return yield* realm.evaluate({ cell: Cell.source(`ctx.done("hi")`), frame: 0, call })
36
+ })))
37
+ console.log(
38
+ frame.outcome._tag,
39
+ frame.outcome._tag === "settled" && frame.outcome.transition._tag === "complete"
40
+ ? frame.outcome.transition.output
41
+ : ""
42
+ )
43
+ ```
44
+
45
+ ```text
46
+ settled hi
47
+ ```
48
+
49
+ ## Entry points
50
+
51
+ | Import | What it is |
52
+ | -------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
53
+ | `@smthrs/harness` | The root barrel: the 33 namespaces listed in the module index. |
54
+ | `@smthrs/harness/<Module>` | Any top-level module directly, for example `@smthrs/harness/CellTurn`. |
55
+ | `@smthrs/harness/QuickJSSandbox` | The QuickJS-WASM `Sandbox` binding. Not re-exported from the root, because it carries an embedded WebAssembly build. |
56
+ | `@smthrs/harness/package.json` | The package manifest. |
57
+
58
+ The `./internal/*` and `./*/index` subpaths map to `null` and do not resolve.
59
+
60
+ ## Module index
61
+
62
+ 34 public modules, 536 documented exports. Each module's full export table is
63
+ in the [module and export inventory](./reference.md); the sections below state
64
+ behavior and signatures.
65
+
66
+ | Module | Public exports | What it is |
67
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
68
+ | `HarnessError` | `HarnessErrorCode`, `HarnessError` | Stable failures reported at the harness translation boundary. |
69
+ | `AgentEvent` | `Observer`, `Journal`, `RelevanceKind`, `CompactionMark`, `CompactionPin`, `MonitorKind`, `Stance`, `Suppression`, `UnjudgedReason`, `DisciplineArmed`, `TurnOpened`, `ModelRequested`, `ModelSelected`, `SeatFailedOver`, `ModelParked`, `ModelUnparked`, `ModelDelta`, `ModelRetried`, `ModelSettled`, `CellProduced`, `CellRejectedInFrame`, `CellCallStarted`, `CellCallSettled`, `CellPrinted`, `CellSettled`, `TransitionApplied`, `ReadOnlyDemandIssued`, `ReadOnlyDemanded`, `RepeatDemanded`, `NarrowedDemanded`, `UnmovedDemanded`, `UnresolvedDemanded`, `FailedCallDemanded`, `UnobservedDemanded`, `NarrowOnlyDemanded`, `ClaimDemanded`, `DecisionAnswer`, `decisionAnswers`, `DecisionSettled`, `SupervisorSettled`, `SupervisorUnjudged`, `DecisionUnjudged`, `RelevanceSettled`, `RelevanceRestored`, `SeatPanel`, `SeatRouted`, `SufficiencyObserved`, `VacuousVerificationObserved`, `MutationObserved`, `CheckpointMinted`, `Suspended`, `CompactionSettled`, `SteeringDrained`, `TurnClosed`, `PermissionRequired`, `Aborted`, `Resolved`, `AgentEvent`, `eventType` | Serializable events emitted by harness adapters. |
70
+ | `Plan` | `Child`, `Batch`, `ChildResult`, `ChildProgress`, `ChildSettled`, `SpliceEvent` | Local structural plan nodes used at the harness-to-engine boundary. |
71
+ | `EngineLike` | `SuspendReasonCode`, `SuspendReason`, `SealedModelStep`, `BoundaryIdentity`, `DurableSchema`, `RecordBoundary`, `Observation`, `Snapshot`, `Binding`, `Resolved`, `CaptureRequest`, `EngineLike`, `make`, `layer`, `resolve`, `makeNoop`, `layerNoop` | Narrow engine port consumed by the built-in harness. |
72
+ | `Tokens` | `Count`, `Segment`, `Accounting`, `Estimator`, `estimate`, `count`, `combine` | Deterministic token accounting for context windows. |
73
+ | `ContextWindow` | `TypeId`, `SegmentKind`, `SegmentZone`, `Content`, `Mark`, `ContextWindowErrorCode`, `ContextWindowError`, `Segment`, `ContextWindow`, `SegmentInput`, `MakeOptions`, `makeSegment`, `make`, `empty`, `appendTurn`, `prefixDigest`, `compactMarked`, `compactPrefix`, `compact`, `render` | The immutable, provider-neutral context assembled for one model request. |
74
+ | `Transcript` | `journalVersion`, `validateJournal`, `TranscriptErrorCode`, `TranscriptError`, `ProjectedMessage`, `ProjectedState`, `CellEvidence`, `projectStateResult`, `projectResult` | Transcript projection from durable journal entries. |
75
+ | `ExternalTranscript` | `AgentKind`, `EditedFile`, `Part`, `Entry`, `ExternalTranscriptErrorCode`, `ExternalTranscriptError`, `codexReleases`, `CodexState`, `CodexCall`, `codexStart`, `Decoded`, `decodeCodex`, `claudeReleases`, `ClaudeCall`, `ClaudeState`, `claudeStart`, `decodeClaude` | Read-only conversation entries decoded from another agent's transcript file. |
76
+ | `Compaction` | `summaryInstruction`, `InvalidStep`, `Summarizer`, `CompactionStep`, `TokenAccounting`, `shouldCompact`, `selectPrefix`, `declare`, `summaryRequest`, `apply` | Declarations for sealed transcript-summary steps. |
77
+ | `Steering` | `Delivery`, `SteerInsert`, `QueueInsert`, `Insert`, `SeatChange`, `ThinkingChange`, `Item`, `Queue`, `Drain`, `BoundaryInput`, `DrainRecord`, `drainRecord`, `empty`, `enqueue`, `drainAtClose`, `Source`, `SourceInput`, `make`, `makeNoop`, `layer`, `layerNoop` | Turn-boundary steering values and their source contract. |
78
+ | `Notifications` | `Options`, `make`, `layer` | Adapter from the durable notification queue to harness turn boundaries. |
79
+ | `Cell` | `Language`, `Source`, `digestOf`, `source`, `Continue`, `Complete`, `Park`, `Transition`, `renderText`, `RejectionCode`, `Settled`, `Raised`, `Rejected`, `Outcome`, `FlowProjection`, `project`, `CallFailureCode`, `defaultCallFailureCode`, `callFailureHint`, `CallIdentity`, `declarationDigest`, `Call`, `baseCheckpoint`, `checkpoint`, `checkpointOf`, `CallResult`, `CallSuccess`, `CallFailure`, `CallResultVariant`, `decodeCallResult`, `decodeOutcome`, `decodeTransition`, `callFailure`, `Extracted`, `extract` | The cell contract. |
80
+ | `Sandbox` | `SandboxErrorCode`, `SandboxError`, `Invocation`, `Mint`, `Minter`, `mintUnavailable`, `Handler`, `Limits`, `Capabilities`, `defaultLimits`, `minimumSteps`, `minimumTimeMs`, `minimumMemoryBytes`, `printFrameBytes`, `printStatementFloor`, `printRetainedBytes`, `withDefaults`, `Intent`, `replTransition`, `RealmEvaluation`, `RealmFrame`, `Realm`, `RealmOptions`, `Sandbox`, `make`, `layer`, `makeNoop`, `layerNoop`, `realmUnsupported`, `callTimedOut`, `compile`, `PendingCall`, `driveCell`, `raisedOutcome` | The deterministic script sandbox port. |
81
+ | `CellTurn` | `defaultMaxFrames`, `defaultReadOnlyFrames`, `defaultModelCallMs`, `defaultRepeatFrames`, `defaultNarrowingDemands`, `defaultUnmovedDemands`, `defaultUnresolvedDemands`, `defaultClaimDemands`, `defaultRevalidations`, `defaultMaxCheckpoints`, `State`, `Input`, `MemoryRow`, `Memory`, `make`, `teach`, `instructionsSegment`, `memorySegment`, `run` | The cell-first controller. |
82
+ | `CellHistory` | `ExecutedCell`, `Service`, `CellHistory`, `make`, `makeCells`, `makeNoop`, `layer`, `layerCells`, `layerNoop` | The source of every cell the current turn executed. |
83
+ | `CellCalls` | `Implementation`, `Prompt`, `PromptRunner`, `Options`, `Resolver`, `make` | Registry-backed resolution for the flow calls a cell makes. |
84
+ | `FlowBinding` | `Declared`, `DescriptorOptions`, `descriptorOf`, `Binding`, `Options`, `make`, `provide`, `Source`, `source`, `Catalog`, `empty`, `catalogResult`, `catalog`, `registry` | The executable-flow binding contract. |
85
+ | `StructuredOutput` | `StructuredOutputFailureCode`, `OutputIssueCode`, `OutputIssue`, `StructuredOutputFailure`, `maxIssues`, `jsonSchema`, `digest`, `instructions`, `issuesDigest`, `correction`, `lastBalanced`, `candidates`, `decode` | Turning one agent's final text into a value the declared output schema accepts, or into a typed failure. |
86
+ | `TruncatedOutput` | `flagSuffix`, `droppedSuffix`, `flagKey`, `minimumBytes`, `retained`, `Capture`, `Reuse`, `captures`, `reuse`, `refusal`, `retain`, `Ledger` | The truncation ledger: which bytes this run was handed as a fragment. |
87
+ | `CallLedger` | `bound`, `width`, `members`, `Entry`, `Ledger`, `subject`, `target`, `digest`, `payload`, `Settlement`, `entry`, `settled`, `remember`, `render` | The call ledger: what this run has already asked, rendered every frame. |
88
+ | `NarrowedCheck` | `retained`, `maxTerms`, `labelWidth`, `label`, `targeting`, `names`, `lex`, `terms`, `conditions`, `Check`, `Narrowing`, `check`, `narrows`, `find`, `demand`, `Only`, `findOnly`, `demandOnly`, `remember`, `Ledger` | The narrowing ledger: which checks this run has run, and over which tree. |
89
+ | `CellValidation` | `Validation`, `normalize`, `validate` | Cell validation at the boundary. |
90
+ | `CompletionClaim` | `outputBytes`, `proseBytes`, `disprovenAt`, `overclaimedAt`, `unsupportedAt`, `inventedAt`, `leafBytes`, `resultBytes`, `receipt`, `Reported`, `Settled`, `record`, `checksRunLimit`, `Check`, `Ran`, `Evidence`, `classifier`, `sentenceLimit`, `sentences`, `sentenceMarker`, `sentenceOf`, `sentenceClassifier`, `Probabilities`, `Reading`, `find`, `unrecorded`, `newest`, `unjudged`, `unproven`, `read`, `demand`, `quote`, `prose` | The completion nothing in the record contradicts. |
91
+ | `Supervisor` | `frameBytes`, `recentFrames`, `recalledLimit`, `closeGraceMs`, `thrashingAt`, `offTargetAt`, `suspectAt`, `contextAt`, `Level`, `levels`, `Help`, `emotions`, `Emotion`, `Frame`, `Signals`, `Recalled`, `skillLimit`, `skillBytes`, `calledLimit`, `Skill`, `skill`, `Snapshot`, `monitorPrefix`, `MonitorQuestions`, `classifierFor`, `classifier`, `Reading`, `read`, `Memory`, `memoryNone`, `nudge`, `recalledInsert`, `head`, `tail`, `prose` | The reading Jev takes of a run while it is still running. |
92
+ | `Monitor` | `Kind`, `Common`, `Questioned`, `Derived`, `Monitor`, `Budget`, `Input`, `budgets`, `idPattern`, `questionId`, `make`, `InvalidMonitor`, `validate`, `lint`, `paranoidText`, `carefulText`, `stepBackText`, `clarifyText`, `moods`, `defaults`, `skillText`, `skills`, `useJevText`, `useJev`, `questions`, `Row`, `Candidate`, `Evaluation`, `evaluate`, `Entry`, `Ledger`, `fresh`, `Gated`, `gate` | What one supervisor reading can put in front of the run, and when. |
93
+ | `Judgement` | `Unjudged`, `unconfigured`, `Asked`, `Read`, `measured`, `read`, `maxStateBytes`, `ItemQuestions`, `ItemAnswers`, `PerItemOptions`, `ItemState`, `ItemsRead`, `PerItem`, `perItem`, `decision`, `unjudgedEvent`, `Recorded`, `recorded`, `emitRecorded`, `taskBytes`, `task` | The one way this package asks Jev a question. |
94
+ | `Relevance` | `Kind`, `Item`, `Context`, `withholdAt`, `itemBytes`, `reader`, `Verdict`, `Reading`, `judge`, `settled`, `flowItem`, `Document`, `Chunk`, `chunks`, `render` | What a run is shown of the human-provided items it could be shown. |
95
+ | `UnmovedTree` | `Unmoved`, `find`, `demand` | The completion with nothing behind it. |
96
+ | `UnresolvedFailure` | `exitStatusKey`, `failed`, `exitStatus`, `passed`, `Displaced`, `revisits`, `find`, `demand` | The failing check a completion stepped around. |
97
+ | `FailedCall` | `cap`, `heading`, `stated`, `Failure`, `reason`, `inspects`, `find`, `demand`, `state` | The completion its own cell wrote before a call in it failed. |
98
+ | `Sufficiency` | `retained`, `Failure`, `Ledger`, `remember`, `Sufficient`, `find`, `observation` | The evidence that is already complete. |
99
+ | `VacuousVerification` | `retained`, `Pass`, `Ledger`, `remember`, `stored`, `find`, `observation` | The proof that was already true before anything changed. Not wired into `CellTurn`. |
100
+ | `VariablesPanel` | `bound`, `Binding`, `Stamp`, `Ledger`, `stamp`, `render` | The variables panel: what the realm holds, stated every frame. |
101
+ | `QuickJSSandbox` _(subpath)_ | `cacheSuccessful`, `VariantService`, `Variant`, `layerVariantLive`, `layerVariant`, `ComputeClockService`, `ComputeClock`, `layerClockLive`, `loadModule`, `makeWithVariant`, `makeWithClock`, `make`, `layerWithVariant`, `layer` | The QuickJS-WASM sandbox binding. |
102
+
103
+ ## Durability
104
+
105
+ Every `ctx.call` is its own keyed, journaled, permission-gated boundary at the
106
+ tier the flow declares, so a crash or a permission park mid-cell is recoverable:
107
+ the cell source re-executes from the top, boundaries that already settled replay
108
+ their recorded values, and execution reaches the parked call deterministically.
109
+
110
+ `EngineLike.record` is the same mechanism for the controller's own reads of the
111
+ world. The controller's state is rebuilt by re-execution, so a read that
112
+ bypasses a record is a replay divergence and, downstream of one, a duplicate
113
+ irreversible effect. `(name, identity)` together form the record key: two
114
+ records in one frame may share an identity as long as their names differ.
115
+
116
+ One call is deliberately not covered by that guarantee. `EngineLike.call` is
117
+ where a cell reaches a durable wait, and a `Flow.suspend` raised inside an
118
+ enclosing activity suspends that activity's attempt rather than the run, so the
119
+ call is issued first and its settlement is recorded after. A call the `callMs`
120
+ ceiling interrupted therefore settles nowhere, and a re-executed frame issues it
121
+ again on the host. The cell's branch is stable either way, because the recorded
122
+ settlement is what the replayed frame is handed; what the run pays for twice is
123
+ the interrupted call itself.
124
+
125
+ ## Limits
126
+
127
+ `Sandbox.defaultLimits` fills every ceiling a caller omits. A caller may raise
128
+ any single ceiling; the others keep their defaults, so a partial override cannot
129
+ disable them.
130
+
131
+ | Limit | Default | Scope | What it bounds |
132
+ | ----------------- | ------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------- |
133
+ | `calls` | 64 | per frame | Flow calls one cell may make. A `ctx.checkpoint()` mint settles on the same channel and counts. |
134
+ | `memoryBytes` | 128 MiB | per **run** | What the realm's own names hold, weighed by the panel probe at each frame's close. |
135
+ | `steps` | 1,000 | per frame | Interrupt checks, not bytecode operations. At least `Sandbox.minimumSteps`. |
136
+ | `timeMs` | 30,000 | per frame | The cell's own JavaScript time. Time suspended in a `ctx.call` or `ctx.checkpoint()` does not count. At least `Sandbox.minimumTimeMs`. |
137
+ | `totalMs` | 900,000 | per frame | Whole-evaluation time, host calls included. The backstop for a call that never settles. |
138
+ | `pauseTotalMsFor` | none | per frame | Flow names whose pending calls pause `totalMs`; the host must bound or settle these calls separately. |
139
+ | `callMs` | 120,000 | per call | Wall-clock time one flow call may take before it settles as a resolved timeout. |
140
+
141
+ `memoryBytes` is a run budget rather than a frame budget because a realm outlives
142
+ its frames. `runtime.setMemoryLimit` covers the object graph but does not count
143
+ string data on the shipped QuickJS variant, so the panel probe weighs the realm's
144
+ own names and a frame that opens over the ceiling is refused before it runs. The
145
+ reading is cleared with the refusal, because freeing is itself done by a cell.
146
+
147
+ ## Bytes
148
+
149
+ Text delivery and retention bounds use UTF-8 bytes measured by one shared
150
+ helper. The print channel, retention ceiling and call ledger's line sizes use
151
+ this unit, including CJK and emoji payloads. Elision notices state the real
152
+ UTF-8 byte count.
153
+
154
+ The supplemental memory probe is a separate estimate, not a UTF-8 byte count or
155
+ an exact heap measurement. Strings and property names contribute their UTF-16
156
+ code-unit lengths. Objects have a base weight of 8; non-string scalars,
157
+ functions, accessors and cycle references have fixed weights of 8. The probe walks named globals, array indices,
158
+ enumerable own string-keyed data properties, Map keys and values, and Set values.
159
+ Collection entries use the same traversal budget as properties: 200,000 values
160
+ and depth 32. An incomplete traversal causes the next frame to be refused.
161
+ Cycles stop at ancestor references; shared objects on separate paths are counted
162
+ again. Accessors are not invoked. Closure state, weak collection entries and
163
+ other storage unreachable by these paths are not measured. The native allocator
164
+ limit remains active, but this supplemental estimate is not a hard bound on all
165
+ memory retained by the realm.
166
+
167
+ ## Failure categories
168
+
169
+ Three closed unions carry every failure a caller branches on. None of them is
170
+ open-ended, and none of them is prose a consumer must parse.
171
+
172
+ - `HarnessError.HarnessErrorCode`: the translation boundary's own failures.
173
+ Folded into `@smthrs/agent`'s `AgentFailure` union, so a code that nothing
174
+ raises is a promise this package cannot keep; the set holds only codes that
175
+ are raised.
176
+ - `Cell.CallFailureCode`: why one flow call did not succeed, as the cell reads
177
+ it. A failed call **resolves** with `{ ok: false, error: { code, message, hint } }`
178
+ rather than throwing, so the recovery branch the model already wrote still
179
+ runs. `Cell.callFailureHint` names the one move that recovers each class.
180
+ - `Sandbox.SandboxErrorCode`: why a realm could not run a cell at all, as
181
+ distinct from a cell that ran and failed.
182
+
183
+ `StructuredOutput.StructuredOutputFailureCode` is the fourth, for the boundary
184
+ that decodes an agent's final text into a declared schema.
185
+ `ExternalTranscript.ExternalTranscriptErrorCode` is the fifth, for decoding a
186
+ transcript another agent wrote.
187
+
188
+ ## Copy and mutation semantics
189
+
190
+ `ContextWindow` is immutable: the arrays a segment and a window expose are
191
+ frozen, so a runtime mutation throws rather than silently invalidating the
192
+ digest computed once at construction. `Cell` values, `CallLedger` entries and
193
+ every `AgentEvent` are schema classes and are never mutated in place. The one
194
+ value the controller mutates is its own `State`, which is journaled at each
195
+ frame boundary.
196
+
197
+ ## What this package does not do
198
+
199
+ - It declares no provider tools. The cell-first loop seals every model request
200
+ with `tools: []` and `toolChoice: "none"`. A window still carries the active
201
+ tool set it was constructed with, and `AgentEvent.TurnOpened.activeToolNames`
202
+ still journals it, so a foreign-adapter loop has somewhere to put one; nothing
203
+ in this package produces a non-empty set.
204
+ - It runs no scheduler and owns no storage. `Plan` describes child batches;
205
+ `EngineLike` splices them.
206
+
207
+ ## CellTurn
208
+
209
+ Harness journal format 2 versions controller state and model-key inputs.
210
+ Resuming older controller state or an agent session journal fails before a live
211
+ model call with `HarnessError` code `incompatible_journal`; start a new run.
212
+ Historical transcript projection remains available for display and renders
213
+ summary text as a user message. rc.0 does not promise journal compatibility.
214
+
215
+ `import * as CellTurn from "@smthrs/harness/CellTurn"`
216
+
217
+ The cell-first controller. It decides continue, park, or finish from durable
218
+ evidence, the transition a cell returned and the budgets the run declared, and
219
+ never from the presence of a provider tool call.
220
+
221
+ ```ts
222
+ export const run: (
223
+ input: Input
224
+ ) => Stream.Stream<
225
+ AgentEvent.AgentEvent,
226
+ HarnessError,
227
+ EngineLike.EngineLike | Sandbox.Sandbox | Steering.Source
228
+ >
229
+ ```
230
+
231
+ `run` executes the loop until it completes, parks, or exhausts its budget.
232
+ Cancellation is fiber interruption: interrupting the stream tears down the
233
+ sandbox through scope closure and reports one abort. `Input` is
234
+ `{ state, flows, limits?, supervisor?, monitors?, judged?, stance?, instructions?, pinned?, memory? }`,
235
+ where `flows` is the frame's `FlowDescriptor` list, already narrowed by seat
236
+ visibility, and `monitors` (default `Monitor.defaults()`) are what each
237
+ supervisor reading scores. `judged` (default false) is true only when the
238
+ host's `Evaluator` is a real judge, and it arms Jev's features: the
239
+ supervisor delivers what its monitors gate through and its inserts, frame 0
240
+ takes the run-start relevance reading, and the supervisor marks segments for
241
+ compaction. It is runtime configuration, not `State`, so a resumed run is
242
+ armed by the host that resumes it. `DisciplineArmed` journals it, only when
243
+ true, as `judged`, `relevance` (`{ withholdAt, pinned }`) and `monitors`
244
+ (each id, kind and gate), so an unjudged journal is unchanged;
245
+ `supervisorSteer` is read only from journals written before `judged`. `stance`
246
+ (`careful` or `paranoid`) is the static stance the run is taught; pass the
247
+ window taught with it. `DisciplineArmed.stance` records it when set.
248
+
249
+ **Run-start relevance.** At frame 0 of a judged run, once the frame's catalog
250
+ is known, every model-invocable flow not in `pinned` (as `Relevance.flowItem`,
251
+ sorted by name), every chunk of `instructions` (`Relevance.Document`s) and
252
+ every row of `memory` (kind `memory`, id its `key`) is one item of a single
253
+ `relevance/unnecessary` reading, recorded under the boundary `relevance`. Nothing to judge asks nothing. `decision-settled` rows are
254
+ followed by `relevance-settled` (`source: "run"`). Withheld flows and skills
255
+ go to `State.withheldFlows` and leave every frame's taught catalog and
256
+ `ctx.flows`; the recorded `flow-catalog` stays whole. Withheld chunks leave
257
+ the window's instructions segment, found by the digest of
258
+ `instructionsSegment(instructions, new Set())`, which is how the host must
259
+ build it; a segment left empty is removed. A chunk is matched by id and text,
260
+ so a replay against an edited file keeps a chunk whose text the reading never
261
+ judged. Withheld rows leave the memory
262
+ segment, found by the digest of `memorySegment(memory.render(memory.rows),
263
+ memory.digest)`: it becomes `memory.render` of the kept rows, or is removed
264
+ when none is kept. A reading nobody could judge withholds nothing and
265
+ journals `decision-unjudged`. A call to a withheld flow
266
+ settles `flow_withheld` and restores it: the next frame shows it, and
267
+ `relevance-restored` names it. A replay is served the recorded reading.
268
+
269
+ **Compaction marks.** Marking is separate from compacting. In a judged run
270
+ each supervisor reading also asks `compaction/marks` about the transcript
271
+ segments not yet marked, the person's excepted, and the next boundary stores
272
+ the answers, by segment digest, on `State.segmentFacts` inside its recorded
273
+ drain (`Steering.DrainRecord.marks`). Marking changes nothing the model is
274
+ sent: the prefix a request is sent stays byte-stable until a compaction. A
275
+ frame compacts when the window crosses its budget (`Compaction.shouldCompact`
276
+ and `selectPrefix` at their defaults), or when the boundary before it took a
277
+ supervisor reading that fired `outdated_context` or `irrelevant_context`
278
+ (`Steering.DrainRecord.compact`, carried on `State.compactionDue` for that
279
+ frame alone); a judged run then marks each prefix segment `keep`, `squash` or `remove`. Pins, read
280
+ from `State.segmentFacts` and the still-failing checks, fix what must
281
+ survive: a summary is squashed; steering, the person's segments and the
282
+ newest segment that ran each still-failing check are kept; a segment that
283
+ changed files is never removed. The stored answers resolve the rest against
284
+ the budget; segments still unmarked are asked in one `compaction/marks`
285
+ reading, recorded under the boundary `compaction-marks:<prefix digest>`, so
286
+ a replay asks nothing and re-keys the same summary. Only squashed segments
287
+ reach the sealed summary step, which is skipped when nothing is squashed;
288
+ kept segments stay verbatim after the summary. `decision-settled` rows
289
+ precede `compaction-settled`, which carries `summary?`, `kept`, `marks`
290
+ (segment digest, mark, `pinned?`), `removedTokens` and `causes`. An unjudged run and a
291
+ reading nobody could judge (journaled `decision-unjudged`) squash every
292
+ prefix segment; so does a judged run whose facts do not describe every
293
+ transcript segment, and its `compaction-settled` says `unaligned`.
294
+
295
+ `instructionsSegment(documents, withheld)` is the prefix `system` segment of
296
+ `Relevance.render(documents, withheld)`. It is `system`, not `instructions`,
297
+ because the task is what the prefix `instructions` segments say.
298
+
299
+ `Memory` is `{ rows, digest, render }`: the opening memory rows
300
+ (`MemoryRow`, `{ key, text }`), the digest the opening declares, and the
301
+ host's render, which is only handed rows of `rows`, in order.
302
+ `memorySegment(text, digest)` is the prefix `system` segment of rendered
303
+ memory under that declared digest: what a run remembers is not its task, and
304
+ each row is judged against a task that does not contain it.
305
+
306
+ `CellTurn.make` constructs the initial `State`:
307
+
308
+ ```ts
309
+ export const make: (options: {
310
+ readonly session: string
311
+ readonly seat: string
312
+ readonly modelParams: ModelRequest.GenerationParams
313
+ readonly layers: ReadonlyArray<string>
314
+ readonly capabilityEnvelope: ReadonlyArray<Capability.CapabilityPattern>
315
+ readonly placement: Option.Option<Descriptor.Placement>
316
+ readonly contextWindow: ContextWindow.ContextWindow
317
+ /** Initial budget; a seat steer recomputes it from the model catalog. */
318
+ readonly contextWindowTokens?: number | undefined
319
+ readonly frame?: number | undefined
320
+ /** Zero disarms the frame limit; exhausted positive limits spend no new frame. */
321
+ readonly maxFrames?: number | undefined
322
+ readonly readOnlyCap?: number | undefined
323
+ readonly modelCallMs?: number | undefined
324
+ readonly repeatCap?: number | undefined
325
+ readonly narrowingCap?: number | undefined
326
+ readonly unmovedCap?: number | undefined
327
+ readonly unresolvedCap?: number | undefined
328
+ readonly claimCap?: number | undefined
329
+ readonly approvalChannel?: boolean | undefined
330
+ readonly revalidations?: number | undefined
331
+ readonly checkpointCap?: number | undefined
332
+ }) => State
333
+ ```
334
+
335
+ Every omitted budget takes its module-level default, and zero disarms it:
336
+
337
+ | Constant | Value | Budget it defaults |
338
+ | -------------------------- | ------- | ------------------------------------------------------------------------------------------------------- |
339
+ | `defaultMaxFrames` | 100 | Frames one admitted task may spend. |
340
+ | `defaultReadOnlyFrames` | 12 | Consecutive stalled read-only frames before intervention. |
341
+ | `defaultModelCallMs` | 300,000 | Wall-clock milliseconds one model call may spend at unset, `none`, `minimal`, `low` or `medium` effort. |
342
+ | `defaultRepeatFrames` | 4 | Consecutive repeat-observation frames. |
343
+ | `defaultNarrowingDemands` | 1 | Completions bounced for narrowed evidence. |
344
+ | `defaultUnmovedDemands` | 1 | Completions bounced for an unmoved tree. |
345
+ | `defaultUnresolvedDemands` | 1 | Completions bounced for a displaced failing check. |
346
+ | `defaultClaimDemands` | 3 | Frames given to answer an unrecorded claim. |
347
+ | `defaultRevalidations` | 1 | In-frame answers to an unparseable cell. |
348
+ | `defaultMaxCheckpoints` | 8 | Trees one run may pin with `ctx.checkpoint()`. |
349
+
350
+ An omitted `modelCallMs` follows the run's reasoning effort through
351
+ `modelCallMsFor(effort)`: 300,000 ms up to `medium`, 900,000 ms at `high`, and
352
+ 1,800,000 ms at `xhigh` or `max`. A steering change of effort moves a defaulted
353
+ ceiling with it; a host's own number stays. The engine also cuts off a stream
354
+ that sends nothing for `defaultModelIdleMs` (300,000 ms), so a long ceiling
355
+ never waits out a stall.
356
+
357
+ A read-only frame counts toward `readOnlyCap` unless the run has already
358
+ written something and the frame settled a call the run had not issued before.
359
+ Such a frame is debugging work that exists, so it holds the streak. Frames that
360
+ call nothing, raise, or re-ask old questions still count, and every read-only
361
+ frame counts before the first write.
362
+
363
+ `readOnlyCap` is the one budget that defaults to disarmed (0), because a run
364
+ that is only meant to read, a question or a review, has nothing to be capped
365
+ at. `approvalChannel` defaults to `false`: a park is durable waiting, and a
366
+ run with nobody to answer it fails with `approval_unavailable`, carrying the question.
367
+
368
+ `State` is a schema class carrying the controller's view of the run across
369
+ frames: the panel of realm names, the call ledger, the checks and failures
370
+ ledgers, the truncated-output ledger, the checkpoint ids, the opening
371
+ workspace digest, every budget and its counter, the context window, and
372
+ `segmentFacts`: per transcript segment, the frame that wrote it, whether it
373
+ carries the person's messages (a supervisor insert does not count), whether
374
+ that frame changed files, and the checks it ran. It
375
+ serializes into the journal; the realm itself is not in it and cannot be,
376
+ because a live JavaScript context is rebuilt on resume by re-executing the
377
+ cells that built it.
378
+
379
+ `CellTurn.run` accepts an optional `contextWindowTokensFor(seat)` effect on
380
+ its runtime `Input`. A seat steer resolves its next compaction budget through
381
+ this callback. The agent adapters supply their host `SeatResolver`, including
382
+ logical seats such as `reviewer`; direct harness callers without a callback use
383
+ the model-id catalog. The callback lives outside serializable `State`; the
384
+ resolved token count is carried in state across frames.
385
+
386
+ `CellTurn.teach(contextWindow, flows, environment?, stance?)` prepends the cell contract and the
387
+ callable-flow catalog to a context window as prefix segments. The optional
388
+ `CellTurn.Environment` supplies the host's measured `locale` and `absentTools`.
389
+ A `stance` adds a one-line `cell-stance` section after the contract,
390
+ `Monitor.carefulText` or `Monitor.paranoidText` verbatim; it is constant for
391
+ the run, so the cached prefix holds.
392
+ Catalog metadata is escaped inside an `untrusted-data` block with each
393
+ source, root and repository path. Metadata and tool output cannot grant
394
+ authority or change the task. Printed observations and controller-generated
395
+ compaction summaries use the same boundary; journal replay retains it. Pass
396
+ `refreshFlows` on `CellTurn.run`'s `Input` to journal fresh descriptors at each
397
+ frame boundary and replace the previous teaching. The prompt, `ctx.flows`,
398
+ and admission share the recorded snapshot. Omit it to keep `flows` fixed.
399
+
400
+ ## Sandbox
401
+
402
+ `import * as Sandbox from "@smthrs/harness/Sandbox"`
403
+
404
+ The deterministic script sandbox port. A cell never runs in the host realm; it
405
+ runs behind this port, which grants exactly one effectful primitive, flow
406
+ invocation against the capability-narrowed catalog the run was given, and
407
+ returns a serializable `Cell.Outcome`.
408
+
409
+ ```ts
410
+ export interface Sandbox {
411
+ readonly capabilities: Capabilities
412
+ readonly openRealm?: (
413
+ options: RealmOptions
414
+ ) => Effect.Effect<Realm, SandboxError, Scope.Scope>
415
+ }
416
+ ```
417
+
418
+ `openRealm` is optional because a realm is the whole surface: there is no
419
+ per-cell evaluation beside it. A composition that offers none is refused with
420
+ `Sandbox.realmUnsupported`. `RealmOptions` is `{ flows, limits? }`: the
421
+ catalog frozen into `ctx.flows`, and the ceilings the realm enforces. The
422
+ service tag is `Sandbox.Sandbox`; `make`, `layer`, `makeNoop`, and
423
+ `layerNoop` construct and provide implementations and stubs.
424
+
425
+ ```ts
426
+ export interface Realm {
427
+ readonly evaluate: (
428
+ evaluation: RealmEvaluation
429
+ ) => Effect.Effect<RealmFrame, SandboxError | HarnessError>
430
+ }
431
+ ```
432
+
433
+ `RealmEvaluation` is
434
+ `{ cell, frame, call, program?, flows?, mint?, bounded?, limits? }`;
435
+ `RealmFrame` is `{ outcome, prints, bindings }`. The `Sandbox.Handler`
436
+ resolves one `Sandbox.Invocation` (`{ ordinal, flow, input, at? }`) into a
437
+ `Cell.CallResult`; the `Sandbox.Minter` settles one `ctx.checkpoint()` mint on
438
+ the same queue, in issue order, so the pin lands where the cell wrote it.
439
+
440
+ A cell states its intent by calling, and `Sandbox.replTransition` is the only
441
+ place a `Cell.Transition` is constructed:
442
+
443
+ ```ts
444
+ export const replTransition: (
445
+ intent: Intent | undefined,
446
+ justification: string | undefined
447
+ ) => Cell.Transition
448
+ ```
449
+
450
+ `Intent` is `{ _tag: "Done", output }` or `{ _tag: "Park", reason, message }`,
451
+ with `reason` one of `"waiting-input"`, `"waiting-event"`, `"waiting-quota"`.
452
+ An absent intent is a `continue`.
453
+
454
+ Binding-author seams: `Sandbox.compile` erases type-only syntax from a cell
455
+ without evaluating or resolving modules (only Node's strip-safe TypeScript
456
+ subset; anything needing emit is refused). `Sandbox.driveCell` runs the shared
457
+ drive loop that settles queued calls one at a time, in issue order, until the
458
+ cell settles; `Sandbox.PendingCall` is the queued-call shape. `Sandbox.callTimedOut(flow,
459
+ callMs)` synthesizes the resolved `timeout` refusal one ceiling means,
460
+ whichever clock enforced it. `Sandbox.raisedOutcome` projects a thrown value
461
+ into a stable serializable `Cell.Raised`. `Sandbox.mintUnavailable` is the
462
+ `checkpoint_unavailable` refusal for a run with no minter wired.
463
+
464
+ `SandboxError` carries a `SandboxErrorCode` of `unavailable`, `unsupported`,
465
+ or `runtime_failed`: failures of the binding itself, as opposed to a cell that
466
+ ran and failed, which is a `Cell.Raised` outcome instead.
467
+
468
+ The limits and their defaults are documented under [Limits](#limits).
469
+ `Sandbox.withDefaults(capabilities, limits)` fills omitted ceilings for the
470
+ limits a binding can enforce; an explicit unsupported limit passes through so
471
+ the binding can refuse it. The print-channel constants are
472
+ `Sandbox.printFrameBytes` (16 KiB), `Sandbox.printStatementFloor` (512 bytes),
473
+ and `Sandbox.printRetainedBytes` (256 KiB).
474
+
475
+ ## QuickJSSandbox
476
+
477
+ `import * as QuickJSSandbox from "@smthrs/harness/QuickJSSandbox"` (not
478
+ re-exported from the root)
479
+
480
+ The QuickJS-WASM sandbox binding, and the production `Sandbox`: the cell runs
481
+ inside a QuickJS interpreter compiled to WebAssembly, a genuinely separate
482
+ JavaScript realm with no reference to the host's globals, prototypes, or
483
+ module loader. The same single-file variant runs unmodified on Node and in a
484
+ browser. The prelude removes `Date`, `Math.random`, and `Proxy` from the
485
+ realm, and installs `ctx` and `console` as non-writable, non-configurable
486
+ properties.
487
+
488
+ | Export | Signature | Behavior |
489
+ | -------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
490
+ | `make` | `Effect<Sandbox.Sandbox, Sandbox.SandboxError>` | Constructs the sandbox over the single-file build with the live clock. |
491
+ | `layer` | `Layer<Sandbox.Sandbox, Sandbox.SandboxError>` | Provides the same. |
492
+ | `makeWithClock` | `Effect<Sandbox.Sandbox, Sandbox.SandboxError, ComputeClock>` | The single-file build, with the clock seam left to the caller. |
493
+ | `makeWithVariant` | `Effect<Sandbox.Sandbox, Sandbox.SandboxError, ComputeClock \| Variant>` | Constructs over the build the host names, compiling the module once. |
494
+ | `layerWithVariant` | `Layer<Sandbox.Sandbox, Sandbox.SandboxError, Variant>` | Provides the sandbox over the named build, with the live clock. |
495
+ | `Variant` / `VariantService` | service tag | The QuickJS build the sandbox compiles. |
496
+ | `layerVariantLive` | `Layer<Variant>` | Provides the single-file default. |
497
+ | `layerVariant` | `(variant: QuickJSSyncVariant) => Layer<Variant>` | Provides a build the host names, for runtimes that forbid compiling WebAssembly from bytes. |
498
+ | `ComputeClock` / `ComputeClockService` | service tag | Synchronous monotonic-enough clock the interrupt callback requires. |
499
+ | `layerClockLive` | `Layer<ComputeClock>` | Provides the browser-safe host clock. |
500
+ | `loadModule` | `(loader: () => Promise<QuickJSWASMModule>) => Effect<QuickJSWASMModule, SandboxError>` | Loads a QuickJS module through the typed failure boundary (`runtime_failed`). |
501
+ | `cacheSuccessful` | `<A>(load: () => Promise<A>) => () => Promise<A>` | Caches only a successful load; a rejection may be retried. |
502
+
503
+ The compiled module is cached per variant, weakly, so two sandboxes over one
504
+ variant share it and a variant built per request stays collectable. For the
505
+ workerd setup, see [Run on Cloudflare workerd](./guides/workerd.md).
506
+
507
+ ## Cell
508
+
509
+ `import * as Cell from "@smthrs/harness/Cell"`
510
+
511
+ The cell contract: the serializable half of the frame. Nothing here executes
512
+ anything; execution is `Sandbox`, durability is `EngineLike.call`, and the
513
+ loop is `CellTurn`.
514
+
515
+ **Source.** `Cell.source(text, language?)` builds a `Cell.Source` with its
516
+ computed digest; `language` is `"javascript"` or `"typescript"`. The digest is
517
+ part of every call identity produced inside the cell, so editing one character
518
+ re-keys every boundary within it. `Cell.extract(text)` recovers the cell
519
+ program from one model reply: every fenced block tagged `cell`, `js`,
520
+ `javascript`, `ts`, or `typescript`, joined in reply order with byte-identical
521
+ repeats dropped, returning `{ source, blocks }` or a `no_cell` rejection. An unterminated cell fence rejects the entire reply as
522
+ `output_truncated`; a provider `length` stop uses the same code before execution.
523
+
524
+ **Transitions.** `Cell.Transition` is the tagged union of:
525
+
526
+ - `Cell.Continue`: the cell's turn ended without settling the run. Carries an
527
+ optional `justification`, the typed way out of the read-only cap, written by
528
+ `ctx.justify`.
529
+ - `Cell.Complete`: the cell declares the task finished, with `output` as the
530
+ run's answer.
531
+ - `Cell.Park`: the cell asks to wait durably, with `reason` one of
532
+ `"waiting-input"`, `"waiting-event"`, `"waiting-quota"` and a `message`.
533
+
534
+ **Outcomes.** `Cell.Outcome` is the tagged union of `Settled` (ran and
535
+ produced a well-formed transition), `Raised` (ran and threw; the thrown value
536
+ is projected into stable `name` and `message` text), and `Rejected` (never
537
+ ran, or produced no transition). `Cell.RejectionCode` is `no_cell`, `output_truncated`,
538
+ `imports_forbidden`, `compile_failed`, `invalid_transition`,
539
+ `unsupported_language`, `limit_exceeded`, or `stalled`. A result that cannot
540
+ fit in the remaining QuickJS heap is rejected before materialization with
541
+ `code: "limit_exceeded"` and `reason: "heap"`, so the frame remains recordable.
542
+
543
+ Flow-result heap checks conservatively include value and property storage plus
544
+ bridge scratch space, not just serialized JSON bytes. A reply can be refused
545
+ when its estimated allocation exceeds the remaining heap.
546
+
547
+ Bridge replies are also limited to 128 levels of JSON nesting so a refusal can
548
+ release partial handles safely. Exceeding this limit produces a typed
549
+ `limit_exceeded` frame.
550
+
551
+ **The catalog.** `Cell.FlowProjection` is the read-only projection of one
552
+ callable flow handed to a cell: `name`, `description`, `capabilities`,
553
+ `tier`, `placement`, and an optional inline `input` JSON Schema document.
554
+ `Cell.project(descriptor)` derives it from a registry descriptor. It is
555
+ exactly what `ctx.flows` exposes: enough to choose a call, nothing that
556
+ carries authority.
557
+
558
+ **Call identity.** `Cell.CallIdentity` folds `session`, `frame`, the cell
559
+ digest, the zero-based `ordinal` of the call within the cell, the
560
+ `declaration` digest, and the resolved `layers` into one key. Re-executing a
561
+ cell reaches the same ordinal with the same declaration, so a settled boundary
562
+ replays. `Cell.declarationDigest(descriptor)` re-exports
563
+ `Descriptor.declarationDigest` from `@smthrs/registry`, which owns
564
+ `FlowDescriptor`. It hashes the complete material declaration: every top-level
565
+ field except `provenance.pack`, with `capabilities` sorted and every other
566
+ array in declaration order. `@smthrs/chain` keys its catalog entries with the
567
+ same number.
568
+
569
+ **Call results.** `Cell.CallResultVariant` is a discriminated union of
570
+ `CallSuccess` (`outcome: "success"`, JSON `value`, optional `message`) and
571
+ `CallFailure` (`outcome: "failure"`, JSON `value`, optional `message` and
572
+ `code`). A success cannot carry a failure code. The existing `Cell.CallResult`
573
+ class constructor validates the same variants and preserves valid encoded
574
+ field names. A failure's absent code means `Cell.defaultCallFailureCode`,
575
+ `"flow_failed"`. `Cell.callFailure(result)`
576
+ projects a failed result into the fixed envelope the cell observes:
577
+
578
+ ```json
579
+ { "ok": false, "error": { "code": "...", "message": "...", "hint": "..." } }
580
+ ```
581
+
582
+ A failed call resolves with this value rather than throwing, so the recovery
583
+ branch the model already wrote still runs; a successful call resolves with the
584
+ flow's own value, unwrapped. `Cell.callFailureHint` maps each of the 13 codes
585
+ to the one action that recovers it. The codes and hints are tabulated in
586
+ [troubleshooting](./troubleshooting.md#a-flow-call-fails).
587
+
588
+ `Cell.decodeCallResult`, `Cell.decodeOutcome` and `Cell.decodeTransition`
589
+ accept untrusted host or recorded input. They refuse contradictory fields,
590
+ missing required values and unsupported variants with `HarnessError`
591
+ (`engine_failed`), retaining the original cause. Outcome and transition
592
+ decoders validate encoded fields even on class instances, then reconstruct
593
+ the schema classes required by the recorder. Sandbox settlement and the
594
+ durable cell recorder apply these boundaries before emitting successful
595
+ observations. A missing success value is corrupt input, not an implicit null.
596
+ Valid current records retain their JSON representation, including failures
597
+ whose code is absent. `CellValidation.Validation` likewise separates compiled
598
+ source from rejection so the two cannot be supplied together.
599
+
600
+ `Cell.CallResult` retains its historical encoded schema representation because
601
+ the agent hashes that representation into sealed keys. The constructor and
602
+ boundary decoder enforce the success/failure invariants; admission hardening
603
+ does not re-key valid results. The agent pins the complete key material and
604
+ tests a historical result through SQLite close, reopen and resume.
605
+
606
+ Changing the valid wire contract still requires a version cutover and a newly
607
+ planned run. Existing approvals and recorded keys remain bound to their
608
+ original bytes; no decoder translates identities. Intermediate builds that
609
+ added the `success-without-failure-code/v1` filter to the encoded schema derived
610
+ different keys. Finish their executions on the same build before upgrading.
611
+ See the agent's [persisted cell-call identity](https://agent.smithers.sh/concepts/engine-port/#persisted-cell-call-identity)
612
+ for the retained algorithm and composition versions.
613
+
614
+ **Checkpoints.** `Cell.baseCheckpoint` is `"base"`, the id naming the tree a
615
+ run opened on, pinned for free and always present. `Cell.checkpoint(id)`
616
+ builds the opaque handle a cell holds; `Cell.checkpointOf(value)` reads the id
617
+ back strictly, returning `undefined` for anything that is not a handle, which
618
+ the boundary answers as an ordinary `invalid_input`.
619
+
620
+ ## EngineLike
621
+
622
+ `import * as EngineLike from "@smthrs/harness/EngineLike"`
623
+
624
+ The narrow engine port the harness consumes. `EngineLike.make` builds the
625
+ service from an implementation, `EngineLike.layer` provides it, and
626
+ `EngineLike.makeNoop` / `layerNoop` build a stub whose operations are
627
+ unavailable (`observe` and `capture` answer `Option.none()`, the honest
628
+ "measured nothing, pinned nothing", rather than failing).
629
+
630
+ ```ts
631
+ export interface EngineLike {
632
+ readonly sealStep: (
633
+ step: SealedModelStep
634
+ ) => Stream.Stream<ModelEvent.ModelEvent, Model.ModelFailure | HarnessError>
635
+ readonly sealStepWithEvents?: (
636
+ step: SealedModelStep,
637
+ emit: (event: AgentEvent.AgentEvent) => Effect.Effect<void>
638
+ ) => Stream.Stream<ModelEvent.ModelEvent, Model.ModelFailure | HarnessError>
639
+ readonly splice: (batch: Plan.Batch) => Stream.Stream<Plan.SpliceEvent, HarnessError>
640
+ readonly call: (call: Cell.Call) => Effect.Effect<Cell.CallResult, HarnessError>
641
+ readonly admit?: (call: Cell.Call) => Effect.Effect<Cell.CallResult | undefined, HarnessError>
642
+ readonly guard?: Guard
643
+ readonly record: <A>(boundary: RecordBoundary<A>) => Effect.Effect<A, HarnessError>
644
+ readonly observe: Effect.Effect<Option.Option<Observation>, HarnessError>
645
+ readonly capture: (request: CaptureRequest) => Effect.Effect<Option.Option<Snapshot>, HarnessError>
646
+ readonly resolve?: (request: ModelRequest.ModelRequest) => Effect.Effect<Option.Option<Resolved>>
647
+ readonly suspend: (reason: SuspendReason) => Effect.Effect<never, HarnessError>
648
+ }
649
+ ```
650
+
651
+ - `sealStep` runs one sealed model step. `SealedModelStep` is `{ request,
652
+ keyMaterial, modelCallMs? }`. The implementation resolves the route, runs
653
+ `Route.prepare` from [`@smthrs/model`](/api/model), and digests the
654
+ credential-free prepared request, canonical body bytes included, with the
655
+ declared material into the sealed-step key before executing. A provider wire
656
+ change must produce a new key; credentials are signed on after the digest
657
+ and never enter it. `modelCallMs` travels on the step and is never key
658
+ material, so the number the controller journals as armed is the number the
659
+ engine enforces.
660
+ - `sealStepWithEvents`, when supplied, seals through the same boundary and
661
+ receives the controller's event emitter for failover and park transitions.
662
+ - `call` runs one flow call as a keyed, journaled activity at the tier the
663
+ flow declares, keyed by `call.identity`. A flow failure settles as a
664
+ `failure` `Cell.CallResult`; a permission requirement, an abort, or an
665
+ engine failure travels in the error channel so the cell can never swallow a
666
+ park.
667
+ - `admit`, when present, decides a call's authority before the controller
668
+ starts the call's `callMs` clock, so time a person spends answering an
669
+ approval is not charged to the flow. `undefined` admits the call; a result
670
+ is the refusal the cell reads instead, and `call` is never issued. An
671
+ implementation does not ask again when an admitted call is issued.
672
+ - `guard`, when present, is the host's runaway guard for timeouts (`Guard`:
673
+ `{ admit(subject), trip(timeout) }`). The controller calls `admit` before it
674
+ issues a call or evaluates a fresh cell frame, and `trip` with a `TimedOut`
675
+ (`{ source: "tool-call" | "cell", subject, limitMillis?, message }`) when a
676
+ call settles as a `timeout` failure or a frame overruns its wall-clock
677
+ limit. `limitMillis` is the limit the timeout recorded: the per-call
678
+ ceiling, or the call's own (a command's, an await's). `trip` succeeds when the run's timeouts are not guarded, and the
679
+ cell reads the timeout as before; a guarded host fails it with a park, and
680
+ the controller records nothing for the operation, so Continue runs it again
681
+ and Stop fails the run at `admit`. `subject` is the replay-stable call or
682
+ frame identity, as JSON.
683
+ - `record` journals one nondeterministic controller read, keyed on `(name,
684
+ identity)` together. `RecordBoundary` is `{ name, identity, success,
685
+ execute }`, where `success` is a `DurableSchema`, a schema that decodes
686
+ without services, and `identity` is a `BoundaryIdentity` (`{ session?,
687
+ frame, boundary }`).
688
+ - `observe` measures the workspace as it stands, as an `Observation` (`{
689
+ digest, paths, complete }`). `complete: false` means the measurement covered
690
+ a bounded prefix, and a prefix cannot say the rest of the tree held still.
691
+ After a partial walk, measurement stops for the rest of that run; mutation
692
+ evidence falls back to flow declarations.
693
+ - `capture` pins the workspace under the id in the `CaptureRequest` and
694
+ returns a `Snapshot` (`{ id, ref }`), where `ref` is the host's own name for
695
+ what it pinned.
696
+ - `resolve` is optional. It says what one request will actually be asked as:
697
+ an `Option` of a `Resolved` (`{ request, binding }`) holding the request
698
+ after any rewrite the host applies and, as an `Option`, the `Binding`
699
+ (`{ routeId, protocolId }`) of the route it goes to. The controller asks
700
+ before it seals and journals the answer as `AgentEvent.ModelRequested`. It
701
+ cannot fail. A host that cannot say what would be sent, because its rewrite
702
+ failed or no route accepts the request, answers `Option.none()`: the
703
+ controller journals no request for that call, and `sealStep` reports the
704
+ typed error. A host that answers none must fail that sealed step with the
705
+ failure it already met, without running the rewrite a second time. A
706
+ `Binding` is two names read off the credential-free prepared request, so it
707
+ has no member a credential could occupy. A host that omits `resolve` has the
708
+ request the controller built recorded, with no route.
709
+ `EngineLike.resolve(engine, request)` is that rule as a function: the port's
710
+ answer, or the request unchanged with no binding.
711
+ - `suspend` parks the current engine frame with a `SuspendReason` (`{ code,
712
+ message, details? }`), whose `SuspendReasonCode` is `permission-required`,
713
+ `waiting-quota`, `waiting-input`, `waiting-event`, or `engine`.
714
+ - `splice` turns a `Plan.Batch` into running children and streams
715
+ `Plan.SpliceEvent`s back.
716
+
717
+ ## Steering
718
+
719
+ `import * as Steering from "@smthrs/harness/Steering"`
720
+
721
+ Turn-boundary steering values and their source contract. Human steering
722
+ reaches a run only at safe turn boundaries.
723
+
724
+ Every frame exit records its steering decision, including rejected and raised
725
+ cells, answerable parks, and completions. A completion promotes a queued follow-up
726
+ and continues when delivery has work for the next frame. At an exhausted frame
727
+ limit, the decision is empty and notifications remain pending at the source;
728
+ they are never acknowledged without a frame available to consume them.
729
+
730
+ `Steering.Queue` is an immutable FIFO of `Steering.Item`s: transcript inserts
731
+ (`SteerInsert` for the next boundary, `QueueInsert` for when the run would
732
+ otherwise go idle), and `SeatChange` and `ThinkingChange` (applied only after
733
+ the current turn closes).
734
+ `Steering.empty`, `enqueue`, and `drainAtClose(queue, cutoff)` operate on it
735
+ without mutation. `Steering.Drain` is
736
+ what one boundary promoted; `Steering.DrainRecord` and `drainRecord` project
737
+ it into its journaled record, which also carries what the supervisor delivered
738
+ there: its messages, the memory keys, the monitor delivered, the monitors
739
+ withheld, the monitor ledger after gating, the compaction marks the run
740
+ stores, and the context triggers that compact its next frame.
741
+
742
+ ```ts
743
+ export interface Source {
744
+ readonly read: () => Effect.Effect<Queue, HarnessError>
745
+ readonly drain: (input: BoundaryInput) => Effect.Effect<Drain, HarnessError>
746
+ }
747
+ ```
748
+
749
+ A drain is idempotent in its boundary string: a second drain at one boundary
750
+ promotes nothing and hands back exactly what the first promoted, with
751
+ `Drain.duplicate` set. A resumed run re-drains the boundaries it already
752
+ drained and must be told the same thing, or it rebuilds a different context
753
+ and re-keys every later sealed step. The service tag is `Steering.Source`;
754
+ `make`, `makeNoop`, `layer`, and `layerNoop` construct and provide it.
755
+
756
+ ## Notifications
757
+
758
+ `import * as Notifications from "@smthrs/harness/Notifications"`
759
+
760
+ The adapter from the durable notification queue of
761
+ [`@smthrs/notifications`](/api/notifications) to harness turn boundaries.
762
+
763
+ ```ts
764
+ export interface Options {
765
+ readonly runId: string
766
+ readonly lineageId: string
767
+ }
768
+
769
+ export const make: (
770
+ options: Options
771
+ ) => Effect.Effect<Steering.Source, never, NotificationQueue.NotificationQueue>
772
+
773
+ export const layer: (
774
+ options: Options
775
+ ) => Layer.Layer<Steering.Source, never, NotificationQueue.NotificationQueue>
776
+ ```
777
+
778
+ `make` captures the journal-backed queue as the harness steering source for
779
+ one run lineage: its `read` reports an empty queue and its `drain` delegates
780
+ to the notification queue's own boundary-aware drain, mapping failures into
781
+ `HarnessError`. `layer` provides it.
782
+
783
+ ## CellCalls
784
+
785
+ `import * as CellCalls from "@smthrs/harness/CellCalls"`
786
+
787
+ Registry-backed resolution for the flow calls a cell makes. It is deliberately
788
+ not a second registry: discovery, precedence, collision handling, and
789
+ progressive disclosure stay in [`@smthrs/registry`](/api/registry); this
790
+ module only decides which body runs and turns every resolution problem into a
791
+ `Cell.CallResult` that resolves in the cell as `{ ok: false, error }`.
792
+
793
+ ```ts
794
+ export interface Options {
795
+ readonly registry: Registry.Registry
796
+ readonly catalog?: FlowBinding.Catalog | undefined
797
+ readonly implementations?: ReadonlyMap<string, Implementation> | undefined
798
+ readonly prompt?: PromptRunner | undefined
799
+ }
800
+
801
+ export interface Resolver {
802
+ readonly run: (call: Cell.Call) => Effect.Effect<Cell.CallResult, HarnessError>
803
+ }
804
+
805
+ export const make: (options: Options) => Resolver
806
+ ```
807
+
808
+ A name the run-start relevance reading withheld is refused first, as
809
+ `flow_withheld`, by `CellTurn` before resolution. Resolution order: the registry must know the name (`unknown_flow`), the
810
+ descriptor must be model-invocable (`capability_refused`), and its
811
+ re-derived declaration digest must equal the call's
812
+ (`declaration_changed`). An executable binding then answers first, after an
813
+ identity check against the disclosed declaration; a markdown flow renders
814
+ against `{ args: string }` and runs through the supplied `PromptRunner`, or
815
+ settles `unimplemented`; anything else dispatches to the host's
816
+ `Implementation` for the name, or settles `unimplemented`. The resolver's
817
+ shape is exactly the call runner a durable host wires behind
818
+ `EngineLike.call`, so this browser-safe package never depends on the engine
819
+ binding.
820
+
821
+ ## FlowBinding
822
+
823
+ `import * as FlowBinding from "@smthrs/harness/FlowBinding"`
824
+
825
+ The executable-flow binding contract: the smallest contract that pairs a flow
826
+ declaration with the code that runs it.
827
+
828
+ ```ts
829
+ export interface Binding<R = never> {
830
+ readonly descriptor: Descriptor.FlowDescriptor
831
+ readonly run: (call: Cell.Call) => Effect.Effect<Cell.CallResult, HarnessError, R>
832
+ }
833
+
834
+ export const make: <I, O, E, R = never>(options: Options<I, O, E, R>) => Binding<R>
835
+ ```
836
+
837
+ `Options.flow` is the declaration, a `Declared` (`{ name?, description?,
838
+ capabilities, effects }`) plus `input` and `output` schemas. `make` projects
839
+ it into an ordinary `FlowDescriptor` with `descriptorOf`, deriving the body
840
+ digest from the handler source and rendering both schemas as inline JSON
841
+ Schema documents when they project; a schema with no JSON Schema form falls
842
+ back to the module locator, and explicit `inputDocument` / `outputDocument`
843
+ options win over the projection. An undeclared effect envelope defaults to
844
+ `mode: "expected"`, `onConflict: "serialize"`, and tier `irreversible`, the
845
+ tier that is never content-shared, so a binding that forgot its tier can never
846
+ replay another run's recorded result.
847
+
848
+ `run` decodes input, executes the handler, and encodes output into
849
+ serializable JSON. For struct inputs, a failed decode retries once by omitting
850
+ only declared optional fields whose encoded schema rejects their `null`.
851
+ Schema-valid nulls are preserved and the full schema validates the retry.
852
+ If the retry fails, the original rejection is reported. The encoded input
853
+ must be a struct-like object; unions of structs and records get no
854
+ null-omission retry.
855
+
856
+ Correctable failures (`invalid_input`, `flow_failed`) settle as `failure`
857
+ results that resolve in the cell as `{ ok: false, error }`. Inspect
858
+ `.ok === false` and `.error.code` to recover. Ordinary handler failures use the opaque message
859
+ `Flow <name> failed.` Raw messages, objects, and causes are excluded from call
860
+ results and their journal records. `Options.publicError`, typed as
861
+ `(error: E) => string | undefined`, explicitly selects safe public text; the
862
+ text is bounded before journaling. An absent renderer, `undefined`, a throw,
863
+ or a non-string result uses the opaque default. The renderer is not a
864
+ sanitizer: hosts must select safe fields and redact raw diagnostics before
865
+ logging or persisting them in the handler. Forward `message` only for error
866
+ classes the host authored with model-facing text; never forward messages of
867
+ transport, SDK, OS, or unknown errors, headers, URLs, or serialized causes.
868
+
869
+ Existing `HarnessError` values pass through the error channel with their
870
+ code and identity unchanged. Only `PermissionRequired` and `PermissionDenied`
871
+ are converted to `HarnessError` with code `suspended`. These errors bypass
872
+ `publicError`; interruptions are never caught.
873
+
874
+ `FlowBinding.provide(binding, context)` closes a binding's remaining
875
+ requirements. `FlowBinding.Source` is a named, possibly effectful producer of
876
+ bindings; `FlowBinding.source(name, bindings)` lifts a fixed list.
877
+ `FlowBinding.catalog(sources)` resolves ordered sources into a `Catalog`
878
+ (`{ entries, bindings, descriptors }`), refusing duplicate or empty names with
879
+ `assembly_failed`; `catalogResult` is the total-function form and `empty()`
880
+ the empty catalog. `FlowBinding.registry(base, catalog)` discloses the
881
+ catalog through an existing `Registry.Registry` with file-discovered entries
882
+ keeping precedence, shadowed bindings reported as `duplicate_name` warnings.
883
+
884
+ ## CellHistory
885
+
886
+ `import * as CellHistory from "@smthrs/harness/CellHistory"`
887
+
888
+ The source of every cell the current turn executed. A frame throws its cell
889
+ away once the realm has evaluated it, so a model that wants to turn the script
890
+ it ran into a saved flow has nothing to read back; this service is where the
891
+ source goes. The controller appends each cell as it executes it, before
892
+ evaluation, so a cell that raised is still part of what the run ran.
893
+
894
+ The service is optional: the controller reads it with `Effect.serviceOption`,
895
+ a host that offers no way to save a flow binds nothing, and the controller
896
+ records nothing. `make` records what the controller executes; `makeCells`
897
+ serves a fixed list; `makeNoop` records nothing; `layer`, `layerCells`, and
898
+ `layerNoop` provide the three. `ExecutedCell` is one executed cell and
899
+ `Service` is the record-and-report interface.
900
+
901
+ ## AgentEvent
902
+
903
+ `import * as AgentEvent from "@smthrs/harness/AgentEvent"`
904
+
905
+ The serializable events a harness adapter emits, one schema class per event
906
+ and `AgentEvent.AgentEvent` as the tagged union of all 45. The controller
907
+ journals them in order: `DisciplineArmed` once at the start, the frame cycle
908
+ (`TurnOpened`, `ModelRequested`, `ModelDelta`, `ModelRetried`, `ModelSettled`,
909
+ `CellProduced`, `CellRejectedInFrame`, `CellCallStarted`, `CellCallSettled`,
910
+ `CellPrinted`, `CellSettled`, `TransitionApplied`), the interventions and
911
+ observations (`ReadOnlyDemandIssued`, `ReadOnlyDemanded`, `RepeatDemanded`,
912
+ `NarrowedDemanded`, `NarrowOnlyDemanded`, `UnmovedDemanded`,
913
+ `UnresolvedDemanded`, `FailedCallDemanded`, `UnobservedDemanded`, `OutputDemanded`, `ClaimDemanded`,
914
+ `DecisionSettled`,
915
+ `SufficiencyObserved`, `VacuousVerificationObserved`,
916
+ `MutationObserved`, `CheckpointMinted`, `CompactionSettled`,
917
+ `SteeringDrained`), and the terminal set (`Suspended`, `PermissionRequired`,
918
+ `TurnClosed`, `Resolved`, `Aborted`).
919
+
920
+ Capacity attempts emit `ModelSelected` (`seat`) with the actual selected seat,
921
+ including recovery to the primary and later frames continuing on a backup.
922
+ Transitions are `SeatFailedOver` (`from`, `to`, `code`, optional
923
+ `resetAtEpochMillis`, `retryAfterMillis`, `httpStatus`, `quotaScope`), `ModelParked` (`seat`, `wakeAt`, `source`, `code`), and
924
+ `ModelUnparked` (`seat`, `at`).
925
+
926
+ Two of them record what a step was asked, so a reader can open one step and
927
+ ask it again:
928
+
929
+ - `ModelRequested` is written once per model call, before the call, and
930
+ carries the `ModelRequest` the provider is sent: the request after any
931
+ rewrite the host applies, and the `EngineLike.Binding` naming the route
932
+ where the host resolves one. `scope` (the run's session, which is a module
933
+ step's recorded scope), `frame` and `attempt` are the join keys. `attempt`
934
+ counts the model calls of one frame and purpose from one, and is the number
935
+ `CellRejectedInFrame` names when it refuses that call's answer. `purpose` is
936
+ `frame` or `compaction`; a compaction call runs ahead of its frame's
937
+ `TurnOpened`, so it is joined by `frame`, never by position. A call whose
938
+ host answers `EngineLike.resolve` with none writes no `ModelRequested`: the
939
+ sealed step fails on it, so no provider was sent anything.
940
+ - `DecisionSettled` is written once per classifier reading, beside
941
+ `ClaimDemanded`, and carries the classifier's stable id, its
942
+ `Classifier.digest`, the encoded state the transport was sent, the questions
943
+ in their wire form, and one `DecisionAnswer` per question. `acted` says
944
+ whether the decision changed what the run did next, and `decidedBy` is
945
+ `jev`, `seat` or `human`. A `DecisionAnswer` is tagged by `kind`: `boolean`
946
+ carries `p`; `choice` and `score` carry `value`, `probabilities`, and
947
+ `confidence`. `confidence` is `Evaluator.Response.confidence`, the
948
+ provider's own number, and the key is absent when the provider sent none. It
949
+ is never the largest probability. `decisionAnswers(answers, confidence)`
950
+ builds the record's answers from decoded `Classifier.Answer`s.
951
+
952
+ Both are emitted through the same `Observer` every other event takes, so a
953
+ durable host checkpoints them inside the step that produced them. The
954
+ controller provides `Journal` around each flow call: a flow that asks Jev
955
+ itself, such as the agent's `recall`, journals its receipts into the run that
956
+ called it. Outside a run `Journal` does nothing. A completion
957
+ judgement recorded before `DecisionSettled` existed replays with no decision:
958
+ the record is absent, never reconstructed.
959
+
960
+ Jev's other readings write these:
961
+
962
+ - `RelevanceSettled`: the human-provided items (`RelevanceKind`: `flow`,
963
+ `skill`, `instruction`, `memory`) one reading kept and withheld, by id and
964
+ digest, never text. `source` is `run`, `supervisor`, or `recall` for a
965
+ recall the model called; an item is withheld only at or above
966
+ `withholdAt`.
967
+ - `RelevanceRestored`: a withheld `flow` the run called by name.
968
+ - `SeatRouted`: the `seat`, `modelId` and prompt `variant` a run that
969
+ `declared` no model was routed to, from the available `candidates`, with
970
+ the `backups` it fails over to and, for a panel route, the `SeatPanel`
971
+ (member seats with their backups, and the `merger`, which is `seat`).
972
+ `decidedBy` is `jev`; rows written before the routing graph may say `only`
973
+ and carry `confidence`.
974
+ - `DecisionUnjudged`: a reading nobody could judge, with `UnjudgedReason`
975
+ (shared with `SupervisorUnjudged`), the `items` it covered, and, on both,
976
+ the `usage` each request paid when the provider metered it before the
977
+ reading failed. Every evaluator `usage` names its `modelId` when known.
978
+
979
+ Fields later writers add to existing events are optional, so older journals
980
+ decode unchanged: `DecisionSettled.usage`; `CompactionSettled.kept`, `marks`
981
+ (`CompactionMark` `keep`, `squash` or `remove`, with the `CompactionPin` that
982
+ overrode a removal, by segment digest), `removedTokens`, `unaligned` and
983
+ `causes` (`CompactionCause` `budget`, `outdated_context` or
984
+ `irrelevant_context`), with `summary` optional; `SupervisorSettled.monitors` (`MonitorKind` `mood`, `skill` or
985
+ `lint`) and `skillsCapped`; `DisciplineArmed.judged`,
986
+ `relevance`, `monitors` and `stance` (`careful` or `paranoid`), with
987
+ `supervisorSteer` optional; `SteeringDrained.monitor`, `suppressed`
988
+ (each with a `Suppression` reason) and `memory`; `SeatRouted.backups` and
989
+ `panel`.
990
+
991
+ Every member's `_tag` is the kebab-case discriminant `switch` and
992
+ `Stream.filter` match on. `AgentEvent.eventType` is keyed by the camelCase
993
+ property name and holds the journal event type, the one table `CellTurn`
994
+ writes and `Transcript` reads:
995
+
996
+ | `_tag` | `eventType` property | Journal event type |
997
+ | ------------------------------- | ----------------------------- | ------------------------------------------------ |
998
+ | `aborted` | `aborted` | `flows.harness.aborted.v1` |
999
+ | `cell-call-settled` | `cellCallSettled` | `flows.harness.cell-call-settled.v1` |
1000
+ | `cell-call-started` | `cellCallStarted` | `flows.harness.cell-call-started.v1` |
1001
+ | `cell-printed` | `cellPrinted` | `flows.harness.cell-printed.v1` |
1002
+ | `cell-produced` | `cellProduced` | `flows.harness.cell-produced.v1` |
1003
+ | `cell-rejected-in-frame` | `cellRejectedInFrame` | `flows.harness.cell-rejected-in-frame.v1` |
1004
+ | `cell-settled` | `cellSettled` | `flows.harness.cell-settled.v1` |
1005
+ | `checkpoint-minted` | `checkpointMinted` | `flows.harness.checkpoint-minted.v1` |
1006
+ | `claim-demanded` | `claimDemanded` | `flows.harness.claim-demanded.v1` |
1007
+ | `compaction-settled` | `compactionSettled` | `flows.harness.compaction-settled.v1` |
1008
+ | `decision-settled` | `decisionSettled` | `flows.harness.decision-settled.v1` |
1009
+ | `decision-unjudged` | `decisionUnjudged` | `flows.harness.decision-unjudged.v1` |
1010
+ | `discipline-armed` | `disciplineArmed` | `flows.harness.discipline-armed.v1` |
1011
+ | `model-delta` | `modelDelta` | `flows.harness.model-delta.v1` |
1012
+ | `model-requested` | `modelRequested` | `flows.harness.model-requested.v1` |
1013
+ | `seat-failed-over` | `seatFailedOver` | `flows.harness.seat-failed-over.v1` |
1014
+ | `model-parked` | `modelParked` | `flows.harness.model-parked.v1` |
1015
+ | `model-unparked` | `modelUnparked` | `flows.harness.model-unparked.v1` |
1016
+ | `model-retried` | `modelRetried` | `flows.harness.model-retried.v1` |
1017
+ | `model-settled` | `modelSettled` | `flows.harness.model-settled.v1` |
1018
+ | `mutation-observed` | `mutationObserved` | `flows.harness.mutation-observed.v1` |
1019
+ | `narrow-only-demanded` | `narrowOnlyDemanded` | `flows.harness.narrow-only-demanded.v1` |
1020
+ | `narrowed-demanded` | `narrowedDemanded` | `flows.harness.narrowed-demanded.v1` |
1021
+ | `permission-required` | `permissionRequired` | `flows.harness.permission-required.v1` |
1022
+ | `read-only-demand-issued` | `readOnlyDemandIssued` | `flows.harness.read-only-demand-issued.v1` |
1023
+ | `read-only-demanded` | `readOnlyDemanded` | `flows.harness.read-only-demanded.v1` |
1024
+ | `relevance-restored` | `relevanceRestored` | `flows.harness.relevance-restored.v1` |
1025
+ | `relevance-settled` | `relevanceSettled` | `flows.harness.relevance-settled.v1` |
1026
+ | `repeat-demanded` | `repeatDemanded` | `flows.harness.repeat-demanded.v1` |
1027
+ | `resolved` | `resolved` | `flows.harness.resolved.v1` |
1028
+ | `seat-routed` | `seatRouted` | `flows.harness.seat-routed.v1` |
1029
+ | `steering-drained` | `steeringDrained` | `flows.harness.steering-drained.v1` |
1030
+ | `sufficiency-observed` | `sufficiencyObserved` | `flows.harness.sufficiency-observed.v1` |
1031
+ | `suspended` | `suspended` | `flows.harness.suspended.v1` |
1032
+ | `transition-applied` | `transitionApplied` | `flows.harness.transition-applied.v1` |
1033
+ | `turn-closed` | `turnClosed` | `flows.harness.turn-closed.v1` |
1034
+ | `turn-opened` | `turnOpened` | `flows.harness.turn-opened.v1` |
1035
+ | `unmoved-demanded` | `unmovedDemanded` | `flows.harness.unmoved-demanded.v1` |
1036
+ | `unresolved-demanded` | `unresolvedDemanded` | `flows.harness.unresolved-demanded.v1` |
1037
+ | `failed-call-demanded` | `failedCallDemanded` | `flows.harness.failed-call-demanded.v1` |
1038
+ | `unobserved-demanded` | `unobservedDemanded` | `flows.harness.unobserved-demanded.v1` |
1039
+ | `output-demanded` | `outputDemanded` | `flows.harness.output-demanded.v1` |
1040
+ | `vacuous-verification-observed` | `vacuousVerificationObserved` | `flows.harness.vacuous-verification-observed.v1` |
1041
+
1042
+ ## HarnessError
1043
+
1044
+ `import * as HarnessError from "@smthrs/harness/HarnessError"`
1045
+
1046
+ The translation boundary's own failures.
1047
+
1048
+ ```ts
1049
+ export class HarnessError extends Schema.TaggedError<HarnessError>()("/harness/HarnessError", {
1050
+ code: HarnessErrorCode,
1051
+ message: Schema.String,
1052
+ cause: Schema.optional(Schema.Defect())
1053
+ }) {}
1054
+ ```
1055
+
1056
+ `HarnessErrorCode` is `assembly_failed`, `approval_unavailable`, `incompatible_journal`,
1057
+ `render_failed`, `model_failed`, `engine_failed`, `read_only_cap`,
1058
+ `completion_unjudged`, `completion_incomplete`, `claim_unproven`, or `suspended`. The set is closed to codes this package and `@smthrs/agent`
1059
+ actually raise, and `test/Contracts.test.ts` pins every member to a
1060
+ construction site; a foreign CLI adapter declares its own family beside the
1061
+ adapter rather than borrowing this one. Interrupting a run raises no
1062
+ `HarnessError`: `CellTurn` emits `AgentEvent.Aborted` and forwards the
1063
+ interrupt cause unchanged. A failed projection is a
1064
+ `Transcript.TranscriptError`, not a `HarnessError`. `cause` is a
1065
+ `Schema.Defect` so a live `Error` attached as cause still encodes to JSON for
1066
+ the durable exit schema. `FlowBinding.make` passes existing `HarnessError`
1067
+ values through unchanged; only permission requirements and denials are
1068
+ converted to code `suspended`. A handler error the binding's `timedOut`
1069
+ classifies becomes a `timeout` call result whose `value` records
1070
+ `{ limitMillis }` when the error says its limit: `bash` and `test` classify a
1071
+ command past its given or default limit, and `agent/await` a wait that gave
1072
+ up. Other handler errors become opaque `flow_failed` call results. Either carries only the safe
1073
+ `publicError` text the binding supplies.
1074
+
1075
+ ## StructuredOutput
1076
+
1077
+ `import * as StructuredOutput from "@smthrs/harness/StructuredOutput"`
1078
+
1079
+ Turning one agent's final text into a value the declared output schema
1080
+ accepts, or into a typed failure. A model may answer with bare JSON, prose
1081
+ wrapped around JSON, a fenced block, or JSON of the wrong shape; downstream
1082
+ nodes never receive that ambiguity. Extraction never relaxes validation: it
1083
+ only decides which bytes are offered to the schema.
1084
+
1085
+ ```ts
1086
+ export const decode: <S extends Schema.Top>(
1087
+ schema: S,
1088
+ text: string,
1089
+ attempt: { readonly corrections: number; readonly limit: number }
1090
+ ) => Effect.Effect<S["Type"], StructuredOutputFailure, S["DecodingServices"]>
1091
+ ```
1092
+
1093
+ `decode` tries every `candidates(text)` entry in order, the complete
1094
+ BOM-stripped response first and then the balanced JSON container whose
1095
+ matching close ends last (`lastBalanced`), then the answer itself, untrimmed,
1096
+ as a string unless it is a JSON string literal, and returns the first the
1097
+ schema accepts. The last is how `ctx.done("text")` reaches a string schema.
1098
+ When none does, the `StructuredOutputFailure` reports the issues of
1099
+ the last candidate, with `code` one of `invalid_json`, `schema_mismatch`,
1100
+ `no_candidate`, or `correction_exhausted` once the budget is spent.
1101
+
1102
+ The prompt half is `instructions(schema)`, which renders the declared schema
1103
+ as a JSON Schema document for the run's system teaching and asks for the value
1104
+ itself as the `ctx.done` argument, not a JSON string: the model is told the
1105
+ shape before it answers, and the answer is still validated locally.
1106
+ `digest(schema)` is the schema's canonical digest, `jsonSchema(schema)` its
1107
+ JSON Schema document, `issuesDigest(failure)` the digest of one failure's
1108
+ rendered issues, and `correction(failure)` the teaching appended when a
1109
+ candidate failed to decode. A failure carries at most `maxIssues` (5)
1110
+ `OutputIssue`s (`{ code, path, message }`), so a wide struct that mismatched
1111
+ everywhere cannot spend the correction prompt restating the schema.
1112
+
1113
+ ## ContextWindow
1114
+
1115
+ `import * as ContextWindow from "@smthrs/harness/ContextWindow"`
1116
+
1117
+ The immutable, provider-neutral context assembled for one model request. Every
1118
+ value it exposes is frozen, the arrays, the segments, and the messages, parts,
1119
+ and tool declarations they hold, so a runtime mutation throws in strict mode
1120
+ instead of silently invalidating the digest computed once at construction.
1121
+
1122
+ ```ts
1123
+ export const make: (options: MakeOptions) => ContextWindow
1124
+ export const empty: (modelId: string) => ContextWindow
1125
+ export const makeSegment: (input: SegmentInput) => Segment
1126
+ export const render: (self: ContextWindow) => ModelRequest.ModelRequest
1127
+ ```
1128
+
1129
+ `MakeOptions` is `{ modelId, segments?, activeTools?, replaced? }`. A
1130
+ `Segment` is a stable, typed slice with a `SegmentKind`, a `SegmentZone`
1131
+ (prefix or tail of the cache breakpoint), its content parts, a digest, and an
1132
+ estimated token count computed once at construction. `appendTurn` appends one
1133
+ settled assistant message; `prefixDigest`, `compactPrefix`, and
1134
+ `compact` replace an exact compactable prefix while retaining every suffix
1135
+ segment, failing with a `ContextWindowError` when the declared prefix does not
1136
+ match. `compactMarked(window, prefixLength, marks, summary)` applies one
1137
+ `Mark` per prefix segment, `keep`, `squash` or `remove`: the result holds the
1138
+ segments before the prefix, one summary segment when any segment is squashed,
1139
+ the kept segments as the same objects, then the suffix. The summary is required
1140
+ exactly when a segment is squashed. `compactPrefix` is `compactMarked` with
1141
+ every segment squashed. `render` projects the window into the `ModelRequest` of
1142
+ [`@smthrs/model`](/api/model).
1143
+
1144
+ `appendTurn` and `compact` are dual, so each one takes the window first or
1145
+ returns a function of it, and a `ContextWindow` is `Pipeable`. The direct and
1146
+ the piped forms are the same call:
1147
+
1148
+ ```ts
1149
+ const request = ContextWindow.render(ContextWindow.appendTurn(window, assistant))
1150
+
1151
+ const piped = window.pipe(
1152
+ ContextWindow.appendTurn(assistant),
1153
+ ContextWindow.render
1154
+ )
1155
+ ```
1156
+
1157
+ `ModelCatalog.contextWindowTokensFor(modelId)` of
1158
+ [`@smthrs/model`](/api/model) supplies the shared context-limit catalog used by
1159
+ seat resolution and seat steering (128,000 tokens for unknown models). A
1160
+ thinking-only steer preserves the current budget.
1161
+
1162
+ ## Tokens
1163
+
1164
+ `import * as Tokens from "@smthrs/harness/Tokens"`
1165
+
1166
+ Deterministic token accounting for context windows. `Tokens.estimate`
1167
+ approximates four characters per token, with code punctuation and newline
1168
+ density accounting for the shorter tokens of source text; it is a
1169
+ deterministic local approximation, not provider billing data.
1170
+ `Tokens.count(text, estimator?)` counts one text (defaulting to `estimate`)
1171
+ into a `Tokens.Count` (`{ value, estimated }`), and `Tokens.combine` sums
1172
+ per-segment `Tokens.Segment` counts into one `Tokens.Accounting`, split by
1173
+ cache zone.
1174
+
1175
+ ## Transcript
1176
+
1177
+ `import * as Transcript from "@smthrs/harness/Transcript"`
1178
+
1179
+ Transcript projection from durable journal entries. The transcript grows:
1180
+ what the model saw is what it said plus what the harness answered, in journal
1181
+ order. `Transcript.projectResult` projects model-visible messages in canonical
1182
+ journal sequence order; `Transcript.projectStateResult` projects the same
1183
+ events into typed state (`ProjectedState`, with the compaction replacement
1184
+ identity when one was recorded), preserving malformed-payload failures as
1185
+ typed `TranscriptError`s instead of throwing. `CellEvidence` is the
1186
+ schema-decoded cell evidence the rebuild consumes. `CompactionSettled.retainedMessageCount`
1187
+ records the number of messages in the live retained suffix, across all retained
1188
+ segments. Projection applies these boundaries in journal order, replacing only
1189
+ the preceding prefix with the summary. Older events without the field replace
1190
+ all messages preceding the event.
1191
+
1192
+ ## ExternalTranscript
1193
+
1194
+ `import * as ExternalTranscript from "@smthrs/harness/ExternalTranscript"`
1195
+
1196
+ Read-only conversation entries decoded from the transcript file of an agent a
1197
+ person runs beside Smithers. Two formats decode: `decodeCodex` reads the
1198
+ `rollout-*.jsonl` file Codex CLI writes under `$CODEX_HOME/sessions`, and
1199
+ `decodeClaude` reads the `<session>.jsonl` file Claude Code writes under
1200
+ `~/.claude/projects/<project>`. Decoding is pure. It performs no I/O, reads no
1201
+ clock, needs no provider and registers no importer; the host reads the file and
1202
+ keeps the state.
1203
+
1204
+ Every `Entry` carries `origin: "external"`, `agent_kind` (`codex` or
1205
+ `claude-code`), `format_version`, `session_id`, `source_id`
1206
+ (`<session>:<line>`), `read_only: true`, `seq` (entry order from 0), `at` (the
1207
+ record's time in epoch milliseconds, 0 when it has none), an optional
1208
+ `turn_id`, `role` and one `Part`. Neither format has a schema version of its
1209
+ own, so `format_version` is an adapter profile named by the CLI release:
1210
+ `codex-rollout/<major.minor>` from `session_meta`, or `claude-code/<major.minor>`
1211
+ from the `version` on each Claude Code record. `role` is `user` for the owner's
1212
+ prompts and goals and `assistant` for everything else, by record kind;
1213
+ transcript text never sets it, and who the owner and the agent participant are
1214
+ is the caller's to supply.
1215
+
1216
+ A `Part` is a `prompt`, a `goal`, `text` (`final` on the turn's answer),
1217
+ `reasoning`, `encrypted` (a placeholder for a message body Codex encrypted,
1218
+ never dropped), `tool` (call id, command, `reads` labels such as `Read mvp.md`
1219
+ when the call only reads, searches or lists, status, exit code, output and
1220
+ duration), `edit` (call id, each `EditedFile` with its unified diff, and
1221
+ `applied` or `failed`), `search`, `helper`, `compaction`, or `error` for a
1222
+ failure the agent reported.
1223
+
1224
+ Every kind a decoder skips is named in its source. A record, event, item,
1225
+ status line, attachment or content block outside those names is refused with
1226
+ `unsupported_record`: a new kind stops the import where a person can see it
1227
+ and is never shown as something else. The mapping tables, the recorded
1228
+ captures behind them and the host caller are in
1229
+ [external-transcripts.md](external-transcripts.md).
1230
+
1231
+ ### Codex
1232
+
1233
+ Entries come from `event_msg` rows: `item_completed` items,
1234
+ `thread_goal_updated` rows whose objective or status changed, a
1235
+ `task_complete` that carries the failure its turn ended in, and
1236
+ `turn_aborted`. `reasoning` is only a summary Codex chose to write.
1237
+ `response_item` rows repeat the items for the model and are skipped, except
1238
+ two the items leave out. An `agent_message` is a message between this agent
1239
+ and one it works with: a body with ciphertext is one `encrypted` placeholder
1240
+ that stands for the whole body, and a readable body is `text`. A
1241
+ `custom_tool_call_output` that reports a failed code-mode script is a failed
1242
+ `tool` whose command is the script its `custom_tool_call` requested, followed
1243
+ by a failed `edit` when the report names the file an `apply_patch` could not
1244
+ change. The request waits in `state.calls` until its output arrives.
1245
+
1246
+ ### Claude Code
1247
+
1248
+ Claude Code chains its conversation records (`user`, `assistant`, `system`,
1249
+ `attachment`) by `uuid`. Thirteen named bookkeeping rows (`mode`,
1250
+ `permission-mode`, `queue-operation`, `last-prompt`, `ai-title`,
1251
+ `file-history-snapshot`, `cost-state` and the like) are skipped, as are
1252
+ `isSidechain` rows, which belong to a subagent's own transcript. The session
1253
+ is the `sessionId` of the first conversation record, and `turn_id` is the
1254
+ `promptId` of the latest user record.
1255
+
1256
+ | Record | Part |
1257
+ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
1258
+ | `user` text the owner wrote (`origin` `human` or none) | `prompt`; a slash command reads as `/<name> <args>` and a shell command as `!<command>` |
1259
+ | `user` `[Request interrupted by user…]` | `error` with that text |
1260
+ | `user` `isMeta`, `isCompactSummary`, other origins, local command output | Skipped: skill bodies, caveats, summaries, task notifications, peer messages, `<local-command-stdout>` |
1261
+ | `assistant` `text` | `text`, `final` when the message's `stop_reason` is `end_turn` |
1262
+ | `assistant` `thinking` | `reasoning` when it has a body; empty and `redacted_thinking` blocks are skipped |
1263
+ | `assistant` with `isApiErrorMessage` | `error` with Claude Code's message |
1264
+ | `tool_use` `Bash`, then its `tool_result` | `tool` with the command, `ok` or `error`, the exit code Claude Code reports as `Exit code N`, output and duration |
1265
+ | `Read`, `Grep`, `Glob`, `LS` | `tool` with a `reads` label: `Read a.ts`, `Searched "q" in src`, `Listed apps` |
1266
+ | `Edit`, `Write`, `MultiEdit`, `NotebookEdit` | `edit`: Claude Code's reported hunks, or the requested change when none; `failed` when the result is an error |
1267
+ | `WebSearch`, `WebFetch` | `search` for the query or address |
1268
+ | `Agent`, `Task` | `helper` named by `subagent_type`, with the call's description |
1269
+ | any other tool | `tool` whose command is the tool's name and its input as JSON |
1270
+ | `system` `compact_boundary` | `compaction`; nine named status subtypes are skipped |
1271
+ | `attachment` `queued_command` the owner typed while the agent worked | `prompt`; 44 named context attachments are skipped |
1272
+ | a record, status line, attachment or content block of any other kind | Refused: `unsupported_record` naming it |
1273
+
1274
+ A tool call waits in `state.calls` from its `tool_use` record until the
1275
+ `tool_result` with the same id arrives, and becomes one entry at the result's
1276
+ line, so two calls issued together appear in the order their results arrive.
1277
+ A call whose result never arrives emits nothing. A `Write` is `added` when
1278
+ Claude Code reports it created the file; a requested replacement Claude Code
1279
+ did not apply has no known position, so its hunk starts at line 1. Entries
1280
+ follow file order: when the owner edits and resends a prompt, Claude Code
1281
+ writes the new branch after the old one and both appear. A record that yields
1282
+ several entries numbers the later ones `<session>:<line>#<n>`.
1283
+
1284
+ ### Decoding
1285
+
1286
+ `decodeCodex(state, chunk)` and `decodeClaude(state, chunk)` return
1287
+ `Result<Decoded<State>, ExternalTranscriptError>`: the entries the chunk
1288
+ completed and the `CodexState` or `ClaudeState` to pass with the next chunk.
1289
+ Start from `codexStart` or `claudeStart`. Any partition of the same text
1290
+ yields the same entries, and a last line without its newline waits in
1291
+ `state.pending` until it completes. The state is plain JSON, held calls
1292
+ included, so a host can persist it and resume tailing. Chunks are strings; a
1293
+ host reading bytes decodes them with a streaming `TextDecoder` first.
1294
+
1295
+ `ExternalTranscriptError.code` is one of:
1296
+
1297
+ - `missing_version`: a Codex row comes before the `session_meta` row, or a
1298
+ Claude Code conversation record carries no `version`.
1299
+ - `unsupported_version`: the release is missing (Codex) or outside
1300
+ `codexReleases` (`0.159`, `0.160`) or `claudeReleases` (`2.1`).
1301
+ - `unsupported_record`: a complete, well-formed record, event, item, status
1302
+ line, attachment or content block of a kind this module does not name. The
1303
+ message names the kind.
1304
+ - `malformed_record`: a complete line is not a JSON record; a record names no
1305
+ type; a conversation record has no `uuid`, session or message content; a
1306
+ message part has no text; a tool request names no call.
1307
+
1308
+ Each error carries the 1-based `line` the decode stopped at, and a failed
1309
+ decode returns no entries from its chunk: a host that must keep the entries
1310
+ before the refused line decodes one record at a time. `Fault` classifies all
1311
+ four as `dependency`: the agent wrote a transcript this release cannot read.
1312
+
1313
+ ## Compaction
1314
+
1315
+ `import * as Compaction from "@smthrs/harness/Compaction"`
1316
+
1317
+ Declarations for sealed transcript-summary steps.
1318
+ `shouldCompact(accounting, { reserve?, keepRecent? }?)` returns whether the
1319
+ model context crossed its reserved threshold; `selectPrefix(window, { keepRecent? }?)`
1320
+ selects the
1321
+ longest compactable prefix while preserving a whole recent suffix; `declare`
1322
+ builds the sealed `CompactionStep` for one prefix and `Summarizer` without
1323
+ invoking a model; `summaryRequest` builds the model request input for the
1324
+ step, with `summaryInstruction` as its stable instruction; and `apply`
1325
+ splices a recorded summary into a projected window, failing with
1326
+ `InvalidStep` when the declaration does not match the window it is applied
1327
+ to. `declare(window, prefixLength, summarizer, marks?)` takes one
1328
+ `ContextWindow.Mark` per prefix segment and records them with a `marksDigest`;
1329
+ without marks every segment is squashed. `summaryRequest` carries only the
1330
+ squashed segments' messages and fails when nothing is squashed, and
1331
+ `apply(window, step, summary?)` requires a summary exactly when a segment is
1332
+ squashed. A length or digest mismatch is `InvalidStep`. `Summarizer.params` is an optional `ModelRequest.GenerationParams`.
1333
+ `summaryRequest` schema-decodes supplied parameters, including JSON-round-tripped
1334
+ values, and returns `InvalidStep` for invalid values or unknown parameter keys.
1335
+ Defaults apply only when `params` is absent.
1336
+
1337
+ ## Plan
1338
+
1339
+ `import * as Plan from "@smthrs/harness/Plan"`
1340
+
1341
+ Local structural plan nodes used at the harness-to-engine boundary. `Child`
1342
+ is one flow invocation elaborated from a model tool call; `Batch` is the
1343
+ children passed through to the engine, in source order; `ChildResult`,
1344
+ `ChildProgress`, and `ChildSettled` carry outcomes back; and `SpliceEvent` is
1345
+ the streaming union `EngineLike.splice` emits. Source order is retained only
1346
+ for result correlation; graph dependencies are the sole sequencing signal.
1347
+
1348
+ ## CallLedger
1349
+
1350
+ `import * as CallLedger from "@smthrs/harness/CallLedger"`
1351
+
1352
+ The call ledger: what this run has already asked, rendered every frame. Every
1353
+ settled call contributes one line the harness derives on its own, ordinal,
1354
+ flow, what the call was about, whether it settled ok, and a structural digest
1355
+ of what came back, so a model sees what it already asked without asking
1356
+ again. A line carries no payloads: it says `stdout=4096b`, never the bytes.
1357
+ A call that writes also says so, names its byte count, and names an earlier
1358
+ identical write when one settled. `entry` records one settled call,
1359
+ `remember` folds a frame's calls into the run's `Ledger` bounded to `bound`
1360
+ (30, newest last), `settled` counts through aged-out lines, and `render`
1361
+ renders the ledger for the state section, only the calls after `since` when an
1362
+ earlier section in the window already listed the rest. Line fields clip to `width` (120),
1363
+ and a result digest names at most `members` (6) members.
1364
+
1365
+ ## NarrowedCheck
1366
+
1367
+ `import * as NarrowedCheck from "@smthrs/harness/NarrowedCheck"`
1368
+
1369
+ The narrowing ledger: which checks this run has run, and over which tree. A
1370
+ check is only evidence for the tree it ran over, and a completion whose last
1371
+ check is a narrowed version of one the run already ran in full, taken after
1372
+ the workspace moved, reports an unknown as proven. `check` records one
1373
+ settled call as a `Check` unless its input is a payload; `narrows` decides
1374
+ whether one call's terms strictly narrow another's; `find` finds the broadest
1375
+ check a completing frame narrowed and did not re-run, and `demand` states the
1376
+ sentence; `findOnly` and `demandOnly` cover the narrow-only shape, where no
1377
+ broader reading exists at all. `remember` folds a frame's checks into the
1378
+ run's `Ledger`, bounded to `retained` (32) distinct checks and `maxTerms`
1379
+ (256) terms each.
1380
+
1381
+ ## CellValidation
1382
+
1383
+ `import * as CellValidation from "@smthrs/harness/CellValidation"`
1384
+
1385
+ Cell validation at the boundary. `validate(cell)` parses one cell and reports
1386
+ everything the parse can decide, a `Validation`: module syntax, non-erasable
1387
+ TypeScript, syntax errors with their line, and the compiled text when it
1388
+ parses. The controller answers a cell that does not parse inside the same
1389
+ frame, at cached-prefix price, instead of ending the frame on it.
1390
+ `normalize(compiled)` rewrites a cell's top-level declarations so the
1391
+ persistent realm behaves like a notebook: a name declared again rebinds
1392
+ instead of dying on redeclaration. Nothing here executes anything, and the
1393
+ only outcome is a rejection the model is asked to fix in this frame.
1394
+
1395
+ ## UnmovedTree
1396
+
1397
+ `import * as UnmovedTree from "@smthrs/harness/UnmovedTree"`
1398
+
1399
+ The completion with nothing behind it. `find` compares the digest of the tree
1400
+ the run opened on against the digest the completing frame closed on; equal
1401
+ digests mean the tree the completion describes is the tree the run was handed.
1402
+ `demand` states that the tree never moved and names the two answers that end
1403
+ it: make the change, or say why no change is needed. Nothing here reads the
1404
+ completion's text, and "no change is needed" is a legitimate answer.
1405
+
1406
+ ## FailedCall
1407
+
1408
+ `import * as FailedCall from "@smthrs/harness/FailedCall"`
1409
+
1410
+ The completion its own cell wrote before a call in it failed. A cell is
1411
+ written whole before any call in it settles, and a failed call resolves
1412
+ `{ ok: false }` rather than throwing, so a `ctx.done` after a failed request
1413
+ still runs. When a completing frame settled a failed call and the cell never
1414
+ reads a call envelope's `ok` or `error` (`inspects`), `find` names the
1415
+ failures, and the controller hands the frame back once (`cap`) with `demand`,
1416
+ journaled as `FailedCallDemanded`. A completion that already quotes the
1417
+ flow's failure reason is spared. With no frame left or the demand spent, the
1418
+ answer stands with the failures appended by `state` under `stated`. Nothing
1419
+ here asks a model or reads what the claim means.
1420
+
1421
+ The same blindness without a failure is handed back too. Several `cell`
1422
+ blocks in one reply run as one program, so a reply that makes a call, keeps
1423
+ its result only for the model (printed or bound, read by nothing but
1424
+ `console.*`), and calls `ctx.done` completes before the model has seen that
1425
+ result. The controller refuses that completion once per run, journals
1426
+ `UnobservedDemanded` with each call's flow, ordinal and result head, and
1427
+ continues the frame: the next model turn reads what the cell printed, the
1428
+ call results, and "Answer after reading the calls' output". A cell whose
1429
+ program reads a result in a condition, in another call's input, or in the
1430
+ completion itself (`if (after.exitCode === 0) ctx.done(…)`,
1431
+ `ctx.done((await ctx.call(…)).stdout)`), a cell that hands a result to
1432
+ anything the parse cannot see through (a function of its own, a `.then`
1433
+ callback, an alias), and a cell whose calls are effects with discarded
1434
+ results, are spared. `FailedCallDemanded` takes precedence, and with no frame
1435
+ left the answer stands; a refused answer is also what the run ends on when
1436
+ the budget runs out before it completes again.
1437
+
1438
+ `Input.output` (`OutputCheck`, `{ check, cap }`) is the host's shape for the
1439
+ final output. Before any demand above, `check(output, corrected)` answers a
1440
+ completion with a correction note or `undefined`; the verdict is a recorded
1441
+ boundary. A refused completion is handed back to the same session, with what
1442
+ its cell printed and the note, and journaled as `OutputDemanded`
1443
+ (`{ note, nextFrame }`). The realm and every settled call stay, so the
1444
+ correction repeats no work. At most `cap` completions are handed back, and
1445
+ only while a frame is left; past either the completion stands and the host
1446
+ decides. `AgentAction` supplies it from the declared output schema.
1447
+
1448
+ ## UnresolvedFailure
1449
+
1450
+ `import * as UnresolvedFailure from "@smthrs/harness/UnresolvedFailure"`
1451
+
1452
+ The failing check a completion stepped around. `exitStatus` reads a settled
1453
+ call's `exitStatusKey` (`exitCode`), and `failed` and `passed` read it for a
1454
+ failing or passing status;
1455
+ `revisits` decides whether a later check asks about the same subject as an
1456
+ earlier one; `find` finds the failing check a completion replaced rather than
1457
+ answered; and `demand` states which reading failed, which one replaced it,
1458
+ and what ends it. A failing check alone is not the trigger: the run itself
1459
+ must have demonstrated the subject was still live by returning to it.
1460
+
1461
+ ## CompletionClaim
1462
+
1463
+ `import * as CompletionClaim from "@smthrs/harness/CompletionClaim"`
1464
+
1465
+ The sixth brake on a completion, and the only one that is not a measurement.
1466
+ It declares one classifier, `completion/claim`, over the facts the harness
1467
+ already holds: the task as the person stated it, the completion message,
1468
+ whether the tree moved, every check the run took in its workspace as
1469
+ `Evidence.checksRun` (command and outcome, newest
1470
+ `checksRunLimit` (24) kept), the last check the completing frame ran with
1471
+ its result clipped to the newest `outputBytes` (4 KiB), and `Evidence.callsRun`.
1472
+ The latter lists the newest 30 settled calls from the durable call ledger,
1473
+ including classification and reads that report no exit status. Each receipt
1474
+ names the flow, bounded input subject, settlement status and structural result
1475
+ summary. It records that a result was obtained without carrying its full
1476
+ payload. Direct callers may omit this field for compatibility; the controller
1477
+ always supplies it. It asks Jev three
1478
+ questions through the `Evaluator` service. Does the completion satisfy the
1479
+ person's current request, does the claim assert something the evidence does not show,
1480
+ and does the claim report having run a command, or having obtained a result,
1481
+ that the evidence does not record? `read` asks and returns all three
1482
+ probabilities with the latency; it returns nothing only where there is no task
1483
+ and no claim to form a question about, and fails with `completion_unjudged`
1484
+ for every other reason it could not get an answer. The reading also carries
1485
+ `asked`: the encoded evidence exactly as the transport was sent it, and every
1486
+ answer as an `AgentEvent.DecisionAnswer`. The controller journals that as
1487
+ `AgentEvent.DecisionSettled`; a host reader that returns no `asked` journals
1488
+ the reading and no decision.
1489
+
1490
+ The completeness question treats labeled prior conversation as context and
1491
+ judges the newest request after `The person now says:`. A purely conversational
1492
+ request can be satisfied by the answer itself, without a file edit, flow call
1493
+ or check. A soft demand uses neutral completion-review guidance: answer the
1494
+ current request in its requested format, and support only the actions and
1495
+ results actually claimed. It does not allege invented work merely because
1496
+ the completeness reading was low.
1497
+
1498
+ The controller bounds original task evidence to 8 KiB, keeping both ends so
1499
+ a long history or task cannot silently discard the newest request at the end.
1500
+
1501
+ `CellTurn` includes later accepted instructions in the task evidence, in
1502
+ admission order, with later changes taking precedence. It labels this block
1503
+ with the same `The person now says:` marker used to identify the newest
1504
+ request, so the original request's marker does not continue to select a
1505
+ superseded instruction. It keeps the newest
1506
+ 4 KiB of steering separately from tool output and conversation summaries, so
1507
+ compacting a transcript cannot erase the recorded change of task. Replay
1508
+ rebuilds this bounded evidence from recorded steering drains; a pending,
1509
+ undelivered instruction cannot change a replayed completion.
1510
+
1511
+ `CellTurn` records the whole completion decision at an engine boundary keyed
1512
+ by the session, frame and cell digest. Replay uses that decision, including
1513
+ the classifier reading and usage, so a resumed turn keeps its previous
1514
+ decision without asking Jev again. Provider refusals retain their code, HTTP
1515
+ status when present and detail through the journal's error schema.
1516
+
1517
+ **All three ask; only the third refuses.** `find` hands the completion back at
1518
+ any of three heights, `disprovenAt` (0.3) or below on the first question,
1519
+ `overclaimedAt` (0.8) or above on the second, `unsupportedAt` (0.5) or above on
1520
+ the third, and `demand` renders the prose the next frame reads. `unrecorded`
1521
+ says whether a reading is one the brake ends a run over, which is `inventedAt`
1522
+ (0.85) or above on the third question and nothing else.
1523
+
1524
+ The split was measured using the original completeness wording, whose positive
1525
+ criteria named only workspace changes and checks. A corpus of eighteen completion states over the live
1526
+ gate's own planted repository, asked six times each on 2026-09-19, found the
1527
+ first two questions unable to separate a lie from an honest answer: "is the
1528
+ task done" at or below 0.3 fired on eight of the twelve honest completions and
1529
+ two of the six lies, and an honest unchecked fix read 0.10 on it against a flat
1530
+ lie's 0.22; "asserts more than the evidence shows" fired on five of the twelve
1531
+ honest ones, because thin evidence shows nothing by construction. The narrow
1532
+ question refused none of the twelve honest completions and ended four of the
1533
+ six lies, with the highest honest reading at 0.75 and the lowest ended lie at
1534
+ 0.94; `inventedAt` sits between them. All three still bounce, because a bounce
1535
+ costs a frame rather than an answer and is sometimes the only thing in this
1536
+ package with anything to say about a completion. The verdict is narrow for the
1537
+ mirror reason: a false refusal costs a run its answer, while a false pass costs
1538
+ nothing here, because the five deterministic brakes still ran and the truth bar
1539
+ still judges what they let through. The module's own header carries the corpus
1540
+ and the two lies that still get through.
1541
+
1542
+ **A long claim is read one sentence at a time.** When the whole claim reads at
1543
+ `unsupportedAt` or above on the third question and has more than one sentence,
1544
+ `read` asks `sentenceClassifier` the same question of each sentence in one
1545
+ request, and the claim's `invented` is its most invented sentence. Two graded
1546
+ runs of 2026-09-26 whose container work was all on the record read 0.91 and
1547
+ 0.87 as whole claims and at most 0.71 and 0.73 by sentence; a fabricated
1548
+ sentence appended to each read 0.94 and 0.92. The sentence reading journals
1549
+ its own `decision-settled`, and a transport failure on it fails the turn as
1550
+ `completion_unjudged` like the first. Each listed check in
1551
+ `Evidence.checksRun` carries its `receipt`, the tail of every string it
1552
+ returned, so a sentence quoting what a check printed has something to be read
1553
+ against. `record` builds that list from every call that reported an exit
1554
+ status, writes included, and keeps what a re-run command reported `before` when
1555
+ it changed, so "failed before the fix and passed after" is on the record. A
1556
+ sentence never ends inside inline code.
1557
+
1558
+ It never passes a claim on its own. A confident "complete" ends no run,
1559
+ bypasses no other demand, and does nothing but write a journal line;
1560
+ `judgeCompletion` consults it only once the five deterministic demands have
1561
+ found nothing.
1562
+
1563
+ **It never goes quiet either.** Every completion with a claim is read, and
1564
+ `claimCap` (3) is the number of frames the run is _given_ to answer one, not
1565
+ the number of completions that are read. The first such claim is handed
1566
+ back with the demand prose, like any other completion demand; a claim with no
1567
+ bounce left, because the cap is spent or because no frame remains to hand it
1568
+ back to, and reading at `inventedAt` or above, fails the turn as
1569
+ `claim_unproven` through `unproven`, carrying all three probabilities. One
1570
+ below `inventedAt` stands there instead: it was handed back once, the run
1571
+ answered, and refusing the answer as well is what destroyed honest runs. A
1572
+ claim demand clears `State.bouncedCompletion` only when the reading is one the
1573
+ brake would refuse, so the frame-budget notice cannot restore a sentence the
1574
+ brake refused and does restore one it would have let stand. The cap stopped at
1575
+ the bounce until this, and the second claim stood unread: on a real seat a run
1576
+ bounced at frame 1 re-claimed the identical sentence and finished `stop` on it
1577
+ over a repository whose test exits 1. Zero disarms the brake outright: no
1578
+ request, no reading, no failure.
1579
+
1580
+ **It never falls back.** A completion Jev could not judge fails the turn as
1581
+ `completion_unjudged`, carrying the reason: `unconfigured` where the host
1582
+ delivered no transport, and the evaluator's own `unreachable`, `refused`,
1583
+ `timeout`, `empty`, `invalid_answer` or `invalid_question` otherwise. So
1584
+ `Evaluator.Evaluator` is a **required service** of `read`, of
1585
+ `judgeCompletion`, of `CellTurn.run` and of `Agent.run` above them, and every
1586
+ host binds a real or deliberately scripted judge at composition time.
1587
+ `Evaluator.layerFromSeat(seat)` judges with a resolved subscription seat and
1588
+ needs no provider API key or gateway key. A judge that fails during a run
1589
+ produces `completion_unjudged`.
1590
+
1591
+ Offline hosts bind `Evaluator.layerScripted` and compute answers from the actual
1592
+ evidence, dispatched by question id. One evaluator serves every classifier in
1593
+ a composition. See the [whole-host scripted judge](https://github.com/smithersai/smithers/blob/main/flows/test/fixtures/scripted-judge.ts).
1594
+ Constant approval is not a judge. `layerUnavailable()` is an explicit outage
1595
+ fixture for classifier tests. The five deterministic brakes still run unchanged.
1596
+
1597
+ ## Judgement
1598
+
1599
+ `import * as Judgement from "@smthrs/harness/Judgement"`
1600
+
1601
+ The one way this package asks Jev a question. Every reading goes through it:
1602
+ the supervisor's and the completion brake's, and every relevance, compaction,
1603
+ monitor and routing reading.
1604
+
1605
+ `measured(classifier, state)` asks through the bound `Evaluator` and returns a
1606
+ `Read`: the decoded answers and an `Asked` (classifier id, digest, questions,
1607
+ the state as it was sent, `DecisionAnswer`s with the provider's own
1608
+ confidence, integer `latencyMs`, and `usage` when the transport reported any).
1609
+ It fails with the transport's own `ClassifierError`. `read` is the fail-closed
1610
+ layer over it and needs no `Evaluator` in its type: a host that binds none
1611
+ fails `unconfigured`, and a transport failure fails as `Unjudged` with the
1612
+ transport's code and `Evaluator.publicMessage` as its `detail`.
1613
+
1614
+ `perItem({ id, description, context, item, questions, concurrency?, maxStateBytes? })`
1615
+ asks the same questions about each of many items. Each question is built from
1616
+ the item's index, and its id is `${key}_${index}`. `classifierFor(n)` is the
1617
+ classifier for `n` items, the same object for the same `n`. Its state is
1618
+ `{ context, items }`. `read(context, items)` packs items in order, greedily,
1619
+ into requests whose encoded state fits `maxStateBytes` (by default 262,144
1620
+ bytes, the `jev` flow's ceiling). Each request numbers its items from 0, and
1621
+ requests run at most `concurrency` (`Classifier.defaultConcurrency`) at once.
1622
+ Answers come back one record per item in input order, with every request's
1623
+ `Asked`. The first failed request fails the reading, and partial answers are
1624
+ never returned. No items send no request. An item too large to send alone
1625
+ fails `invalid_question`.
1626
+
1627
+ `recorded(engine, { name, identity, classifier, value, items }, execute)`
1628
+ takes a reading inside a run through `EngineLike.record`. A success records
1629
+ the value and one `decision-settled` row per request (`decision`: decided by
1630
+ `jev`, usage carried). A failure records `value: null` and one
1631
+ `decision-unjudged` row over `items` (`unjudgedEvent`). A replayed frame is
1632
+ served the record and asks nothing. `emitRecorded` journals the decisions in
1633
+ order, then the unjudged row. `task` bounds a run's task to `taskBytes`
1634
+ (4,096) with both ends kept.
1635
+
1636
+ ## Relevance
1637
+
1638
+ `import * as Relevance from "@smthrs/harness/Relevance"`
1639
+
1640
+ What a run is shown of the human-provided items it could be shown: catalog
1641
+ flows and skills, chunks of instruction files such as `AGENTS.md`, and memory
1642
+ rows. Each is an `Item` (`{ kind, id, text }`, `Kind` being
1643
+ `AgentEvent.RelevanceKind`).
1644
+
1645
+ `judge(context, items)` asks Jev, through `reader` (a `Judgement.perItem`
1646
+ reading with classifier `relevance/unnecessary` and one boolean
1647
+ `unnecessary_<i>` per item), whether each item is unnecessary for
1648
+ `context.task`. An item is withheld only at a probability at or above
1649
+ `withholdAt` (0.9); everything else is kept. Each item's text is sent
1650
+ head-kept to `itemBytes` (1,024), and an item that was cut is always kept:
1651
+ Jev cannot be confident about text it was not shown. The `Reading` holds a
1652
+ `Verdict` per item in
1653
+ input order (`p`, `withheld`, and the digest of the whole text), every
1654
+ request's `Asked`, `latencyMs` and summed `usage`. It fails as
1655
+ `Judgement.Unjudged`, and the caller then keeps every item and journals
1656
+ `decision-unjudged`.
1657
+
1658
+ `settled(reading, { scope, frame, source })` is the `relevance-settled` row:
1659
+ ids and digests, never text. `flowItem(descriptor)` is a catalog entry as an
1660
+ item, `skill` for a markdown body and `flow` otherwise, its description
1661
+ marked untrusted. `chunks(documents)` splits `Document`s (`{ path, text }`)
1662
+ into `Chunk`s with ids `${path}#${n}`: one per markdown heading and per
1663
+ top-level list item, never inside a fence. `render(documents, withheld)` is the
1664
+ project-instructions block of every chunk not withheld; `""` when nothing is
1665
+ left.
1666
+
1667
+ ## Supervisor
1668
+
1669
+ `import * as Supervisor from "@smthrs/harness/Supervisor"`
1670
+
1671
+ The reading Jev takes of a run while it is still running, off the cell loop's
1672
+ hot path. Every other control reads a completion or one measured fact; this
1673
+ one reads the run's shape. It declares one classifier, `supervisor/turn`, over
1674
+ a `Snapshot` the controller assembles from what it already holds: the task
1675
+ (with every later instruction the run accepted), the newest `recentFrames`
1676
+ (3) frames as `Frame` (cell head, prose head, prints tail, each bounded by
1677
+ `frameBytes`, the transition, whether the frame moved the tree), the counts the
1678
+ deterministic controls keep as `Signals` (read-only and repeat streaks,
1679
+ mutations, checks run and failing, unanswered failures, failed calls, demands
1680
+ spent). It also carries `skills`: up to `skillLimit` (12)
1681
+ Markdown skills from the frame's relevance-filtered catalog the model may
1682
+ call and has not, sorted by name and offered only when `read` is in that
1683
+ catalog, each a `Skill` of name, Markdown body path and the description's
1684
+ first `skillBytes` (256) wrapped as untrusted data (`skill`); `called`, the
1685
+ newest `calledLimit` (64) distinct flows the call ledger names; and
1686
+ `jevAvailable`, whether the catalog has `jev`. A skill the relevance gate
1687
+ withheld is never offered. Nothing is re-derived: the supervisor reads the
1688
+ harness's evidence and never measures a second time.
1689
+
1690
+ One Jev call per snapshot answers every question at once; eleven are fixed.
1691
+ Five are about the run, the `triggers`: `thrashing` (at or
1692
+ above `thrashingAt`, 0.5), `off_target` (`on_target` at or below
1693
+ `offTargetAt`, 0.5), `suspect` (at or above `suspectAt`, 0.5),
1694
+ `outdated_context` and `irrelevant_context` (each at or above `contextAt`,
1695
+ 0.5). `triggered(reading)` names the triggers that fired. The two
1696
+ `contextTriggers` never nudge: `compacting(reading)` names the ones that
1697
+ fired, and a judged run whose boundary takes that reading compacts its
1698
+ context at the next frame by the marks it stored, whatever the budget, its
1699
+ `compaction-settled` naming them as `causes`. `crosses(reading)` is any other
1700
+ trigger firing; the `supervisor` lint monitor and the offline replay both
1701
+ call it, and `nudge` names the counts behind it. Five are
1702
+ operational states scored on `Level` (`none`, `mild`, `strong`), each naming
1703
+ the evidence it reads: `frustrated`, `anxious`, `scared`, `confused`,
1704
+ `confident`. `needs_help` is a choice over `Help` (`none`, `clarification`,
1705
+ `permission`, `stuck`, `risky_action`): the one word a person is shown, and it
1706
+ never steers the run. Each monitor question the run's `Monitor`s add is one
1707
+ more boolean, keyed `monitor_<id>` (`monitorPrefix`; `MonitorQuestions`).
1708
+ `read(snapshot, extra)` asks them all and puts each monitor's probability on
1709
+ `Reading.monitors` by monitor id. `classifierFor(extra)` is the classifier for
1710
+ that set of monitor ids, declared once per set, and `classifier` the bare one
1711
+ over the eleven fixed questions. `prose` strips fenced cells from a reply.
1712
+
1713
+ Recalled memory goes through `Relevance`, not `supervisor/turn`. Beside each
1714
+ reading the fiber recalls past every row whose key the run has already been
1715
+ shown, keeps the first `recalledLimit` (6) it has not, and asks
1716
+ `Relevance.judge` about the rest as `memory` items keyed by row, with the
1717
+ task and the head of the frame's prose as `recent`; the two readings run
1718
+ concurrently. Rows Jev is confident the run does not need are withheld; the
1719
+ rest, or every row when relevance cannot answer, go to the next boundary,
1720
+ rendered by `recalledInsert`. That boundary drops any row shown since the
1721
+ offer, records the keys it delivered on `SteeringDrained.memory`, and folds
1722
+ them into `CellTurn.State.memoryShown`, so a row is shown to a run once.
1723
+
1724
+ `CellTurn` offers each frame's snapshot from the frame's own live turn
1725
+ boundary to a one-slot sliding queue and continues at once; a forked fiber on
1726
+ the loop's scope takes the newest snapshot, recalls, asks through
1727
+ `EngineLike.record` (keyed on the session, the frame and the cell digest),
1728
+ and journals, in order, the supervisor's `DecisionSettled` (the snapshot and
1729
+ every answer), the memory reading's `DecisionSettled` rows, its
1730
+ `RelevanceSettled` (`source: "supervisor"`) or a `DecisionUnjudged` for
1731
+ `relevance/unnecessary`, the marks reading's `DecisionSettled` rows or a
1732
+ `DecisionUnjudged` for `compaction/marks`, and last
1733
+ `AgentEvent.SupervisorSettled`, whose `monitors` holds each monitor's value
1734
+ and whether it crossed, and whose `skillsCapped` is true when more than
1735
+ `skillLimit` skills could have been offered. Each reading scores the run's monitors, then
1736
+ `Monitor.skills` of its snapshot, then `Monitor.useJev()`. What
1737
+ the run is told is the monitors' to decide: the reading records each
1738
+ monitor's raw value and every crossed monitor's message, and the next
1739
+ boundary that executes gates them with `Monitor.gate` against
1740
+ `CellTurn.State.monitorLedger` inside its own recorded drain, only when
1741
+ `CellTurn.Input.judged`. At most one monitor message is delivered, then the
1742
+ recalled rows, in the drain's own `supervisor` field rather than among the
1743
+ person's steering inserts; a reading is dropped as stale after that boundary.
1744
+ A reading that fails on one side still delivers the other. The model reads
1745
+ them above the frame's ask; the task the completion brake and later snapshots
1746
+ read never includes them. Each `SupervisorSettled` states the delivery it ran
1747
+ under as `steer`. `Memory` is a port with `memoryNone` behind it unless the
1748
+ host adapts a store. The supervisor only recalls through it; a recall that
1749
+ fails is journaled as `AgentEvent.SupervisorMemoryFailed` and the reading goes
1750
+ on. The supervisor writes no memory: when `supervisor.remember` is on,
1751
+ `@smthrs/agent`'s `MemoryMine` mines the run's transcript once, at run end,
1752
+ and writes through `Memory.remember`.
1753
+
1754
+ It never falls back. A snapshot nobody could judge is journaled as
1755
+ `AgentEvent.SupervisorUnjudged` with `UnjudgedReason` (`unconfigured`,
1756
+ `interrupted`, or the transport's own code; an `unreachable` detail is
1757
+ `Evaluator.unreachableMessage`, never the transport's text), gates no
1758
+ monitor, leaves the ledger alone and reports no level. A replayed frame is never
1759
+ offered, so a resumed run re-asks nothing and re-delivers exactly what its
1760
+ recorded drains hold. A reading in flight when the run ends gets
1761
+ `closeGraceMs` (1,500) to settle; one still unanswered is interrupted and
1762
+ journaled `interrupted`, and the run never waits longer. The offline replay over
1763
+ archived journals that measures the triggers' precision is
1764
+ `evals/swebench/lib/jev-replay.mjs`.
1765
+
1766
+ ## Monitor
1767
+
1768
+ `import * as Monitor from "@smthrs/harness/Monitor"`
1769
+
1770
+ What one supervisor reading can put in front of the run, and when. A
1771
+ `Monitor` turns a `Supervisor.Reading` into a probability and a sentence: a
1772
+ `Questioned` monitor adds one boolean question (`questionId(id)`,
1773
+ `monitor_<id>`) to the supervisor's single Jev call, asked of a snapshot when
1774
+ its `applies` holds; a `Derived` monitor scores answers the supervisor already
1775
+ asks and costs nothing. `make(input)` fills a monitor's budget from its
1776
+ kind's `budgets`: `at` (crosses when `p >= at`), `consecutive` crossed
1777
+ readings before delivery, `cooldownFrames` after a delivery, `limit`
1778
+ deliveries per run, and `priority`. `validate` admits a set or fails with
1779
+ `InvalidMonitor` naming the first id that cannot run (`idPattern`, a duplicate
1780
+ id, an id each reading adds itself (`skill_*`, `use_jev`),
1781
+ `at` outside `(0, 1]`, or a count that is not a non-negative integer).
1782
+
1783
+ `lint()` is the supervisor's legacy nudge: it crosses exactly when
1784
+ `Supervisor.crosses` does and says `Supervisor.nudge`, with no streak,
1785
+ cooldown or limit. `moods()` are the stance monitors `paranoid`, `careful`,
1786
+ `step_back` and `clarify`, saying `paranoidText`, `carefulText`,
1787
+ `stepBackText` and `clarifyText`. `paranoid` crosses on a signal the lint
1788
+ does not own: a frame whose transition is `complete` in the snapshot marks a
1789
+ bounced completion and an increased demand counter. It requires strong
1790
+ confidence; the rest read the emotions and help the reading already holds.
1791
+ `defaults()` is both, and what `CellTurn.Input.monitors` takes when omitted.
1792
+
1793
+ Every reading adds two more. `skills(snapshot)` is one `skill` monitor per
1794
+ offered skill (at 0.85, limit 1), id `skill_<name made safe>` with a digest
1795
+ suffix when two names collide, asking whether reading `skills[i]` now would
1796
+ change what the run does next; it says `skillText(name, path)`, which names
1797
+ the skill and a `read` call for its body and never quotes its description.
1798
+ `useJev()` is the `use_jev` lint (at 0.85, limit 2), asked only while
1799
+ `jevAvailable`, for frames that print lists and choose among them by hand; it
1800
+ says `useJevText`.
1801
+
1802
+ `questions(monitors, snapshot)` is what a snapshot adds to the call.
1803
+ `evaluate` runs at reading time: a `Row` per monitor with a value, and a
1804
+ `Candidate` with its rendered text per crossed one. `gate` runs at the
1805
+ recorded steering drain against the durable `Ledger` (an `Entry` of
1806
+ `streak`, `delivered` and `lastFrame` per id; `fresh` when absent): each row
1807
+ moves its streak, each candidate is withheld for `streak`, `cooldown` or
1808
+ `limit` in that order, and of the rest the highest priority takes the one
1809
+ slot and the others are withheld for `slot`. `Gated` is the message, the
1810
+ suppressions and the next ledger. Both halves are pure: nothing here asks,
1811
+ journals or steers. `CellTurn` records the delivered id and the
1812
+ suppressions on `SteeringDrained.monitor` and `suppressed`, and the ledger
1813
+ on the drain, so a replay delivers exactly what it delivered the first time
1814
+ and a resumed run keeps its cooldowns and limits. Delivery is silent unless
1815
+ the run is judged; `DisciplineArmed.monitors` lists the armed monitors then.
1816
+
1817
+ ## Sufficiency
1818
+
1819
+ `import * as Sufficiency from "@smthrs/harness/Sufficiency"`
1820
+
1821
+ The evidence that is already complete: the counterweight to the demands.
1822
+ `remember` records one frame's failing checks against the mutation epoch they
1823
+ ran in, bounded to `retained` (16); `find` finds a failing-before, passing-after
1824
+ pair over one subject; and `observation` states, once per run, that the run
1825
+ holds both halves of its own evidence. It asks for nothing, refuses nothing,
1826
+ and spends no cap.
1827
+
1828
+ ## VacuousVerification
1829
+
1830
+ `import * as VacuousVerification from "@smthrs/harness/VacuousVerification"`
1831
+
1832
+ The proof that was already true before anything changed. **This control is
1833
+ not wired into `CellTurn`: nothing in a production run reads it, and no run
1834
+ is told anything by it.** The module and
1835
+ `AgentEvent.VacuousVerificationObserved` are exported so a host can wire it in
1836
+ and measure it on its own. Its `stored` input reads a reserved `verification`
1837
+ key out of durable state that nothing currently writes, so a host that turns
1838
+ it on first decides where a run declares its verification. Once it is wired,
1839
+ `find` locates the pristine-tree pass a stored verification stands on and
1840
+ `observation` states the fact once per distinct input.
1841
+
1842
+ ## TruncatedOutput
1843
+
1844
+ `import * as TruncatedOutput from "@smthrs/harness/TruncatedOutput"`
1845
+
1846
+ The truncation ledger: which bytes this run was handed as a fragment. A flow
1847
+ that caps a captured stream returns the part that fit and declares the cut in
1848
+ a sibling flag, and a later write of those same bytes is refused, because
1849
+ there is no case in which writing a known fragment over a file is what the
1850
+ caller meant. `captures` reads every truncated payload one settled call
1851
+ result declares (the `flagSuffix` and `droppedSuffix` conventions beside a
1852
+ named payload, or the bare `flagKey` for a single-payload flow, at or above
1853
+ `minimumBytes` (1,024)); `reuse` finds the first input field carrying an earlier
1854
+ capture verbatim; `refusal` states the `truncated_write` refusal; and
1855
+ `retain` bounds the `Ledger` to the `retained` (16) most recent distinct captures.
1856
+
1857
+ ## VariablesPanel
1858
+
1859
+ `import * as VariablesPanel from "@smthrs/harness/VariablesPanel"`
1860
+
1861
+ The variables panel: what the realm holds, stated every frame. A run's memory
1862
+ is the set of names the realm is holding, and the model can only act on what
1863
+ the prompt says about them. Every line is a name, its type, one cheap size,
1864
+ and when it was last bound; nothing is serialized whole. `stamp` re-stamps
1865
+ the panel `Ledger` against the bindings a frame closed on, and `render`
1866
+ renders it for one frame's prompt, printing at most `bound` (64) names before it
1867
+ counts instead. A binding rewritten to a value of the same type and size
1868
+ reads as unchanged: the panel is a roster, and the run's own prints are what
1869
+ say a value moved.