@cleocode/core 2026.10.4 → 2026.10.5

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 (1260) hide show
  1. package/dist/bootstrap.d.ts.map +1 -1
  2. package/dist/bootstrap.js +7 -37
  3. package/dist/bootstrap.js.map +1 -1
  4. package/dist/build-provenance.json +2 -2
  5. package/dist/caamp/adapter.d.ts.map +1 -1
  6. package/dist/caamp/adapter.js +5 -2
  7. package/dist/caamp/adapter.js.map +1 -1
  8. package/dist/changesets/parse-frontmatter.d.ts +1 -1
  9. package/dist/changesets/parse-frontmatter.d.ts.map +1 -1
  10. package/dist/changesets/parse-frontmatter.js +2 -1
  11. package/dist/changesets/parse-frontmatter.js.map +1 -1
  12. package/dist/changesets/parser.d.ts +1 -1
  13. package/dist/changesets/parser.d.ts.map +1 -1
  14. package/dist/changesets/parser.js +2 -1
  15. package/dist/changesets/parser.js.map +1 -1
  16. package/dist/changesets/writer.d.ts +8 -1
  17. package/dist/changesets/writer.d.ts.map +1 -1
  18. package/dist/changesets/writer.js +56 -5
  19. package/dist/changesets/writer.js.map +1 -1
  20. package/dist/cloud/keys.d.ts +9 -0
  21. package/dist/cloud/keys.d.ts.map +1 -1
  22. package/dist/cloud/keys.js +11 -0
  23. package/dist/cloud/keys.js.map +1 -1
  24. package/dist/cloud/nexus-attach.d.ts +17 -0
  25. package/dist/cloud/nexus-attach.d.ts.map +1 -1
  26. package/dist/cloud/nexus-attach.js +30 -9
  27. package/dist/cloud/nexus-attach.js.map +1 -1
  28. package/dist/cloud/nexus-auth.d.ts +7 -1
  29. package/dist/cloud/nexus-auth.d.ts.map +1 -1
  30. package/dist/cloud/nexus-auth.js +7 -1
  31. package/dist/cloud/nexus-auth.js.map +1 -1
  32. package/dist/cloud/nexus-cloud-activity.d.ts.map +1 -1
  33. package/dist/cloud/nexus-cloud-activity.js +2 -1
  34. package/dist/cloud/nexus-cloud-activity.js.map +1 -1
  35. package/dist/cloud/nexus-cloud-conflicts.d.ts +48 -0
  36. package/dist/cloud/nexus-cloud-conflicts.d.ts.map +1 -0
  37. package/dist/cloud/nexus-cloud-conflicts.js +68 -0
  38. package/dist/cloud/nexus-cloud-conflicts.js.map +1 -0
  39. package/dist/cloud/nexus-cloud-status.d.ts +42 -6
  40. package/dist/cloud/nexus-cloud-status.d.ts.map +1 -1
  41. package/dist/cloud/nexus-cloud-status.js +233 -19
  42. package/dist/cloud/nexus-cloud-status.js.map +1 -1
  43. package/dist/cloud/nexus-cloud.d.ts +18 -1
  44. package/dist/cloud/nexus-cloud.d.ts.map +1 -1
  45. package/dist/cloud/nexus-cloud.js +56 -2
  46. package/dist/cloud/nexus-cloud.js.map +1 -1
  47. package/dist/cloud/nexus-credentials.d.ts +1 -1
  48. package/dist/cloud/nexus-credentials.d.ts.map +1 -1
  49. package/dist/cloud/nexus-credentials.js +1 -1
  50. package/dist/cloud/nexus-credentials.js.map +1 -1
  51. package/dist/cloud/nexus-enrol.d.ts +1 -1
  52. package/dist/cloud/nexus-enrol.d.ts.map +1 -1
  53. package/dist/cloud/nexus-enrol.js +2 -1
  54. package/dist/cloud/nexus-enrol.js.map +1 -1
  55. package/dist/cloud/nexus-first-run.d.ts +6 -2
  56. package/dist/cloud/nexus-first-run.d.ts.map +1 -1
  57. package/dist/cloud/nexus-first-run.js +8 -2
  58. package/dist/cloud/nexus-first-run.js.map +1 -1
  59. package/dist/cloud/nexus-link.d.ts +35 -4
  60. package/dist/cloud/nexus-link.d.ts.map +1 -1
  61. package/dist/cloud/nexus-link.js +172 -7
  62. package/dist/cloud/nexus-link.js.map +1 -1
  63. package/dist/cloud/nexus-presence-refresh.d.ts +65 -0
  64. package/dist/cloud/nexus-presence-refresh.d.ts.map +1 -0
  65. package/dist/cloud/nexus-presence-refresh.js +122 -0
  66. package/dist/cloud/nexus-presence-refresh.js.map +1 -0
  67. package/dist/cloud/nexus-project-history.d.ts +54 -0
  68. package/dist/cloud/nexus-project-history.d.ts.map +1 -0
  69. package/dist/cloud/nexus-project-history.js +108 -0
  70. package/dist/cloud/nexus-project-history.js.map +1 -0
  71. package/dist/cloud/nexus-vault-keys.d.ts.map +1 -1
  72. package/dist/cloud/nexus-vault-keys.js +12 -6
  73. package/dist/cloud/nexus-vault-keys.js.map +1 -1
  74. package/dist/cloud/nexus-vault.d.ts +7 -3
  75. package/dist/cloud/nexus-vault.d.ts.map +1 -1
  76. package/dist/cloud/nexus-vault.js +176 -29
  77. package/dist/cloud/nexus-vault.js.map +1 -1
  78. package/dist/cloud/presence.d.ts +1 -1
  79. package/dist/cloud/presence.d.ts.map +1 -1
  80. package/dist/cloud/presence.js +1 -1
  81. package/dist/cloud/presence.js.map +1 -1
  82. package/dist/cloud/projects.d.ts +7 -4
  83. package/dist/cloud/projects.d.ts.map +1 -1
  84. package/dist/cloud/projects.js +10 -1
  85. package/dist/cloud/projects.js.map +1 -1
  86. package/dist/cloud/signing.d.ts +14 -0
  87. package/dist/cloud/signing.d.ts.map +1 -1
  88. package/dist/cloud/signing.js +9 -0
  89. package/dist/cloud/signing.js.map +1 -1
  90. package/dist/conduit/cloud-endpoint.d.ts +96 -0
  91. package/dist/conduit/cloud-endpoint.d.ts.map +1 -0
  92. package/dist/conduit/cloud-endpoint.js +191 -0
  93. package/dist/conduit/cloud-endpoint.js.map +1 -0
  94. package/dist/conduit/conduit-client.d.ts.map +1 -1
  95. package/dist/conduit/conduit-client.js +2 -1
  96. package/dist/conduit/conduit-client.js.map +1 -1
  97. package/dist/conduit/factory.d.ts +4 -0
  98. package/dist/conduit/factory.d.ts.map +1 -1
  99. package/dist/conduit/factory.js +7 -1
  100. package/dist/conduit/factory.js.map +1 -1
  101. package/dist/conduit/http-transport.d.ts +12 -7
  102. package/dist/conduit/http-transport.d.ts.map +1 -1
  103. package/dist/conduit/http-transport.js +18 -11
  104. package/dist/conduit/http-transport.js.map +1 -1
  105. package/dist/conduit/index.d.ts +3 -1
  106. package/dist/conduit/index.d.ts.map +1 -1
  107. package/dist/conduit/index.js +3 -1
  108. package/dist/conduit/index.js.map +1 -1
  109. package/dist/conduit/sse-transport.d.ts +5 -1
  110. package/dist/conduit/sse-transport.d.ts.map +1 -1
  111. package/dist/conduit/sse-transport.js +10 -2
  112. package/dist/conduit/sse-transport.js.map +1 -1
  113. package/dist/config/registry.js +1 -1
  114. package/dist/config/registry.js.map +1 -1
  115. package/dist/core-paths.d.ts +13 -0
  116. package/dist/core-paths.d.ts.map +1 -0
  117. package/dist/core-paths.js +13 -0
  118. package/dist/core-paths.js.map +1 -0
  119. package/dist/decide/bench/source.js +1 -1
  120. package/dist/decide/bench/source.js.map +1 -1
  121. package/dist/decide/client.d.ts +1 -1
  122. package/dist/decide/client.d.ts.map +1 -1
  123. package/dist/decide/client.js +1 -1
  124. package/dist/decide/client.js.map +1 -1
  125. package/dist/decide/credentials.d.ts +1 -1
  126. package/dist/decide/credentials.d.ts.map +1 -1
  127. package/dist/decide/credentials.js +1 -1
  128. package/dist/decide/credentials.js.map +1 -1
  129. package/dist/decide/jev-wire.d.ts +1 -1
  130. package/dist/decide/jev-wire.d.ts.map +1 -1
  131. package/dist/decide/jev-wire.js +1 -1
  132. package/dist/decide/jev-wire.js.map +1 -1
  133. package/dist/decide/operations.d.ts +1 -1
  134. package/dist/decide/operations.d.ts.map +1 -1
  135. package/dist/decide/operations.js +1 -1
  136. package/dist/decide/operations.js.map +1 -1
  137. package/dist/decide/providers.d.ts +1 -1
  138. package/dist/decide/providers.d.ts.map +1 -1
  139. package/dist/decide/providers.js +1 -1
  140. package/dist/decide/providers.js.map +1 -1
  141. package/dist/decide/wizard.d.ts.map +1 -1
  142. package/dist/decide/wizard.js +1 -1
  143. package/dist/decide/wizard.js.map +1 -1
  144. package/dist/dispatch/config-domain-handler.d.ts +1 -1
  145. package/dist/dispatch/config-domain-handler.d.ts.map +1 -1
  146. package/dist/dispatch/config-domain-handler.js +1 -1
  147. package/dist/dispatch/config-domain-handler.js.map +1 -1
  148. package/dist/dispatch/contracts/ensures-schema.d.ts +1 -1
  149. package/dist/dispatch/contracts/ensures-schema.d.ts.map +1 -1
  150. package/dist/dispatch/contracts/ensures-schema.js +1 -1
  151. package/dist/dispatch/contracts/ensures-schema.js.map +1 -1
  152. package/dist/dispatch/contracts/input-contracts.d.ts +1 -1
  153. package/dist/dispatch/contracts/input-contracts.d.ts.map +1 -1
  154. package/dist/dispatch/contracts/input-contracts.js +3 -1
  155. package/dist/dispatch/contracts/input-contracts.js.map +1 -1
  156. package/dist/dispatch/describe-operation.d.ts +1 -1
  157. package/dist/dispatch/describe-operation.d.ts.map +1 -1
  158. package/dist/dispatch/describe-operation.js +1 -1
  159. package/dist/dispatch/describe-operation.js.map +1 -1
  160. package/dist/docs/display-alias.js +1 -1
  161. package/dist/docs/display-alias.js.map +1 -1
  162. package/dist/docs/docs-update.d.ts +1 -1
  163. package/dist/docs/docs-update.d.ts.map +1 -1
  164. package/dist/docs/docs-update.js +2 -1
  165. package/dist/docs/docs-update.js.map +1 -1
  166. package/dist/docs/export-document.js +14 -58300
  167. package/dist/docs/export-document.js.map +3 -3
  168. package/dist/docs/publish-pr.js +1 -1
  169. package/dist/docs/publish-pr.js.map +1 -1
  170. package/dist/docs/supersede.js +1 -1
  171. package/dist/docs/supersede.js.map +1 -1
  172. package/dist/docs/validate-body.d.ts +1 -1
  173. package/dist/docs/validate-body.d.ts.map +1 -1
  174. package/dist/docs/validate-body.js +1 -1
  175. package/dist/docs/validate-body.js.map +1 -1
  176. package/dist/docs/writer-registry.js +1 -1
  177. package/dist/docs/writer-registry.js.map +1 -1
  178. package/dist/doctor/acceptance-drift.js +1 -1
  179. package/dist/doctor/acceptance-drift.js.map +1 -1
  180. package/dist/doctor/db-substrate.d.ts +1 -1
  181. package/dist/doctor/db-substrate.d.ts.map +1 -1
  182. package/dist/doctor/db-substrate.js +1 -1
  183. package/dist/doctor/db-substrate.js.map +1 -1
  184. package/dist/doctor/invariant-audit.js +1 -1
  185. package/dist/doctor/invariant-audit.js.map +1 -1
  186. package/dist/doctor/malformed-task-ids.js +1 -1
  187. package/dist/doctor/malformed-task-ids.js.map +1 -1
  188. package/dist/doctor/row-identity-refill.d.ts +43 -0
  189. package/dist/doctor/row-identity-refill.d.ts.map +1 -0
  190. package/dist/doctor/row-identity-refill.js +186 -0
  191. package/dist/doctor/row-identity-refill.js.map +1 -0
  192. package/dist/doctor/superseded-store.d.ts.map +1 -1
  193. package/dist/doctor/superseded-store.js +51 -2
  194. package/dist/doctor/superseded-store.js.map +1 -1
  195. package/dist/doctor/sync-repair.d.ts +39 -0
  196. package/dist/doctor/sync-repair.d.ts.map +1 -0
  197. package/dist/doctor/sync-repair.js +71 -0
  198. package/dist/doctor/sync-repair.js.map +1 -0
  199. package/dist/doctor/sync-triggers.d.ts +63 -4
  200. package/dist/doctor/sync-triggers.d.ts.map +1 -1
  201. package/dist/doctor/sync-triggers.js +352 -9
  202. package/dist/doctor/sync-triggers.js.map +1 -1
  203. package/dist/doctor/twin-collapse.js +1 -1
  204. package/dist/doctor/twin-collapse.js.map +1 -1
  205. package/dist/engine/engine-ops.d.ts.map +1 -1
  206. package/dist/engine/engine-ops.js +7 -1
  207. package/dist/engine/engine-ops.js.map +1 -1
  208. package/dist/engine-result.d.ts +1 -1
  209. package/dist/engine-result.d.ts.map +1 -1
  210. package/dist/engine-result.js +1 -1
  211. package/dist/engine-result.js.map +1 -1
  212. package/dist/error-registry.d.ts +1 -1
  213. package/dist/error-registry.d.ts.map +1 -1
  214. package/dist/error-registry.js +1 -1
  215. package/dist/error-registry.js.map +1 -1
  216. package/dist/errors-to-engine.d.ts +20 -0
  217. package/dist/errors-to-engine.d.ts.map +1 -1
  218. package/dist/errors-to-engine.js +37 -0
  219. package/dist/errors-to-engine.js.map +1 -1
  220. package/dist/gc/janitor.d.ts +23 -4
  221. package/dist/gc/janitor.d.ts.map +1 -1
  222. package/dist/gc/janitor.js +71 -11
  223. package/dist/gc/janitor.js.map +1 -1
  224. package/dist/goal/continuation.d.ts +1 -1
  225. package/dist/goal/continuation.d.ts.map +1 -1
  226. package/dist/goal/continuation.js +1 -1
  227. package/dist/goal/continuation.js.map +1 -1
  228. package/dist/goal/judge.d.ts.map +1 -1
  229. package/dist/goal/judge.js +2 -1
  230. package/dist/goal/judge.js.map +1 -1
  231. package/dist/hooks/handlers/session-hooks.d.ts.map +1 -1
  232. package/dist/hooks/handlers/session-hooks.js +1 -1
  233. package/dist/hooks/handlers/session-hooks.js.map +1 -1
  234. package/dist/init/engine-ops.js +1 -1
  235. package/dist/init/engine-ops.js.map +1 -1
  236. package/dist/init.d.ts.map +1 -1
  237. package/dist/init.js +10 -41
  238. package/dist/init.js.map +1 -1
  239. package/dist/inject/index.js +1 -1
  240. package/dist/inject/index.js.map +1 -1
  241. package/dist/injection.d.ts.map +1 -1
  242. package/dist/injection.js +13 -0
  243. package/dist/injection.js.map +1 -1
  244. package/dist/internal.d.ts +4 -3
  245. package/dist/internal.d.ts.map +1 -1
  246. package/dist/internal.js +7 -4
  247. package/dist/internal.js.map +1 -1
  248. package/dist/issue/create.js +1 -1
  249. package/dist/issue/create.js.map +1 -1
  250. package/dist/json-schema-validator.js +1 -1
  251. package/dist/json-schema-validator.js.map +1 -1
  252. package/dist/lifecycle/index.d.ts +2 -23
  253. package/dist/lifecycle/index.d.ts.map +1 -1
  254. package/dist/lifecycle/index.js +5 -112
  255. package/dist/lifecycle/index.js.map +1 -1
  256. package/dist/lifecycle/kind-requirements.d.ts +1 -1
  257. package/dist/lifecycle/kind-requirements.d.ts.map +1 -1
  258. package/dist/lifecycle/kind-requirements.js +1 -1
  259. package/dist/lifecycle/kind-requirements.js.map +1 -1
  260. package/dist/lifecycle/pipeline.js +1 -1
  261. package/dist/lifecycle/pipeline.js.map +1 -1
  262. package/dist/lifecycle/resume.js +2 -2
  263. package/dist/lifecycle/resume.js.map +1 -1
  264. package/dist/lifecycle/state-machine.js +1 -1
  265. package/dist/lifecycle/state-machine.js.map +1 -1
  266. package/dist/lifecycle/status.d.ts +46 -0
  267. package/dist/lifecycle/status.d.ts.map +1 -0
  268. package/dist/lifecycle/status.js +147 -0
  269. package/dist/lifecycle/status.js.map +1 -0
  270. package/dist/lifecycle/verification/satisfies-validator.js +1 -1
  271. package/dist/lifecycle/verification/satisfies-validator.js.map +1 -1
  272. package/dist/llm/catalog-seeder.d.ts +1 -1
  273. package/dist/llm/catalog-seeder.d.ts.map +1 -1
  274. package/dist/llm/catalog-seeder.js +1 -1
  275. package/dist/llm/catalog-seeder.js.map +1 -1
  276. package/dist/llm/cli-ops.d.ts +1 -2
  277. package/dist/llm/cli-ops.d.ts.map +1 -1
  278. package/dist/llm/cli-ops.js +2 -1
  279. package/dist/llm/cli-ops.js.map +1 -1
  280. package/dist/llm/credential-seeders/claude-code-seeder.js +1 -1
  281. package/dist/llm/credential-seeders/claude-code-seeder.js.map +1 -1
  282. package/dist/llm/credential-seeders/cleo-pkce-seeder.js +1 -1
  283. package/dist/llm/credential-seeders/cleo-pkce-seeder.js.map +1 -1
  284. package/dist/llm/credential-writeback.js +1 -1
  285. package/dist/llm/credential-writeback.js.map +1 -1
  286. package/dist/llm/entity-ops.d.ts +1 -1
  287. package/dist/llm/entity-ops.d.ts.map +1 -1
  288. package/dist/llm/entity-ops.js +2 -1
  289. package/dist/llm/entity-ops.js.map +1 -1
  290. package/dist/llm/llm-queue-admit.d.ts +1 -1
  291. package/dist/llm/llm-queue-admit.d.ts.map +1 -1
  292. package/dist/llm/llm-queue-admit.js +2 -1
  293. package/dist/llm/llm-queue-admit.js.map +1 -1
  294. package/dist/llm/onboarding/login-engine.js +1 -1
  295. package/dist/llm/onboarding/login-engine.js.map +1 -1
  296. package/dist/llm/pi/pi-errors.d.ts +1 -1
  297. package/dist/llm/pi/pi-errors.d.ts.map +1 -1
  298. package/dist/llm/pi/pi-errors.js +1 -1
  299. package/dist/llm/pi/pi-errors.js.map +1 -1
  300. package/dist/llm/plugin-facade.d.ts.map +1 -1
  301. package/dist/llm/plugin-facade.js +14 -93552
  302. package/dist/llm/plugin-facade.js.map +3 -3
  303. package/dist/llm/system-key.d.ts +1 -1
  304. package/dist/llm/system-key.d.ts.map +1 -1
  305. package/dist/llm/system-key.js +1 -1
  306. package/dist/llm/system-key.js.map +1 -1
  307. package/dist/llm/system-of-use-registry.d.ts +1 -1
  308. package/dist/llm/system-of-use-registry.d.ts.map +1 -1
  309. package/dist/llm/system-of-use-registry.js +1 -1
  310. package/dist/llm/system-of-use-registry.js.map +1 -1
  311. package/dist/llm/system-resolver.js +1 -1
  312. package/dist/llm/system-resolver.js.map +1 -1
  313. package/dist/memory/brain-host.d.ts +71 -0
  314. package/dist/memory/brain-host.d.ts.map +1 -0
  315. package/dist/memory/brain-host.js +84 -0
  316. package/dist/memory/brain-host.js.map +1 -0
  317. package/dist/memory/brain-writer-handlers.d.ts.map +1 -1
  318. package/dist/memory/brain-writer-handlers.js +24 -7
  319. package/dist/memory/brain-writer-handlers.js.map +1 -1
  320. package/dist/memory/brain-writer-thread.d.ts +66 -6
  321. package/dist/memory/brain-writer-thread.d.ts.map +1 -1
  322. package/dist/memory/brain-writer-thread.js +67 -10
  323. package/dist/memory/brain-writer-thread.js.map +1 -1
  324. package/dist/memory/brain-writer-worker.js +7 -0
  325. package/dist/memory/brain-writer-worker.js.map +1 -1
  326. package/dist/memory/decisions.js +2 -1
  327. package/dist/memory/decisions.js.map +1 -1
  328. package/dist/memory/embedding-backfill.d.ts +70 -0
  329. package/dist/memory/embedding-backfill.d.ts.map +1 -0
  330. package/dist/memory/embedding-backfill.js +110 -0
  331. package/dist/memory/embedding-backfill.js.map +1 -0
  332. package/dist/memory/index.js +1 -1
  333. package/dist/memory/index.js.map +1 -1
  334. package/dist/memory/manifest-identity.js +1 -1
  335. package/dist/memory/manifest-identity.js.map +1 -1
  336. package/dist/memory/retrieval/observe.d.ts +23 -0
  337. package/dist/memory/retrieval/observe.d.ts.map +1 -1
  338. package/dist/memory/retrieval/observe.js +82 -36
  339. package/dist/memory/retrieval/observe.js.map +1 -1
  340. package/dist/metrics/model-provider-registry.d.ts.map +1 -1
  341. package/dist/metrics/model-provider-registry.js +6 -0
  342. package/dist/metrics/model-provider-registry.js.map +1 -1
  343. package/dist/metrics/token-service.d.ts +17 -0
  344. package/dist/metrics/token-service.d.ts.map +1 -1
  345. package/dist/metrics/token-service.js +17 -0
  346. package/dist/metrics/token-service.js.map +1 -1
  347. package/dist/migration/index.js +1 -1
  348. package/dist/migration/index.js.map +1 -1
  349. package/dist/migration/manual/T10165-backfill-adr-index.js +1 -1
  350. package/dist/migration/manual/T10165-backfill-adr-index.js.map +1 -1
  351. package/dist/nexus/assessment-projection.d.ts +1 -1
  352. package/dist/nexus/assessment-projection.d.ts.map +1 -1
  353. package/dist/nexus/assessment-projection.js +1 -1
  354. package/dist/nexus/assessment-projection.js.map +1 -1
  355. package/dist/nexus/deps.d.ts +1 -1
  356. package/dist/nexus/deps.d.ts.map +1 -1
  357. package/dist/nexus/deps.js +1 -1
  358. package/dist/nexus/deps.js.map +1 -1
  359. package/dist/nexus/fleet-status.d.ts +1 -1
  360. package/dist/nexus/fleet-status.d.ts.map +1 -1
  361. package/dist/nexus/fleet-status.js +1 -1
  362. package/dist/nexus/fleet-status.js.map +1 -1
  363. package/dist/nexus/identity.js +1 -1
  364. package/dist/nexus/identity.js.map +1 -1
  365. package/dist/nexus/permissions.d.ts +1 -1
  366. package/dist/nexus/permissions.d.ts.map +1 -1
  367. package/dist/nexus/permissions.js +1 -1
  368. package/dist/nexus/permissions.js.map +1 -1
  369. package/dist/nexus/query-dsl.js +1 -1
  370. package/dist/nexus/query-dsl.js.map +1 -1
  371. package/dist/nexus/query.d.ts +1 -2
  372. package/dist/nexus/query.d.ts.map +1 -1
  373. package/dist/nexus/query.js +1 -1
  374. package/dist/nexus/query.js.map +1 -1
  375. package/dist/nexus/registry-errors.js +1 -1
  376. package/dist/nexus/registry-errors.js.map +1 -1
  377. package/dist/nexus/registry.d.ts +1 -1
  378. package/dist/nexus/registry.d.ts.map +1 -1
  379. package/dist/nexus/registry.js +1 -1
  380. package/dist/nexus/registry.js.map +1 -1
  381. package/dist/nexus/workspace.js +1 -1
  382. package/dist/nexus/workspace.js.map +1 -1
  383. package/dist/orchestrate/pivot.d.ts.map +1 -1
  384. package/dist/orchestrate/pivot.js +2 -1
  385. package/dist/orchestrate/pivot.js.map +1 -1
  386. package/dist/orchestrate/query-ops.js +1 -1
  387. package/dist/orchestrate/query-ops.js.map +1 -1
  388. package/dist/orchestrate/spawn-ops.js +1 -1
  389. package/dist/orchestrate/spawn-ops.js.map +1 -1
  390. package/dist/orchestration/atomicity.d.ts +1 -1
  391. package/dist/orchestration/atomicity.d.ts.map +1 -1
  392. package/dist/orchestration/atomicity.js +1 -1
  393. package/dist/orchestration/atomicity.js.map +1 -1
  394. package/dist/orchestration/classify.js +1 -1
  395. package/dist/orchestration/classify.js.map +1 -1
  396. package/dist/orchestration/index.js +1 -1
  397. package/dist/orchestration/index.js.map +1 -1
  398. package/dist/orchestration/parallel.js +1 -1
  399. package/dist/orchestration/parallel.js.map +1 -1
  400. package/dist/orchestration/protocol-validators.d.ts +1 -1
  401. package/dist/orchestration/protocol-validators.d.ts.map +1 -1
  402. package/dist/orchestration/protocol-validators.js +1 -1
  403. package/dist/orchestration/protocol-validators.js.map +1 -1
  404. package/dist/orchestration/skill-ops.js +1 -1
  405. package/dist/orchestration/skill-ops.js.map +1 -1
  406. package/dist/orchestration/spawn-prompt.d.ts +9 -0
  407. package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
  408. package/dist/orchestration/spawn-prompt.js +13 -2
  409. package/dist/orchestration/spawn-prompt.js.map +1 -1
  410. package/dist/orchestration/spawn.js +1 -1
  411. package/dist/orchestration/spawn.js.map +1 -1
  412. package/dist/paths.d.ts +3 -1
  413. package/dist/paths.d.ts.map +1 -1
  414. package/dist/paths.js +3 -1
  415. package/dist/paths.js.map +1 -1
  416. package/dist/phases/deps.js +1 -1
  417. package/dist/phases/deps.js.map +1 -1
  418. package/dist/phases/index.js +1 -1
  419. package/dist/phases/index.js.map +1 -1
  420. package/dist/project-lifecycle.js +3 -3
  421. package/dist/project-lifecycle.js.map +1 -1
  422. package/dist/registrations.d.ts +30 -0
  423. package/dist/registrations.d.ts.map +1 -0
  424. package/dist/registrations.js +30 -0
  425. package/dist/registrations.js.map +1 -0
  426. package/dist/release/changesets-aggregator.js +1 -1
  427. package/dist/release/changesets-aggregator.js.map +1 -1
  428. package/dist/release/ci-evidence.d.ts +68 -2
  429. package/dist/release/ci-evidence.d.ts.map +1 -1
  430. package/dist/release/ci-evidence.js +203 -39
  431. package/dist/release/ci-evidence.js.map +1 -1
  432. package/dist/release/invariants/archive-reason-invariant.d.ts +1 -1
  433. package/dist/release/invariants/archive-reason-invariant.d.ts.map +1 -1
  434. package/dist/release/invariants/archive-reason-invariant.js +1 -1
  435. package/dist/release/invariants/archive-reason-invariant.js.map +1 -1
  436. package/dist/release/invariants/registry.d.ts +1 -1
  437. package/dist/release/invariants/registry.d.ts.map +1 -1
  438. package/dist/release/invariants/registry.js +1 -1
  439. package/dist/release/invariants/registry.js.map +1 -1
  440. package/dist/release/open.d.ts +1 -1
  441. package/dist/release/open.d.ts.map +1 -1
  442. package/dist/release/open.js +3 -1
  443. package/dist/release/open.js.map +1 -1
  444. package/dist/release/plan.d.ts +1 -2
  445. package/dist/release/plan.d.ts.map +1 -1
  446. package/dist/release/plan.js +4 -1
  447. package/dist/release/plan.js.map +1 -1
  448. package/dist/release/pr-evidence.d.ts +1 -1
  449. package/dist/release/pr-evidence.d.ts.map +1 -1
  450. package/dist/release/pr-evidence.js +2 -2
  451. package/dist/release/pr-evidence.js.map +1 -1
  452. package/dist/release/preflight-skip.d.ts +5 -0
  453. package/dist/release/preflight-skip.d.ts.map +1 -1
  454. package/dist/release/preflight-skip.js +60 -1
  455. package/dist/release/preflight-skip.js.map +1 -1
  456. package/dist/release/reconcile.d.ts +1 -1
  457. package/dist/release/reconcile.d.ts.map +1 -1
  458. package/dist/release/reconcile.js +19 -3
  459. package/dist/release/reconcile.js.map +1 -1
  460. package/dist/release/version-bump.d.ts +1 -1
  461. package/dist/release/version-bump.d.ts.map +1 -1
  462. package/dist/release/version-bump.js +1 -1
  463. package/dist/release/version-bump.js.map +1 -1
  464. package/dist/resources/admission-ledger.d.ts +587 -0
  465. package/dist/resources/admission-ledger.d.ts.map +1 -0
  466. package/dist/resources/admission-ledger.js +1401 -0
  467. package/dist/resources/admission-ledger.js.map +1 -0
  468. package/dist/resources/backend.d.ts +37 -1
  469. package/dist/resources/backend.d.ts.map +1 -1
  470. package/dist/resources/backend.js +1 -1
  471. package/dist/resources/darwin-backend.d.ts +152 -26
  472. package/dist/resources/darwin-backend.d.ts.map +1 -1
  473. package/dist/resources/darwin-backend.js +217 -34
  474. package/dist/resources/darwin-backend.js.map +1 -1
  475. package/dist/resources/governor.d.ts +36 -39
  476. package/dist/resources/governor.d.ts.map +1 -1
  477. package/dist/resources/governor.js +140 -49
  478. package/dist/resources/governor.js.map +1 -1
  479. package/dist/resources/pressure-gate.d.ts +148 -0
  480. package/dist/resources/pressure-gate.d.ts.map +1 -0
  481. package/dist/resources/pressure-gate.js +273 -0
  482. package/dist/resources/pressure-gate.js.map +1 -0
  483. package/dist/resources/run-admission.d.ts +33 -45
  484. package/dist/resources/run-admission.d.ts.map +1 -1
  485. package/dist/resources/run-admission.js +50 -118
  486. package/dist/resources/run-admission.js.map +1 -1
  487. package/dist/resources/run-class.d.ts +60 -4
  488. package/dist/resources/run-class.d.ts.map +1 -1
  489. package/dist/resources/run-class.js +473 -6
  490. package/dist/resources/run-class.js.map +1 -1
  491. package/dist/resources/run-governed.d.ts +43 -11
  492. package/dist/resources/run-governed.d.ts.map +1 -1
  493. package/dist/resources/run-governed.js +139 -99
  494. package/dist/resources/run-governed.js.map +1 -1
  495. package/dist/resources/slot-holder.d.ts +12 -4
  496. package/dist/resources/slot-holder.d.ts.map +1 -1
  497. package/dist/resources/slot-holder.js +19 -14
  498. package/dist/resources/slot-holder.js.map +1 -1
  499. package/dist/resources/spawn-wrapper.js +1 -1
  500. package/dist/resources/spawn-wrapper.js.map +1 -1
  501. package/dist/resources/supervisor-admit.d.ts +1 -1
  502. package/dist/resources/supervisor-admit.d.ts.map +1 -1
  503. package/dist/resources/supervisor-admit.js +2 -1
  504. package/dist/resources/supervisor-admit.js.map +1 -1
  505. package/dist/runtime/openapi/generate-openapi.d.ts +1 -1
  506. package/dist/runtime/openapi/generate-openapi.d.ts.map +1 -1
  507. package/dist/runtime/openapi/generate-openapi.js +1 -1
  508. package/dist/runtime/openapi/generate-openapi.js.map +1 -1
  509. package/dist/sagas/index.d.ts +3 -1
  510. package/dist/sagas/index.d.ts.map +1 -1
  511. package/dist/sagas/index.js +2 -5
  512. package/dist/sagas/index.js.map +1 -1
  513. package/dist/scaffold/project-identity.js +1 -1
  514. package/dist/scaffold/project-identity.js.map +1 -1
  515. package/dist/sdk/validator-attest.d.ts +1 -1
  516. package/dist/sdk/validator-attest.d.ts.map +1 -1
  517. package/dist/sdk/validator-attest.js +1 -1
  518. package/dist/sdk/validator-attest.js.map +1 -1
  519. package/dist/sdk/validator-reject.d.ts +1 -1
  520. package/dist/sdk/validator-reject.d.ts.map +1 -1
  521. package/dist/sdk/validator-reject.js +1 -1
  522. package/dist/sdk/validator-reject.js.map +1 -1
  523. package/dist/security/input-sanitization.js +2 -1
  524. package/dist/security/input-sanitization.js.map +1 -1
  525. package/dist/security/override-cap.js +1 -1
  526. package/dist/security/override-cap.js.map +1 -1
  527. package/dist/security/owner-override-auth.js +1 -1
  528. package/dist/security/owner-override-auth.js.map +1 -1
  529. package/dist/security/shared-evidence-tracker.js +1 -1
  530. package/dist/security/shared-evidence-tracker.js.map +1 -1
  531. package/dist/selfimprove/fix-gen.js +35 -93037
  532. package/dist/selfimprove/fix-gen.js.map +3 -3
  533. package/dist/sentient/daemon.d.ts.map +1 -1
  534. package/dist/sentient/daemon.js +3 -0
  535. package/dist/sentient/daemon.js.map +1 -1
  536. package/dist/sentient/tick.d.ts +7 -0
  537. package/dist/sentient/tick.d.ts.map +1 -1
  538. package/dist/sentient/tick.js +11 -0
  539. package/dist/sentient/tick.js.map +1 -1
  540. package/dist/sequence/index.js +1 -1
  541. package/dist/sequence/index.js.map +1 -1
  542. package/dist/session/engine-ops.d.ts +3 -45
  543. package/dist/session/engine-ops.d.ts.map +1 -1
  544. package/dist/session/engine-ops.js +63 -112
  545. package/dist/session/engine-ops.js.map +1 -1
  546. package/dist/session/status-op.d.ts +40 -0
  547. package/dist/session/status-op.d.ts.map +1 -0
  548. package/dist/session/status-op.js +71 -0
  549. package/dist/session/status-op.js.map +1 -0
  550. package/dist/session/task-current.d.ts +31 -0
  551. package/dist/session/task-current.d.ts.map +1 -0
  552. package/dist/session/task-current.js +59 -0
  553. package/dist/session/task-current.js.map +1 -0
  554. package/dist/sessions/assumptions.d.ts +1 -1
  555. package/dist/sessions/assumptions.d.ts.map +1 -1
  556. package/dist/sessions/assumptions.js +1 -1
  557. package/dist/sessions/assumptions.js.map +1 -1
  558. package/dist/sessions/context-inject.js +1 -1
  559. package/dist/sessions/context-inject.js.map +1 -1
  560. package/dist/sessions/decisions.d.ts +1 -1
  561. package/dist/sessions/decisions.d.ts.map +1 -1
  562. package/dist/sessions/decisions.js +1 -1
  563. package/dist/sessions/decisions.js.map +1 -1
  564. package/dist/sessions/focus-state-store.d.ts.map +1 -1
  565. package/dist/sessions/focus-state-store.js +2 -1
  566. package/dist/sessions/focus-state-store.js.map +1 -1
  567. package/dist/sessions/handoff.js +1 -1
  568. package/dist/sessions/handoff.js.map +1 -1
  569. package/dist/sessions/index.d.ts +1 -2
  570. package/dist/sessions/index.d.ts.map +1 -1
  571. package/dist/sessions/index.js +3 -2
  572. package/dist/sessions/index.js.map +1 -1
  573. package/dist/sessions/session-drift.js +1 -1
  574. package/dist/sessions/session-drift.js.map +1 -1
  575. package/dist/sessions/session-end-snapshot-entry.d.ts +4 -0
  576. package/dist/sessions/session-end-snapshot-entry.d.ts.map +1 -1
  577. package/dist/sessions/session-end-snapshot-entry.js +11 -0
  578. package/dist/sessions/session-end-snapshot-entry.js.map +1 -1
  579. package/dist/sessions/session-end-snapshot.d.ts.map +1 -1
  580. package/dist/sessions/session-end-snapshot.js +4 -0
  581. package/dist/sessions/session-end-snapshot.js.map +1 -1
  582. package/dist/sessions/session-enforcement.js +1 -1
  583. package/dist/sessions/session-enforcement.js.map +1 -1
  584. package/dist/sessions/session-show.d.ts +1 -2
  585. package/dist/sessions/session-show.d.ts.map +1 -1
  586. package/dist/sessions/session-show.js +1 -1
  587. package/dist/sessions/session-show.js.map +1 -1
  588. package/dist/sessions/session-stats.js +1 -1
  589. package/dist/sessions/session-stats.js.map +1 -1
  590. package/dist/sessions/session-suspend.d.ts +1 -2
  591. package/dist/sessions/session-suspend.d.ts.map +1 -1
  592. package/dist/sessions/session-suspend.js +1 -1
  593. package/dist/sessions/session-suspend.js.map +1 -1
  594. package/dist/sessions/session-switch.js +1 -1
  595. package/dist/sessions/session-switch.js.map +1 -1
  596. package/dist/sessions/snapshot.js +1 -1
  597. package/dist/sessions/snapshot.js.map +1 -1
  598. package/dist/sessions/terminal-identity.d.ts +1 -1
  599. package/dist/sessions/terminal-identity.d.ts.map +1 -1
  600. package/dist/sessions/terminal-identity.js +1 -1
  601. package/dist/sessions/terminal-identity.js.map +1 -1
  602. package/dist/setup/sections/integrations.d.ts.map +1 -1
  603. package/dist/setup/sections/integrations.js +9 -0
  604. package/dist/setup/sections/integrations.js.map +1 -1
  605. package/dist/setup/sections/models-roles.js +1 -1
  606. package/dist/setup/sections/models-roles.js.map +1 -1
  607. package/dist/setup/sections/verification.d.ts.map +1 -1
  608. package/dist/setup/sections/verification.js +8 -2
  609. package/dist/setup/sections/verification.js.map +1 -1
  610. package/dist/shutdown.d.ts +24 -0
  611. package/dist/shutdown.d.ts.map +1 -1
  612. package/dist/shutdown.js +30 -1
  613. package/dist/shutdown.js.map +1 -1
  614. package/dist/skills/agents/install.d.ts +46 -6
  615. package/dist/skills/agents/install.d.ts.map +1 -1
  616. package/dist/skills/agents/install.js +86 -17
  617. package/dist/skills/agents/install.js.map +1 -1
  618. package/dist/skills/injection/subagent.js +1 -1
  619. package/dist/skills/injection/subagent.js.map +1 -1
  620. package/dist/skills/manifests/research.d.ts.map +1 -1
  621. package/dist/skills/manifests/research.js +2 -1
  622. package/dist/skills/manifests/research.js.map +1 -1
  623. package/dist/skills/orchestrator/spawn.js +1 -1
  624. package/dist/skills/orchestrator/spawn.js.map +1 -1
  625. package/dist/skills/orchestrator/validator.js +1 -1
  626. package/dist/skills/orchestrator/validator.js.map +1 -1
  627. package/dist/snapshot/index.d.ts.map +1 -1
  628. package/dist/snapshot/index.js +13 -0
  629. package/dist/snapshot/index.js.map +1 -1
  630. package/dist/spawn/agent-identity.js +1 -1
  631. package/dist/spawn/agent-identity.js.map +1 -1
  632. package/dist/stats/index.d.ts.map +1 -1
  633. package/dist/stats/index.js +2 -1
  634. package/dist/stats/index.js.map +1 -1
  635. package/dist/store/agent-install.d.ts.map +1 -1
  636. package/dist/store/agent-install.js +2 -1
  637. package/dist/store/agent-install.js.map +1 -1
  638. package/dist/store/agent-registry-accessor.d.ts +1 -0
  639. package/dist/store/agent-registry-accessor.d.ts.map +1 -1
  640. package/dist/store/agent-registry-accessor.js +3 -1
  641. package/dist/store/agent-registry-accessor.js.map +1 -1
  642. package/dist/store/atomic.js +1 -1
  643. package/dist/store/atomic.js.map +1 -1
  644. package/dist/store/attachment-store.js +1 -1
  645. package/dist/store/attachment-store.js.map +1 -1
  646. package/dist/store/audit-log-schema.d.ts +645 -0
  647. package/dist/store/audit-log-schema.d.ts.map +1 -0
  648. package/dist/store/audit-log-schema.js +30 -0
  649. package/dist/store/audit-log-schema.js.map +1 -0
  650. package/dist/store/background-ops.d.ts +26 -0
  651. package/dist/store/background-ops.d.ts.map +1 -1
  652. package/dist/store/background-ops.js +46 -0
  653. package/dist/store/background-ops.js.map +1 -1
  654. package/dist/store/backup-recover.d.ts +36 -1
  655. package/dist/store/backup-recover.d.ts.map +1 -1
  656. package/dist/store/backup-recover.js +99 -1
  657. package/dist/store/backup-recover.js.map +1 -1
  658. package/dist/store/backup-verify.d.ts +1 -1
  659. package/dist/store/backup-verify.d.ts.map +1 -1
  660. package/dist/store/backup-verify.js +6 -1
  661. package/dist/store/backup-verify.js.map +1 -1
  662. package/dist/store/backup.js +1 -1
  663. package/dist/store/backup.js.map +1 -1
  664. package/dist/store/conduit-sqlite.d.ts.map +1 -1
  665. package/dist/store/conduit-sqlite.js +2 -26
  666. package/dist/store/conduit-sqlite.js.map +1 -1
  667. package/dist/store/converters.js +1 -1
  668. package/dist/store/converters.js.map +1 -1
  669. package/dist/store/db-helpers.js +1 -1
  670. package/dist/store/db-helpers.js.map +1 -1
  671. package/dist/store/dependency-cycles.js +1 -1
  672. package/dist/store/dependency-cycles.js.map +1 -1
  673. package/dist/store/display-id-alias.d.ts +2 -2
  674. package/dist/store/display-id-alias.d.ts.map +1 -1
  675. package/dist/store/display-id-alias.js +5 -28
  676. package/dist/store/display-id-alias.js.map +1 -1
  677. package/dist/store/drizzle-node-sqlite.d.ts +56 -0
  678. package/dist/store/drizzle-node-sqlite.d.ts.map +1 -0
  679. package/dist/store/drizzle-node-sqlite.js +87 -0
  680. package/dist/store/drizzle-node-sqlite.js.map +1 -0
  681. package/dist/store/dual-scope-db.d.ts +26 -33
  682. package/dist/store/dual-scope-db.d.ts.map +1 -1
  683. package/dist/store/dual-scope-db.js +416 -127
  684. package/dist/store/dual-scope-db.js.map +1 -1
  685. package/dist/store/exodus/abort-events.d.ts +134 -0
  686. package/dist/store/exodus/abort-events.d.ts.map +1 -1
  687. package/dist/store/exodus/abort-events.js +201 -0
  688. package/dist/store/exodus/abort-events.js.map +1 -1
  689. package/dist/store/exodus/migrate.d.ts +7 -0
  690. package/dist/store/exodus/migrate.d.ts.map +1 -1
  691. package/dist/store/exodus/migrate.js +156 -118
  692. package/dist/store/exodus/migrate.js.map +1 -1
  693. package/dist/store/exodus/on-open.d.ts +36 -0
  694. package/dist/store/exodus/on-open.d.ts.map +1 -1
  695. package/dist/store/exodus/on-open.js +102 -27
  696. package/dist/store/exodus/on-open.js.map +1 -1
  697. package/dist/store/exodus/prior-recoveries.d.ts +75 -0
  698. package/dist/store/exodus/prior-recoveries.d.ts.map +1 -0
  699. package/dist/store/exodus/prior-recoveries.js +122 -0
  700. package/dist/store/exodus/prior-recoveries.js.map +1 -0
  701. package/dist/store/exodus/reconcile.d.ts.map +1 -1
  702. package/dist/store/exodus/reconcile.js +188 -24
  703. package/dist/store/exodus/reconcile.js.map +1 -1
  704. package/dist/store/exodus/runtime-targets.d.ts +3 -3
  705. package/dist/store/exodus/runtime-targets.js +3 -3
  706. package/dist/store/exodus/task-id-collision-sql.d.ts +52 -0
  707. package/dist/store/exodus/task-id-collision-sql.d.ts.map +1 -0
  708. package/dist/store/exodus/task-id-collision-sql.js +97 -0
  709. package/dist/store/exodus/task-id-collision-sql.js.map +1 -0
  710. package/dist/store/exodus/task-id-remap.d.ts +113 -0
  711. package/dist/store/exodus/task-id-remap.d.ts.map +1 -0
  712. package/dist/store/exodus/task-id-remap.js +301 -0
  713. package/dist/store/exodus/task-id-remap.js.map +1 -0
  714. package/dist/store/exodus/verify-migration.js +1 -1
  715. package/dist/store/exodus/verify-migration.js.map +1 -1
  716. package/dist/store/exodus/write-guard.d.ts +136 -0
  717. package/dist/store/exodus/write-guard.d.ts.map +1 -0
  718. package/dist/store/exodus/write-guard.js +289 -0
  719. package/dist/store/exodus/write-guard.js.map +1 -0
  720. package/dist/store/identity-share.d.ts +31 -0
  721. package/dist/store/identity-share.d.ts.map +1 -0
  722. package/dist/store/identity-share.js +54 -0
  723. package/dist/store/identity-share.js.map +1 -0
  724. package/dist/store/import-remap.js +1 -1
  725. package/dist/store/import-remap.js.map +1 -1
  726. package/dist/store/import-sort.js +1 -1
  727. package/dist/store/import-sort.js.map +1 -1
  728. package/dist/store/json.js +1 -1
  729. package/dist/store/json.js.map +1 -1
  730. package/dist/store/legacy-tasks-lineage.js +3 -3
  731. package/dist/store/legacy-tasks-lineage.js.map +1 -1
  732. package/dist/store/lock.d.ts +17 -0
  733. package/dist/store/lock.d.ts.map +1 -1
  734. package/dist/store/lock.js +18 -1
  735. package/dist/store/lock.js.map +1 -1
  736. package/dist/store/memory-sqlite.d.ts.map +1 -1
  737. package/dist/store/memory-sqlite.js +2 -25
  738. package/dist/store/memory-sqlite.js.map +1 -1
  739. package/dist/store/migration-files.d.ts +30 -0
  740. package/dist/store/migration-files.d.ts.map +1 -0
  741. package/dist/store/migration-files.js +59 -0
  742. package/dist/store/migration-files.js.map +1 -0
  743. package/dist/store/migration-manager.d.ts.map +1 -1
  744. package/dist/store/migration-manager.js +14 -14
  745. package/dist/store/migration-manager.js.map +1 -1
  746. package/dist/store/migration-runner.d.ts.map +1 -1
  747. package/dist/store/migration-runner.js +2 -2
  748. package/dist/store/migration-runner.js.map +1 -1
  749. package/dist/store/migration-sqlite.d.ts +1 -1
  750. package/dist/store/migration-sqlite.d.ts.map +1 -1
  751. package/dist/store/migration-sqlite.js +290 -355
  752. package/dist/store/migration-sqlite.js.map +1 -1
  753. package/dist/store/open-cleo-db.d.ts.map +1 -1
  754. package/dist/store/open-cleo-db.js +4 -2
  755. package/dist/store/open-cleo-db.js.map +1 -1
  756. package/dist/store/pid-alive.d.ts +15 -0
  757. package/dist/store/pid-alive.d.ts.map +1 -0
  758. package/dist/store/pid-alive.js +24 -0
  759. package/dist/store/pid-alive.js.map +1 -0
  760. package/dist/store/portable-bundle-scan.d.ts +1 -1
  761. package/dist/store/portable-bundle-scan.d.ts.map +1 -1
  762. package/dist/store/portable-bundle-scan.js +1 -1
  763. package/dist/store/portable-bundle-scan.js.map +1 -1
  764. package/dist/store/portable-bundle.d.ts +10 -1
  765. package/dist/store/portable-bundle.d.ts.map +1 -1
  766. package/dist/store/portable-bundle.js +10 -1
  767. package/dist/store/portable-bundle.js.map +1 -1
  768. package/dist/store/recover-malformed-db.d.ts +1 -1
  769. package/dist/store/recover-malformed-db.d.ts.map +1 -1
  770. package/dist/store/recover-malformed-db.js +1 -1
  771. package/dist/store/recover-malformed-db.js.map +1 -1
  772. package/dist/store/repair-malformed-dbs.d.ts +1 -1
  773. package/dist/store/repair-malformed-dbs.d.ts.map +1 -1
  774. package/dist/store/repair-malformed-dbs.js +1 -1
  775. package/dist/store/repair-malformed-dbs.js.map +1 -1
  776. package/dist/store/restore-marker.d.ts +89 -0
  777. package/dist/store/restore-marker.d.ts.map +1 -0
  778. package/dist/store/restore-marker.js +197 -0
  779. package/dist/store/restore-marker.js.map +1 -0
  780. package/dist/store/restore-store.d.ts +85 -0
  781. package/dist/store/restore-store.d.ts.map +1 -0
  782. package/dist/store/restore-store.js +391 -0
  783. package/dist/store/restore-store.js.map +1 -0
  784. package/dist/store/row-identity.d.ts +123 -1
  785. package/dist/store/row-identity.d.ts.map +1 -1
  786. package/dist/store/row-identity.js +454 -80
  787. package/dist/store/row-identity.js.map +1 -1
  788. package/dist/store/schema/agent-registry-schema.d.ts +1 -1
  789. package/dist/store/schema/agent-registry-schema.d.ts.map +1 -1
  790. package/dist/store/schema/agent-registry-schema.js +5 -1
  791. package/dist/store/schema/agent-registry-schema.js.map +1 -1
  792. package/dist/store/schema/cleo-global/agent-registry.d.ts +1 -1
  793. package/dist/store/schema/cleo-global/agent-registry.d.ts.map +1 -1
  794. package/dist/store/schema/cleo-global/agent-registry.js +9 -5
  795. package/dist/store/schema/cleo-global/agent-registry.js.map +1 -1
  796. package/dist/store/schema/cleo-global/models-catalog.js +1 -1
  797. package/dist/store/schema/cleo-global/models-catalog.js.map +1 -1
  798. package/dist/store/schema/cleo-global/nexus.js +1 -1
  799. package/dist/store/schema/cleo-global/nexus.js.map +1 -1
  800. package/dist/store/schema/cleo-project/provenance-commits.d.ts +1 -1
  801. package/dist/store/schema/cleo-project/provenance-orphans.d.ts +1 -1
  802. package/dist/store/schema/cleo-project/provenance-orphans.d.ts.map +1 -1
  803. package/dist/store/schema/cleo-project/provenance-orphans.js +9 -2
  804. package/dist/store/schema/cleo-project/provenance-orphans.js.map +1 -1
  805. package/dist/store/schema/cleo-project/provenance-rest.d.ts +1 -1
  806. package/dist/store/schema/cleo-project/provenance-rest.js +1 -1
  807. package/dist/store/schema/cleo-project/provenance-rest.js.map +1 -1
  808. package/dist/store/schema/cleo-shared/brain.js +1 -1
  809. package/dist/store/schema/cleo-shared/brain.js.map +1 -1
  810. package/dist/store/schema/memory-schema.d.ts +1 -1
  811. package/dist/store/schema/memory-schema.d.ts.map +1 -1
  812. package/dist/store/schema/memory-schema.js +1 -1
  813. package/dist/store/schema/memory-schema.js.map +1 -1
  814. package/dist/store/schema/nexus-schema.js +1 -1
  815. package/dist/store/schema/nexus-schema.js.map +1 -1
  816. package/dist/store/service-host-matcher.d.ts +1 -1
  817. package/dist/store/service-host-matcher.d.ts.map +1 -1
  818. package/dist/store/service-host-matcher.js +1 -1
  819. package/dist/store/service-host-matcher.js.map +1 -1
  820. package/dist/store/service-oauth.js +1 -1
  821. package/dist/store/service-oauth.js.map +1 -1
  822. package/dist/store/session-store.d.ts.map +1 -1
  823. package/dist/store/session-store.js +7 -1
  824. package/dist/store/session-store.js.map +1 -1
  825. package/dist/store/sqlite-backup.d.ts +1 -1
  826. package/dist/store/sqlite-backup.d.ts.map +1 -1
  827. package/dist/store/sqlite-backup.js +1 -1
  828. package/dist/store/sqlite-backup.js.map +1 -1
  829. package/dist/store/sqlite-data-accessor.d.ts +52 -1
  830. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  831. package/dist/store/sqlite-data-accessor.js +95 -22
  832. package/dist/store/sqlite-data-accessor.js.map +1 -1
  833. package/dist/store/sqlite-native.d.ts.map +1 -1
  834. package/dist/store/sqlite-native.js +9 -9
  835. package/dist/store/sqlite-native.js.map +1 -1
  836. package/dist/store/sqlite-pragmas.d.ts +12 -5
  837. package/dist/store/sqlite-pragmas.d.ts.map +1 -1
  838. package/dist/store/sqlite-pragmas.js +13 -2
  839. package/dist/store/sqlite-pragmas.js.map +1 -1
  840. package/dist/store/sqlite.d.ts.map +1 -1
  841. package/dist/store/sqlite.js +7 -32
  842. package/dist/store/sqlite.js.map +1 -1
  843. package/dist/store/status-registry.d.ts +1 -1
  844. package/dist/store/status-registry.d.ts.map +1 -1
  845. package/dist/store/status-registry.js +1 -1
  846. package/dist/store/status-registry.js.map +1 -1
  847. package/dist/store/sync/apply/applier.d.ts +119 -0
  848. package/dist/store/sync/apply/applier.d.ts.map +1 -0
  849. package/dist/store/sync/apply/applier.js +1239 -0
  850. package/dist/store/sync/apply/applier.js.map +1 -0
  851. package/dist/store/sync/apply/fk.d.ts +47 -0
  852. package/dist/store/sync/apply/fk.d.ts.map +1 -0
  853. package/dist/store/sync/apply/fk.js +89 -0
  854. package/dist/store/sync/apply/fk.js.map +1 -0
  855. package/dist/store/sync/apply/footprints.d.ts +60 -0
  856. package/dist/store/sync/apply/footprints.d.ts.map +1 -0
  857. package/dist/store/sync/apply/footprints.js +235 -0
  858. package/dist/store/sync/apply/footprints.js.map +1 -0
  859. package/dist/store/sync/apply/frame.d.ts +80 -0
  860. package/dist/store/sync/apply/frame.d.ts.map +1 -0
  861. package/dist/store/sync/apply/frame.js +127 -0
  862. package/dist/store/sync/apply/frame.js.map +1 -0
  863. package/dist/store/sync/apply/index.d.ts +11 -0
  864. package/dist/store/sync/apply/index.d.ts.map +1 -0
  865. package/dist/store/sync/apply/index.js +11 -0
  866. package/dist/store/sync/apply/index.js.map +1 -0
  867. package/dist/store/sync/apply/parent-delete.d.ts +38 -0
  868. package/dist/store/sync/apply/parent-delete.d.ts.map +1 -0
  869. package/dist/store/sync/apply/parent-delete.js +41 -0
  870. package/dist/store/sync/apply/parent-delete.js.map +1 -0
  871. package/dist/store/sync/apply/post-apply.d.ts +67 -0
  872. package/dist/store/sync/apply/post-apply.d.ts.map +1 -0
  873. package/dist/store/sync/apply/post-apply.js +118 -0
  874. package/dist/store/sync/apply/post-apply.js.map +1 -0
  875. package/dist/store/sync/apply/refs.d.ts +60 -0
  876. package/dist/store/sync/apply/refs.d.ts.map +1 -0
  877. package/dist/store/sync/apply/refs.js +90 -0
  878. package/dist/store/sync/apply/refs.js.map +1 -0
  879. package/dist/store/sync/apply/write-api.d.ts +195 -0
  880. package/dist/store/sync/apply/write-api.d.ts.map +1 -0
  881. package/dist/store/sync/apply/write-api.js +416 -0
  882. package/dist/store/sync/apply/write-api.js.map +1 -0
  883. package/dist/store/sync/apply-intent.d.ts +117 -0
  884. package/dist/store/sync/apply-intent.d.ts.map +1 -0
  885. package/dist/store/sync/apply-intent.js +225 -0
  886. package/dist/store/sync/apply-intent.js.map +1 -0
  887. package/dist/store/sync/capture.d.ts +32 -2
  888. package/dist/store/sync/capture.d.ts.map +1 -1
  889. package/dist/store/sync/capture.js +47 -13
  890. package/dist/store/sync/capture.js.map +1 -1
  891. package/dist/store/sync/conflicts.d.ts +81 -0
  892. package/dist/store/sync/conflicts.d.ts.map +1 -0
  893. package/dist/store/sync/conflicts.js +98 -0
  894. package/dist/store/sync/conflicts.js.map +1 -0
  895. package/dist/store/sync/field-leave.d.ts +146 -0
  896. package/dist/store/sync/field-leave.d.ts.map +1 -0
  897. package/dist/store/sync/field-leave.js +241 -0
  898. package/dist/store/sync/field-leave.js.map +1 -0
  899. package/dist/store/sync/flags.d.ts +119 -0
  900. package/dist/store/sync/flags.d.ts.map +1 -1
  901. package/dist/store/sync/flags.js +360 -0
  902. package/dist/store/sync/flags.js.map +1 -1
  903. package/dist/store/sync/held.d.ts +197 -0
  904. package/dist/store/sync/held.d.ts.map +1 -0
  905. package/dist/store/sync/held.js +314 -0
  906. package/dist/store/sync/held.js.map +1 -0
  907. package/dist/store/sync/identity-fill.d.ts.map +1 -1
  908. package/dist/store/sync/identity-fill.js +10 -2
  909. package/dist/store/sync/identity-fill.js.map +1 -1
  910. package/dist/store/sync/inbox.d.ts +114 -0
  911. package/dist/store/sync/inbox.d.ts.map +1 -0
  912. package/dist/store/sync/inbox.js +222 -0
  913. package/dist/store/sync/inbox.js.map +1 -0
  914. package/dist/store/sync/inherit.d.ts +36 -0
  915. package/dist/store/sync/inherit.d.ts.map +1 -0
  916. package/dist/store/sync/inherit.js +38 -0
  917. package/dist/store/sync/inherit.js.map +1 -0
  918. package/dist/store/sync/merge/engine.d.ts +114 -0
  919. package/dist/store/sync/merge/engine.d.ts.map +1 -0
  920. package/dist/store/sync/merge/engine.js +698 -0
  921. package/dist/store/sync/merge/engine.js.map +1 -0
  922. package/dist/store/sync/merge/index.d.ts +11 -0
  923. package/dist/store/sync/merge/index.d.ts.map +1 -0
  924. package/dist/store/sync/merge/index.js +11 -0
  925. package/dist/store/sync/merge/index.js.map +1 -0
  926. package/dist/store/sync/merge/rules.d.ts +91 -0
  927. package/dist/store/sync/merge/rules.d.ts.map +1 -0
  928. package/dist/store/sync/merge/rules.js +151 -0
  929. package/dist/store/sync/merge/rules.js.map +1 -0
  930. package/dist/store/sync/merge/types.d.ts +206 -0
  931. package/dist/store/sync/merge/types.d.ts.map +1 -0
  932. package/dist/store/sync/merge/types.js +15 -0
  933. package/dist/store/sync/merge/types.js.map +1 -0
  934. package/dist/store/sync/migration-hooks.d.ts +47 -0
  935. package/dist/store/sync/migration-hooks.d.ts.map +1 -0
  936. package/dist/store/sync/migration-hooks.js +74 -0
  937. package/dist/store/sync/migration-hooks.js.map +1 -0
  938. package/dist/store/sync/netting.d.ts +5 -0
  939. package/dist/store/sync/netting.d.ts.map +1 -1
  940. package/dist/store/sync/netting.js +29 -2
  941. package/dist/store/sync/netting.js.map +1 -1
  942. package/dist/store/sync/remap.d.ts +72 -0
  943. package/dist/store/sync/remap.d.ts.map +1 -0
  944. package/dist/store/sync/remap.js +209 -0
  945. package/dist/store/sync/remap.js.map +1 -0
  946. package/dist/store/sync/repair.d.ts +180 -0
  947. package/dist/store/sync/repair.d.ts.map +1 -0
  948. package/dist/store/sync/repair.js +499 -0
  949. package/dist/store/sync/repair.js.map +1 -0
  950. package/dist/store/sync/replica-registry.d.ts +54 -0
  951. package/dist/store/sync/replica-registry.d.ts.map +1 -1
  952. package/dist/store/sync/replica-registry.js +72 -2
  953. package/dist/store/sync/replica-registry.js.map +1 -1
  954. package/dist/store/sync/replica.d.ts +71 -9
  955. package/dist/store/sync/replica.d.ts.map +1 -1
  956. package/dist/store/sync/replica.js +95 -11
  957. package/dist/store/sync/replica.js.map +1 -1
  958. package/dist/store/sync/row-meta.d.ts +148 -0
  959. package/dist/store/sync/row-meta.d.ts.map +1 -0
  960. package/dist/store/sync/row-meta.js +200 -0
  961. package/dist/store/sync/row-meta.js.map +1 -0
  962. package/dist/store/sync/schema.d.ts +13 -5
  963. package/dist/store/sync/schema.d.ts.map +1 -1
  964. package/dist/store/sync/schema.js +34 -7
  965. package/dist/store/sync/schema.js.map +1 -1
  966. package/dist/store/sync/sealer-values.d.ts.map +1 -1
  967. package/dist/store/sync/sealer-values.js +1 -0
  968. package/dist/store/sync/sealer-values.js.map +1 -1
  969. package/dist/store/sync/sealer.d.ts +96 -0
  970. package/dist/store/sync/sealer.d.ts.map +1 -1
  971. package/dist/store/sync/sealer.js +532 -58
  972. package/dist/store/sync/sealer.js.map +1 -1
  973. package/dist/store/sync/sequencing.d.ts +175 -0
  974. package/dist/store/sync/sequencing.d.ts.map +1 -0
  975. package/dist/store/sync/sequencing.js +295 -0
  976. package/dist/store/sync/sequencing.js.map +1 -0
  977. package/dist/store/sync/structural.d.ts +30 -2
  978. package/dist/store/sync/structural.d.ts.map +1 -1
  979. package/dist/store/sync/structural.js +64 -2
  980. package/dist/store/sync/structural.js.map +1 -1
  981. package/dist/store/sync/timestamp-canon.d.ts +44 -0
  982. package/dist/store/sync/timestamp-canon.d.ts.map +1 -0
  983. package/dist/store/sync/timestamp-canon.js +102 -0
  984. package/dist/store/sync/timestamp-canon.js.map +1 -0
  985. package/dist/store/sync/timestamps.d.ts +1 -30
  986. package/dist/store/sync/timestamps.d.ts.map +1 -1
  987. package/dist/store/sync/timestamps.js +2 -89
  988. package/dist/store/sync/timestamps.js.map +1 -1
  989. package/dist/store/sync/trigger-classes.d.ts +8 -0
  990. package/dist/store/sync/trigger-classes.d.ts.map +1 -1
  991. package/dist/store/sync/trigger-classes.js +13 -0
  992. package/dist/store/sync/trigger-classes.js.map +1 -1
  993. package/dist/store/sync/write-actor.d.ts +58 -0
  994. package/dist/store/sync/write-actor.d.ts.map +1 -0
  995. package/dist/store/sync/write-actor.js +67 -0
  996. package/dist/store/sync/write-actor.js.map +1 -0
  997. package/dist/store/table-classification.d.ts.map +1 -1
  998. package/dist/store/table-classification.js +84 -0
  999. package/dist/store/table-classification.js.map +1 -1
  1000. package/dist/store/task-claim.d.ts +1 -1
  1001. package/dist/store/task-claim.d.ts.map +1 -1
  1002. package/dist/store/task-claim.js +1 -1
  1003. package/dist/store/task-claim.js.map +1 -1
  1004. package/dist/store/task-reference-columns.d.ts +27 -0
  1005. package/dist/store/task-reference-columns.d.ts.map +1 -0
  1006. package/dist/store/task-reference-columns.js +65 -0
  1007. package/dist/store/task-reference-columns.js.map +1 -0
  1008. package/dist/store/task-version.d.ts +1 -1
  1009. package/dist/store/task-version.d.ts.map +1 -1
  1010. package/dist/store/task-version.js +1 -1
  1011. package/dist/store/task-version.js.map +1 -1
  1012. package/dist/store/tasks-schema.d.ts +2 -1
  1013. package/dist/store/tasks-schema.d.ts.map +1 -1
  1014. package/dist/store/tasks-schema.js +5 -4
  1015. package/dist/store/tasks-schema.js.map +1 -1
  1016. package/dist/store/tasks-sqlite.d.ts +1 -1
  1017. package/dist/store/tasks-sqlite.d.ts.map +1 -1
  1018. package/dist/store/tasks-sqlite.js +3 -1
  1019. package/dist/store/tasks-sqlite.js.map +1 -1
  1020. package/dist/store/twin-collapse.d.ts +43 -14
  1021. package/dist/store/twin-collapse.d.ts.map +1 -1
  1022. package/dist/store/twin-collapse.js +373 -32
  1023. package/dist/store/twin-collapse.js.map +1 -1
  1024. package/dist/store/validation-schemas.d.ts +44 -674
  1025. package/dist/store/validation-schemas.d.ts.map +1 -1
  1026. package/dist/store/validation-schemas.js +2 -22
  1027. package/dist/store/validation-schemas.js.map +1 -1
  1028. package/dist/store/vault-manifest.d.ts +1 -1
  1029. package/dist/store/vault-manifest.d.ts.map +1 -1
  1030. package/dist/store/vault-manifest.js +1 -1
  1031. package/dist/store/vault-manifest.js.map +1 -1
  1032. package/dist/store/worktree-build-guard.js +1 -1
  1033. package/dist/store/worktree-build-guard.js.map +1 -1
  1034. package/dist/store/worktree-isolation-guard.js +1 -1
  1035. package/dist/store/worktree-isolation-guard.js.map +1 -1
  1036. package/dist/store/writer-lease.d.ts.map +1 -1
  1037. package/dist/store/writer-lease.js +1 -11
  1038. package/dist/store/writer-lease.js.map +1 -1
  1039. package/dist/store/zod-schema-factory.d.ts +16 -0
  1040. package/dist/store/zod-schema-factory.d.ts.map +1 -0
  1041. package/dist/store/zod-schema-factory.js +23 -0
  1042. package/dist/store/zod-schema-factory.js.map +1 -0
  1043. package/dist/system/backup.d.ts +106 -0
  1044. package/dist/system/backup.d.ts.map +1 -1
  1045. package/dist/system/backup.js +295 -19
  1046. package/dist/system/backup.js.map +1 -1
  1047. package/dist/system/cleanup.js +1 -1
  1048. package/dist/system/cleanup.js.map +1 -1
  1049. package/dist/system/labels.js +1 -1
  1050. package/dist/system/labels.js.map +1 -1
  1051. package/dist/system/migrate.js +1 -1
  1052. package/dist/system/migrate.js.map +1 -1
  1053. package/dist/system/safestop.d.ts.map +1 -1
  1054. package/dist/system/safestop.js +1 -1
  1055. package/dist/system/safestop.js.map +1 -1
  1056. package/dist/task-work/current.d.ts +34 -0
  1057. package/dist/task-work/current.d.ts.map +1 -0
  1058. package/dist/task-work/current.js +34 -0
  1059. package/dist/task-work/current.js.map +1 -0
  1060. package/dist/task-work/index.d.ts +2 -19
  1061. package/dist/task-work/index.d.ts.map +1 -1
  1062. package/dist/task-work/index.js +6 -20
  1063. package/dist/task-work/index.js.map +1 -1
  1064. package/dist/tasks/ac-identity.d.ts +28 -0
  1065. package/dist/tasks/ac-identity.d.ts.map +1 -0
  1066. package/dist/tasks/ac-identity.js +43 -0
  1067. package/dist/tasks/ac-identity.js.map +1 -0
  1068. package/dist/tasks/ac-immutability.d.ts +1 -1
  1069. package/dist/tasks/ac-immutability.d.ts.map +1 -1
  1070. package/dist/tasks/ac-immutability.js +1 -1
  1071. package/dist/tasks/ac-immutability.js.map +1 -1
  1072. package/dist/tasks/ac-table.d.ts +2 -14
  1073. package/dist/tasks/ac-table.d.ts.map +1 -1
  1074. package/dist/tasks/ac-table.js +6 -29
  1075. package/dist/tasks/ac-table.js.map +1 -1
  1076. package/dist/tasks/acceptance-input.js +1 -1
  1077. package/dist/tasks/acceptance-input.js.map +1 -1
  1078. package/dist/tasks/add.d.ts.map +1 -1
  1079. package/dist/tasks/add.js +3 -1
  1080. package/dist/tasks/add.js.map +1 -1
  1081. package/dist/tasks/affected-packages.d.ts +80 -12
  1082. package/dist/tasks/affected-packages.d.ts.map +1 -1
  1083. package/dist/tasks/affected-packages.js +130 -19
  1084. package/dist/tasks/affected-packages.js.map +1 -1
  1085. package/dist/tasks/archive.d.ts.map +1 -1
  1086. package/dist/tasks/archive.js +1 -1
  1087. package/dist/tasks/archive.js.map +1 -1
  1088. package/dist/tasks/axis-filters.d.ts.map +1 -1
  1089. package/dist/tasks/axis-filters.js +2 -1
  1090. package/dist/tasks/axis-filters.js.map +1 -1
  1091. package/dist/tasks/child-disposition.js +1 -1
  1092. package/dist/tasks/child-disposition.js.map +1 -1
  1093. package/dist/tasks/collection.js +1 -1
  1094. package/dist/tasks/collection.js.map +1 -1
  1095. package/dist/tasks/complete.d.ts.map +1 -1
  1096. package/dist/tasks/complete.js +2 -1
  1097. package/dist/tasks/complete.js.map +1 -1
  1098. package/dist/tasks/decompose.js +1 -1
  1099. package/dist/tasks/decompose.js.map +1 -1
  1100. package/dist/tasks/delete.js +1 -1
  1101. package/dist/tasks/delete.js.map +1 -1
  1102. package/dist/tasks/done-plan.d.ts +2 -1
  1103. package/dist/tasks/done-plan.d.ts.map +1 -1
  1104. package/dist/tasks/done-plan.js +10 -20
  1105. package/dist/tasks/done-plan.js.map +1 -1
  1106. package/dist/tasks/done-record.d.ts +1 -1
  1107. package/dist/tasks/done-record.d.ts.map +1 -1
  1108. package/dist/tasks/done-record.js +1 -1
  1109. package/dist/tasks/done-record.js.map +1 -1
  1110. package/dist/tasks/enforcement.d.ts +2 -1
  1111. package/dist/tasks/enforcement.d.ts.map +1 -1
  1112. package/dist/tasks/enforcement.js +1 -1
  1113. package/dist/tasks/enforcement.js.map +1 -1
  1114. package/dist/tasks/engine-wrap-ops.js +1 -1
  1115. package/dist/tasks/engine-wrap-ops.js.map +1 -1
  1116. package/dist/tasks/engine-wrap.d.ts.map +1 -1
  1117. package/dist/tasks/engine-wrap.js +7 -3
  1118. package/dist/tasks/engine-wrap.js.map +1 -1
  1119. package/dist/tasks/epic-enforcement.js +1 -1
  1120. package/dist/tasks/epic-enforcement.js.map +1 -1
  1121. package/dist/tasks/evidence.d.ts.map +1 -1
  1122. package/dist/tasks/evidence.js +41 -19
  1123. package/dist/tasks/evidence.js.map +1 -1
  1124. package/dist/tasks/find.js +1 -1
  1125. package/dist/tasks/find.js.map +1 -1
  1126. package/dist/tasks/gate-result-cache.js +1 -1
  1127. package/dist/tasks/gate-result-cache.js.map +1 -1
  1128. package/dist/tasks/gate-runner.d.ts.map +1 -1
  1129. package/dist/tasks/gate-runner.js +1 -1
  1130. package/dist/tasks/gate-runner.js.map +1 -1
  1131. package/dist/tasks/heavy-tool-env.d.ts +79 -11
  1132. package/dist/tasks/heavy-tool-env.d.ts.map +1 -1
  1133. package/dist/tasks/heavy-tool-env.js +111 -14
  1134. package/dist/tasks/heavy-tool-env.js.map +1 -1
  1135. package/dist/tasks/index.d.ts +1 -1
  1136. package/dist/tasks/index.d.ts.map +1 -1
  1137. package/dist/tasks/index.js +2 -2
  1138. package/dist/tasks/index.js.map +1 -1
  1139. package/dist/tasks/labels.js +1 -1
  1140. package/dist/tasks/labels.js.map +1 -1
  1141. package/dist/tasks/nexus-impact-gate.js +1 -1
  1142. package/dist/tasks/nexus-impact-gate.js.map +1 -1
  1143. package/dist/tasks/pipeline-stage.js +1 -1
  1144. package/dist/tasks/pipeline-stage.js.map +1 -1
  1145. package/dist/tasks/population.js +1 -1
  1146. package/dist/tasks/population.js.map +1 -1
  1147. package/dist/tasks/ranking-audit.js +1 -1
  1148. package/dist/tasks/ranking-audit.js.map +1 -1
  1149. package/dist/tasks/reconcile-scope.js +1 -1
  1150. package/dist/tasks/reconcile-scope.js.map +1 -1
  1151. package/dist/tasks/relates.js +1 -1
  1152. package/dist/tasks/relates.js.map +1 -1
  1153. package/dist/tasks/req.d.ts.map +1 -1
  1154. package/dist/tasks/req.js +2 -1
  1155. package/dist/tasks/req.js.map +1 -1
  1156. package/dist/tasks/severity-attestation.d.ts +1 -1
  1157. package/dist/tasks/severity-attestation.d.ts.map +1 -1
  1158. package/dist/tasks/severity-attestation.js +1 -1
  1159. package/dist/tasks/severity-attestation.js.map +1 -1
  1160. package/dist/tasks/show.d.ts.map +1 -1
  1161. package/dist/tasks/show.js +47 -3
  1162. package/dist/tasks/show.js.map +1 -1
  1163. package/dist/tasks/task-import.js +1 -1
  1164. package/dist/tasks/task-import.js.map +1 -1
  1165. package/dist/tasks/task-reparent.d.ts.map +1 -1
  1166. package/dist/tasks/task-reparent.js +2 -1
  1167. package/dist/tasks/task-reparent.js.map +1 -1
  1168. package/dist/tasks/test-run-binding.d.ts.map +1 -1
  1169. package/dist/tasks/test-run-binding.js +9 -2
  1170. package/dist/tasks/test-run-binding.js.map +1 -1
  1171. package/dist/tasks/tool-cache.d.ts +23 -8
  1172. package/dist/tasks/tool-cache.d.ts.map +1 -1
  1173. package/dist/tasks/tool-cache.js +57 -16
  1174. package/dist/tasks/tool-cache.js.map +1 -1
  1175. package/dist/tasks/tool-resolver.d.ts +8 -0
  1176. package/dist/tasks/tool-resolver.d.ts.map +1 -1
  1177. package/dist/tasks/tool-resolver.js +15 -1
  1178. package/dist/tasks/tool-resolver.js.map +1 -1
  1179. package/dist/tasks/tool-runner-guard.d.ts +131 -0
  1180. package/dist/tasks/tool-runner-guard.d.ts.map +1 -0
  1181. package/dist/tasks/tool-runner-guard.js +141 -0
  1182. package/dist/tasks/tool-runner-guard.js.map +1 -0
  1183. package/dist/tasks/tool-semaphore.d.ts +103 -342
  1184. package/dist/tasks/tool-semaphore.d.ts.map +1 -1
  1185. package/dist/tasks/tool-semaphore.js +131 -619
  1186. package/dist/tasks/tool-semaphore.js.map +1 -1
  1187. package/dist/tasks/update.d.ts.map +1 -1
  1188. package/dist/tasks/update.js +2 -1
  1189. package/dist/tasks/update.js.map +1 -1
  1190. package/dist/upgrade.d.ts.map +1 -1
  1191. package/dist/upgrade.js +5 -34
  1192. package/dist/upgrade.js.map +1 -1
  1193. package/dist/validation/doctor/checks.d.ts +24 -0
  1194. package/dist/validation/doctor/checks.d.ts.map +1 -1
  1195. package/dist/validation/doctor/checks.js +168 -0
  1196. package/dist/validation/doctor/checks.js.map +1 -1
  1197. package/dist/validation/doctor/index.d.ts +1 -1
  1198. package/dist/validation/doctor/index.d.ts.map +1 -1
  1199. package/dist/validation/doctor/index.js +1 -1
  1200. package/dist/validation/doctor/index.js.map +1 -1
  1201. package/dist/validation/engine-ops.js +1 -1
  1202. package/dist/validation/engine-ops.js.map +1 -1
  1203. package/dist/validation/engine.d.ts +1 -1
  1204. package/dist/validation/engine.d.ts.map +1 -1
  1205. package/dist/validation/engine.js +2 -1
  1206. package/dist/validation/engine.js.map +1 -1
  1207. package/dist/validation/index.d.ts +1 -1
  1208. package/dist/validation/index.d.ts.map +1 -1
  1209. package/dist/validation/index.js +1 -1
  1210. package/dist/validation/index.js.map +1 -1
  1211. package/dist/validation/operation-gate-validators.js +1 -1
  1212. package/dist/validation/operation-gate-validators.js.map +1 -1
  1213. package/dist/validation/protocol-common.js +1 -1
  1214. package/dist/validation/protocol-common.js.map +1 -1
  1215. package/dist/validation/protocols/_shared.js +1 -1
  1216. package/dist/validation/protocols/_shared.js.map +1 -1
  1217. package/dist/validation/validate-ops.js +1 -1
  1218. package/dist/validation/validate-ops.js.map +1 -1
  1219. package/dist/validation/verification.js +1 -1
  1220. package/dist/validation/verification.js.map +1 -1
  1221. package/dist/workgraph/index.d.ts +1 -1
  1222. package/dist/workgraph/index.d.ts.map +1 -1
  1223. package/dist/workgraph/index.js +1 -1
  1224. package/dist/workgraph/index.js.map +1 -1
  1225. package/dist/workgraph/reparent-preflight.d.ts +1 -2
  1226. package/dist/workgraph/reparent-preflight.d.ts.map +1 -1
  1227. package/dist/workgraph/reparent-preflight.js +1 -1
  1228. package/dist/workgraph/reparent-preflight.js.map +1 -1
  1229. package/dist/workgraph/scaffold-validate.js +1 -1
  1230. package/dist/workgraph/scaffold-validate.js.map +1 -1
  1231. package/dist/worktree/force-unlock.d.ts +1 -1
  1232. package/dist/worktree/force-unlock.d.ts.map +1 -1
  1233. package/dist/worktree/force-unlock.js +1 -1
  1234. package/dist/worktree/force-unlock.js.map +1 -1
  1235. package/dist/worktree/isolation.d.ts +1 -1
  1236. package/dist/worktree/isolation.d.ts.map +1 -1
  1237. package/dist/worktree/isolation.js +1 -1
  1238. package/dist/worktree/isolation.js.map +1 -1
  1239. package/dist/worktree/list.d.ts +1 -1
  1240. package/dist/worktree/list.d.ts.map +1 -1
  1241. package/dist/worktree/list.js +1 -1
  1242. package/dist/worktree/list.js.map +1 -1
  1243. package/dist/worktree/prune.d.ts +1 -1
  1244. package/dist/worktree/prune.d.ts.map +1 -1
  1245. package/dist/worktree/prune.js +1 -1
  1246. package/dist/worktree/prune.js.map +1 -1
  1247. package/dist/worktree/worktree-adopt.d.ts +1 -2
  1248. package/dist/worktree/worktree-adopt.d.ts.map +1 -1
  1249. package/dist/worktree/worktree-adopt.js +1 -1
  1250. package/dist/worktree/worktree-adopt.js.map +1 -1
  1251. package/migrations/sync-journal/20261004120000_t12757-apply-intent/migration.sql +21 -0
  1252. package/migrations/sync-journal/20261005120000_t12344-inbox/migration.sql +67 -0
  1253. package/migrations/sync-journal/20261006120000_t13193-rebase-undo/migration.sql +51 -0
  1254. package/migrations/sync-journal/20261006130000_t13193-rebase-state/migration.sql +17 -0
  1255. package/migrations/sync-journal/20261006140000_t13193-held-rows/migration.sql +24 -0
  1256. package/package.json +13 -13
  1257. package/schemas/project-context.schema.json +14 -0
  1258. package/templates/CLEO-INJECTION.md +11 -11
  1259. package/templates/CLEO-REFERENCE.md +2 -2
  1260. package/templates/workflows/release-prepare.yml.tmpl +10 -10
