looply-cli 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (785) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -3
  3. package/dist/.src-hash +1 -0
  4. package/dist/acceptance-observe.d.ts +108 -0
  5. package/dist/acceptance-observe.d.ts.map +1 -0
  6. package/dist/acceptance-observe.js +152 -0
  7. package/dist/acceptance-observe.js.map +1 -0
  8. package/dist/agent-cmd.d.ts +131 -0
  9. package/dist/agent-cmd.d.ts.map +1 -0
  10. package/dist/agent-cmd.js +154 -0
  11. package/dist/agent-cmd.js.map +1 -0
  12. package/dist/agent-contained.d.ts +114 -0
  13. package/dist/agent-contained.d.ts.map +1 -0
  14. package/dist/agent-contained.js +292 -0
  15. package/dist/agent-contained.js.map +1 -0
  16. package/dist/agent-driver.d.ts +130 -0
  17. package/dist/agent-driver.d.ts.map +1 -0
  18. package/dist/agent-driver.js +170 -0
  19. package/dist/agent-driver.js.map +1 -0
  20. package/dist/agent-envelope.d.ts +94 -0
  21. package/dist/agent-envelope.d.ts.map +1 -0
  22. package/dist/agent-envelope.js +214 -0
  23. package/dist/agent-envelope.js.map +1 -0
  24. package/dist/agent-exec.d.ts +182 -0
  25. package/dist/agent-exec.d.ts.map +1 -0
  26. package/dist/agent-exec.js +125 -0
  27. package/dist/agent-exec.js.map +1 -0
  28. package/dist/agent-runtime.d.ts +23 -0
  29. package/dist/agent-runtime.d.ts.map +1 -0
  30. package/dist/agent-runtime.js +143 -0
  31. package/dist/agent-runtime.js.map +1 -0
  32. package/dist/approval-gate-read.d.ts +66 -0
  33. package/dist/approval-gate-read.d.ts.map +1 -0
  34. package/dist/approval-gate-read.js +138 -0
  35. package/dist/approval-gate-read.js.map +1 -0
  36. package/dist/approval-resolution.d.ts +87 -0
  37. package/dist/approval-resolution.d.ts.map +1 -0
  38. package/dist/approval-resolution.js +100 -0
  39. package/dist/approval-resolution.js.map +1 -0
  40. package/dist/approval-resumes.d.ts +102 -0
  41. package/dist/approval-resumes.d.ts.map +1 -0
  42. package/dist/approval-resumes.js +167 -0
  43. package/dist/approval-resumes.js.map +1 -0
  44. package/dist/ask-brain.d.ts +167 -0
  45. package/dist/ask-brain.d.ts.map +1 -0
  46. package/dist/ask-brain.js +355 -0
  47. package/dist/ask-brain.js.map +1 -0
  48. package/dist/autonomy-authority.d.ts +80 -0
  49. package/dist/autonomy-authority.d.ts.map +1 -0
  50. package/dist/autonomy-authority.js +82 -0
  51. package/dist/autonomy-authority.js.map +1 -0
  52. package/dist/autonomy-controller.d.ts +321 -0
  53. package/dist/autonomy-controller.d.ts.map +1 -0
  54. package/dist/autonomy-controller.js +517 -0
  55. package/dist/autonomy-controller.js.map +1 -0
  56. package/dist/autonomy-store.d.ts +327 -0
  57. package/dist/autonomy-store.d.ts.map +1 -0
  58. package/dist/autonomy-store.js +581 -0
  59. package/dist/autonomy-store.js.map +1 -0
  60. package/dist/autonomy-tick.d.ts +257 -0
  61. package/dist/autonomy-tick.d.ts.map +1 -0
  62. package/dist/autonomy-tick.js +616 -0
  63. package/dist/autonomy-tick.js.map +1 -0
  64. package/dist/bin.d.ts +3 -0
  65. package/dist/bin.d.ts.map +1 -0
  66. package/dist/bin.js +2719 -0
  67. package/dist/bin.js.map +1 -0
  68. package/dist/brain-advice.d.ts +21 -0
  69. package/dist/brain-advice.d.ts.map +1 -0
  70. package/dist/brain-advice.js +51 -0
  71. package/dist/brain-advice.js.map +1 -0
  72. package/dist/candidate-replay-runtime.d.ts +125 -0
  73. package/dist/candidate-replay-runtime.d.ts.map +1 -0
  74. package/dist/candidate-replay-runtime.js +188 -0
  75. package/dist/candidate-replay-runtime.js.map +1 -0
  76. package/dist/checkout-carry.d.ts +76 -0
  77. package/dist/checkout-carry.d.ts.map +1 -0
  78. package/dist/checkout-carry.js +125 -0
  79. package/dist/checkout-carry.js.map +1 -0
  80. package/dist/citation-readers.d.ts +26 -0
  81. package/dist/citation-readers.d.ts.map +1 -0
  82. package/dist/citation-readers.js +102 -0
  83. package/dist/citation-readers.js.map +1 -0
  84. package/dist/command-receipts.d.ts +79 -0
  85. package/dist/command-receipts.d.ts.map +1 -0
  86. package/dist/command-receipts.js +143 -0
  87. package/dist/command-receipts.js.map +1 -0
  88. package/dist/command-runner.d.ts +32 -0
  89. package/dist/command-runner.d.ts.map +1 -0
  90. package/dist/command-runner.js +108 -0
  91. package/dist/command-runner.js.map +1 -0
  92. package/dist/compatible-sets.d.ts +67 -0
  93. package/dist/compatible-sets.d.ts.map +1 -0
  94. package/dist/compatible-sets.js +81 -0
  95. package/dist/compatible-sets.js.map +1 -0
  96. package/dist/compile-check.d.ts +31 -0
  97. package/dist/compile-check.d.ts.map +1 -0
  98. package/dist/compile-check.js +34 -0
  99. package/dist/compile-check.js.map +1 -0
  100. package/dist/compile-store.d.ts +16 -0
  101. package/dist/compile-store.d.ts.map +1 -0
  102. package/dist/compile-store.js +21 -0
  103. package/dist/compile-store.js.map +1 -0
  104. package/dist/completion.d.ts +106 -0
  105. package/dist/completion.d.ts.map +1 -0
  106. package/dist/completion.js +131 -0
  107. package/dist/completion.js.map +1 -0
  108. package/dist/config.d.ts +549 -0
  109. package/dist/config.d.ts.map +1 -0
  110. package/dist/config.js +763 -0
  111. package/dist/config.js.map +1 -0
  112. package/dist/control-file.d.ts +142 -0
  113. package/dist/control-file.d.ts.map +1 -0
  114. package/dist/control-file.js +144 -0
  115. package/dist/control-file.js.map +1 -0
  116. package/dist/coordinator-state.d.ts +131 -0
  117. package/dist/coordinator-state.d.ts.map +1 -0
  118. package/dist/coordinator-state.js +380 -0
  119. package/dist/coordinator-state.js.map +1 -0
  120. package/dist/coordinator.d.ts +95 -0
  121. package/dist/coordinator.d.ts.map +1 -0
  122. package/dist/coordinator.js +97 -0
  123. package/dist/coordinator.js.map +1 -0
  124. package/dist/cursor-store.d.ts +53 -0
  125. package/dist/cursor-store.d.ts.map +1 -0
  126. package/dist/cursor-store.js +98 -0
  127. package/dist/cursor-store.js.map +1 -0
  128. package/dist/daemon-cmd.d.ts +239 -0
  129. package/dist/daemon-cmd.d.ts.map +1 -0
  130. package/dist/daemon-cmd.js +1751 -0
  131. package/dist/daemon-cmd.js.map +1 -0
  132. package/dist/daemon-lock.d.ts +140 -0
  133. package/dist/daemon-lock.d.ts.map +1 -0
  134. package/dist/daemon-lock.js +352 -0
  135. package/dist/daemon-lock.js.map +1 -0
  136. package/dist/daemon-recovery.d.ts +78 -0
  137. package/dist/daemon-recovery.d.ts.map +1 -0
  138. package/dist/daemon-recovery.js +161 -0
  139. package/dist/daemon-recovery.js.map +1 -0
  140. package/dist/daemon.d.ts +368 -0
  141. package/dist/daemon.d.ts.map +1 -0
  142. package/dist/daemon.js +601 -0
  143. package/dist/daemon.js.map +1 -0
  144. package/dist/declared-response-shape.d.ts +93 -0
  145. package/dist/declared-response-shape.d.ts.map +1 -0
  146. package/dist/declared-response-shape.js +200 -0
  147. package/dist/declared-response-shape.js.map +1 -0
  148. package/dist/declared-surfaces.d.ts +16 -0
  149. package/dist/declared-surfaces.d.ts.map +1 -0
  150. package/dist/declared-surfaces.js +19 -0
  151. package/dist/declared-surfaces.js.map +1 -0
  152. package/dist/depends-review.d.ts +113 -0
  153. package/dist/depends-review.d.ts.map +1 -0
  154. package/dist/depends-review.js +110 -0
  155. package/dist/depends-review.js.map +1 -0
  156. package/dist/doctor.d.ts +91 -0
  157. package/dist/doctor.d.ts.map +1 -0
  158. package/dist/doctor.js +71 -0
  159. package/dist/doctor.js.map +1 -0
  160. package/dist/edge-approval.d.ts +105 -0
  161. package/dist/edge-approval.d.ts.map +1 -0
  162. package/dist/edge-approval.js +100 -0
  163. package/dist/edge-approval.js.map +1 -0
  164. package/dist/evidence-cache.d.ts +45 -0
  165. package/dist/evidence-cache.d.ts.map +1 -0
  166. package/dist/evidence-cache.js +90 -0
  167. package/dist/evidence-cache.js.map +1 -0
  168. package/dist/evidence-cmd.d.ts +133 -0
  169. package/dist/evidence-cmd.d.ts.map +1 -0
  170. package/dist/evidence-cmd.js +347 -0
  171. package/dist/evidence-cmd.js.map +1 -0
  172. package/dist/evidence-facts.d.ts +40 -0
  173. package/dist/evidence-facts.d.ts.map +1 -0
  174. package/dist/evidence-facts.js +114 -0
  175. package/dist/evidence-facts.js.map +1 -0
  176. package/dist/exclusive-lock.d.ts +52 -0
  177. package/dist/exclusive-lock.d.ts.map +1 -0
  178. package/dist/exclusive-lock.js +150 -0
  179. package/dist/exclusive-lock.js.map +1 -0
  180. package/dist/exec-domains.d.ts +140 -0
  181. package/dist/exec-domains.d.ts.map +1 -0
  182. package/dist/exec-domains.js +287 -0
  183. package/dist/exec-domains.js.map +1 -0
  184. package/dist/exemption-store.d.ts +197 -0
  185. package/dist/exemption-store.d.ts.map +1 -0
  186. package/dist/exemption-store.js +266 -0
  187. package/dist/exemption-store.js.map +1 -0
  188. package/dist/explicit-start-gate.d.ts +96 -0
  189. package/dist/explicit-start-gate.d.ts.map +1 -0
  190. package/dist/explicit-start-gate.js +103 -0
  191. package/dist/explicit-start-gate.js.map +1 -0
  192. package/dist/fs-trouble.d.ts +70 -0
  193. package/dist/fs-trouble.d.ts.map +1 -0
  194. package/dist/fs-trouble.js +98 -0
  195. package/dist/fs-trouble.js.map +1 -0
  196. package/dist/gate.d.ts +278 -0
  197. package/dist/gate.d.ts.map +1 -0
  198. package/dist/gate.js +278 -0
  199. package/dist/gate.js.map +1 -0
  200. package/dist/git-driver.d.ts +519 -0
  201. package/dist/git-driver.d.ts.map +1 -0
  202. package/dist/git-driver.js +900 -0
  203. package/dist/git-driver.js.map +1 -0
  204. package/dist/git-push-executor.d.ts +41 -0
  205. package/dist/git-push-executor.d.ts.map +1 -0
  206. package/dist/git-push-executor.js +142 -0
  207. package/dist/git-push-executor.js.map +1 -0
  208. package/dist/glob.d.ts +26 -0
  209. package/dist/glob.d.ts.map +1 -0
  210. package/dist/glob.js +93 -0
  211. package/dist/glob.js.map +1 -0
  212. package/dist/goal-adaptive.d.ts +295 -0
  213. package/dist/goal-adaptive.d.ts.map +1 -0
  214. package/dist/goal-adaptive.js +393 -0
  215. package/dist/goal-adaptive.js.map +1 -0
  216. package/dist/goal-compile.d.ts +342 -0
  217. package/dist/goal-compile.d.ts.map +1 -0
  218. package/dist/goal-compile.js +444 -0
  219. package/dist/goal-compile.js.map +1 -0
  220. package/dist/goal-depends-executor.d.ts +55 -0
  221. package/dist/goal-depends-executor.d.ts.map +1 -0
  222. package/dist/goal-depends-executor.js +202 -0
  223. package/dist/goal-depends-executor.js.map +1 -0
  224. package/dist/goal-execution-evidence.d.ts +135 -0
  225. package/dist/goal-execution-evidence.d.ts.map +1 -0
  226. package/dist/goal-execution-evidence.js +159 -0
  227. package/dist/goal-execution-evidence.js.map +1 -0
  228. package/dist/goal-gap.d.ts +140 -0
  229. package/dist/goal-gap.d.ts.map +1 -0
  230. package/dist/goal-gap.js +197 -0
  231. package/dist/goal-gap.js.map +1 -0
  232. package/dist/goal-met-target.d.ts +98 -0
  233. package/dist/goal-met-target.d.ts.map +1 -0
  234. package/dist/goal-met-target.js +92 -0
  235. package/dist/goal-met-target.js.map +1 -0
  236. package/dist/goal-ownership.d.ts +416 -0
  237. package/dist/goal-ownership.d.ts.map +1 -0
  238. package/dist/goal-ownership.js +576 -0
  239. package/dist/goal-ownership.js.map +1 -0
  240. package/dist/goal-runs.d.ts +82 -0
  241. package/dist/goal-runs.d.ts.map +1 -0
  242. package/dist/goal-runs.js +120 -0
  243. package/dist/goal-runs.js.map +1 -0
  244. package/dist/goal-store.d.ts +146 -0
  245. package/dist/goal-store.d.ts.map +1 -0
  246. package/dist/goal-store.js +294 -0
  247. package/dist/goal-store.js.map +1 -0
  248. package/dist/goal-view.d.ts +156 -0
  249. package/dist/goal-view.d.ts.map +1 -0
  250. package/dist/goal-view.js +499 -0
  251. package/dist/goal-view.js.map +1 -0
  252. package/dist/governed-approvals.d.ts +152 -0
  253. package/dist/governed-approvals.d.ts.map +1 -0
  254. package/dist/governed-approvals.js +246 -0
  255. package/dist/governed-approvals.js.map +1 -0
  256. package/dist/governed-broker.d.ts +169 -0
  257. package/dist/governed-broker.d.ts.map +1 -0
  258. package/dist/governed-broker.js +196 -0
  259. package/dist/governed-broker.js.map +1 -0
  260. package/dist/governed-run.d.ts +220 -0
  261. package/dist/governed-run.d.ts.map +1 -0
  262. package/dist/governed-run.js +406 -0
  263. package/dist/governed-run.js.map +1 -0
  264. package/dist/grant-reconcile.d.ts +63 -0
  265. package/dist/grant-reconcile.d.ts.map +1 -0
  266. package/dist/grant-reconcile.js +121 -0
  267. package/dist/grant-reconcile.js.map +1 -0
  268. package/dist/index-for-head.d.ts +56 -0
  269. package/dist/index-for-head.d.ts.map +1 -0
  270. package/dist/index-for-head.js +103 -0
  271. package/dist/index-for-head.js.map +1 -0
  272. package/dist/index.d.ts +39 -0
  273. package/dist/index.d.ts.map +1 -0
  274. package/dist/index.js +55 -0
  275. package/dist/index.js.map +1 -0
  276. package/dist/init-detect.d.ts +39 -0
  277. package/dist/init-detect.d.ts.map +1 -0
  278. package/dist/init-detect.js +188 -0
  279. package/dist/init-detect.js.map +1 -0
  280. package/dist/integration-deps.d.ts +62 -0
  281. package/dist/integration-deps.d.ts.map +1 -0
  282. package/dist/integration-deps.js +251 -0
  283. package/dist/integration-deps.js.map +1 -0
  284. package/dist/integration-runtime.d.ts +458 -0
  285. package/dist/integration-runtime.d.ts.map +1 -0
  286. package/dist/integration-runtime.js +681 -0
  287. package/dist/integration-runtime.js.map +1 -0
  288. package/dist/integration.d.ts +45 -0
  289. package/dist/integration.d.ts.map +1 -0
  290. package/dist/integration.js +87 -0
  291. package/dist/integration.js.map +1 -0
  292. package/dist/integrator.d.ts +84 -0
  293. package/dist/integrator.d.ts.map +1 -0
  294. package/dist/integrator.js +193 -0
  295. package/dist/integrator.js.map +1 -0
  296. package/dist/lane-claims.d.ts +174 -0
  297. package/dist/lane-claims.d.ts.map +1 -0
  298. package/dist/lane-claims.js +218 -0
  299. package/dist/lane-claims.js.map +1 -0
  300. package/dist/lane-coverage.d.ts +87 -0
  301. package/dist/lane-coverage.d.ts.map +1 -0
  302. package/dist/lane-coverage.js +129 -0
  303. package/dist/lane-coverage.js.map +1 -0
  304. package/dist/ledger-replay.d.ts +115 -0
  305. package/dist/ledger-replay.d.ts.map +1 -0
  306. package/dist/ledger-replay.js +155 -0
  307. package/dist/ledger-replay.js.map +1 -0
  308. package/dist/ledger-store.d.ts +68 -0
  309. package/dist/ledger-store.d.ts.map +1 -0
  310. package/dist/ledger-store.js +111 -0
  311. package/dist/ledger-store.js.map +1 -0
  312. package/dist/loop-safety-observer.d.ts +132 -0
  313. package/dist/loop-safety-observer.d.ts.map +1 -0
  314. package/dist/loop-safety-observer.js +76 -0
  315. package/dist/loop-safety-observer.js.map +1 -0
  316. package/dist/loop-safety-store.d.ts +339 -0
  317. package/dist/loop-safety-store.d.ts.map +1 -0
  318. package/dist/loop-safety-store.js +800 -0
  319. package/dist/loop-safety-store.js.map +1 -0
  320. package/dist/machine-store.d.ts +54 -0
  321. package/dist/machine-store.d.ts.map +1 -0
  322. package/dist/machine-store.js +149 -0
  323. package/dist/machine-store.js.map +1 -0
  324. package/dist/mcp-main.d.ts +2 -0
  325. package/dist/mcp-main.d.ts.map +1 -0
  326. package/dist/mcp-main.js +116 -0
  327. package/dist/mcp-main.js.map +1 -0
  328. package/dist/mcp-server.d.ts +72 -0
  329. package/dist/mcp-server.d.ts.map +1 -0
  330. package/dist/mcp-server.js +259 -0
  331. package/dist/mcp-server.js.map +1 -0
  332. package/dist/model-routing.d.ts +75 -0
  333. package/dist/model-routing.d.ts.map +1 -0
  334. package/dist/model-routing.js +108 -0
  335. package/dist/model-routing.js.map +1 -0
  336. package/dist/model-transport.d.ts +188 -0
  337. package/dist/model-transport.d.ts.map +1 -0
  338. package/dist/model-transport.js +625 -0
  339. package/dist/model-transport.js.map +1 -0
  340. package/dist/notify-cadence.d.ts +55 -0
  341. package/dist/notify-cadence.d.ts.map +1 -0
  342. package/dist/notify-cadence.js +68 -0
  343. package/dist/notify-cadence.js.map +1 -0
  344. package/dist/notify-channel.d.ts +69 -0
  345. package/dist/notify-channel.d.ts.map +1 -0
  346. package/dist/notify-channel.js +151 -0
  347. package/dist/notify-channel.js.map +1 -0
  348. package/dist/notify.d.ts +71 -0
  349. package/dist/notify.d.ts.map +1 -0
  350. package/dist/notify.js +125 -0
  351. package/dist/notify.js.map +1 -0
  352. package/dist/observation-inventory.d.ts +65 -0
  353. package/dist/observation-inventory.d.ts.map +1 -0
  354. package/dist/observation-inventory.js +139 -0
  355. package/dist/observation-inventory.js.map +1 -0
  356. package/dist/owned-children.d.ts +45 -0
  357. package/dist/owned-children.d.ts.map +1 -0
  358. package/dist/owned-children.js +64 -0
  359. package/dist/owned-children.js.map +1 -0
  360. package/dist/packet-for-goal.d.ts +19 -0
  361. package/dist/packet-for-goal.d.ts.map +1 -0
  362. package/dist/packet-for-goal.js +32 -0
  363. package/dist/packet-for-goal.js.map +1 -0
  364. package/dist/pair-cmd.d.ts +85 -0
  365. package/dist/pair-cmd.d.ts.map +1 -0
  366. package/dist/pair-cmd.js +205 -0
  367. package/dist/pair-cmd.js.map +1 -0
  368. package/dist/partial-asker.d.ts +96 -0
  369. package/dist/partial-asker.d.ts.map +1 -0
  370. package/dist/partial-asker.js +117 -0
  371. package/dist/partial-asker.js.map +1 -0
  372. package/dist/pdf-text-lines.d.ts +17 -0
  373. package/dist/pdf-text-lines.d.ts.map +1 -0
  374. package/dist/pdf-text-lines.js +70 -0
  375. package/dist/pdf-text-lines.js.map +1 -0
  376. package/dist/pdf-text-worker.d.ts +2 -0
  377. package/dist/pdf-text-worker.d.ts.map +1 -0
  378. package/dist/pdf-text-worker.js +81 -0
  379. package/dist/pdf-text-worker.js.map +1 -0
  380. package/dist/pdf-text.d.ts +56 -0
  381. package/dist/pdf-text.d.ts.map +1 -0
  382. package/dist/pdf-text.js +64 -0
  383. package/dist/pdf-text.js.map +1 -0
  384. package/dist/pending-action.d.ts +154 -0
  385. package/dist/pending-action.d.ts.map +1 -0
  386. package/dist/pending-action.js +148 -0
  387. package/dist/pending-action.js.map +1 -0
  388. package/dist/preemptor.d.ts +40 -0
  389. package/dist/preemptor.d.ts.map +1 -0
  390. package/dist/preemptor.js +49 -0
  391. package/dist/preemptor.js.map +1 -0
  392. package/dist/programme-mode.d.ts +29 -0
  393. package/dist/programme-mode.d.ts.map +1 -0
  394. package/dist/programme-mode.js +50 -0
  395. package/dist/programme-mode.js.map +1 -0
  396. package/dist/progress-view.d.ts +14 -0
  397. package/dist/progress-view.d.ts.map +1 -0
  398. package/dist/progress-view.js +114 -0
  399. package/dist/progress-view.js.map +1 -0
  400. package/dist/project-graph-builder.d.ts +81 -0
  401. package/dist/project-graph-builder.d.ts.map +1 -0
  402. package/dist/project-graph-builder.js +246 -0
  403. package/dist/project-graph-builder.js.map +1 -0
  404. package/dist/project-graph-runtime.d.ts +86 -0
  405. package/dist/project-graph-runtime.d.ts.map +1 -0
  406. package/dist/project-graph-runtime.js +112 -0
  407. package/dist/project-graph-runtime.js.map +1 -0
  408. package/dist/project-index-builder.d.ts +96 -0
  409. package/dist/project-index-builder.d.ts.map +1 -0
  410. package/dist/project-index-builder.js +298 -0
  411. package/dist/project-index-builder.js.map +1 -0
  412. package/dist/project-index-facts.d.ts +51 -0
  413. package/dist/project-index-facts.d.ts.map +1 -0
  414. package/dist/project-index-facts.js +117 -0
  415. package/dist/project-index-facts.js.map +1 -0
  416. package/dist/project-index-store.d.ts +97 -0
  417. package/dist/project-index-store.d.ts.map +1 -0
  418. package/dist/project-index-store.js +140 -0
  419. package/dist/project-index-store.js.map +1 -0
  420. package/dist/project-memory-store.d.ts +127 -0
  421. package/dist/project-memory-store.d.ts.map +1 -0
  422. package/dist/project-memory-store.js +302 -0
  423. package/dist/project-memory-store.js.map +1 -0
  424. package/dist/proposal-store.d.ts +14 -0
  425. package/dist/proposal-store.d.ts.map +1 -0
  426. package/dist/proposal-store.js +19 -0
  427. package/dist/proposal-store.js.map +1 -0
  428. package/dist/prover.d.ts +80 -0
  429. package/dist/prover.d.ts.map +1 -0
  430. package/dist/prover.js +137 -0
  431. package/dist/prover.js.map +1 -0
  432. package/dist/provider-identity-store.d.ts +34 -0
  433. package/dist/provider-identity-store.d.ts.map +1 -0
  434. package/dist/provider-identity-store.js +72 -0
  435. package/dist/provider-identity-store.js.map +1 -0
  436. package/dist/provider-identity.d.ts +104 -0
  437. package/dist/provider-identity.d.ts.map +1 -0
  438. package/dist/provider-identity.js +167 -0
  439. package/dist/provider-identity.js.map +1 -0
  440. package/dist/provider-limit.d.ts +79 -0
  441. package/dist/provider-limit.d.ts.map +1 -0
  442. package/dist/provider-limit.js +148 -0
  443. package/dist/provider-limit.js.map +1 -0
  444. package/dist/provider-preflight.d.ts +171 -0
  445. package/dist/provider-preflight.d.ts.map +1 -0
  446. package/dist/provider-preflight.js +395 -0
  447. package/dist/provider-preflight.js.map +1 -0
  448. package/dist/provider-state.d.ts +120 -0
  449. package/dist/provider-state.d.ts.map +1 -0
  450. package/dist/provider-state.js +182 -0
  451. package/dist/provider-state.js.map +1 -0
  452. package/dist/providers.d.ts +132 -0
  453. package/dist/providers.d.ts.map +1 -0
  454. package/dist/providers.js +161 -0
  455. package/dist/providers.js.map +1 -0
  456. package/dist/publication-recorder.d.ts +117 -0
  457. package/dist/publication-recorder.d.ts.map +1 -0
  458. package/dist/publication-recorder.js +124 -0
  459. package/dist/publication-recorder.js.map +1 -0
  460. package/dist/pursuit-delivery.d.ts +24 -0
  461. package/dist/pursuit-delivery.d.ts.map +1 -0
  462. package/dist/pursuit-delivery.js +38 -0
  463. package/dist/pursuit-delivery.js.map +1 -0
  464. package/dist/queue-store.d.ts +132 -0
  465. package/dist/queue-store.d.ts.map +1 -0
  466. package/dist/queue-store.js +185 -0
  467. package/dist/queue-store.js.map +1 -0
  468. package/dist/queue-summary.d.ts +14 -0
  469. package/dist/queue-summary.d.ts.map +1 -0
  470. package/dist/queue-summary.js +82 -0
  471. package/dist/queue-summary.js.map +1 -0
  472. package/dist/queue-view.d.ts +20 -0
  473. package/dist/queue-view.d.ts.map +1 -0
  474. package/dist/queue-view.js +163 -0
  475. package/dist/queue-view.js.map +1 -0
  476. package/dist/queue-write-lease.d.ts +106 -0
  477. package/dist/queue-write-lease.d.ts.map +1 -0
  478. package/dist/queue-write-lease.js +282 -0
  479. package/dist/queue-write-lease.js.map +1 -0
  480. package/dist/rails-home.d.ts +162 -0
  481. package/dist/rails-home.d.ts.map +1 -0
  482. package/dist/rails-home.js +452 -0
  483. package/dist/rails-home.js.map +1 -0
  484. package/dist/rails-migrations.d.ts +75 -0
  485. package/dist/rails-migrations.d.ts.map +1 -0
  486. package/dist/rails-migrations.js +199 -0
  487. package/dist/rails-migrations.js.map +1 -0
  488. package/dist/rails-stores.d.ts +49 -0
  489. package/dist/rails-stores.d.ts.map +1 -0
  490. package/dist/rails-stores.js +100 -0
  491. package/dist/rails-stores.js.map +1 -0
  492. package/dist/reaper.d.ts +69 -0
  493. package/dist/reaper.d.ts.map +1 -0
  494. package/dist/reaper.js +152 -0
  495. package/dist/reaper.js.map +1 -0
  496. package/dist/record-store.d.ts +36 -0
  497. package/dist/record-store.d.ts.map +1 -0
  498. package/dist/record-store.js +78 -0
  499. package/dist/record-store.js.map +1 -0
  500. package/dist/recovery-io.d.ts +50 -0
  501. package/dist/recovery-io.d.ts.map +1 -0
  502. package/dist/recovery-io.js +122 -0
  503. package/dist/recovery-io.js.map +1 -0
  504. package/dist/recovery.d.ts +146 -0
  505. package/dist/recovery.d.ts.map +1 -0
  506. package/dist/recovery.js +110 -0
  507. package/dist/recovery.js.map +1 -0
  508. package/dist/redraw.d.ts +34 -0
  509. package/dist/redraw.d.ts.map +1 -0
  510. package/dist/redraw.js +62 -0
  511. package/dist/redraw.js.map +1 -0
  512. package/dist/rejected-evidence.d.ts +255 -0
  513. package/dist/rejected-evidence.d.ts.map +1 -0
  514. package/dist/rejected-evidence.js +324 -0
  515. package/dist/rejected-evidence.js.map +1 -0
  516. package/dist/report-cmd.d.ts +32 -0
  517. package/dist/report-cmd.d.ts.map +1 -0
  518. package/dist/report-cmd.js +201 -0
  519. package/dist/report-cmd.js.map +1 -0
  520. package/dist/repos-cmd.d.ts +80 -0
  521. package/dist/repos-cmd.d.ts.map +1 -0
  522. package/dist/repos-cmd.js +240 -0
  523. package/dist/repos-cmd.js.map +1 -0
  524. package/dist/request-body-shape.d.ts +93 -0
  525. package/dist/request-body-shape.d.ts.map +1 -0
  526. package/dist/request-body-shape.js +407 -0
  527. package/dist/request-body-shape.js.map +1 -0
  528. package/dist/requirement-claims.d.ts +89 -0
  529. package/dist/requirement-claims.d.ts.map +1 -0
  530. package/dist/requirement-claims.js +92 -0
  531. package/dist/requirement-claims.js.map +1 -0
  532. package/dist/retention-apply-runtime.d.ts +105 -0
  533. package/dist/retention-apply-runtime.d.ts.map +1 -0
  534. package/dist/retention-apply-runtime.js +269 -0
  535. package/dist/retention-apply-runtime.js.map +1 -0
  536. package/dist/reverify.d.ts +41 -0
  537. package/dist/reverify.d.ts.map +1 -0
  538. package/dist/reverify.js +69 -0
  539. package/dist/reverify.js.map +1 -0
  540. package/dist/round-records.d.ts +65 -0
  541. package/dist/round-records.d.ts.map +1 -0
  542. package/dist/round-records.js +61 -0
  543. package/dist/round-records.js.map +1 -0
  544. package/dist/round-runner.d.ts +924 -0
  545. package/dist/round-runner.d.ts.map +1 -0
  546. package/dist/round-runner.js +1693 -0
  547. package/dist/round-runner.js.map +1 -0
  548. package/dist/run-approval.d.ts +180 -0
  549. package/dist/run-approval.d.ts.map +1 -0
  550. package/dist/run-approval.js +199 -0
  551. package/dist/run-approval.js.map +1 -0
  552. package/dist/run-cmd.d.ts +359 -0
  553. package/dist/run-cmd.d.ts.map +1 -0
  554. package/dist/run-cmd.js +4418 -0
  555. package/dist/run-cmd.js.map +1 -0
  556. package/dist/run-delivery.d.ts +71 -0
  557. package/dist/run-delivery.d.ts.map +1 -0
  558. package/dist/run-delivery.js +104 -0
  559. package/dist/run-delivery.js.map +1 -0
  560. package/dist/run-ended.d.ts +75 -0
  561. package/dist/run-ended.d.ts.map +1 -0
  562. package/dist/run-ended.js +27 -0
  563. package/dist/run-ended.js.map +1 -0
  564. package/dist/run-ending-locator.d.ts +125 -0
  565. package/dist/run-ending-locator.d.ts.map +1 -0
  566. package/dist/run-ending-locator.js +133 -0
  567. package/dist/run-ending-locator.js.map +1 -0
  568. package/dist/run-launcher.d.ts +459 -0
  569. package/dist/run-launcher.d.ts.map +1 -0
  570. package/dist/run-launcher.js +652 -0
  571. package/dist/run-launcher.js.map +1 -0
  572. package/dist/run-lease.d.ts +208 -0
  573. package/dist/run-lease.d.ts.map +1 -0
  574. package/dist/run-lease.js +301 -0
  575. package/dist/run-lease.js.map +1 -0
  576. package/dist/run-refusal-marks.d.ts +189 -0
  577. package/dist/run-refusal-marks.d.ts.map +1 -0
  578. package/dist/run-refusal-marks.js +249 -0
  579. package/dist/run-refusal-marks.js.map +1 -0
  580. package/dist/run-start-marks.d.ts +153 -0
  581. package/dist/run-start-marks.d.ts.map +1 -0
  582. package/dist/run-start-marks.js +269 -0
  583. package/dist/run-start-marks.js.map +1 -0
  584. package/dist/scan-cmd.d.ts +14 -0
  585. package/dist/scan-cmd.d.ts.map +1 -0
  586. package/dist/scan-cmd.js +270 -0
  587. package/dist/scan-cmd.js.map +1 -0
  588. package/dist/scan-events.d.ts +50 -0
  589. package/dist/scan-events.d.ts.map +1 -0
  590. package/dist/scan-events.js +91 -0
  591. package/dist/scan-events.js.map +1 -0
  592. package/dist/scan.d.ts +191 -0
  593. package/dist/scan.d.ts.map +1 -0
  594. package/dist/scan.js +417 -0
  595. package/dist/scan.js.map +1 -0
  596. package/dist/scope-rule.d.ts +148 -0
  597. package/dist/scope-rule.d.ts.map +1 -0
  598. package/dist/scope-rule.js +121 -0
  599. package/dist/scope-rule.js.map +1 -0
  600. package/dist/self-repo-id.d.ts +18 -0
  601. package/dist/self-repo-id.d.ts.map +1 -0
  602. package/dist/self-repo-id.js +70 -0
  603. package/dist/self-repo-id.js.map +1 -0
  604. package/dist/server-client.d.ts +766 -0
  605. package/dist/server-client.d.ts.map +1 -0
  606. package/dist/server-client.js +475 -0
  607. package/dist/server-client.js.map +1 -0
  608. package/dist/session-adapter-runtime.d.ts +195 -0
  609. package/dist/session-adapter-runtime.d.ts.map +1 -0
  610. package/dist/session-adapter-runtime.js +373 -0
  611. package/dist/session-adapter-runtime.js.map +1 -0
  612. package/dist/session-checkpoint-runtime.d.ts +62 -0
  613. package/dist/session-checkpoint-runtime.d.ts.map +1 -0
  614. package/dist/session-checkpoint-runtime.js +268 -0
  615. package/dist/session-checkpoint-runtime.js.map +1 -0
  616. package/dist/session-control-transport.d.ts +106 -0
  617. package/dist/session-control-transport.d.ts.map +1 -0
  618. package/dist/session-control-transport.js +232 -0
  619. package/dist/session-control-transport.js.map +1 -0
  620. package/dist/session-observation-store.d.ts +98 -0
  621. package/dist/session-observation-store.d.ts.map +1 -0
  622. package/dist/session-observation-store.js +155 -0
  623. package/dist/session-observation-store.js.map +1 -0
  624. package/dist/session-observe-runtime.d.ts +123 -0
  625. package/dist/session-observe-runtime.d.ts.map +1 -0
  626. package/dist/session-observe-runtime.js +317 -0
  627. package/dist/session-observe-runtime.js.map +1 -0
  628. package/dist/session-store.d.ts +98 -0
  629. package/dist/session-store.d.ts.map +1 -0
  630. package/dist/session-store.js +116 -0
  631. package/dist/session-store.js.map +1 -0
  632. package/dist/sessions-cmd.d.ts +202 -0
  633. package/dist/sessions-cmd.d.ts.map +1 -0
  634. package/dist/sessions-cmd.js +609 -0
  635. package/dist/sessions-cmd.js.map +1 -0
  636. package/dist/settings-overlay.d.ts +53 -0
  637. package/dist/settings-overlay.d.ts.map +1 -0
  638. package/dist/settings-overlay.js +175 -0
  639. package/dist/settings-overlay.js.map +1 -0
  640. package/dist/setup-prompt.d.ts +34 -0
  641. package/dist/setup-prompt.d.ts.map +1 -0
  642. package/dist/setup-prompt.js +92 -0
  643. package/dist/setup-prompt.js.map +1 -0
  644. package/dist/setup.d.ts +103 -0
  645. package/dist/setup.d.ts.map +1 -0
  646. package/dist/setup.js +283 -0
  647. package/dist/setup.js.map +1 -0
  648. package/dist/shared-grants.d.ts +164 -0
  649. package/dist/shared-grants.d.ts.map +1 -0
  650. package/dist/shared-grants.js +242 -0
  651. package/dist/shared-grants.js.map +1 -0
  652. package/dist/signals.d.ts +55 -0
  653. package/dist/signals.d.ts.map +1 -0
  654. package/dist/signals.js +85 -0
  655. package/dist/signals.js.map +1 -0
  656. package/dist/source-cmd.d.ts +201 -0
  657. package/dist/source-cmd.d.ts.map +1 -0
  658. package/dist/source-cmd.js +684 -0
  659. package/dist/source-cmd.js.map +1 -0
  660. package/dist/source-verdict.d.ts +99 -0
  661. package/dist/source-verdict.d.ts.map +1 -0
  662. package/dist/source-verdict.js +182 -0
  663. package/dist/source-verdict.js.map +1 -0
  664. package/dist/spend-ledger.d.ts +350 -0
  665. package/dist/spend-ledger.d.ts.map +1 -0
  666. package/dist/spend-ledger.js +546 -0
  667. package/dist/spend-ledger.js.map +1 -0
  668. package/dist/stale-run-sweep.d.ts +79 -0
  669. package/dist/stale-run-sweep.d.ts.map +1 -0
  670. package/dist/stale-run-sweep.js +116 -0
  671. package/dist/stale-run-sweep.js.map +1 -0
  672. package/dist/start-attempts.d.ts +385 -0
  673. package/dist/start-attempts.d.ts.map +1 -0
  674. package/dist/start-attempts.js +613 -0
  675. package/dist/start-attempts.js.map +1 -0
  676. package/dist/status-cmd.d.ts +28 -0
  677. package/dist/status-cmd.d.ts.map +1 -0
  678. package/dist/status-cmd.js +116 -0
  679. package/dist/status-cmd.js.map +1 -0
  680. package/dist/stop-follow-up.d.ts +107 -0
  681. package/dist/stop-follow-up.d.ts.map +1 -0
  682. package/dist/stop-follow-up.js +172 -0
  683. package/dist/stop-follow-up.js.map +1 -0
  684. package/dist/surface-lease.d.ts +118 -0
  685. package/dist/surface-lease.d.ts.map +1 -0
  686. package/dist/surface-lease.js +485 -0
  687. package/dist/surface-lease.js.map +1 -0
  688. package/dist/sync.d.ts +54 -0
  689. package/dist/sync.d.ts.map +1 -0
  690. package/dist/sync.js +93 -0
  691. package/dist/sync.js.map +1 -0
  692. package/dist/syncing-ledger.d.ts +45 -0
  693. package/dist/syncing-ledger.d.ts.map +1 -0
  694. package/dist/syncing-ledger.js +53 -0
  695. package/dist/syncing-ledger.js.map +1 -0
  696. package/dist/temp-fixtures.d.ts +68 -0
  697. package/dist/temp-fixtures.d.ts.map +1 -0
  698. package/dist/temp-fixtures.js +38 -0
  699. package/dist/temp-fixtures.js.map +1 -0
  700. package/dist/token-window.d.ts +84 -0
  701. package/dist/token-window.d.ts.map +1 -0
  702. package/dist/token-window.js +143 -0
  703. package/dist/token-window.js.map +1 -0
  704. package/dist/tool-bridge.d.ts +177 -0
  705. package/dist/tool-bridge.d.ts.map +1 -0
  706. package/dist/tool-bridge.js +329 -0
  707. package/dist/tool-bridge.js.map +1 -0
  708. package/dist/tool-call-record.d.ts +197 -0
  709. package/dist/tool-call-record.d.ts.map +1 -0
  710. package/dist/tool-call-record.js +276 -0
  711. package/dist/tool-call-record.js.map +1 -0
  712. package/dist/tool-protocol.d.ts +135 -0
  713. package/dist/tool-protocol.d.ts.map +1 -0
  714. package/dist/tool-protocol.js +104 -0
  715. package/dist/tool-protocol.js.map +1 -0
  716. package/dist/tool-worker.d.ts +3 -0
  717. package/dist/tool-worker.d.ts.map +1 -0
  718. package/dist/tool-worker.js +478 -0
  719. package/dist/tool-worker.js.map +1 -0
  720. package/dist/toolchain-mirror.d.ts +86 -0
  721. package/dist/toolchain-mirror.d.ts.map +1 -0
  722. package/dist/toolchain-mirror.js +307 -0
  723. package/dist/toolchain-mirror.js.map +1 -0
  724. package/dist/trusted-git.d.ts +243 -0
  725. package/dist/trusted-git.d.ts.map +1 -0
  726. package/dist/trusted-git.js +920 -0
  727. package/dist/trusted-git.js.map +1 -0
  728. package/dist/ui.d.ts +76 -0
  729. package/dist/ui.d.ts.map +1 -0
  730. package/dist/ui.js +118 -0
  731. package/dist/ui.js.map +1 -0
  732. package/dist/untrusted-exec.d.ts +275 -0
  733. package/dist/untrusted-exec.d.ts.map +1 -0
  734. package/dist/untrusted-exec.js +479 -0
  735. package/dist/untrusted-exec.js.map +1 -0
  736. package/dist/untrusted-gate.d.ts +73 -0
  737. package/dist/untrusted-gate.d.ts.map +1 -0
  738. package/dist/untrusted-gate.js +226 -0
  739. package/dist/untrusted-gate.js.map +1 -0
  740. package/dist/uploader.d.ts +153 -0
  741. package/dist/uploader.d.ts.map +1 -0
  742. package/dist/uploader.js +204 -0
  743. package/dist/uploader.js.map +1 -0
  744. package/dist/verifier.d.ts +66 -0
  745. package/dist/verifier.d.ts.map +1 -0
  746. package/dist/verifier.js +170 -0
  747. package/dist/verifier.js.map +1 -0
  748. package/dist/verify-apply.d.ts +26 -0
  749. package/dist/verify-apply.d.ts.map +1 -0
  750. package/dist/verify-apply.js +36 -0
  751. package/dist/verify-apply.js.map +1 -0
  752. package/dist/verify-cmd.d.ts +44 -0
  753. package/dist/verify-cmd.d.ts.map +1 -0
  754. package/dist/verify-cmd.js +125 -0
  755. package/dist/verify-cmd.js.map +1 -0
  756. package/dist/verify-pass.d.ts +73 -0
  757. package/dist/verify-pass.d.ts.map +1 -0
  758. package/dist/verify-pass.js +103 -0
  759. package/dist/verify-pass.js.map +1 -0
  760. package/dist/welcome.d.ts +43 -0
  761. package/dist/welcome.d.ts.map +1 -0
  762. package/dist/welcome.js +116 -0
  763. package/dist/welcome.js.map +1 -0
  764. package/dist/workspace-provisioner.d.ts +65 -0
  765. package/dist/workspace-provisioner.d.ts.map +1 -0
  766. package/dist/workspace-provisioner.js +66 -0
  767. package/dist/workspace-provisioner.js.map +1 -0
  768. package/dist/workspace-quarantine.d.ts +64 -0
  769. package/dist/workspace-quarantine.d.ts.map +1 -0
  770. package/dist/workspace-quarantine.js +156 -0
  771. package/dist/workspace-quarantine.js.map +1 -0
  772. package/dist/workspace-residue-sweep.d.ts +113 -0
  773. package/dist/workspace-residue-sweep.d.ts.map +1 -0
  774. package/dist/workspace-residue-sweep.js +158 -0
  775. package/dist/workspace-residue-sweep.js.map +1 -0
  776. package/dist/workspace.d.ts +639 -0
  777. package/dist/workspace.d.ts.map +1 -0
  778. package/dist/workspace.js +2026 -0
  779. package/dist/workspace.js.map +1 -0
  780. package/package.json +54 -6
  781. package/win/CredProbe.cs +64 -0
  782. package/win/FakeClaude.cs +56 -0
  783. package/win/HandleProbe.cs +116 -0
  784. package/win/TokenProbe.cs +53 -0
  785. package/win/appcontainer.ps1 +500 -0
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExemptionStore = void 0;
4
+ exports.grantKey = grantKey;
5
+ exports.offerableFor = offerableFor;
6
+ exports.grantsFromServer = grantsFromServer;
7
+ /** Built, not typed: a literal NUL in source is an invisible control character,
8
+ * and `source-hygiene.spec.ts` refuses those for exactly this reason. */
9
+ const NUL = String.fromCharCode(0);
10
+ /**
11
+ * A grant's identity, for a model that has no id of its own.
12
+ *
13
+ * 🔴 EXPIRY IS PART OF IT. Two grants for the same item and path with different
14
+ * expiries are two separate acts of permission — somebody granting the same door
15
+ * again tomorrow is not re-using yesterday's grant, and keying without the
16
+ * expiry would silently treat the new one as already spent.
17
+ *
18
+ * A NUL separator, so a path containing the separator cannot forge another
19
+ * grant's key; paths cannot contain NUL on any filesystem this runs on.
20
+ */
21
+ function grantKey(e) {
22
+ return [e.itemId, e.path, e.expiresAt].join(NUL);
23
+ }
24
+ class ExemptionStore {
25
+ stateDir;
26
+ fs;
27
+ migrate;
28
+ /** Distinguishes two writes from ONE process; the pid distinguishes processes. */
29
+ static writes = 0;
30
+ spent = {};
31
+ readable = true;
32
+ /**
33
+ * ⚠️ `migrate` RUNS BEFORE ANY READ, AND ITS REFUSAL IS AN UNREADABLE STORE.
34
+ *
35
+ * The ledger's home moved out of the repository (see `rails-home.ts`), and a
36
+ * move is the one moment when "I could not see the old records" and "there
37
+ * were no old records" look identical. This store's entire safety argument is
38
+ * that they must never look identical: an unreadable ledger answers `isSpent`
39
+ * true for everything, because treating a corrupt ledger as "nothing spent"
40
+ * re-opens every door the machine has already used.
41
+ *
42
+ * So a migration that cannot prove what was spent fails the store closed,
43
+ * exactly as an unparseable `exemptions.json` does. Omitted, there is no
44
+ * migration and nothing changes — which is what every existing test relies on.
45
+ */
46
+ constructor(stateDir, fs, migrate) {
47
+ this.stateDir = stateDir;
48
+ this.fs = fs;
49
+ this.migrate = migrate;
50
+ }
51
+ get path() {
52
+ return `${this.stateDir}/exemptions.json`;
53
+ }
54
+ /**
55
+ * Where spends are written now: APPEND-ONLY, one JSON object per line.
56
+ *
57
+ * 🔴 THE WHOLE-MAP REWRITE BECAME A RAILS BYPASS THE MOMENT THIS LEDGER WAS
58
+ * SHARED. `record` used to serialise the entire `spent` map from the snapshot
59
+ * loaded at `open()` and rename it over the file. That was sound while one run
60
+ * owned one checkout. Phase 1 moved this file to the PROJECT state directory —
61
+ * so that a single-use grant could not be spent once per workspace — and made
62
+ * two runs concurrent in the same change. Two runs spending two DIFFERENT
63
+ * grants then each wrote a map that did not contain the other's spend, and the
64
+ * loser's spend was erased: a single-use grant over a railed path, spendable
65
+ * again. The scope fix had turned into a lost-update bug, which is precisely
66
+ * what the recon warned would happen if the format were left alone.
67
+ *
68
+ * An append never loses a concurrent write. `exemptions.json` is still READ,
69
+ * so a machine that has spent grants before this change keeps them, and it is
70
+ * never written again — that is the whole migration.
71
+ */
72
+ get spendLogPath() {
73
+ return `${this.stateDir}/exemptions.spent.jsonl`;
74
+ }
75
+ /**
76
+ * Read what is on disk.
77
+ *
78
+ * 🔴 AN UNREADABLE FILE FAILS CLOSED, WHICH IS THE OPPOSITE OF `CursorStore`.
79
+ *
80
+ * There it is safe to replay too much, so a corrupt cursor is treated as no
81
+ * cursor. Here the equivalent — treating a corrupt file as "nothing spent" —
82
+ * would re-open every door this machine has already used. So an unreadable
83
+ * store stops handing out grants entirely: `isSpent` answers true for
84
+ * everything, and every rail stays shut. Deny is the default the whole rails
85
+ * design rests on.
86
+ */
87
+ async open() {
88
+ if (this.migrate !== undefined) {
89
+ const moved = await this.migrate();
90
+ if (!moved.ok) {
91
+ this.readable = false;
92
+ return 'unreadable';
93
+ }
94
+ }
95
+ let text;
96
+ try {
97
+ text = await this.fs.readFile(this.path);
98
+ }
99
+ catch {
100
+ this.readable = false;
101
+ return 'unreadable';
102
+ }
103
+ // NO legacy file is the ORDINARY case now, and it is not the end of `open`:
104
+ // the append-only spend log below is where every spend since this store
105
+ // stopped rewriting a map lives. Returning 'ok' here — which the first
106
+ // version of this change did — meant a machine with no `exemptions.json`
107
+ // saw no spends at all, and every single-use grant read as unspent.
108
+ if (text === null)
109
+ return this.readSpendLog();
110
+ try {
111
+ const parsed = JSON.parse(text);
112
+ const spent = parsed?.spent;
113
+ if (typeof spent !== 'object' || spent === null) {
114
+ this.readable = false;
115
+ return 'unreadable';
116
+ }
117
+ for (const [key, round] of Object.entries(spent)) {
118
+ if (typeof round === 'number' && Number.isInteger(round))
119
+ this.spent[key] = round;
120
+ }
121
+ return this.readSpendLog();
122
+ }
123
+ catch {
124
+ this.readable = false;
125
+ return 'unreadable';
126
+ }
127
+ }
128
+ /**
129
+ * Fold the append-only spend log over whatever the legacy file held.
130
+ *
131
+ * ⚠️ FAILS CLOSED LIKE ITS SIBLING. A log that exists and cannot be read is a
132
+ * log whose spends cannot be seen, and a store that cannot see a spend would
133
+ * re-open a door somebody already used. A MALFORMED LINE is different and is
134
+ * skipped: an append can be torn by a crash mid-write, and discarding every
135
+ * spend on the strength of one truncated last line would be the same
136
+ * fail-open by another route.
137
+ */
138
+ async readSpendLog() {
139
+ let text;
140
+ try {
141
+ text = await this.fs.readFile(this.spendLogPath);
142
+ }
143
+ catch {
144
+ this.readable = false;
145
+ return 'unreadable';
146
+ }
147
+ if (text === null)
148
+ return 'ok';
149
+ for (const line of text.split('\n')) {
150
+ if (line.trim() === '')
151
+ continue;
152
+ try {
153
+ const row = JSON.parse(line);
154
+ if (typeof row.key === 'string' && typeof row.round === 'number' && Number.isInteger(row.round)) {
155
+ this.spent[row.key] = row.round;
156
+ }
157
+ }
158
+ catch {
159
+ // A torn final line, almost certainly. Skip it; the rest still count.
160
+ }
161
+ }
162
+ return 'ok';
163
+ }
164
+ /** True when this grant must not be handed to another round. Fails closed. */
165
+ isSpent(e) {
166
+ if (!this.readable)
167
+ return true;
168
+ return grantKey(e) in this.spent;
169
+ }
170
+ /**
171
+ * Record a grant as spent.
172
+ *
173
+ * ⚠️ IDEMPOTENT, AND THE FIRST ROUND WINS. A retry that spends the same grant
174
+ * again must not rewrite the round number: the round recorded is the one that
175
+ * actually used the door, and overwriting it would make the trailer and this
176
+ * file disagree about which commit opened it.
177
+ *
178
+ * A store that could not be read refuses to write. Writing a fresh file over
179
+ * one that failed to parse would discard every spend it contained.
180
+ */
181
+ async record(e) {
182
+ if (!this.readable)
183
+ return;
184
+ const key = grantKey(e);
185
+ if (key in this.spent)
186
+ return;
187
+ if (e.usedInRound === null)
188
+ return;
189
+ this.spent[key] = e.usedInRound;
190
+ await this.fs.mkdir(this.stateDir);
191
+ /**
192
+ * ONE LINE, APPENDED. No read, no map, no rename — see `spendLogPath`.
193
+ *
194
+ * ⚠️ AND NOTHING REWRITES `exemptions.json` EVER AGAIN. Leaving it alone is
195
+ * what makes the migration a non-event: a machine with spends recorded the
196
+ * old way keeps them, because `open` still reads it.
197
+ */
198
+ await this.fs.appendFile(this.spendLogPath, `${JSON.stringify({ key, round: e.usedInRound })}\n`);
199
+ }
200
+ /** What this machine has spent, for a report or a test. */
201
+ all() {
202
+ return { ...this.spent };
203
+ }
204
+ }
205
+ exports.ExemptionStore = ExemptionStore;
206
+ /**
207
+ * The grants a round may be offered for one item.
208
+ *
209
+ * ─────────────────────────────────────────────────────────────────────────────
210
+ * 🔴 THE `!isSpent` HERE IS NOT A DUPLICATE OF THE ONE IN `grantsFromServer`.
211
+ *
212
+ * That one runs ONCE, when the run starts. This one runs every time the gate
213
+ * asks, which is once per item per ROUND — and between two rounds of the same
214
+ * run a grant can be spent.
215
+ *
216
+ * Without it the wiring reproduced exactly the failure `RoundRunner` refuses to
217
+ * allow: its constructor rejects a grant source with no spend sink because that
218
+ * is "one grant reopening the same rail every round until it expires". Wiring
219
+ * both halves satisfied that check STRUCTURALLY while defeating it in fact —
220
+ * the sink recorded the spend and the source, a plain array captured before the
221
+ * first round, kept offering the same grant to every round after it. One grant,
222
+ * one round, was true only across runs and false within one.
223
+ *
224
+ * ⚠️ IT READS THE STORE'S IN-MEMORY STATE, WHICH IS WHAT MAKES IT WORK. `record`
225
+ * assigns `spent[key]` before it awaits the write, so the very next round sees
226
+ * the spend whether or not the file has landed. A store that cannot be read
227
+ * answers true for everything and every rail stays shut.
228
+ *
229
+ * ⚠️ WHAT IT DOES NOT DO: notice a grant made DURING a run. The source is
230
+ * fetched once at start, so a person who grants a rail while a run is going
231
+ * opens it for the NEXT run, not this one. That is a closed door rather than an
232
+ * open one, so it is recorded here instead of being engineered away with a
233
+ * mid-run refetch nothing asked for.
234
+ */
235
+ function offerableFor(grants, itemId, isSpent) {
236
+ return grants.filter((e) => e.itemId === itemId && !isSpent(e));
237
+ }
238
+ /**
239
+ * Server rows → the grants a round may be offered.
240
+ *
241
+ * 🔴 THREE FILTERS, AND EACH ONE IS LOAD-BEARING.
242
+ *
243
+ * - `decision === 'granted'` — a REFUSAL is recorded in the same table, and
244
+ * handing one to a gate would open the door a person explicitly shut.
245
+ * - a real `expiresAt` — the model treats a grant with no expiry as no grant;
246
+ * `listGranted` already excludes both, and asking again means a source that
247
+ * widened cannot widen the rails silently.
248
+ * - not already spent on this machine — one grant, one round.
249
+ *
250
+ * ⚠️ IT DOES NOT JUDGE THE PATH, AND MUST NOT. Whether a grant opens the file
251
+ * actually being written is decided at the interlock by `isExemptionValid`,
252
+ * which is the only place that sees it. Pre-filtering here would be a second
253
+ * opinion about the same question, free to disagree.
254
+ */
255
+ function grantsFromServer(rows, isSpent, fromGrant) {
256
+ return rows
257
+ .filter((r) => r.decision === 'granted' && typeof r.expiresAt === 'string')
258
+ .map((r) => fromGrant({
259
+ itemId: r.itemId,
260
+ path: r.path,
261
+ expiresAt: r.expiresAt,
262
+ actor: r.actor,
263
+ }))
264
+ .filter((e) => !isSpent(e));
265
+ }
266
+ //# sourceMappingURL=exemption-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exemption-store.js","sourceRoot":"","sources":["../src/exemption-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { type ApprovalGate } from '@looply/core';
2
+ import type { ApprovalResumes } from './approval-resumes';
3
+ import type { GovernedApprovals } from './governed-approvals';
4
+ import { type LeaseState } from './run-lease';
5
+ /**
6
+ * WHAT AN EXPLICIT START IS ALLOWED TO CARRY, AND WHETHER IT MAY HAPPEN AT ALL.
7
+ *
8
+ * ─────────────────────────────────────────────────────────────────────────────
9
+ * THIS EXISTS AS A MODULE BECAUSE IT USED TO BE A CLOSURE, AND THE CLOSURE HID A
10
+ * PERMANENT WEDGE
11
+ *
12
+ * `daemon-cmd.ts` built this inline over five captured values, so it had no
13
+ * export and no test seam. Every other property of the Start path had one; this
14
+ * one was reachable only by running a daemon. What it hid:
15
+ *
16
+ * `refusesExplicitStart` deliberately ADMITS `claimed`, `executing` and
17
+ * `result-pending` — it says so in as many words, because refusing them
18
+ * "would strand authority that was legitimately taken ... something has to be
19
+ * allowed to go and look". The closure then handed the run an approval id in
20
+ * ONE arm, `approved`, and dropped the other three to an ordinary Start. So
21
+ * the gate admitted the Start, nothing looked, `run-cmd` killed the run on its
22
+ * own re-read of the same gate, and the approval stayed `claimed` for ever —
23
+ * which meant every later Start did the same thing again.
24
+ *
25
+ * The behavioural half of the rule now lives in `governedStartApproval`, and
26
+ * this module is what makes the WIRING testable: the collaborators injected
27
+ * rather than captured, so a spec can hand it a gate in any state and read what
28
+ * a Start would be given.
29
+ *
30
+ * ─────────────────────────────────────────────────────────────────────────────
31
+ * WHAT IT DECIDES, IN ORDER
32
+ *
33
+ * 1. A gate that refuses is a refusal, and `terminal` decides whether the phone
34
+ * may offer the command again. Only "nobody could tell" is worth retrying.
35
+ * 2. An approval the Start must carry is reserved, so the claim key is durable
36
+ * before the run exists — and a lost reservation means opposite things
37
+ * depending on what the SERVER already recorded.
38
+ * 3. A denial is claimed, and losing that race is NOT a refusal: the winner has
39
+ * the answer, and this Start carries on as an ordinary one.
40
+ *
41
+ * Resolving WHICH pursuit is being started is the daemon's, and stays there.
42
+ */
43
+ export interface ExplicitStartDecision {
44
+ /** Why not, when not. `terminal` decides whether the phone may offer it again. */
45
+ readonly refuse?: {
46
+ readonly reason: string;
47
+ readonly terminal: boolean;
48
+ };
49
+ readonly resumedFromApprovalId?: string;
50
+ /**
51
+ * The approved action this Start has just been given the right to carry out.
52
+ *
53
+ * Never alongside `resumedFromApprovalId`: a Start either picks up an answer
54
+ * or carries one out, and both at once would be a run acting on a refusal and
55
+ * an approval in the same breath.
56
+ */
57
+ readonly governedApprovalId?: string;
58
+ }
59
+ /** Just enough of each collaborator to decide. Injected so a spec can drive it. */
60
+ export interface ExplicitStartDeps {
61
+ readonly governed: Pick<GovernedApprovals, 'reserve' | 'takeOver'>;
62
+ readonly resumes: Pick<ApprovalResumes, 'claim'>;
63
+ /**
64
+ * IS ANYTHING STILL CARRYING WORK ON THIS TREE?
65
+ *
66
+ * The run lease, read durably. This is the question a stale reservation turns
67
+ * on, and the lease already answers it in exactly the right four ways —
68
+ * `active` is a process that is running, `dead` is one that is gone,
69
+ * `ambiguous` fails closed, and `free` is nobody. Reusing it means this is not
70
+ * a second, weaker notion of liveness sitting beside the real one.
71
+ */
72
+ readonly carrier: () => Promise<LeaseState>;
73
+ readonly log: (line: string) => void;
74
+ }
75
+ /**
76
+ * 🔴 IT TAKES A GATE, NOT A WAY TO READ ONE, AND THAT IS AN ARCHITECTURAL RULE
77
+ * RATHER THAN A CONVENIENCE.
78
+ *
79
+ * The first version of this module took a gate READER plus the two identifiers
80
+ * that name a pursuit, and `apps/app/src/goal-wiring.spec.ts` failed it
81
+ * immediately: that vocabulary is confined to an allow-list of files across the
82
+ * whole tree, and this is not one of them. Widening the list would have been the
83
+ * easy answer and the wrong one — **this decision does not need to know what a
84
+ * pursuit IS.** It needs a gate and a Start. Reading the gate stays in the
85
+ * daemon, which is allowed that vocabulary because it is the thing holding one.
86
+ *
87
+ * ⚠️ Note the guardrail scans RAW LINES, comments included, so even naming those
88
+ * identifiers in this paragraph failed it a second time. That is coarse, and it
89
+ * is the safe direction: a confinement rule that reasoned about which mentions
90
+ * were "only prose" would be a rule with an exemption in it.
91
+ *
92
+ * The seam is not weakened by it: every arm, every reservation outcome and the
93
+ * takeover are all still driven from here.
94
+ */
95
+ export declare function decideExplicitStart(deps: ExplicitStartDeps, gate: ApprovalGate, requestId: string): Promise<ExplicitStartDecision>;
96
+ //# sourceMappingURL=explicit-start-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explicit-start-gate.d.ts","sourceRoot":"","sources":["../src/explicit-start-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,MAAM,WAAW,qBAAqB;IACpC,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1E,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,mFAAmF;AACnF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,UAAU,CAAC,CAAC;IACnE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IACjD;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,iBAAiB,EACvB,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC,CA4EhC"}
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decideExplicitStart = decideExplicitStart;
4
+ const core_1 = require("@looply/core");
5
+ const run_lease_1 = require("./run-lease");
6
+ /**
7
+ * 🔴 IT TAKES A GATE, NOT A WAY TO READ ONE, AND THAT IS AN ARCHITECTURAL RULE
8
+ * RATHER THAN A CONVENIENCE.
9
+ *
10
+ * The first version of this module took a gate READER plus the two identifiers
11
+ * that name a pursuit, and `apps/app/src/goal-wiring.spec.ts` failed it
12
+ * immediately: that vocabulary is confined to an allow-list of files across the
13
+ * whole tree, and this is not one of them. Widening the list would have been the
14
+ * easy answer and the wrong one — **this decision does not need to know what a
15
+ * pursuit IS.** It needs a gate and a Start. Reading the gate stays in the
16
+ * daemon, which is allowed that vocabulary because it is the thing holding one.
17
+ *
18
+ * ⚠️ Note the guardrail scans RAW LINES, comments included, so even naming those
19
+ * identifiers in this paragraph failed it a second time. That is coarse, and it
20
+ * is the safe direction: a confinement rule that reasoned about which mentions
21
+ * were "only prose" would be a rule with an exemption in it.
22
+ *
23
+ * The seam is not weakened by it: every arm, every reservation outcome and the
24
+ * takeover are all still driven from here.
25
+ */
26
+ async function decideExplicitStart(deps, gate, requestId) {
27
+ if ((0, core_1.refusesExplicitStart)(gate)) {
28
+ return {
29
+ refuse: {
30
+ reason: (0, core_1.approvalHold)(gate) ?? 'this pursuit is waiting on a person',
31
+ // Definite answers are terminal: the person taps Start again when they
32
+ // have decided, and offering the same command back every three seconds
33
+ // for an hour would be noise rather than resilience. Only "nobody could
34
+ // tell" is worth retrying.
35
+ terminal: gate.kind !== 'unknown',
36
+ },
37
+ };
38
+ }
39
+ /**
40
+ * WHICH APPROVAL THIS START CARRIES.
41
+ *
42
+ * `governedStartApproval` owns the rule, and it is stated there as an
43
+ * equality over every arm rather than as a list here — because a list here is
44
+ * exactly what drifted out of step with `refusesExplicitStart`.
45
+ *
46
+ * The reservation is taken BEFORE the run exists, because that is where two
47
+ * Starts race, and because the claim key derives from it and has to survive
48
+ * the process that made it.
49
+ */
50
+ const approvalId = (0, core_1.governedStartApproval)(gate);
51
+ if (approvalId !== null) {
52
+ const held = await deps.governed.reserve(approvalId, requestId);
53
+ if (held.ok)
54
+ return { governedApprovalId: approvalId };
55
+ /**
56
+ * A RESERVATION IS ALREADY THERE, AND THE QUESTION IS WHETHER ANYTHING IS
57
+ * STILL CARRYING IT — not which arm the gate is in.
58
+ *
59
+ * The first version of this asked the arm: it took a stale record over only
60
+ * for the three where the server had recorded a claim, and left `approved`
61
+ * on the one-shot rule with the comment "it is retryable, because the winner
62
+ * may yet fail to produce a run". That was exactly backwards. If the winner
63
+ * fails to produce a run, the approval stays `approved` for ever, the gate
64
+ * never becomes one of the other arms, the takeover is never reachable, and
65
+ * every later Start is refused non-terminally and redelivered for ever —
66
+ * the same permanent wedge this module was written to remove, surviving in
67
+ * the one arm it did not touch.
68
+ */
69
+ if (held.held === null) {
70
+ // Present and UNREADABLE is never taken over: it may name the key an
71
+ // in-flight claim is using, and nothing here can tell that from a corrupt
72
+ // file. `takeOver` refuses this too; asked here so the reason is the one
73
+ // the reader gets.
74
+ return { refuse: { reason: held.because, terminal: false } };
75
+ }
76
+ const lease = await deps.carrier();
77
+ if (lease.kind !== 'free' && lease.kind !== 'dead') {
78
+ /**
79
+ * Something holds the tree, or nobody can tell. Refuse, and RETRYABLY:
80
+ * the holder may finish, and `ambiguous` may become decidable. Taking the
81
+ * record over here is what would kill a live, correctly authorised run —
82
+ * its prehook re-reads the reservation and refuses when the name is no
83
+ * longer its own.
84
+ */
85
+ return { refuse: { reason: (0, run_lease_1.describeLease)(lease), terminal: false } };
86
+ }
87
+ const taken = await deps.governed.takeOver(approvalId, requestId);
88
+ if (!taken.ok)
89
+ return { refuse: { reason: taken.because, terminal: false } };
90
+ deps.log(`daemon : taking over an unfinished action on approval ${approvalId}`);
91
+ return { governedApprovalId: approvalId };
92
+ }
93
+ if (gate.kind !== 'resume-required')
94
+ return {};
95
+ /**
96
+ * A DENIAL TO CARRY BACK, and losing this race is deliberately NOT a refusal.
97
+ * The other Start has the answer and is about to hold the working tree; this
98
+ * one carries on as an ordinary Start and meets the lease like any other.
99
+ */
100
+ const claim = await deps.resumes.claim(gate.approvalId, requestId);
101
+ return claim.ok ? { resumedFromApprovalId: gate.approvalId } : {};
102
+ }
103
+ //# sourceMappingURL=explicit-start-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explicit-start-gate.js","sourceRoot":"","sources":["../src/explicit-start-gate.ts"],"names":[],"mappings":";;AAoGA,kDAgFC;AApLD,uCAKsB;AAGtB,2CAA6D;AAwE7D;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,UAAU,mBAAmB,CACvC,IAAuB,EACvB,IAAkB,EAClB,SAAiB;IAEjB,IAAI,IAAA,2BAAoB,EAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,OAAO;YACL,MAAM,EAAE;gBACN,MAAM,EAAE,IAAA,mBAAY,EAAC,IAAI,CAAC,IAAI,qCAAqC;gBACnE,uEAAuE;gBACvE,uEAAuE;gBACvE,wEAAwE;gBACxE,2BAA2B;gBAC3B,QAAQ,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS;aAClC;SACF,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACH,MAAM,UAAU,GAAG,IAAA,4BAAqB,EAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAChE,IAAI,IAAI,CAAC,EAAE;YAAE,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,CAAC;QAEvD;;;;;;;;;;;;;WAaG;QACH,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACvB,qEAAqE;YACrE,0EAA0E;YAC1E,yEAAyE;YACzE,mBAAmB;YACnB,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC;QAC/D,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACnD;;;;;;eAMG;YACH,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,IAAA,yBAAa,EAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC;QACvE,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAClE,IAAI,CAAC,KAAK,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7E,IAAI,CAAC,GAAG,CAAC,0DAA0D,UAAU,EAAE,CAAC,CAAC;QACjF,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,CAAC;IAC5C,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB;QAAE,OAAO,EAAE,CAAC;IAC/C;;;;OAIG;IACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACnE,OAAO,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,qBAAqB,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACpE,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * WHY A FILE COULD NOT BE READ, WHEN THE ANSWER CHANGES WHAT HAPPENS.
3
+ *
4
+ * ─────────────────────────────────────────────────────────────────────────────
5
+ * Two failures wear the same clothes and mean opposite things.
6
+ *
7
+ * A file whose CONTENTS cannot be trusted is durable damage. Retrying reads the
8
+ * same bytes and reaches the same conclusion, so a machine that kept trying
9
+ * would spin until the grant expired without ever telling anybody. That has to
10
+ * stop and ask a person.
11
+ *
12
+ * A file that could not be OPENED THIS INSTANT is weather. On Windows it is
13
+ * ordinary: an antivirus scanner, the search indexer, a backup agent or another
14
+ * process holding a handle produces EPERM or EBUSY for a few milliseconds and
15
+ * then stops. Nothing is wrong with the data. A machine that treated it as
16
+ * damage would end somebody's night over a file lock that cleared before they
17
+ * read the message.
18
+ *
19
+ * A certification pass reproduced exactly that: one transient read, and a
20
+ * pursuit irreversibly terminated as `human_required`.
21
+ *
22
+ * ─────────────────────────────────────────────────────────────────────────────
23
+ * ENOENT IS NOT HERE, deliberately.
24
+ *
25
+ * The filesystem contract these stores are written against resolves a missing
26
+ * file to `null` rather than throwing (see `nodeLedgerFs.readFile`), because
27
+ * absence is usually legal — the first receipt of a request, a grant nothing has
28
+ * been spent against yet. Where absence is NOT legal, the store that knows the
29
+ * history says so itself: a hole among receipts is a contradiction, and that
30
+ * judgement belongs to the store, not to an errno.
31
+ *
32
+ * ─────────────────────────────────────────────────────────────────────────────
33
+ * UNKNOWN IS NOT TRANSIENT.
34
+ *
35
+ * Anything not on the list below is reported as unknown, and callers treat
36
+ * unknown the same way they treat transient — hold, do not conclude — because
37
+ * the alternative is inventing durable corruption out of an errno nobody
38
+ * recognised. What it must never do is silently widen: a list that swallowed
39
+ * every error would make the corrupt path unreachable, and the corrupt path is
40
+ * the one that protects the budget.
41
+ */
42
+ export type FsTrouble =
43
+ /** Could not read it now. The bytes are not accused of anything. */
44
+ {
45
+ kind: 'transient';
46
+ code: string;
47
+ because: string;
48
+ }
49
+ /** An error nobody here recognises. Treated as "not now", never as damage. */
50
+ | {
51
+ kind: 'unknown';
52
+ code: string;
53
+ because: string;
54
+ };
55
+ /**
56
+ * Classify a thrown read error.
57
+ *
58
+ * Never decides that contents are corrupt — it has not seen any contents. That
59
+ * judgement belongs to whoever parsed them.
60
+ */
61
+ export declare function classifyFsError(e: unknown, what: string): FsTrouble;
62
+ /**
63
+ * Whether this trouble should make a caller wait rather than conclude.
64
+ *
65
+ * Both arms today, and the function exists so that the decision has one home
66
+ * instead of being re-derived at each call site — which is how the two would
67
+ * eventually come to disagree.
68
+ */
69
+ export declare function shouldWaitFor(t: FsTrouble): boolean;
70
+ //# sourceMappingURL=fs-trouble.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-trouble.d.ts","sourceRoot":"","sources":["../src/fs-trouble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAuBH,MAAM,MAAM,SAAS;AACnB,oEAAoE;AAClE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AACtD,8EAA8E;GAC5E;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAenE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAEnD"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ /**
3
+ * WHY A FILE COULD NOT BE READ, WHEN THE ANSWER CHANGES WHAT HAPPENS.
4
+ *
5
+ * ─────────────────────────────────────────────────────────────────────────────
6
+ * Two failures wear the same clothes and mean opposite things.
7
+ *
8
+ * A file whose CONTENTS cannot be trusted is durable damage. Retrying reads the
9
+ * same bytes and reaches the same conclusion, so a machine that kept trying
10
+ * would spin until the grant expired without ever telling anybody. That has to
11
+ * stop and ask a person.
12
+ *
13
+ * A file that could not be OPENED THIS INSTANT is weather. On Windows it is
14
+ * ordinary: an antivirus scanner, the search indexer, a backup agent or another
15
+ * process holding a handle produces EPERM or EBUSY for a few milliseconds and
16
+ * then stops. Nothing is wrong with the data. A machine that treated it as
17
+ * damage would end somebody's night over a file lock that cleared before they
18
+ * read the message.
19
+ *
20
+ * A certification pass reproduced exactly that: one transient read, and a
21
+ * pursuit irreversibly terminated as `human_required`.
22
+ *
23
+ * ─────────────────────────────────────────────────────────────────────────────
24
+ * ENOENT IS NOT HERE, deliberately.
25
+ *
26
+ * The filesystem contract these stores are written against resolves a missing
27
+ * file to `null` rather than throwing (see `nodeLedgerFs.readFile`), because
28
+ * absence is usually legal — the first receipt of a request, a grant nothing has
29
+ * been spent against yet. Where absence is NOT legal, the store that knows the
30
+ * history says so itself: a hole among receipts is a contradiction, and that
31
+ * judgement belongs to the store, not to an errno.
32
+ *
33
+ * ─────────────────────────────────────────────────────────────────────────────
34
+ * UNKNOWN IS NOT TRANSIENT.
35
+ *
36
+ * Anything not on the list below is reported as unknown, and callers treat
37
+ * unknown the same way they treat transient — hold, do not conclude — because
38
+ * the alternative is inventing durable corruption out of an errno nobody
39
+ * recognised. What it must never do is silently widen: a list that swallowed
40
+ * every error would make the corrupt path unreachable, and the corrupt path is
41
+ * the one that protects the budget.
42
+ */
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.classifyFsError = classifyFsError;
45
+ exports.shouldWaitFor = shouldWaitFor;
46
+ /**
47
+ * Codes that mean "not this instant", on the platforms looply runs on.
48
+ *
49
+ * EPERM and EACCES are what Windows reports for a sharing violation, which is
50
+ * the case that actually bit. EBUSY is the same thing under another name. The
51
+ * descriptor-exhaustion pair (EMFILE/ENFILE) and the non-blocking pair
52
+ * (EAGAIN/EWOULDBLOCK) are here for the same reason: they describe the machine
53
+ * being busy, never the bytes being wrong.
54
+ */
55
+ const TRANSIENT = new Set([
56
+ 'EPERM',
57
+ 'EACCES',
58
+ 'EBUSY',
59
+ 'EMFILE',
60
+ 'ENFILE',
61
+ 'EAGAIN',
62
+ 'EWOULDBLOCK',
63
+ 'ETXTBSY',
64
+ 'ETIMEDOUT',
65
+ ]);
66
+ /**
67
+ * Classify a thrown read error.
68
+ *
69
+ * Never decides that contents are corrupt — it has not seen any contents. That
70
+ * judgement belongs to whoever parsed them.
71
+ */
72
+ function classifyFsError(e, what) {
73
+ const code = e?.code ?? '';
74
+ const detail = e?.message ?? String(e);
75
+ if (TRANSIENT.has(code)) {
76
+ return {
77
+ kind: 'transient',
78
+ code,
79
+ because: `${what} could not be read just now (${code}) — something else is holding it`,
80
+ };
81
+ }
82
+ return {
83
+ kind: 'unknown',
84
+ code,
85
+ because: `${what} could not be read (${detail})`,
86
+ };
87
+ }
88
+ /**
89
+ * Whether this trouble should make a caller wait rather than conclude.
90
+ *
91
+ * Both arms today, and the function exists so that the decision has one home
92
+ * instead of being re-derived at each call site — which is how the two would
93
+ * eventually come to disagree.
94
+ */
95
+ function shouldWaitFor(t) {
96
+ return t.kind === 'transient' || t.kind === 'unknown';
97
+ }
98
+ //# sourceMappingURL=fs-trouble.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-trouble.js","sourceRoot":"","sources":["../src/fs-trouble.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;;AAmCH,0CAeC;AASD,sCAEC;AA3DD;;;;;;;;GAQG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,SAAS;IACT,WAAW;CACZ,CAAC,CAAC;AAQH;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,CAAU,EAAE,IAAY;IACtD,MAAM,IAAI,GAAI,CAAkC,EAAE,IAAI,IAAI,EAAE,CAAC;IAC7D,MAAM,MAAM,GAAI,CAAkB,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;IACzD,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,IAAI,EAAE,WAAW;YACjB,IAAI;YACJ,OAAO,EAAE,GAAG,IAAI,gCAAgC,IAAI,kCAAkC;SACvF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,IAAI;QACJ,OAAO,EAAE,GAAG,IAAI,uBAAuB,MAAM,GAAG;KACjD,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,aAAa,CAAC,CAAY;IACxC,OAAO,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;AACxD,CAAC"}