@@ -0,0 +1,1401 @@
1
+ /**
2
+ * The admission ledger: ONE machine-wide budget and ONE FIFO queue for every
3
+ * heavy run (T13133, epic T13121).
4
+ *
5
+ * It replaces the layers that admitted heavy work before it: the tool
6
+ * semaphore's per-tool slot directories, the governor's `test-run`,
7
+ * `scoped-build` and `full-build` slots, `cleo run`'s per-class queues and the
8
+ * darwin one-slot rule. Each layer bounded only what it could see, and two of
9
+ * them taken in opposite orders deadlocked the machine queue (T13133). Here
10
+ * every heavy run — a `cleo verify` evidence run, a `cleo run` job, the vitest
11
+ * project probe — asks one ledger for a share of one budget.
12
+ *
13
+ * ## Budget
14
+ *
15
+ * Bytes, not runs: `capacity = totalRAM − max(4 GiB, 25%)`. A run asks for its
16
+ * footprint ({@link footprintForTool}, {@link footprintForClass}); a run larger
17
+ * than the capacity is clamped to it and runs alone, so nothing waits forever
18
+ * on its size. Pressure scales the budget: the memory gate (`pressure-gate.ts`,
19
+ * T13127) refusing means nothing starts; a `hold` verdict halves the budget and
20
+ * a CPU-saturated `backoff` admits one run at a time (each keeps one run
21
+ * going when nothing else is running).
22
+ *
23
+ * ## Exclusive runs
24
+ *
25
+ * A `full-build` (`cleo run --class full-build`: a workspace-wide build,
26
+ * turbo/nx across every package) is EXCLUSIVE: at most one exclusive run is
27
+ * admitted machine-wide at a time, whatever its footprint (T13237). Bytes
28
+ * alone stopped guaranteeing that once T13132 charged a heavy run half the
29
+ * budget: two whole-workspace builds fit and ran at once, the saturation
30
+ * shape behind the P0 crash. Other runs still share the budget beside it.
31
+ *
32
+ * ## Queue
33
+ *
34
+ * FIFO with backfill: the oldest waiting run starts when it fits; a later run
35
+ * may start ahead of it while it is young, if it fits now. Once the oldest
36
+ * waiting run has waited {@link LEDGER_RESERVATION_MS} it holds a reservation
37
+ * and nothing passes it, so neither a big run nor a stream of small ones can
38
+ * starve the other. Any process that enters the ledger (an arrival, a waiter's
39
+ * periodic pass, a release) runs the scheduling pass for everyone; waiters see
40
+ * their admission by reading the file.
41
+ *
42
+ * ## Re-entrancy
43
+ *
44
+ * A grant exports `CLEO_ADMISSION=<id>.<nonce>` to its children. A request
45
+ * made inside an admitted run's process tree rides that grant (no new budget,
46
+ * no queue), so a `cleo verify` under `cleo run`, or a `cleo run` under an
47
+ * evidence run, never waits for the budget its own ancestor holds. The token
48
+ * only says which grant to check: the caller must descend from the holder
49
+ * (ancestry, or membership of a tool process group it started), with the
50
+ * holder's start time matching, so the env var alone grants nothing. A wrapper
51
+ * that scrubs the environment is caught by the same ancestry scan.
52
+ *
53
+ * ## The file
54
+ *
55
+ * `<cleoHome>/admission/ledger.json`, rewritten by tmp + rename inside a
56
+ * `proper-lockfile` critical section that only reads, decides and writes:
57
+ * pressure samples and process probes happen before it is entered, and it is
58
+ * never held across a spawn or a wait. An entry is dropped once its holder is
59
+ * provably gone: pid gone (or recycled, by start time) and every tool group it
60
+ * started gone; a fresh heartbeat or an unreadable probe keeps it.
61
+ *
62
+ * @module resources/admission-ledger
63
+ * @task T13133
64
+ * @epic T13121
65
+ */
66
+ import { execFileSync } from 'node:child_process';
67
+ import { randomBytes } from 'node:crypto';
68
+ import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
69
+ import { hostname, totalmem } from 'node:os';
70
+ import { join } from 'node:path';
71
+ import lockfile from 'proper-lockfile';
72
+ import { getLogger } from '../logger.js';
73
+ import { getCleoHome } from '../paths.js';
74
+ import { admissionCapacityBytes, admissionReserveBytes, defaultSingleProcessHeapMb, GIB_PER_WORKER, HEAVY_TOOL_HEAP_MB, heavyToolWorkers, isHeavyTool, isMemoryBoundTool, } from '../tasks/heavy-tool-env.js';
75
+ import { pressureScore, ResourceMonitor } from './monitor.js';
76
+ import { checkMemoryGate, MEMORY_GATE_RETRY_AFTER_MS, } from './pressure-gate.js';
77
+ import { processAncestors, processGroupOf } from './run-admission.js';
78
+ import { ownProcessStartedAt, systemPidProbe } from './slot-holder.js';
79
+ import { followToolGroups, isProbeableId } from './tool-groups.js';
80
+ let _log = null;
81
+ function log() {
82
+ if (_log === null)
83
+ _log = getLogger('admission-ledger');
84
+ return _log;
85
+ }
86
+ // ---------------------------------------------------------------------------
87
+ // Constants
88
+ // ---------------------------------------------------------------------------
89
+ /** The env var a grant exports to its children: `<id>.<nonce>`. */
90
+ export const ADMISSION_ENV = 'CLEO_ADMISSION';
91
+ /** The oldest waiting run holds a reservation (no backfill passes it) after this long. */
92
+ export const LEDGER_RESERVATION_MS = 120_000;
93
+ /** An admitted run refreshes its heartbeat this often. */
94
+ export const LEDGER_HEARTBEAT_MS = 15_000;
95
+ /** A heartbeat older than this no longer proves its holder alive on its own. */
96
+ export const LEDGER_HEARTBEAT_STALE_MS = 60_000;
97
+ /** A waiter names the holders (and any suspected cycle) after this long, then this often. */
98
+ export const LEDGER_HOLDER_REPORT_MS = 60_000;
99
+ /** A crashed process's critical-section lock is taken over after this long. */
100
+ export const LEDGER_CRITICAL_STALE_MS = 10_000;
101
+ /** How often a waiter re-reads the ledger to see whether it was admitted. */
102
+ const READ_POLL_MS = 250;
103
+ /** How often a waiter runs a scheduling pass of its own when nobody has sampled pressure lately. */
104
+ const PASS_EVERY_MS = 2_000;
105
+ /** A pressure verdict written to the ledger this recently is reused instead of sampling again. */
106
+ const PRESSURE_REUSE_MS = PASS_EVERY_MS;
107
+ /**
108
+ * The ledger file format this CLEO reads and writes. A file with a newer
109
+ * version is never rewritten by this one: admission runs ungoverned instead.
110
+ */
111
+ export const LEDGER_VERSION = 1;
112
+ /**
113
+ * An entry whose holder cannot be positively identified (pid gone, recycled,
114
+ * unprobeable, or no recorded start time) is dropped once its heartbeat is
115
+ * this old. A live holder heartbeats every {@link LEDGER_HEARTBEAT_MS}. The
116
+ * old slot locks had the same 10-minute takeover as a backstop.
117
+ */
118
+ export const LEDGER_ORPHAN_MS = 600_000;
119
+ /**
120
+ * `CLEO_ADMISSION_PRESSURE=off`: admission ignores memory and CPU pressure
121
+ * and admits on the byte budget alone (a CI runner whose PSI is noisy, and
122
+ * the test suite, which must never depend on the host's load). An explicit
123
+ * sampler passed to {@link admit} is still used.
124
+ */
125
+ export const ADMISSION_PRESSURE_ENV = 'CLEO_ADMISSION_PRESSURE';
126
+ /** One GiB in bytes. */
127
+ export const GIB = 1024 ** 3;
128
+ /** What a light run (audit, security scan) or a config probe is charged. */
129
+ export const LIGHT_FOOTPRINT_BYTES = GIB;
130
+ /**
131
+ * Resident memory one Node process holds beyond its V8 heap ceiling, in MiB:
132
+ * code, native allocations, buffers (the same allowance the heavy worker count
133
+ * makes: {@link GIB_PER_WORKER} minus the default heap).
134
+ */
135
+ export const PROCESS_OVERHEAD_MB = GIB_PER_WORKER * 1024 - HEAVY_TOOL_HEAP_MB;
136
+ /** Lock retries for the critical section: up to ~15 s, longer than the stale takeover. */
137
+ /**
138
+ * Lock attempts while another process is inside the critical section, and the
139
+ * backoff between them (ms, growing by 1.2, randomized up to 2x): about 15 s
140
+ * in all. Only contention (`ELOCKED`) is retried; any other error (a
141
+ * read-only CLEO home) fails at once, so a sandbox runs ungoverned without
142
+ * first waiting out the retries.
143
+ */
144
+ const LOCK_ATTEMPTS = 400;
145
+ const LOCK_BACKOFF_MS = [2, 40];
146
+ // ---------------------------------------------------------------------------
147
+ // Budget and footprints
148
+ // ---------------------------------------------------------------------------
149
+ /** The machine budget and the reserve it leaves (owned by the heavy-tool plan, which sizes runs to it). */
150
+ export { admissionCapacityBytes, admissionReserveBytes };
151
+ /**
152
+ * What one heavy test or build run is charged: the worker count the heavy-tool
153
+ * overlay gives it (`heavyToolWorkers`) × {@link GIB_PER_WORKER}.
154
+ *
155
+ * @param totalBytes - physical RAM. @defaultValue os.totalmem()
156
+ * @param env - the environment (the per-run share). @defaultValue process.env
157
+ */
158
+ export function heavyRunFootprintBytes(totalBytes = totalmem(), env = process.env) {
159
+ return heavyToolWorkers(totalBytes / GIB, env) * GIB_PER_WORKER * GIB;
160
+ }
161
+ /**
162
+ * What an evidence run of a canonical tool is charged: a heavy test or build
163
+ * run its workers × {@link GIB_PER_WORKER}; a single-process memory-bound run
164
+ * (`typecheck`, `lint`) its heap ceiling plus {@link PROCESS_OVERHEAD_MB} (the
165
+ * heap the run is planned with, T13122, or the machine's default for a single
166
+ * process); anything else {@link LIGHT_FOOTPRINT_BYTES}.
167
+ *
168
+ * @param canonical - the canonical tool.
169
+ * @param totalBytes - physical RAM. @defaultValue os.totalmem()
170
+ * @param heapMb - the heap ceiling the run is spawned with, in MiB, when known.
171
+ *
172
+ * @example
173
+ * ```ts
174
+ * footprintForTool('test', 48 * GIB); // 36 GiB (6 workers × 6 GiB)
175
+ * footprintForTool('typecheck', 48 * GIB); // 6 GiB (4096 MiB heap + 2048 MiB)
176
+ * footprintForTool('typecheck', 48 * GIB, 8192); // 10 GiB
177
+ * ```
178
+ */
179
+ export function footprintForTool(canonical, totalBytes = totalmem(), heapMb) {
180
+ if (isHeavyTool(canonical))
181
+ return heavyRunFootprintBytes(totalBytes);
182
+ if (isMemoryBoundTool(canonical)) {
183
+ const heap = heapMb ?? defaultSingleProcessHeapMb(totalBytes / GIB);
184
+ return (Math.max(0, heap) + PROCESS_OVERHEAD_MB) * 1024 * 1024;
185
+ }
186
+ return LIGHT_FOOTPRINT_BYTES;
187
+ }
188
+ /**
189
+ * What a planned memory-bound run is charged: every process it may start ×
190
+ * (its heap ceiling + {@link PROCESS_OVERHEAD_MB}), i.e. workspace packages in
191
+ * flight × workers × per-process cost. The plan's limits are what the child is
192
+ * spawned with, so the charge is enforced, not estimated (T13132).
193
+ *
194
+ * @param plan - the `resources` of `planHeavyToolEnv`.
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * // 1 package × 3 workers × (4096 + 2048) MiB
199
+ * planFootprintBytes({ workspaceConcurrency: 1, workers: 3, heapMb: 4096 }); // 18 GiB
200
+ * ```
201
+ */
202
+ export function planFootprintBytes(plan) {
203
+ const processes = Math.max(1, plan.workspaceConcurrency) * Math.max(1, plan.workers);
204
+ return processes * (Math.max(0, plan.heapMb) + PROCESS_OVERHEAD_MB) * 1024 * 1024;
205
+ }
206
+ /** Governor classes whose admission is the ledger's. */
207
+ export const LEDGER_CLASSES = new Set([
208
+ 'test-run',
209
+ 'scoped-build',
210
+ 'full-build',
211
+ ]);
212
+ /**
213
+ * Whether the ledger admits a governor class.
214
+ *
215
+ * @param cls - the governor class.
216
+ */
217
+ export function isLedgerClass(cls) {
218
+ return LEDGER_CLASSES.has(cls);
219
+ }
220
+ /**
221
+ * What a `cleo run` job of a ledger class is charged.
222
+ *
223
+ * @param cls - the governor class.
224
+ * @param totalBytes - physical RAM. @defaultValue os.totalmem()
225
+ */
226
+ export function footprintForClass(cls, totalBytes = totalmem()) {
227
+ return isLedgerClass(cls) ? heavyRunFootprintBytes(totalBytes) : LIGHT_FOOTPRINT_BYTES;
228
+ }
229
+ /**
230
+ * The ledger directory under the CLEO home.
231
+ *
232
+ * @param cleoHome - the CLEO home. @defaultValue {@link getCleoHome}
233
+ */
234
+ export function admissionDir(cleoHome = getCleoHome()) {
235
+ return join(cleoHome, 'admission');
236
+ }
237
+ function ledgerFile(dir) {
238
+ return join(dir, 'ledger.json');
239
+ }
240
+ function isEntry(v) {
241
+ if (typeof v !== 'object' || v === null)
242
+ return false;
243
+ const e = v;
244
+ return (typeof e.id === 'string' &&
245
+ typeof e.nonce === 'string' &&
246
+ isProbeableId(e.pid) &&
247
+ typeof e.host === 'string' &&
248
+ (e.startedAt === null || typeof e.startedAt === 'string') &&
249
+ typeof e.label === 'string' &&
250
+ typeof e.command === 'string' &&
251
+ typeof e.footprintBytes === 'number' &&
252
+ Number.isFinite(e.footprintBytes) &&
253
+ (e.state === 'waiting' || e.state === 'admitted') &&
254
+ typeof e.enqueuedAtMs === 'number' &&
255
+ typeof e.heartbeatAtMs === 'number' &&
256
+ Array.isArray(e.toolGroups));
257
+ }
258
+ const SHARES = new Set(['full', 'half', 'one', 'none']);
259
+ function isCachedPressure(v) {
260
+ if (typeof v !== 'object' || v === null)
261
+ return false;
262
+ const c = v;
263
+ return (typeof c.share === 'string' &&
264
+ SHARES.has(c.share) &&
265
+ (c.lightShare === undefined ||
266
+ (typeof c.lightShare === 'string' && SHARES.has(c.lightShare))) &&
267
+ typeof c.sampledAtMs === 'number' &&
268
+ (c.reading === null || (typeof c.reading === 'object' && c.reading !== null)));
269
+ }
270
+ function readLedgerDoc(dir) {
271
+ const empty = {
272
+ version: LEDGER_VERSION,
273
+ entries: [],
274
+ foreign: [],
275
+ pressure: null,
276
+ corrupt: false,
277
+ };
278
+ let raw;
279
+ try {
280
+ raw = readFileSync(ledgerFile(dir), 'utf-8');
281
+ }
282
+ catch {
283
+ return empty;
284
+ }
285
+ let parsed;
286
+ try {
287
+ parsed = JSON.parse(raw);
288
+ }
289
+ catch {
290
+ return { ...empty, corrupt: true };
291
+ }
292
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
293
+ return { ...empty, corrupt: true };
294
+ }
295
+ const o = parsed;
296
+ const version = typeof o.version === 'number' && Number.isFinite(o.version) ? o.version : LEDGER_VERSION;
297
+ const entries = [];
298
+ const foreign = [];
299
+ for (const v of Array.isArray(o.entries) ? o.entries : []) {
300
+ if (isEntry(v))
301
+ entries.push(v);
302
+ else if (typeof v === 'object' && v !== null && !Array.isArray(v))
303
+ foreign.push(v);
304
+ }
305
+ return {
306
+ version,
307
+ entries,
308
+ foreign,
309
+ pressure: isCachedPressure(o.pressure) ? o.pressure : null,
310
+ corrupt: false,
311
+ };
312
+ }
313
+ /**
314
+ * Read the ledger's entries without the lock (writes are atomic renames, so a
315
+ * reader sees a whole file). A missing or corrupt file has no entries;
316
+ * entries of a format this CLEO does not know are left out (they are kept in
317
+ * the file and still charged).
318
+ *
319
+ * @param dir - the ledger directory. @defaultValue {@link admissionDir}
320
+ */
321
+ export function readLedger(dir = admissionDir()) {
322
+ return readLedgerDoc(dir).entries;
323
+ }
324
+ /**
325
+ * Entries of a format this CLEO does not know (written by another CLEO
326
+ * version sharing the CLEO home), read without the lock.
327
+ *
328
+ * @param dir - the ledger directory. @defaultValue {@link admissionDir}
329
+ */
330
+ export function readForeignEntries(dir = admissionDir()) {
331
+ return readLedgerDoc(dir).foreign;
332
+ }
333
+ function writeLedgerDoc(dir, doc) {
334
+ const file = ledgerFile(dir);
335
+ const tmp = `${file}.${process.pid}.${randomBytes(4).toString('hex')}.tmp`;
336
+ try {
337
+ writeFileSync(tmp, JSON.stringify({
338
+ version: LEDGER_VERSION,
339
+ // Foreign entries go back where they were found, verbatim.
340
+ entries: [...doc.entries, ...doc.foreign],
341
+ pressure: doc.pressure,
342
+ }), 'utf-8');
343
+ renameSync(tmp, file);
344
+ }
345
+ catch (err) {
346
+ try {
347
+ rmSync(tmp, { force: true });
348
+ }
349
+ catch {
350
+ // Nothing more to do.
351
+ }
352
+ throw err;
353
+ }
354
+ }
355
+ /**
356
+ * The ledger file was written by a newer CLEO: this one never rewrites it.
357
+ * Admission treats it like unwritable state and runs ungoverned.
358
+ */
359
+ export class LedgerVersionError extends Error {
360
+ /** Error code, matched by {@link admissionIoError}. */
361
+ code = 'E_LEDGER_VERSION';
362
+ /** The ledger file. */
363
+ path;
364
+ /**
365
+ * @param version - the version found in the file.
366
+ * @param path - the ledger file.
367
+ */
368
+ constructor(version, path) {
369
+ super(`admission ledger ${path} has format version ${version}; this CLEO understands ${LEDGER_VERSION} and will not rewrite it`);
370
+ this.name = 'LedgerVersionError';
371
+ this.path = path;
372
+ }
373
+ }
374
+ /** Take the ledger lock, retrying only while another process holds it. */
375
+ async function lockLedger(file) {
376
+ for (let attempt = 1;; attempt++) {
377
+ try {
378
+ return await lockfile.lock(file, {
379
+ lockfilePath: `${file}.lock`,
380
+ realpath: false,
381
+ stale: LEDGER_CRITICAL_STALE_MS,
382
+ retries: 0,
383
+ onCompromised: (err) => {
384
+ log().warn({ err: err.message }, 'admission ledger lock compromised; continuing');
385
+ },
386
+ });
387
+ }
388
+ catch (err) {
389
+ const code = err?.code;
390
+ if (code !== 'ELOCKED' || attempt >= LOCK_ATTEMPTS)
391
+ throw err;
392
+ const backoff = Math.min(LOCK_BACKOFF_MS[1], LOCK_BACKOFF_MS[0] * 1.2 ** attempt);
393
+ await new Promise((resolve) => {
394
+ setTimeout(resolve, backoff * (1 + Math.random()));
395
+ });
396
+ }
397
+ }
398
+ }
399
+ /**
400
+ * Run `fn` inside the ledger's critical section: read, decide, write. `fn`
401
+ * must be synchronous and do no I/O of its own; its `doc` (or `null` for no
402
+ * change) is written back before the lock is released. A file of a newer
403
+ * format throws {@link LedgerVersionError} and is left untouched; a corrupt
404
+ * file is moved aside before it is replaced.
405
+ */
406
+ async function withLedger(dir, fn) {
407
+ mkdirSync(dir, { recursive: true });
408
+ const file = ledgerFile(dir);
409
+ const unlock = await lockLedger(file);
410
+ try {
411
+ const current = readLedgerDoc(dir);
412
+ if (current.version > LEDGER_VERSION) {
413
+ // @sync-invariant none:local-only the admission ledger is a machine-local file, not a store write
414
+ throw new LedgerVersionError(current.version, file);
415
+ }
416
+ const { doc, result } = fn(current);
417
+ if (doc !== null) {
418
+ if (current.corrupt) {
419
+ log().warn({ file }, 'admission ledger was not valid JSON; moved aside and replaced');
420
+ renameSync(file, `${file}.corrupt-${Date.now()}`);
421
+ }
422
+ writeLedgerDoc(dir, doc);
423
+ }
424
+ return result;
425
+ }
426
+ finally {
427
+ try {
428
+ await unlock();
429
+ }
430
+ catch {
431
+ // Already released (stale takeover): the post-condition holds.
432
+ }
433
+ }
434
+ }
435
+ // ---------------------------------------------------------------------------
436
+ // Liveness
437
+ // ---------------------------------------------------------------------------
438
+ /**
439
+ * Whether an entry's holder is still there.
440
+ *
441
+ * - A pid that is provably gone (or recycled: alive with another start time,
442
+ * once the heartbeat is stale) is dead as soon as every tool group it
443
+ * started is gone too; a detached tool outlives a SIGKILLed cleo.
444
+ * - A fresh heartbeat, or a live pid whose start time matches the recorded
445
+ * one, is alive.
446
+ * - A holder that cannot be identified (the probe fails, or no start time was
447
+ * recorded or can be read) is alive until its heartbeat is
448
+ * {@link LEDGER_ORPHAN_MS} old, and so is a gone holder whose tool group id
449
+ * still runs (a group id carries no start time, so it may be recycled).
450
+ * Past that bound both are dead: nothing holds the budget forever.
451
+ * - An entry of another host is judged by its heartbeat alone.
452
+ *
453
+ * @param entry - the ledger entry.
454
+ * @param nowMs - the clock.
455
+ * @param probe - pid probe (tests inject one).
456
+ */
457
+ export function entryLiveness(entry, nowMs, probe = systemPidProbe) {
458
+ const age = nowMs - entry.heartbeatAtMs;
459
+ if (entry.host !== hostname())
460
+ return age < LEDGER_HEARTBEAT_STALE_MS ? 'alive' : 'dead';
461
+ const orphaned = age >= LEDGER_ORPHAN_MS;
462
+ const goneUnlessGroups = () => orphaned || entry.toolGroups.every((g) => isProbeableId(g) && probe.groupLiveness(g) === 'gone')
463
+ ? 'dead'
464
+ : 'alive';
465
+ const pid = probe.liveness(entry.pid);
466
+ if (pid === 'gone')
467
+ return goneUnlessGroups();
468
+ if (age < LEDGER_HEARTBEAT_STALE_MS)
469
+ return 'alive';
470
+ if (pid === 'alive' && entry.startedAt !== null) {
471
+ const startedAt = probe.startedAt(entry.pid);
472
+ if (startedAt === entry.startedAt)
473
+ return 'alive';
474
+ if (startedAt !== null)
475
+ return goneUnlessGroups(); // a recycled pid
476
+ }
477
+ return orphaned ? 'dead' : 'alive';
478
+ }
479
+ /**
480
+ * The budget an entry of an unknown format is charged: its numeric
481
+ * `footprintBytes` when it has one, else the whole capacity.
482
+ */
483
+ function foreignCharge(f, capacityBytes) {
484
+ const fp = f.footprintBytes;
485
+ return typeof fp === 'number' && Number.isFinite(fp) && fp >= 0
486
+ ? Math.min(fp, capacityBytes)
487
+ : capacityBytes;
488
+ }
489
+ /**
490
+ * Whether an entry of an unknown format is provably finished: its heartbeat
491
+ * (when it has one) is {@link LEDGER_ORPHAN_MS} old, or its pid on this host
492
+ * is gone.
493
+ */
494
+ function foreignLiveness(f, nowMs, probe) {
495
+ const hb = f.heartbeatAtMs;
496
+ if (typeof hb === 'number' && Number.isFinite(hb) && nowMs - hb >= LEDGER_ORPHAN_MS)
497
+ return 'dead';
498
+ if (isProbeableId(f.pid) && f.host === hostname() && probe.liveness(f.pid) === 'gone') {
499
+ return 'dead';
500
+ }
501
+ return 'alive';
502
+ }
503
+ /**
504
+ * A run larger than this is heavy: more than one worker's footprint
505
+ * ({@link GIB_PER_WORKER}), i.e. a multi-process test or build run. CPU
506
+ * saturation narrows only heavy runs (T13132): a single-process typecheck or
507
+ * lint, a single-file test run and the config probe are one process each, and
508
+ * serialising them behind a whole suite only starved them.
509
+ */
510
+ export const HEAVY_FOOTPRINT_BYTES = GIB_PER_WORKER * GIB;
511
+ /**
512
+ * The budget share for light runs ({@link HEAVY_FOOTPRINT_BYTES} or less): the
513
+ * memory signal alone — `none` while the memory gate refuses, `half` at memory
514
+ * hold, else `full`. CPU pressure never narrows it (T13132, T13170).
515
+ *
516
+ * @param sample - a backend sample.
517
+ * @param gateRefuses - the memory gate's verdict for the sample.
518
+ */
519
+ export function lightBudgetShare(sample, gateRefuses) {
520
+ if (gateRefuses)
521
+ return 'none';
522
+ const memory = (sample.globalPressure?.some ?? sample.slicePressure?.some)?.avg10 ?? 0;
523
+ return memory > 10 ? 'half' : 'full';
524
+ }
525
+ /**
526
+ * The budget share for HEAVY runs (above {@link HEAVY_FOOTPRINT_BYTES}), from
527
+ * the memory gate's verdict and the pressure score (memory, or CPU rescaled;
528
+ * see `pressureScore`). Light runs use {@link lightBudgetShare}.
529
+ *
530
+ * @param sample - a backend sample.
531
+ * @param gateRefuses - the memory gate's verdict for the sample.
532
+ */
533
+ export function budgetShare(sample, gateRefuses) {
534
+ if (gateRefuses)
535
+ return 'none';
536
+ const score = pressureScore(sample);
537
+ if (score > 25)
538
+ return 'one';
539
+ if (score > 10)
540
+ return 'half';
541
+ return 'full';
542
+ }
543
+ function charged(entry, capacityBytes) {
544
+ return Math.min(Math.max(0, entry.footprintBytes), capacityBytes);
545
+ }
546
+ /**
547
+ * One scheduling pass: admit every waiting entry the budget and the queue
548
+ * order allow. Pure.
549
+ *
550
+ * - FIFO by `enqueuedAtMs`. A later entry may be admitted ahead of an older
551
+ * one that does not fit (backfill) until that older one has waited
552
+ * `reservationMs`; from then on nothing passes it.
553
+ * - A footprint above the capacity is charged the capacity (it runs alone).
554
+ * - Heavy runs (above {@link HEAVY_FOOTPRINT_BYTES}) take `share`: `half`
555
+ * halves the budget, `one` admits a single heavy run at a time (CPU
556
+ * saturated). Light runs take `lightShare` (memory alone), so CPU saturation
557
+ * never serialises them behind a heavy run (T13132). Either still admits the
558
+ * oldest waiting entry when nothing is admitted; `none` admits nothing.
559
+ *
560
+ * @param entries - the ledger.
561
+ * @param ctx - capacity, pressure share and clock.
562
+ * @returns the ledger with admissions applied (same order).
563
+ *
564
+ * @example
565
+ * ```ts
566
+ * schedulePass(entries, { capacityBytes: 36 * GIB, share: 'full', nowMs: Date.now() });
567
+ * ```
568
+ */
569
+ export function schedulePass(entries, ctx) {
570
+ const lightShare = ctx.lightShare ?? ctx.share;
571
+ if (ctx.share === 'none' && lightShare === 'none')
572
+ return [...entries];
573
+ const reservationMs = ctx.reservationMs ?? LEDGER_RESERVATION_MS;
574
+ const bytesFor = (share) => share === 'full' || share === 'one'
575
+ ? ctx.capacityBytes
576
+ : share === 'half'
577
+ ? ctx.capacityBytes / 2
578
+ : 0;
579
+ // Light runs see the memory budget. Heavy runs see the narrower of it and
580
+ // their own share; `one` admits a single heavy run at a time.
581
+ const lightBudget = bytesFor(lightShare);
582
+ const heavyBudget = Math.min(lightBudget, bytesFor(ctx.share));
583
+ let used = ctx.foreign?.bytes ?? 0;
584
+ let running = ctx.foreign?.count ?? 0;
585
+ // Conservative: an entry of an unknown format counts as heavy under `one`.
586
+ let heavyRunning = ctx.foreign?.count ?? 0;
587
+ // T13237: admitted exclusive runs (a full-build holds the machine-wide slot).
588
+ let exclusiveRunning = 0;
589
+ for (const e of entries) {
590
+ if (e.state === 'admitted') {
591
+ used += charged(e, ctx.capacityBytes);
592
+ running++;
593
+ if (isHeavy(e))
594
+ heavyRunning++;
595
+ if (e.exclusive === true)
596
+ exclusiveRunning++;
597
+ }
598
+ }
599
+ const fits = (w, cost) => {
600
+ if (w.exclusive === true && exclusiveRunning > 0)
601
+ return false;
602
+ if (!isHeavy(w))
603
+ return lightShare !== 'none' && used + cost <= lightBudget;
604
+ if (ctx.share === 'none')
605
+ return false;
606
+ if (ctx.share === 'one' && heavyRunning > 0)
607
+ return false;
608
+ return used + cost <= heavyBudget;
609
+ };
610
+ const waiting = entries
611
+ .filter((e) => e.state === 'waiting')
612
+ .sort((a, b) => a.enqueuedAtMs - b.enqueuedAtMs || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
613
+ const admit = new Set();
614
+ let blocked = false;
615
+ // Bytes held for a reserved heavy head that only the `one` rule blocks: light
616
+ // runs may still pass it, but only within what is left after its share.
617
+ let reservedForHead = null;
618
+ /** Admit `w` (every admission goes through here, so the counters stay true). */
619
+ const take = (w, cost) => {
620
+ admit.add(w.id);
621
+ used += cost;
622
+ running++;
623
+ if (isHeavy(w))
624
+ heavyRunning++;
625
+ if (w.exclusive === true)
626
+ exclusiveRunning++;
627
+ };
628
+ for (const w of waiting) {
629
+ const cost = charged(w, ctx.capacityBytes);
630
+ if (reservedForHead !== null) {
631
+ // Only light runs pass a reserved head, within what its share leaves —
632
+ // and never a second exclusive run (T13237, #1899 review HIGH: a full
633
+ // build is "light" at exactly HEAVY_FOOTPRINT_BYTES on a 16 GiB host).
634
+ if (!isHeavy(w) &&
635
+ !(w.exclusive === true && exclusiveRunning > 0) &&
636
+ lightShare !== 'none' &&
637
+ used + cost + reservedForHead <= lightBudget) {
638
+ take(w, cost);
639
+ }
640
+ continue;
641
+ }
642
+ const share = isHeavy(w) ? ctx.share : lightShare;
643
+ // With nothing running, the oldest waiting run always starts (it is
644
+ // charged at most the capacity), so pressure narrows but never stops work;
645
+ // only the memory gate (`none`) stops it.
646
+ if (fits(w, cost) || (running === 0 && share !== 'none')) {
647
+ take(w, cost);
648
+ continue;
649
+ }
650
+ if (!blocked) {
651
+ blocked = true;
652
+ if (ctx.nowMs - w.enqueuedAtMs >= reservationMs) {
653
+ // A heavy head blocked by bytes stops everything behind it. One blocked
654
+ // only by CPU saturation (`one`) would starve light runs that cannot
655
+ // delay it, so its bytes are reserved and light runs keep backfilling
656
+ // around them (T13132, #1865 review MED-1).
657
+ const cpuOnly = isHeavy(w) && ctx.share === 'one' && heavyRunning > 0 && used + cost <= heavyBudget;
658
+ // Likewise a head blocked only because another exclusive run holds
659
+ // the slot (T13237): reserve its bytes, let light runs pass around it.
660
+ const exclusiveOnly = w.exclusive === true &&
661
+ exclusiveRunning > 0 &&
662
+ used + cost <= (isHeavy(w) ? heavyBudget : lightBudget);
663
+ if (!cpuOnly && !exclusiveOnly)
664
+ break;
665
+ reservedForHead = cost;
666
+ }
667
+ }
668
+ }
669
+ return entries.map((e) => admit.has(e.id)
670
+ ? { ...e, state: 'admitted', admittedAtMs: ctx.nowMs, heartbeatAtMs: ctx.nowMs }
671
+ : e);
672
+ }
673
+ /** Whether an entry is a heavy (multi-process) run: above {@link HEAVY_FOOTPRINT_BYTES}. */
674
+ function isHeavy(e) {
675
+ return e.footprintBytes > HEAVY_FOOTPRINT_BYTES;
676
+ }
677
+ // ---------------------------------------------------------------------------
678
+ // Re-entrancy
679
+ // ---------------------------------------------------------------------------
680
+ /**
681
+ * Split a {@link ADMISSION_ENV} value into its id and nonce, or `null`.
682
+ *
683
+ * @param value - the env value.
684
+ */
685
+ export function parseAdmissionToken(value) {
686
+ if (!value)
687
+ return null;
688
+ const at = value.lastIndexOf('.');
689
+ if (at <= 0 || at === value.length - 1)
690
+ return null;
691
+ return { id: value.slice(0, at), nonce: value.slice(at + 1) };
692
+ }
693
+ const systemProcessFacts = {
694
+ ancestorsOf: processAncestors,
695
+ groupOf: processGroupOf,
696
+ startedAt: (pid) => systemPidProbe.startedAt(pid),
697
+ };
698
+ /**
699
+ * The admitted entry whose process tree `pid` belongs to, or `null`.
700
+ *
701
+ * Proof is ancestry: the holder is an ancestor of `pid`, with its recorded
702
+ * start time matching. A holder recorded without a start time (`ps` failed)
703
+ * proves nothing by ancestry alone, since its pid may have been recycled into
704
+ * an ancestor: it also needs the token to name it (T13188). The token in `env`
705
+ * only narrows which entry is checked
706
+ * first; a missing or foreign token falls back to checking every admitted
707
+ * entry by ancestry, so a wrapper that scrubs the environment cannot deadlock
708
+ * a nested run — except under a holder recorded without a start time, which
709
+ * needs the token: such a nested run waits for its own parent until it times
710
+ * out or the entry is reaped as unidentifiable ({@link LEDGER_ORPHAN_MS}). A
711
+ * rare case (`ps` failed at admission), and safer than letting a recycled pid
712
+ * ride a dead grant.
713
+ *
714
+ * Group membership (`pid` runs in a tool process group the holder started,
715
+ * which covers a tool that outlived a killed holder) is accepted only for the
716
+ * entry the token names on this host: a process group id carries no start
717
+ * time, so a recycled group id alone proves nothing.
718
+ *
719
+ * @param entries - the ledger.
720
+ * @param pid - the requesting process.
721
+ * @param env - its environment.
722
+ * @param facts - process probes (tests inject them).
723
+ */
724
+ export function enclosingGrant(entries, pid, env, facts = systemProcessFacts) {
725
+ const host = hostname();
726
+ // No host filter for ancestry: an ancestor is local by definition, and a
727
+ // laptop's hostname follows the network (LOW-4 of the #1829 review).
728
+ const admitted = entries.filter((e) => e.state === 'admitted' && e.pid !== pid);
729
+ if (admitted.length === 0)
730
+ return null;
731
+ const token = parseAdmissionToken(env[ADMISSION_ENV]);
732
+ const hinted = token ? admitted.filter((e) => e.id === token.id && e.nonce === token.nonce) : [];
733
+ const ordered = [...hinted, ...admitted.filter((e) => !hinted.includes(e))];
734
+ let ancestors;
735
+ let group;
736
+ for (const e of ordered) {
737
+ ancestors ??= facts.ancestorsOf(pid);
738
+ group ??= facts.groupOf(pid);
739
+ const byAncestry = ancestors?.includes(e.pid) === true &&
740
+ (e.startedAt === null ? hinted.includes(e) : facts.startedAt(e.pid) === e.startedAt);
741
+ const byGroup = e.host === host &&
742
+ hinted.includes(e) &&
743
+ group !== null &&
744
+ isProbeableId(group) &&
745
+ e.toolGroups.includes(group);
746
+ if (!byAncestry && !byGroup)
747
+ continue;
748
+ // A known start time that differs means a recycled pid: never this holder.
749
+ if (ancestors?.includes(e.pid) === true && e.startedAt !== null && !byAncestry)
750
+ continue;
751
+ return e;
752
+ }
753
+ return null;
754
+ }
755
+ /** The {@link ADMISSION_ENV} value of an entry. */
756
+ export function admissionToken(entry) {
757
+ return `${entry.id}.${entry.nonce}`;
758
+ }
759
+ // ---------------------------------------------------------------------------
760
+ // Reports
761
+ // ---------------------------------------------------------------------------
762
+ function gib(bytes) {
763
+ return `${(bytes / GIB).toFixed(bytes < 10 * GIB ? 1 : 0)} GiB`;
764
+ }
765
+ function age(ms) {
766
+ const s = Math.max(0, Math.round(ms / 1000));
767
+ return s < 60 ? `${s}s` : `${Math.floor(s / 60)}m ${String(s % 60).padStart(2, '0')}s`;
768
+ }
769
+ /**
770
+ * ` [scope=full, task T1043]` for an entry that says what it covers, else ''.
771
+ *
772
+ * @param e - a ledger entry.
773
+ */
774
+ export function describeScope(e) {
775
+ const parts = [
776
+ ...(e.scope !== undefined ? [`scope=${e.scope}`] : []),
777
+ ...(e.task !== undefined ? [`task ${e.task}`] : []),
778
+ ];
779
+ return parts.length > 0 ? ` [${parts.join(', ')}]` : '';
780
+ }
781
+ /**
782
+ * One line per admitted run: label, scope and task, pid, command, directory and age.
783
+ *
784
+ * @param entries - the ledger.
785
+ * @param nowMs - the clock.
786
+ */
787
+ export function describeHolders(entries, nowMs) {
788
+ return entries
789
+ .filter((e) => e.state === 'admitted')
790
+ .map((e) => `${e.label}${describeScope(e)} pid ${e.pid} (${e.command})${e.cwd ? ` in ${e.cwd}` : ''}, ${gib(e.footprintBytes)}, for ${age(nowMs - (e.admittedAtMs ?? e.enqueuedAtMs))}`);
791
+ }
792
+ /** Commands too generic to name a lock-taking wrapper. */
793
+ const GENERIC_PROGRAMS = new Set([
794
+ 'node',
795
+ 'cleo',
796
+ 'ct',
797
+ 'sh',
798
+ 'bash',
799
+ 'zsh',
800
+ 'env',
801
+ 'nice',
802
+ 'nohup',
803
+ 'time',
804
+ 'npm',
805
+ 'pnpm',
806
+ 'npx',
807
+ 'yarn',
808
+ 'bun',
809
+ 'vitest',
810
+ 'tsc',
811
+ 'login',
812
+ 'tmux',
813
+ 'claude',
814
+ ]);
815
+ /** The program a command line runs: the first argument that is not an interpreter or a flag. */
816
+ function programOf(command) {
817
+ for (const token of command.trim().split(/\s+/)) {
818
+ if (token.startsWith('-') || token.includes('='))
819
+ continue;
820
+ const base = token.split('/').pop() ?? token;
821
+ if (/^(node|bash|sh|zsh|env|nice|nohup|time|python3?)$/.test(base))
822
+ continue;
823
+ return base;
824
+ }
825
+ return null;
826
+ }
827
+ /** `ps -A -o pid=,ppid=,command=`, or `null` when `ps` fails. */
828
+ function processTable() {
829
+ let out;
830
+ try {
831
+ out = execFileSync('/bin/ps', ['-A', '-o', 'pid=,ppid=,command='], {
832
+ encoding: 'utf-8',
833
+ timeout: 2000,
834
+ stdio: ['ignore', 'pipe', 'ignore'],
835
+ env: { ...process.env, LC_ALL: 'C' },
836
+ });
837
+ }
838
+ catch {
839
+ return null;
840
+ }
841
+ const table = new Map();
842
+ for (const line of out.split('\n')) {
843
+ const m = /^\s*(\d+)\s+(\d+)\s+(.*)$/.exec(line);
844
+ if (m?.[1] && m[2])
845
+ table.set(Number(m[1]), { ppid: Number(m[2]), command: m[3] ?? '' });
846
+ }
847
+ return table;
848
+ }
849
+ /**
850
+ * A suspected wait cycle through a lock outside CLEO: a holder's process tree
851
+ * and this waiter's ancestry run the same (non-generic) program, such as a
852
+ * wrapper script that takes its own lock. `null` when nothing points to one.
853
+ *
854
+ * @param pid - the waiting process.
855
+ * @param holders - admitted entries.
856
+ * @param table - the process table (`pid → {ppid, command}`).
857
+ */
858
+ export function suspectCycle(pid, holders, table) {
859
+ const ours = new Map();
860
+ for (let at = table.get(pid)?.ppid, n = 0; at !== undefined && at > 1 && n < 64; n++) {
861
+ const row = table.get(at);
862
+ if (!row)
863
+ break;
864
+ const prog = programOf(row.command);
865
+ if (prog && !GENERIC_PROGRAMS.has(prog) && !ours.has(prog))
866
+ ours.set(prog, at);
867
+ at = row.ppid;
868
+ }
869
+ if (ours.size === 0)
870
+ return null;
871
+ const children = new Map();
872
+ for (const [child, row] of table) {
873
+ const list = children.get(row.ppid) ?? [];
874
+ list.push(child);
875
+ children.set(row.ppid, list);
876
+ }
877
+ for (const h of holders) {
878
+ const stack = [...(children.get(h.pid) ?? [])];
879
+ const seen = new Set();
880
+ while (stack.length > 0) {
881
+ const at = stack.pop();
882
+ if (seen.has(at) || seen.size > 4096)
883
+ continue;
884
+ seen.add(at);
885
+ const prog = programOf(table.get(at)?.command ?? '');
886
+ const mine = prog ? ours.get(prog) : undefined;
887
+ if (prog && mine !== undefined) {
888
+ return (`suspected wait cycle: holder pid ${h.pid} (${h.label}) runs ${prog} (pid ${at}), and this ` +
889
+ `waiter runs under ${prog} (pid ${mine}). If ${prog} takes a lock of its own, neither can ` +
890
+ `proceed: run heavy work under one of them, not both.`);
891
+ }
892
+ stack.push(...(children.get(at) ?? []));
893
+ }
894
+ }
895
+ return null;
896
+ }
897
+ /** Filesystem errors meaning the ledger cannot be kept here. */
898
+ const STATE_IO_CODES = new Set([
899
+ 'EACCES',
900
+ 'EPERM',
901
+ 'EROFS',
902
+ 'ENOSPC',
903
+ 'EDQUOT',
904
+ 'ENOTDIR',
905
+ 'ELOOP',
906
+ // A ledger written by a newer CLEO: never rewritten, so admission runs ungoverned.
907
+ 'E_LEDGER_VERSION',
908
+ ]);
909
+ /**
910
+ * The code and path of an error that means "admission state cannot be kept
911
+ * here" (a sandbox that blocks writes to the CLEO home, a read-only or full
912
+ * disk, a broken CLEO home), or `null` for any other error, which is a bug and
913
+ * must not be hidden.
914
+ *
915
+ * @param err - a caught error.
916
+ */
917
+ export function admissionIoError(err) {
918
+ const e = err;
919
+ if (!e || typeof e !== 'object' || typeof e.code !== 'string')
920
+ return null;
921
+ if (!STATE_IO_CODES.has(e.code))
922
+ return null;
923
+ return { code: e.code, path: typeof e.path === 'string' ? e.path : null };
924
+ }
925
+ /**
926
+ * Why a run is ungoverned, in words: `admission state is not writable (EACCES
927
+ * /path)`, or, for a ledger a newer CLEO wrote, that this CLEO will not
928
+ * rewrite it. Callers append what they do about it.
929
+ *
930
+ * @param io - from {@link admissionIoError} or a grant's `ungoverned`.
931
+ */
932
+ export function describeAdmissionIoError(io) {
933
+ const at = io.path ? ` ${io.path}` : '';
934
+ return io.code === 'E_LEDGER_VERSION'
935
+ ? `the admission ledger${at} was written by a newer CLEO, which this one never rewrites (upgrade CLEO to share the machine budget)`
936
+ : `admission state is not writable (${io.code}${at})`;
937
+ }
938
+ function passThrough(token, nested, ungoverned) {
939
+ return {
940
+ id: null,
941
+ token,
942
+ nested,
943
+ ungoverned,
944
+ waitedMs: 0,
945
+ footprintBytes: 0,
946
+ release: async () => { },
947
+ };
948
+ }
949
+ function newId(pid, nowMs) {
950
+ return `${pid}-${nowMs}-${randomBytes(3).toString('hex')}`;
951
+ }
952
+ /**
953
+ * Sample pressure and ask the memory gate, outside the critical section. A
954
+ * verdict another process wrote to the ledger less than
955
+ * {@link PRESSURE_REUSE_MS} ago is reused instead, unless `opts.sample` is
956
+ * given, so a crowd of waiters costs one sample per interval, not one each.
957
+ */
958
+ async function sampleShare(opts, cached, nowMs) {
959
+ if (!opts.sample) {
960
+ if (process.env[ADMISSION_PRESSURE_ENV] === 'off') {
961
+ return { share: 'full', lightShare: 'full', reading: null, sampled: null };
962
+ }
963
+ if (cached !== null && isFresh(cached, nowMs)) {
964
+ return {
965
+ share: cached.share,
966
+ lightShare: cached.lightShare ?? cached.share,
967
+ reading: cached.reading,
968
+ sampled: null,
969
+ };
970
+ }
971
+ }
972
+ let sample;
973
+ try {
974
+ sample = await (opts.sample ?? (() => new ResourceMonitor().sample()))();
975
+ }
976
+ catch {
977
+ sample = null;
978
+ }
979
+ if (sample === null)
980
+ return { share: 'full', lightShare: 'full', reading: null, sampled: null };
981
+ const gate = checkMemoryGate(sample, opts.now ? { now: opts.now } : {});
982
+ const share = budgetShare(sample, gate.refuse);
983
+ const lightShare = lightBudgetShare(sample, gate.refuse);
984
+ const reading = gate.refuse ? gate.reading : null;
985
+ return {
986
+ share,
987
+ lightShare,
988
+ reading,
989
+ sampled: { share, lightShare, reading, sampledAtMs: nowMs },
990
+ };
991
+ }
992
+ function isFresh(cached, nowMs) {
993
+ const age = nowMs - cached.sampledAtMs;
994
+ return age >= 0 && age < PRESSURE_REUSE_MS;
995
+ }
996
+ /** The provably finished entries of a ledger, probed outside the critical section. */
997
+ function findDead(doc, nowMs, probe) {
998
+ const entries = new Map();
999
+ for (const e of doc.entries) {
1000
+ if (entryLiveness(e, nowMs, probe) === 'dead')
1001
+ entries.set(e.id, e.heartbeatAtMs);
1002
+ }
1003
+ const foreign = new Set();
1004
+ for (const f of doc.foreign) {
1005
+ if (foreignLiveness(f, nowMs, probe) === 'dead')
1006
+ foreign.add(JSON.stringify(f));
1007
+ }
1008
+ return { entries, foreign };
1009
+ }
1010
+ const NO_DEAD = { entries: new Map(), foreign: new Set() };
1011
+ /** The budget foreign entries take, counted as running. */
1012
+ function foreignLoad(foreign, capacityBytes) {
1013
+ let bytes = 0;
1014
+ for (const f of foreign)
1015
+ bytes += foreignCharge(f, capacityBytes);
1016
+ return { bytes, count: foreign.length };
1017
+ }
1018
+ /**
1019
+ * Drop the dead (unless they heartbeated since the probe), charge foreign
1020
+ * entries, schedule, and keep the freshest pressure verdict.
1021
+ */
1022
+ function reapAndSchedule(doc, dead, ctx, sampled) {
1023
+ const live = doc.entries.filter((e) => dead.entries.get(e.id) !== e.heartbeatAtMs);
1024
+ const foreign = doc.foreign.filter((f) => !dead.foreign.has(JSON.stringify(f)));
1025
+ return {
1026
+ ...doc,
1027
+ entries: schedulePass(live, { ...ctx, foreign: foreignLoad(foreign, ctx.capacityBytes) }),
1028
+ foreign,
1029
+ pressure: sampled ?? doc.pressure,
1030
+ };
1031
+ }
1032
+ /**
1033
+ * Ask the ledger for a share of the machine budget.
1034
+ *
1035
+ * `CLEO_RESOURCES_MODE=off` admits everything. Re-entrant: inside an admitted
1036
+ * run's process tree it returns a pass-through grant at once. Otherwise it joins the FIFO queue; with `wait: false` it
1037
+ * leaves again unless admitted on the spot, and with `wait: true` it waits
1038
+ * (reporting memory-pressure waits and, after a minute, the holders and any
1039
+ * suspected cycle) until admitted or `timeoutMs`. Never throws for admission
1040
+ * control. An unwritable ledger, or one written by a newer CLEO, is a
1041
+ * pass-through grant with `ungoverned` set (callers say so with
1042
+ * {@link describeAdmissionIoError}); any other error propagates.
1043
+ *
1044
+ * @param req - what is asked for.
1045
+ * @param opts - waiting and reporting.
1046
+ *
1047
+ * @example
1048
+ * ```ts
1049
+ * const out = await admit({ label: 'tool:test', footprintBytes: footprintForTool('test') }, { wait: true });
1050
+ * if (out.admitted) {
1051
+ * try { await run({ env: { [ADMISSION_ENV]: out.grant.token } }); } finally { await out.grant.release(); }
1052
+ * }
1053
+ * ```
1054
+ */
1055
+ export async function admit(req, opts) {
1056
+ // The governor's off switch turns admission off here too.
1057
+ if (process.env.CLEO_RESOURCES_MODE === 'off') {
1058
+ return { admitted: true, grant: passThrough('', false, null) };
1059
+ }
1060
+ try {
1061
+ return await admitInner(req, opts);
1062
+ }
1063
+ catch (err) {
1064
+ const io = admissionIoError(err);
1065
+ if (io === null)
1066
+ throw err;
1067
+ return { admitted: true, grant: passThrough('', false, io) };
1068
+ }
1069
+ }
1070
+ async function admitInner(req, opts) {
1071
+ const now = opts.now ?? Date.now;
1072
+ const sleep = opts.sleep ??
1073
+ ((ms) => new Promise((resolve) => {
1074
+ setTimeout(resolve, ms);
1075
+ }));
1076
+ const dir = opts.dir ?? admissionDir();
1077
+ const pid = opts.pid ?? process.pid;
1078
+ const env = opts.env ?? process.env;
1079
+ const probe = opts.probe ?? systemPidProbe;
1080
+ const capacityBytes = opts.capacityBytes ?? admissionCapacityBytes();
1081
+ const timeoutMs = opts.timeoutMs ?? 3_600_000;
1082
+ const t0 = now();
1083
+ // Re-entrant: a request inside an admitted run's tree rides its grant.
1084
+ const parent = enclosingGrant(readLedger(dir), pid, env, opts.facts);
1085
+ if (parent !== null) {
1086
+ return { admitted: true, grant: passThrough(admissionToken(parent), true, null) };
1087
+ }
1088
+ const entry = {
1089
+ id: newId(pid, t0),
1090
+ nonce: randomBytes(12).toString('hex'),
1091
+ pid,
1092
+ host: hostname(),
1093
+ startedAt: pid === process.pid ? ownProcessStartedAt() : probe.startedAt(pid),
1094
+ label: req.label,
1095
+ command: req.command ?? process.argv.slice(1).join(' '),
1096
+ cwd: req.cwd === undefined ? process.cwd() : req.cwd, // CWD-OK: display only — where the run was started, shown in status and reports
1097
+ footprintBytes: Math.max(0, req.footprintBytes),
1098
+ state: 'waiting',
1099
+ enqueuedAtMs: t0,
1100
+ admittedAtMs: null,
1101
+ heartbeatAtMs: t0,
1102
+ toolGroups: [],
1103
+ ...(req.scope !== undefined ? { scope: req.scope } : {}),
1104
+ ...(req.task !== undefined ? { task: req.task } : {}),
1105
+ ...(req.exclusive === true ? { exclusive: true } : {}),
1106
+ };
1107
+ /** One pass: reap, (re-)enqueue ourselves, schedule; returns our entry's state. */
1108
+ const pass = async () => {
1109
+ const before = readLedgerDoc(dir);
1110
+ const nowMs = now();
1111
+ const { share, lightShare, reading, sampled } = await sampleShare(opts, before.pressure, nowMs);
1112
+ const dead = findDead(before, nowMs, probe);
1113
+ return withLedger(dir, (doc) => {
1114
+ let entries = doc.entries;
1115
+ const at = entries.findIndex((e) => e.id === entry.id);
1116
+ if (at < 0)
1117
+ entries = [...entries, { ...entry, heartbeatAtMs: nowMs }];
1118
+ else if (entries[at]?.state === 'waiting') {
1119
+ entries = entries.map((e) => (e.id === entry.id ? { ...e, heartbeatAtMs: nowMs } : e));
1120
+ }
1121
+ const next = reapAndSchedule({ ...doc, entries }, dead, { capacityBytes, share, lightShare, nowMs }, sampled);
1122
+ return {
1123
+ doc: next,
1124
+ result: { mine: next.entries.find((e) => e.id === entry.id) ?? null, doc: next, reading },
1125
+ };
1126
+ });
1127
+ };
1128
+ const leave = async () => withLedger(dir, (doc) => {
1129
+ const mine = doc.entries.find((e) => e.id === entry.id) ?? null;
1130
+ if (mine?.state === 'admitted')
1131
+ return { doc: null, result: mine };
1132
+ return {
1133
+ doc: { ...doc, entries: doc.entries.filter((e) => e.id !== entry.id) },
1134
+ result: null,
1135
+ };
1136
+ });
1137
+ const refusal = (doc, reading) => {
1138
+ const nowMs = now();
1139
+ const ahead = doc.entries.filter((e) => e.state === 'waiting' && e.id !== entry.id && e.enqueuedAtMs <= entry.enqueuedAtMs).length;
1140
+ const load = budgetLoad(doc, capacityBytes);
1141
+ const exclusiveHolder = entry.exclusive === true
1142
+ ? doc.entries.find((e) => e.state === 'admitted' && e.exclusive === true && e.id !== entry.id)
1143
+ : undefined;
1144
+ const reason = reading !== null
1145
+ ? `memory pressure ${reading.score} (refused above ${reading.refuseAbove}, resumes at ` +
1146
+ `${reading.resumeAtOrBelow} or below): ${reading.summary}`
1147
+ : exclusiveHolder !== undefined
1148
+ ? `another full build holds the machine-wide full-build slot (${exclusiveHolder.label} pid ` +
1149
+ `${exclusiveHolder.pid}); one runs at a time, whatever its size${ahead > 0 ? `; ${ahead} waiting ahead` : ''}`
1150
+ : `machine budget in use: ${gib(load.bytes)} of ${gib(capacityBytes)} by ${load.runs} run(s); ` +
1151
+ `this run needs ${gib(charged(entry, capacityBytes))}${ahead > 0 ? `; ${ahead} waiting ahead` : ''}`;
1152
+ return {
1153
+ reason,
1154
+ retryAfterMs: reading !== null ? MEMORY_GATE_RETRY_AFTER_MS : 2_000,
1155
+ memoryPressure: reading,
1156
+ ahead,
1157
+ holders: describeLoad(doc, nowMs),
1158
+ };
1159
+ };
1160
+ let first = await pass();
1161
+ if (first.mine?.state === 'admitted') {
1162
+ return { admitted: true, grant: holdGrant(first.mine, dir, now() - t0, opts) };
1163
+ }
1164
+ if (!opts.wait) {
1165
+ const raced = await leave();
1166
+ if (raced !== null)
1167
+ return { admitted: true, grant: holdGrant(raced, dir, now() - t0, opts) };
1168
+ return { admitted: false, refusal: refusal(first.doc, first.reading) };
1169
+ }
1170
+ let lastPassAt = now();
1171
+ let lastReportAt = t0;
1172
+ let reading = first.reading;
1173
+ for (;;) {
1174
+ if (reading !== null)
1175
+ opts.memoryPressure?.waiting(reading, now() - t0);
1176
+ if (now() - lastReportAt >= LEDGER_HOLDER_REPORT_MS && opts.notice) {
1177
+ lastReportAt = now();
1178
+ opts.notice(holderReport(first.doc, entry, pid, now() - t0, capacityBytes, now()));
1179
+ }
1180
+ const remaining = timeoutMs - (now() - t0);
1181
+ if (remaining <= 0) {
1182
+ const raced = await leave();
1183
+ if (raced !== null)
1184
+ return { admitted: true, grant: holdGrant(raced, dir, now() - t0, opts) };
1185
+ return { admitted: false, refusal: refusal(first.doc, reading) };
1186
+ }
1187
+ await sleep(Math.min(opts.pollMs ?? READ_POLL_MS, remaining));
1188
+ const seen = readLedgerDoc(dir);
1189
+ const mine = seen.entries.find((e) => e.id === entry.id);
1190
+ if (mine?.state === 'admitted') {
1191
+ opts.memoryPressure?.admitted(now() - t0, null);
1192
+ return { admitted: true, grant: holdGrant(mine, dir, now() - t0, opts) };
1193
+ }
1194
+ if (seen.pressure !== null && isFresh(seen.pressure, now()))
1195
+ reading = seen.pressure.reading;
1196
+ if (passDue(mine === undefined, now() - lastPassAt, seen.pressure, now(), opts)) {
1197
+ lastPassAt = now();
1198
+ first = await pass();
1199
+ reading = first.reading;
1200
+ if (first.mine?.state === 'admitted') {
1201
+ opts.memoryPressure?.admitted(now() - t0, null);
1202
+ return { admitted: true, grant: holdGrant(first.mine, dir, now() - t0, opts) };
1203
+ }
1204
+ }
1205
+ }
1206
+ }
1207
+ /**
1208
+ * Whether a waiter runs a pass of its own now: its entry is gone (reaped or
1209
+ * never written), its heartbeat is due, or a pass is due and nobody has
1210
+ * sampled pressure lately (a fresh verdict in the ledger means another
1211
+ * process just ran a pass, which scheduled everyone).
1212
+ */
1213
+ function passDue(missing, sinceLastPassMs, pressure, nowMs, opts) {
1214
+ if (missing || sinceLastPassMs >= LEDGER_HEARTBEAT_MS)
1215
+ return true;
1216
+ if (sinceLastPassMs < PASS_EVERY_MS)
1217
+ return false;
1218
+ // An injected sampler never reads the cache, so it never waits on it either.
1219
+ return opts.sample !== undefined || pressure === null || !isFresh(pressure, nowMs);
1220
+ }
1221
+ /** What the admitted runs and foreign entries take from the budget. */
1222
+ function budgetLoad(doc, capacityBytes) {
1223
+ const admitted = doc.entries.filter((e) => e.state === 'admitted');
1224
+ const foreign = foreignLoad(doc.foreign, capacityBytes);
1225
+ return {
1226
+ bytes: admitted.reduce((n, e) => n + charged(e, capacityBytes), 0) + foreign.bytes,
1227
+ runs: admitted.length + foreign.count,
1228
+ };
1229
+ }
1230
+ /** {@link describeHolders}, plus a line for entries of another CLEO version. */
1231
+ function describeLoad(doc, nowMs) {
1232
+ const lines = describeHolders(doc.entries, nowMs);
1233
+ if (doc.foreign.length > 0) {
1234
+ lines.push(`${doc.foreign.length} entr${doc.foreign.length === 1 ? 'y' : 'ies'} of another CLEO version`);
1235
+ }
1236
+ return lines;
1237
+ }
1238
+ /** The holder report a long waiter prints. */
1239
+ function holderReport(doc, mine, pid, waitedMs, capacityBytes, nowMs) {
1240
+ const holders = doc.entries.filter((e) => e.state === 'admitted');
1241
+ const used = budgetLoad(doc, capacityBytes).bytes;
1242
+ const ahead = doc.entries.filter((e) => e.state === 'waiting' && e.id !== mine.id && e.enqueuedAtMs <= mine.enqueuedAtMs).length;
1243
+ const lines = [
1244
+ `still waiting after ${age(waitedMs)} for the machine budget (${gib(used)} of ${gib(capacityBytes)} in use, ` +
1245
+ `${ahead} waiting ahead). Holders: ${describeLoad(doc, nowMs).join('; ') || 'none'}.`,
1246
+ ];
1247
+ const table = holders.length > 0 ? processTable() : null;
1248
+ const cycle = table ? suspectCycle(pid, holders, table) : null;
1249
+ if (cycle)
1250
+ lines.push(cycle);
1251
+ return lines.join(' ');
1252
+ }
1253
+ /** First and longest delay between attempts to remove a released entry that failed. */
1254
+ const RELEASE_RETRY_MS = [1_000, LEDGER_HEARTBEAT_MS];
1255
+ /** Hold an admitted entry: heartbeat, follow tool groups, release. */
1256
+ function holdGrant(entry, dir, waitedMs, opts) {
1257
+ const update = (patch) => withLedger(dir, (doc) => {
1258
+ if (!doc.entries.some((e) => e.id === entry.id))
1259
+ return { doc: null, result: undefined };
1260
+ return {
1261
+ doc: { ...doc, entries: doc.entries.map((e) => (e.id === entry.id ? patch(e) : e)) },
1262
+ result: undefined,
1263
+ };
1264
+ }).catch(() => {
1265
+ // Best effort: a missed heartbeat only means the next probe asks ps.
1266
+ });
1267
+ const now = opts.now ?? Date.now;
1268
+ const timer = setInterval(() => {
1269
+ void update((e) => ({ ...e, heartbeatAtMs: now() }));
1270
+ }, LEDGER_HEARTBEAT_MS);
1271
+ timer.unref();
1272
+ const following = followToolGroups((groups) => {
1273
+ void update((e) => ({ ...e, toolGroups: [...groups] }));
1274
+ });
1275
+ if (following.groups.length > 0)
1276
+ void update((e) => ({ ...e, toolGroups: [...following.groups] }));
1277
+ /** Remove the entry and schedule the queue. True when done (or never possible here). */
1278
+ const removeOnce = async () => {
1279
+ try {
1280
+ const before = readLedgerDoc(dir);
1281
+ const nowMs = now();
1282
+ const { share, lightShare, sampled } = await sampleShare(opts, before.pressure, nowMs);
1283
+ const capacityBytes = opts.capacityBytes ?? admissionCapacityBytes();
1284
+ await withLedger(dir, (doc) => ({
1285
+ doc: reapAndSchedule({ ...doc, entries: doc.entries.filter((e) => e.id !== entry.id) }, NO_DEAD, { capacityBytes, share, lightShare, nowMs }, sampled),
1286
+ result: undefined,
1287
+ }));
1288
+ return true;
1289
+ }
1290
+ catch (err) {
1291
+ // State that cannot be written cannot be cleaned either: the entry is
1292
+ // reaped once this process is gone.
1293
+ if (admissionIoError(err) !== null)
1294
+ return true;
1295
+ log().warn({ err: err instanceof Error ? err.message : String(err), id: entry.id }, 'admission release failed; retrying in the background');
1296
+ return false;
1297
+ }
1298
+ };
1299
+ /** Keep trying in the background (never keeping the process alive) until removed. */
1300
+ const retry = (delayMs) => {
1301
+ const t = setTimeout(() => {
1302
+ void removeOnce().then((done) => {
1303
+ if (!done)
1304
+ retry(Math.min(delayMs * 2, RELEASE_RETRY_MS[1]));
1305
+ });
1306
+ }, delayMs);
1307
+ t.unref();
1308
+ };
1309
+ let released = false;
1310
+ return {
1311
+ id: entry.id,
1312
+ token: admissionToken(entry),
1313
+ nested: false,
1314
+ ungoverned: null,
1315
+ waitedMs,
1316
+ footprintBytes: entry.footprintBytes,
1317
+ release: async () => {
1318
+ if (released)
1319
+ return;
1320
+ released = true;
1321
+ clearInterval(timer);
1322
+ following.stop();
1323
+ if (!(await removeOnce()))
1324
+ retry(RELEASE_RETRY_MS[0]);
1325
+ },
1326
+ };
1327
+ }
1328
+ /** Remove the ledger file (tests). @internal */
1329
+ export function _resetAdmissionLedgerForTest(dir) {
1330
+ try {
1331
+ rmSync(ledgerFile(dir ?? admissionDir()), { force: true });
1332
+ }
1333
+ catch {
1334
+ // Absent already, or no CLEO home to clean.
1335
+ }
1336
+ }
1337
+ /** The id shown for an entry of an unknown format. */
1338
+ function foreignId(f) {
1339
+ return typeof f.id === 'string' ? f.id : `foreign:${JSON.stringify(f).slice(0, 60)}`;
1340
+ }
1341
+ /**
1342
+ * Drop every entry whose holder is provably gone, and schedule. For
1343
+ * `cleo doctor tool-locks --reap`; admission does this on every pass.
1344
+ *
1345
+ * @param opts - ledger directory, capacity and probes (tests).
1346
+ * @returns the ids removed (entries of another CLEO version included).
1347
+ */
1348
+ export async function reapLedger(opts = {}) {
1349
+ const dir = opts.dir ?? admissionDir();
1350
+ const now = opts.now ?? Date.now;
1351
+ const before = readLedgerDoc(dir);
1352
+ const nowMs = now();
1353
+ const dead = findDead(before, nowMs, opts.probe ?? systemPidProbe);
1354
+ if (dead.entries.size === 0 && dead.foreign.size === 0)
1355
+ return [];
1356
+ const { share, lightShare, sampled } = await sampleShare({ wait: false, ...opts }, before.pressure, nowMs);
1357
+ const capacityBytes = opts.capacityBytes ?? admissionCapacityBytes();
1358
+ return withLedger(dir, (doc) => {
1359
+ const removed = [
1360
+ ...doc.entries.filter((e) => dead.entries.get(e.id) === e.heartbeatAtMs).map((e) => e.id),
1361
+ ...doc.foreign.filter((f) => dead.foreign.has(JSON.stringify(f))).map(foreignId),
1362
+ ];
1363
+ return {
1364
+ doc: reapAndSchedule(doc, dead, { capacityBytes, share, lightShare, nowMs }, sampled),
1365
+ result: removed,
1366
+ };
1367
+ });
1368
+ }
1369
+ /**
1370
+ * Remove one entry by id, whatever its liveness, and schedule. For
1371
+ * `cleo doctor tool-locks --remove <id>`, when an entry cannot be proven dead
1372
+ * (its holder is unidentifiable) but the operator knows it is.
1373
+ *
1374
+ * @param id - the entry id (as `cleo doctor tool-locks` lists it).
1375
+ * @param opts - ledger directory, capacity and probes (tests).
1376
+ * @returns whether an entry was removed.
1377
+ */
1378
+ export async function removeLedgerEntry(id, opts = {}) {
1379
+ const dir = opts.dir ?? admissionDir();
1380
+ const now = opts.now ?? Date.now;
1381
+ const before = readLedgerDoc(dir);
1382
+ if (!before.entries.some((e) => e.id === id) &&
1383
+ !before.foreign.some((f) => foreignId(f) === id)) {
1384
+ return false;
1385
+ }
1386
+ const nowMs = now();
1387
+ const { share, lightShare, sampled } = await sampleShare({ wait: false, ...opts }, before.pressure, nowMs);
1388
+ const capacityBytes = opts.capacityBytes ?? admissionCapacityBytes();
1389
+ return withLedger(dir, (doc) => {
1390
+ const entries = doc.entries.filter((e) => e.id !== id);
1391
+ const foreign = doc.foreign.filter((f) => foreignId(f) !== id);
1392
+ if (entries.length === doc.entries.length && foreign.length === doc.foreign.length) {
1393
+ return { doc: null, result: false };
1394
+ }
1395
+ return {
1396
+ doc: reapAndSchedule({ ...doc, entries, foreign }, NO_DEAD, { capacityBytes, share, lightShare, nowMs }, sampled),
1397
+ result: true,
1398
+ };
1399
+ });
1400
+ }
1401
+ //# sourceMappingURL=admission-ledger.js.map