@cleocode/core 2026.10.1 → 2026.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/dist/build-provenance.json +2 -2
  2. package/dist/cloud/journal.d.ts +9 -5
  3. package/dist/cloud/journal.d.ts.map +1 -1
  4. package/dist/cloud/journal.js +29 -8
  5. package/dist/cloud/journal.js.map +1 -1
  6. package/dist/cloud/manifest-check.d.ts +140 -4
  7. package/dist/cloud/manifest-check.d.ts.map +1 -1
  8. package/dist/cloud/manifest-check.js +309 -10
  9. package/dist/cloud/manifest-check.js.map +1 -1
  10. package/dist/cloud/nexus-attach.d.ts +25 -0
  11. package/dist/cloud/nexus-attach.d.ts.map +1 -1
  12. package/dist/cloud/nexus-attach.js +81 -6
  13. package/dist/cloud/nexus-attach.js.map +1 -1
  14. package/dist/cloud/nexus-cloud-activity.d.ts +37 -0
  15. package/dist/cloud/nexus-cloud-activity.d.ts.map +1 -0
  16. package/dist/cloud/nexus-cloud-activity.js +79 -0
  17. package/dist/cloud/nexus-cloud-activity.js.map +1 -0
  18. package/dist/cloud/nexus-cloud-status.d.ts.map +1 -1
  19. package/dist/cloud/nexus-cloud-status.js +36 -0
  20. package/dist/cloud/nexus-cloud-status.js.map +1 -1
  21. package/dist/cloud/nexus-device.d.ts +1 -1
  22. package/dist/cloud/nexus-enrol.d.ts.map +1 -1
  23. package/dist/cloud/nexus-enrol.js +5 -0
  24. package/dist/cloud/nexus-enrol.js.map +1 -1
  25. package/dist/cloud/nexus-home.d.ts +74 -0
  26. package/dist/cloud/nexus-home.d.ts.map +1 -0
  27. package/dist/cloud/nexus-home.js +97 -0
  28. package/dist/cloud/nexus-home.js.map +1 -0
  29. package/dist/cloud/nexus-vault-keys.d.ts +129 -0
  30. package/dist/cloud/nexus-vault-keys.d.ts.map +1 -0
  31. package/dist/cloud/nexus-vault-keys.js +277 -0
  32. package/dist/cloud/nexus-vault-keys.js.map +1 -0
  33. package/dist/cloud/nexus-vault-state.d.ts +121 -0
  34. package/dist/cloud/nexus-vault-state.d.ts.map +1 -0
  35. package/dist/cloud/nexus-vault-state.js +274 -0
  36. package/dist/cloud/nexus-vault-state.js.map +1 -0
  37. package/dist/cloud/nexus-vault.d.ts +160 -0
  38. package/dist/cloud/nexus-vault.d.ts.map +1 -0
  39. package/dist/cloud/nexus-vault.js +1733 -0
  40. package/dist/cloud/nexus-vault.js.map +1 -0
  41. package/dist/cloud/signing.d.ts +24 -8
  42. package/dist/cloud/signing.d.ts.map +1 -1
  43. package/dist/cloud/signing.js +61 -15
  44. package/dist/cloud/signing.js.map +1 -1
  45. package/dist/docs/export-document.js +8137 -3318
  46. package/dist/docs/export-document.js.map +3 -3
  47. package/dist/doctor/migrations.d.ts +75 -0
  48. package/dist/doctor/migrations.d.ts.map +1 -0
  49. package/dist/doctor/migrations.js +136 -0
  50. package/dist/doctor/migrations.js.map +1 -0
  51. package/dist/doctor/sync-sealer.d.ts +48 -0
  52. package/dist/doctor/sync-sealer.d.ts.map +1 -0
  53. package/dist/doctor/sync-sealer.js +109 -0
  54. package/dist/doctor/sync-sealer.js.map +1 -0
  55. package/dist/doctor/sync-triggers.d.ts +53 -0
  56. package/dist/doctor/sync-triggers.d.ts.map +1 -0
  57. package/dist/doctor/sync-triggers.js +157 -0
  58. package/dist/doctor/sync-triggers.js.map +1 -0
  59. package/dist/init.d.ts.map +1 -1
  60. package/dist/init.js +5 -1
  61. package/dist/init.js.map +1 -1
  62. package/dist/internal.d.ts +1 -1
  63. package/dist/internal.d.ts.map +1 -1
  64. package/dist/internal.js +1 -1
  65. package/dist/internal.js.map +1 -1
  66. package/dist/llm/plugin-facade.js +8442 -3623
  67. package/dist/llm/plugin-facade.js.map +3 -3
  68. package/dist/nexus/projects-clean.d.ts +3 -0
  69. package/dist/nexus/projects-clean.d.ts.map +1 -1
  70. package/dist/nexus/projects-clean.js +9 -3
  71. package/dist/nexus/projects-clean.js.map +1 -1
  72. package/dist/nexus/registry-roots.d.ts +3 -1
  73. package/dist/nexus/registry-roots.d.ts.map +1 -1
  74. package/dist/nexus/registry-roots.js +5 -2
  75. package/dist/nexus/registry-roots.js.map +1 -1
  76. package/dist/nexus/registry.d.ts +8 -1
  77. package/dist/nexus/registry.d.ts.map +1 -1
  78. package/dist/nexus/registry.js +24 -10
  79. package/dist/nexus/registry.js.map +1 -1
  80. package/dist/nexus/workspace.d.ts +4 -1
  81. package/dist/nexus/workspace.d.ts.map +1 -1
  82. package/dist/nexus/workspace.js +10 -4
  83. package/dist/nexus/workspace.js.map +1 -1
  84. package/dist/orchestrate/spawn-ops.d.ts.map +1 -1
  85. package/dist/orchestrate/spawn-ops.js +7 -2
  86. package/dist/orchestrate/spawn-ops.js.map +1 -1
  87. package/dist/orchestrate/worker-verify.d.ts +121 -12
  88. package/dist/orchestrate/worker-verify.d.ts.map +1 -1
  89. package/dist/orchestrate/worker-verify.js +172 -21
  90. package/dist/orchestrate/worker-verify.js.map +1 -1
  91. package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
  92. package/dist/orchestration/spawn-prompt.js +15 -9
  93. package/dist/orchestration/spawn-prompt.js.map +1 -1
  94. package/dist/release/ci-evidence.d.ts +9 -0
  95. package/dist/release/ci-evidence.d.ts.map +1 -1
  96. package/dist/release/ci-evidence.js +9 -2
  97. package/dist/release/ci-evidence.js.map +1 -1
  98. package/dist/resources/backend.d.ts +15 -3
  99. package/dist/resources/backend.d.ts.map +1 -1
  100. package/dist/resources/backend.js +7 -3
  101. package/dist/resources/backend.js.map +1 -1
  102. package/dist/resources/darwin-backend.d.ts +142 -0
  103. package/dist/resources/darwin-backend.d.ts.map +1 -0
  104. package/dist/resources/darwin-backend.js +288 -0
  105. package/dist/resources/darwin-backend.js.map +1 -0
  106. package/dist/resources/governor.d.ts +44 -1
  107. package/dist/resources/governor.d.ts.map +1 -1
  108. package/dist/resources/governor.js +100 -36
  109. package/dist/resources/governor.js.map +1 -1
  110. package/dist/resources/heavy-command.d.ts +132 -0
  111. package/dist/resources/heavy-command.d.ts.map +1 -0
  112. package/dist/resources/heavy-command.js +768 -0
  113. package/dist/resources/heavy-command.js.map +1 -0
  114. package/dist/resources/monitor.d.ts +50 -1
  115. package/dist/resources/monitor.d.ts.map +1 -1
  116. package/dist/resources/monitor.js +83 -1
  117. package/dist/resources/monitor.js.map +1 -1
  118. package/dist/resources/run-admission.d.ts +303 -0
  119. package/dist/resources/run-admission.d.ts.map +1 -0
  120. package/dist/resources/run-admission.js +648 -0
  121. package/dist/resources/run-admission.js.map +1 -0
  122. package/dist/resources/run-class.d.ts +111 -0
  123. package/dist/resources/run-class.d.ts.map +1 -0
  124. package/dist/resources/run-class.js +658 -0
  125. package/dist/resources/run-class.js.map +1 -0
  126. package/dist/resources/run-governed.d.ts +158 -0
  127. package/dist/resources/run-governed.d.ts.map +1 -0
  128. package/dist/resources/run-governed.js +406 -0
  129. package/dist/resources/run-governed.js.map +1 -0
  130. package/dist/resources/slot-holder.d.ts +267 -0
  131. package/dist/resources/slot-holder.d.ts.map +1 -0
  132. package/dist/resources/slot-holder.js +505 -0
  133. package/dist/resources/slot-holder.js.map +1 -0
  134. package/dist/resources/tool-groups.d.ts +74 -0
  135. package/dist/resources/tool-groups.d.ts.map +1 -0
  136. package/dist/resources/tool-groups.js +118 -0
  137. package/dist/resources/tool-groups.js.map +1 -0
  138. package/dist/routing/build-command-groups.d.ts.map +1 -1
  139. package/dist/routing/build-command-groups.js +1 -0
  140. package/dist/routing/build-command-groups.js.map +1 -1
  141. package/dist/selfimprove/fix-gen.js +8446 -3627
  142. package/dist/selfimprove/fix-gen.js.map +3 -3
  143. package/dist/sentient/cross-project-hygiene.d.ts +3 -2
  144. package/dist/sentient/cross-project-hygiene.d.ts.map +1 -1
  145. package/dist/sentient/cross-project-hygiene.js +5 -2
  146. package/dist/sentient/cross-project-hygiene.js.map +1 -1
  147. package/dist/sentient/state.d.ts +7 -0
  148. package/dist/sentient/state.d.ts.map +1 -1
  149. package/dist/sentient/state.js.map +1 -1
  150. package/dist/sentient/tick.d.ts +14 -2
  151. package/dist/sentient/tick.d.ts.map +1 -1
  152. package/dist/sentient/tick.js +63 -4
  153. package/dist/sentient/tick.js.map +1 -1
  154. package/dist/store/backup-recover.d.ts.map +1 -1
  155. package/dist/store/backup-recover.js +5 -0
  156. package/dist/store/backup-recover.js.map +1 -1
  157. package/dist/store/data-accessor.d.ts +1 -0
  158. package/dist/store/data-accessor.d.ts.map +1 -1
  159. package/dist/store/data-accessor.js +7 -0
  160. package/dist/store/data-accessor.js.map +1 -1
  161. package/dist/store/dual-scope-db.d.ts +23 -1
  162. package/dist/store/dual-scope-db.d.ts.map +1 -1
  163. package/dist/store/dual-scope-db.js +126 -36
  164. package/dist/store/dual-scope-db.js.map +1 -1
  165. package/dist/store/exodus/recovery.d.ts.map +1 -1
  166. package/dist/store/exodus/recovery.js +15 -0
  167. package/dist/store/exodus/recovery.js.map +1 -1
  168. package/dist/store/legacy-tasks-lineage.d.ts.map +1 -1
  169. package/dist/store/legacy-tasks-lineage.js +5 -0
  170. package/dist/store/legacy-tasks-lineage.js.map +1 -1
  171. package/dist/store/lock.d.ts +8 -1
  172. package/dist/store/lock.d.ts.map +1 -1
  173. package/dist/store/lock.js +10 -2
  174. package/dist/store/lock.js.map +1 -1
  175. package/dist/store/migration-manager.d.ts +5 -0
  176. package/dist/store/migration-manager.d.ts.map +1 -1
  177. package/dist/store/migration-manager.js +11 -0
  178. package/dist/store/migration-manager.js.map +1 -1
  179. package/dist/store/migration-runner.d.ts +158 -0
  180. package/dist/store/migration-runner.d.ts.map +1 -0
  181. package/dist/store/migration-runner.js +493 -0
  182. package/dist/store/migration-runner.js.map +1 -0
  183. package/dist/store/portable-bundle-import.d.ts +15 -1
  184. package/dist/store/portable-bundle-import.d.ts.map +1 -1
  185. package/dist/store/portable-bundle-import.js +24 -4
  186. package/dist/store/portable-bundle-import.js.map +1 -1
  187. package/dist/store/portable-bundle-relocate.d.ts +43 -0
  188. package/dist/store/portable-bundle-relocate.d.ts.map +1 -1
  189. package/dist/store/portable-bundle-relocate.js +79 -5
  190. package/dist/store/portable-bundle-relocate.js.map +1 -1
  191. package/dist/store/portable-bundle-scan.d.ts +20 -0
  192. package/dist/store/portable-bundle-scan.d.ts.map +1 -1
  193. package/dist/store/portable-bundle-scan.js +38 -3
  194. package/dist/store/portable-bundle-scan.js.map +1 -1
  195. package/dist/store/portable-bundle.d.ts +33 -0
  196. package/dist/store/portable-bundle.d.ts.map +1 -1
  197. package/dist/store/portable-bundle.js +34 -7
  198. package/dist/store/portable-bundle.js.map +1 -1
  199. package/dist/store/row-identity-registry.d.ts +137 -7
  200. package/dist/store/row-identity-registry.d.ts.map +1 -1
  201. package/dist/store/row-identity-registry.js +364 -9
  202. package/dist/store/row-identity-registry.js.map +1 -1
  203. package/dist/store/row-identity.d.ts.map +1 -1
  204. package/dist/store/row-identity.js +9 -10
  205. package/dist/store/row-identity.js.map +1 -1
  206. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  207. package/dist/store/sqlite-data-accessor.js +10 -0
  208. package/dist/store/sqlite-data-accessor.js.map +1 -1
  209. package/dist/store/sqlite.d.ts +31 -0
  210. package/dist/store/sqlite.d.ts.map +1 -1
  211. package/dist/store/sqlite.js +5 -1
  212. package/dist/store/sqlite.js.map +1 -1
  213. package/dist/store/sync/capture.d.ts +203 -0
  214. package/dist/store/sync/capture.d.ts.map +1 -0
  215. package/dist/store/sync/capture.js +562 -0
  216. package/dist/store/sync/capture.js.map +1 -0
  217. package/dist/store/sync/clock-store.d.ts.map +1 -1
  218. package/dist/store/sync/clock-store.js +2 -0
  219. package/dist/store/sync/clock-store.js.map +1 -1
  220. package/dist/store/sync/fk-orphans.d.ts +133 -0
  221. package/dist/store/sync/fk-orphans.d.ts.map +1 -0
  222. package/dist/store/sync/fk-orphans.js +265 -0
  223. package/dist/store/sync/fk-orphans.js.map +1 -0
  224. package/dist/store/sync/flags.d.ts +7 -0
  225. package/dist/store/sync/flags.d.ts.map +1 -1
  226. package/dist/store/sync/flags.js +16 -0
  227. package/dist/store/sync/flags.js.map +1 -1
  228. package/dist/store/sync/hlc.d.ts.map +1 -1
  229. package/dist/store/sync/hlc.js +4 -0
  230. package/dist/store/sync/hlc.js.map +1 -1
  231. package/dist/store/sync/identity-fill.d.ts +45 -0
  232. package/dist/store/sync/identity-fill.d.ts.map +1 -0
  233. package/dist/store/sync/identity-fill.js +85 -0
  234. package/dist/store/sync/identity-fill.js.map +1 -0
  235. package/dist/store/sync/machinery.d.ts +27 -0
  236. package/dist/store/sync/machinery.d.ts.map +1 -0
  237. package/dist/store/sync/machinery.js +44 -0
  238. package/dist/store/sync/machinery.js.map +1 -0
  239. package/dist/store/sync/netting.d.ts +120 -0
  240. package/dist/store/sync/netting.d.ts.map +1 -0
  241. package/dist/store/sync/netting.js +336 -0
  242. package/dist/store/sync/netting.js.map +1 -0
  243. package/dist/store/sync/replica.d.ts +27 -2
  244. package/dist/store/sync/replica.d.ts.map +1 -1
  245. package/dist/store/sync/replica.js +47 -3
  246. package/dist/store/sync/replica.js.map +1 -1
  247. package/dist/store/sync/schema.d.ts +12 -0
  248. package/dist/store/sync/schema.d.ts.map +1 -1
  249. package/dist/store/sync/schema.js +21 -0
  250. package/dist/store/sync/schema.js.map +1 -1
  251. package/dist/store/sync/seal-backlog.d.ts +21 -0
  252. package/dist/store/sync/seal-backlog.d.ts.map +1 -0
  253. package/dist/store/sync/seal-backlog.js +24 -0
  254. package/dist/store/sync/seal-backlog.js.map +1 -0
  255. package/dist/store/sync/sealer-values.d.ts +34 -0
  256. package/dist/store/sync/sealer-values.d.ts.map +1 -0
  257. package/dist/store/sync/sealer-values.js +53 -0
  258. package/dist/store/sync/sealer-values.js.map +1 -0
  259. package/dist/store/sync/sealer.d.ts +145 -0
  260. package/dist/store/sync/sealer.d.ts.map +1 -0
  261. package/dist/store/sync/sealer.js +906 -0
  262. package/dist/store/sync/sealer.js.map +1 -0
  263. package/dist/store/sync/structural.d.ts +63 -0
  264. package/dist/store/sync/structural.d.ts.map +1 -0
  265. package/dist/store/sync/structural.js +180 -0
  266. package/dist/store/sync/structural.js.map +1 -0
  267. package/dist/store/sync/timestamps.d.ts +92 -0
  268. package/dist/store/sync/timestamps.d.ts.map +1 -0
  269. package/dist/store/sync/timestamps.js +228 -0
  270. package/dist/store/sync/timestamps.js.map +1 -0
  271. package/dist/store/sync/tombstones.d.ts +75 -0
  272. package/dist/store/sync/tombstones.d.ts.map +1 -0
  273. package/dist/store/sync/tombstones.js +103 -0
  274. package/dist/store/sync/tombstones.js.map +1 -0
  275. package/dist/store/sync/trigger-classes.d.ts +221 -0
  276. package/dist/store/sync/trigger-classes.d.ts.map +1 -0
  277. package/dist/store/sync/trigger-classes.js +441 -0
  278. package/dist/store/sync/trigger-classes.js.map +1 -0
  279. package/dist/store/sync/trigger-suspend-at-path.d.ts +23 -0
  280. package/dist/store/sync/trigger-suspend-at-path.d.ts.map +1 -0
  281. package/dist/store/sync/trigger-suspend-at-path.js +44 -0
  282. package/dist/store/sync/trigger-suspend-at-path.js.map +1 -0
  283. package/dist/store/sync/writer-version.d.ts +43 -0
  284. package/dist/store/sync/writer-version.d.ts.map +1 -0
  285. package/dist/store/sync/writer-version.js +90 -0
  286. package/dist/store/sync/writer-version.js.map +1 -0
  287. package/dist/store/table-classification.d.ts.map +1 -1
  288. package/dist/store/table-classification.js +102 -0
  289. package/dist/store/table-classification.js.map +1 -1
  290. package/dist/store/trigger-suspend-schema.d.ts +44 -0
  291. package/dist/store/trigger-suspend-schema.d.ts.map +1 -0
  292. package/dist/store/trigger-suspend-schema.js +25 -0
  293. package/dist/store/trigger-suspend-schema.js.map +1 -0
  294. package/dist/store/vault-manifest.d.ts +365 -0
  295. package/dist/store/vault-manifest.d.ts.map +1 -0
  296. package/dist/store/vault-manifest.js +812 -0
  297. package/dist/store/vault-manifest.js.map +1 -0
  298. package/dist/store/writer-lease.d.ts +31 -0
  299. package/dist/store/writer-lease.d.ts.map +1 -1
  300. package/dist/store/writer-lease.js +65 -2
  301. package/dist/store/writer-lease.js.map +1 -1
  302. package/dist/system/health.d.ts.map +1 -1
  303. package/dist/system/health.js +21 -0
  304. package/dist/system/health.js.map +1 -1
  305. package/dist/system/project-health.d.ts.map +1 -1
  306. package/dist/system/project-health.js +3 -1
  307. package/dist/system/project-health.js.map +1 -1
  308. package/dist/tasks/affected-packages.d.ts +58 -0
  309. package/dist/tasks/affected-packages.d.ts.map +1 -1
  310. package/dist/tasks/affected-packages.js +75 -6
  311. package/dist/tasks/affected-packages.js.map +1 -1
  312. package/dist/tasks/affected-scope.d.ts +150 -23
  313. package/dist/tasks/affected-scope.d.ts.map +1 -1
  314. package/dist/tasks/affected-scope.js +320 -32
  315. package/dist/tasks/affected-scope.js.map +1 -1
  316. package/dist/tasks/change-set.d.ts +96 -0
  317. package/dist/tasks/change-set.d.ts.map +1 -1
  318. package/dist/tasks/change-set.js +169 -4
  319. package/dist/tasks/change-set.js.map +1 -1
  320. package/dist/tasks/complete-ci.d.ts +115 -0
  321. package/dist/tasks/complete-ci.d.ts.map +1 -0
  322. package/dist/tasks/complete-ci.js +171 -0
  323. package/dist/tasks/complete-ci.js.map +1 -0
  324. package/dist/tasks/complete.d.ts.map +1 -1
  325. package/dist/tasks/complete.js +50 -17
  326. package/dist/tasks/complete.js.map +1 -1
  327. package/dist/tasks/compute-task-view.d.ts.map +1 -1
  328. package/dist/tasks/compute-task-view.js +7 -0
  329. package/dist/tasks/compute-task-view.js.map +1 -1
  330. package/dist/tasks/done-plan.d.ts.map +1 -1
  331. package/dist/tasks/done-plan.js +51 -30
  332. package/dist/tasks/done-plan.js.map +1 -1
  333. package/dist/tasks/done-record.d.ts +6 -0
  334. package/dist/tasks/done-record.d.ts.map +1 -1
  335. package/dist/tasks/done-record.js +9 -3
  336. package/dist/tasks/done-record.js.map +1 -1
  337. package/dist/tasks/evidence.d.ts +3 -2
  338. package/dist/tasks/evidence.d.ts.map +1 -1
  339. package/dist/tasks/evidence.js +143 -12
  340. package/dist/tasks/evidence.js.map +1 -1
  341. package/dist/tasks/gate-notes.d.ts +22 -0
  342. package/dist/tasks/gate-notes.d.ts.map +1 -0
  343. package/dist/tasks/gate-notes.js +33 -0
  344. package/dist/tasks/gate-notes.js.map +1 -0
  345. package/dist/tasks/index.d.ts +2 -1
  346. package/dist/tasks/index.d.ts.map +1 -1
  347. package/dist/tasks/index.js +2 -1
  348. package/dist/tasks/index.js.map +1 -1
  349. package/dist/tasks/test-run-binding.d.ts +117 -0
  350. package/dist/tasks/test-run-binding.d.ts.map +1 -0
  351. package/dist/tasks/test-run-binding.js +365 -0
  352. package/dist/tasks/test-run-binding.js.map +1 -0
  353. package/dist/tasks/tool-cache-env.d.ts +123 -0
  354. package/dist/tasks/tool-cache-env.d.ts.map +1 -0
  355. package/dist/tasks/tool-cache-env.js +287 -0
  356. package/dist/tasks/tool-cache-env.js.map +1 -0
  357. package/dist/tasks/tool-cache-failed-first.d.ts +155 -0
  358. package/dist/tasks/tool-cache-failed-first.d.ts.map +1 -0
  359. package/dist/tasks/tool-cache-failed-first.js +285 -0
  360. package/dist/tasks/tool-cache-failed-first.js.map +1 -0
  361. package/dist/tasks/tool-cache.d.ts +375 -55
  362. package/dist/tasks/tool-cache.d.ts.map +1 -1
  363. package/dist/tasks/tool-cache.js +912 -303
  364. package/dist/tasks/tool-cache.js.map +1 -1
  365. package/dist/tasks/tool-resolver.d.ts +4 -3
  366. package/dist/tasks/tool-resolver.d.ts.map +1 -1
  367. package/dist/tasks/tool-resolver.js +15 -4
  368. package/dist/tasks/tool-resolver.js.map +1 -1
  369. package/dist/tasks/tool-semaphore.d.ts +67 -7
  370. package/dist/tasks/tool-semaphore.d.ts.map +1 -1
  371. package/dist/tasks/tool-semaphore.js +134 -56
  372. package/dist/tasks/tool-semaphore.js.map +1 -1
  373. package/dist/upgrade.d.ts.map +1 -1
  374. package/dist/upgrade.js +4 -0
  375. package/dist/upgrade.js.map +1 -1
  376. package/dist/validation/engine-ops.d.ts +6 -0
  377. package/dist/validation/engine-ops.d.ts.map +1 -1
  378. package/dist/validation/engine-ops.js +8 -0
  379. package/dist/validation/engine-ops.js.map +1 -1
  380. package/migrations/drizzle-cleo-project/20260930170000_t12819-trigger-suspend-clause/migration.sql +367 -0
  381. package/migrations/sync-journal/20260930120000_t12343-capture/migration.sql +47 -0
  382. package/migrations/sync-journal/20261001170000_t12984-sealer/migration.sql +101 -0
  383. package/package.json +13 -13
  384. package/templates/CLEO-INJECTION.md +5 -5
  385. package/templates/CLEO-REFERENCE.md +8 -4
@@ -0,0 +1,288 @@
1
+ /**
2
+ * macOS ResourceMonitor backend.
3
+ *
4
+ * macOS has no PSI. This backend maps the kernel's own signals onto the
5
+ * PSI-shaped {@link ResourceSample}, so `evaluateState` and the slot scaling
6
+ * work unchanged:
7
+ *
8
+ * - `kern.memorystatus_vm_pressure_level` — the kernel's memory pressure
9
+ * verdict (1 normal, 2 warning, 4 critical), the signal jetsam acts on
10
+ * - `kern.memorystatus_level` — free memory as a percentage of RAM, counting
11
+ * reclaimable pages (unlike `os.freemem()`, which reports only the free
12
+ * page list and reads near zero on a healthy Mac)
13
+ * - `vm.swapusage` — swap in use (reported, not scored: macOS allocates
14
+ * swapfiles on demand, so used/total sits at 80–95% on a healthy Mac)
15
+ * - `vm.loadavg` + `hw.perflevel{0,1}.logicalcpu` (or `hw.ncpu`) —
16
+ * run-queue length per effective core (CPU saturation)
17
+ *
18
+ * ## Sampling discipline (darwin amendment)
19
+ *
20
+ * Node has no sysctl binding, so `sample()` runs ONE `/usr/sbin/sysctl` exec
21
+ * (≈4 ms) for all names, and caches its output for `cacheTtlMs` (default 2 s)
22
+ * across every backend instance in the process. A poll loop or a burst of
23
+ * admissions therefore spawns at most one child per TTL. No other process or
24
+ * file read happens on the sample path; `sweepChildRss` (low frequency) uses
25
+ * `ps`.
26
+ *
27
+ * ## Mapping
28
+ *
29
+ * Memory (`globalPressure`): `some avg10` is the higher of a kernel-level score
30
+ * (warning 15, critical 40) and a free-memory score (`2 × (20 − free%)`,
31
+ * clamped at 0). `full avg10` is
32
+ * 15 when the kernel reports critical. With the monitor's default thresholds
33
+ * (hold 10 / backoff 20), a kernel warning holds and critical backs off.
34
+ *
35
+ * CPU (`cpuPressure`): effective cores are performance cores plus half the
36
+ * efficiency cores (a 6P+12E machine counts as 12; `hw.ncpu` when the split is
37
+ * unknown). With `r = load / cores`, `some = 100 × (r − 1) / r`
38
+ * once `r > 1`: the share of runnable work that is waiting for a core. A box
39
+ * running twice its cores scores 50. avg10/avg60/avg300 come from the 1/5/15
40
+ * minute load averages. Memory is instantaneous in all three windows.
41
+ *
42
+ * @module resources/darwin-backend
43
+ * @task T12981
44
+ * @epic T12978
45
+ */
46
+ import { execFile } from 'node:child_process';
47
+ import { totalmem } from 'node:os';
48
+ /** The sysctl names one sample reads, in one exec. */
49
+ export const DARWIN_SYSCTL_NAMES = [
50
+ 'kern.memorystatus_vm_pressure_level',
51
+ 'kern.memorystatus_level',
52
+ 'vm.swapusage',
53
+ 'vm.loadavg',
54
+ 'hw.ncpu',
55
+ 'hw.perflevel0.logicalcpu',
56
+ 'hw.perflevel1.logicalcpu',
57
+ ];
58
+ const MIB = 1024 * 1024;
59
+ function parseSize(value) {
60
+ const m = /^([\d.]+)([KMGT])?$/.exec(value.trim());
61
+ if (!m?.[1])
62
+ return null;
63
+ const n = Number.parseFloat(m[1]);
64
+ const unit = { K: 1024, M: MIB, G: 1024 * MIB, T: 1024 * 1024 * MIB }[m[2] ?? ''] ?? 1;
65
+ return Number.isFinite(n) ? n * unit : null;
66
+ }
67
+ /**
68
+ * Parse `sysctl <names>` output (`name: value` per line).
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * parseDarwinSysctl('kern.memorystatus_vm_pressure_level: 2\nhw.ncpu: 18\n');
73
+ * // → { pressureLevel: 2, ncpu: 18, freePercent: null, ... }
74
+ * ```
75
+ */
76
+ export function parseDarwinSysctl(output) {
77
+ const values = new Map();
78
+ for (const line of output.split('\n')) {
79
+ const idx = line.indexOf(':');
80
+ if (idx <= 0)
81
+ continue;
82
+ values.set(line.slice(0, idx).trim(), line.slice(idx + 1).trim());
83
+ }
84
+ const int = (name) => {
85
+ const raw = values.get(name);
86
+ if (raw === undefined || !/^-?\d+$/.test(raw))
87
+ return null;
88
+ return Number.parseInt(raw, 10);
89
+ };
90
+ let swapTotalBytes = null;
91
+ let swapUsedBytes = null;
92
+ const swap = values.get('vm.swapusage');
93
+ if (swap) {
94
+ swapTotalBytes = parseSize(/total = (\S+)/.exec(swap)?.[1] ?? '');
95
+ swapUsedBytes = parseSize(/used = (\S+)/.exec(swap)?.[1] ?? '');
96
+ }
97
+ let loadAvg = null;
98
+ const load = values.get('vm.loadavg');
99
+ if (load) {
100
+ const nums = load
101
+ .replace(/[{}]/g, ' ')
102
+ .trim()
103
+ .split(/\s+/)
104
+ .map((s) => Number.parseFloat(s));
105
+ if (nums.length >= 3 && nums.slice(0, 3).every(Number.isFinite)) {
106
+ loadAvg = [nums[0], nums[1], nums[2]];
107
+ }
108
+ }
109
+ return {
110
+ pressureLevel: int('kern.memorystatus_vm_pressure_level'),
111
+ freePercent: int('kern.memorystatus_level'),
112
+ swapTotalBytes,
113
+ swapUsedBytes,
114
+ loadAvg,
115
+ ncpu: int('hw.ncpu'),
116
+ perfCores: int('hw.perflevel0.logicalcpu'),
117
+ efficiencyCores: int('hw.perflevel1.logicalcpu'),
118
+ };
119
+ }
120
+ function clamp(n) {
121
+ return Math.max(0, Math.min(100, n));
122
+ }
123
+ /**
124
+ * Memory pressure score (PSI `some`-equivalent, 0–100) from darwin signals.
125
+ * Returns `null` when neither the kernel level nor free% is readable.
126
+ */
127
+ export function darwinMemorySome(s) {
128
+ if (s.pressureLevel === null && s.freePercent === null)
129
+ return null;
130
+ const levelScore = s.pressureLevel === 4 ? 40 : s.pressureLevel === 2 ? 15 : 0;
131
+ const freeScore = s.freePercent === null ? 0 : Math.max(0, 2 * (20 - s.freePercent));
132
+ return clamp(Math.max(levelScore, freeScore));
133
+ }
134
+ /**
135
+ * Cores that absorb load: performance cores plus half the efficiency cores,
136
+ * else `hw.ncpu`. `null` when neither is known.
137
+ */
138
+ export function effectiveCores(s) {
139
+ if (s.perfCores !== null && s.perfCores > 0) {
140
+ return s.perfCores + (s.efficiencyCores ?? 0) / 2;
141
+ }
142
+ return s.ncpu;
143
+ }
144
+ /** CPU waiting share (0–100) for a load average on `ncpu` cores. */
145
+ export function cpuSomeFromLoad(load, ncpu) {
146
+ const r = load / Math.max(1, ncpu);
147
+ return r <= 1 ? 0 : clamp((100 * (r - 1)) / r);
148
+ }
149
+ function line(avg10, avg60, avg300) {
150
+ return { avg10, avg60, avg300, totalUs: 0 };
151
+ }
152
+ /** Build the memory and CPU PSI-equivalents from parsed signals. */
153
+ export function darwinPressure(s) {
154
+ const some = darwinMemorySome(s);
155
+ const memory = some === null
156
+ ? null
157
+ : {
158
+ some: line(some, some, some),
159
+ full: s.pressureLevel === 4 ? line(15, 15, 15) : line(0, 0, 0),
160
+ };
161
+ let cpu = null;
162
+ const cores = effectiveCores(s);
163
+ if (s.loadAvg && cores) {
164
+ const [l1, l5, l15] = s.loadAvg;
165
+ cpu = {
166
+ some: line(cpuSomeFromLoad(l1, cores), cpuSomeFromLoad(l5, cores), cpuSomeFromLoad(l15, cores)),
167
+ full: null,
168
+ };
169
+ }
170
+ return { memory, cpu };
171
+ }
172
+ const defaultSysctl = (names) => new Promise((resolve, reject) => {
173
+ execFile('/usr/sbin/sysctl', [...names], { timeout: 2000 }, (err, stdout) => {
174
+ // sysctl exits non-zero when ONE name is unknown but still prints the
175
+ // others; keep whatever it printed.
176
+ if (stdout)
177
+ resolve(stdout);
178
+ else
179
+ reject(err ?? new Error('sysctl produced no output'));
180
+ });
181
+ });
182
+ const defaultPsRss = (pids) => new Promise((resolve) => {
183
+ execFile('/bin/ps', ['-o', 'pid=,rss=', '-p', pids.join(',')], { timeout: 2000 }, (_err, stdout) => resolve(stdout ?? ''));
184
+ });
185
+ const defaultStat = async (path) => {
186
+ const { stat } = await import('node:fs/promises');
187
+ try {
188
+ return { size: (await stat(path)).size };
189
+ }
190
+ catch {
191
+ return null;
192
+ }
193
+ };
194
+ /** Process-wide cache of the default sysctl read. */
195
+ let sharedRead = null;
196
+ /** Reset the process-wide sysctl cache (tests). @internal */
197
+ export function resetDarwinSysctlCache() {
198
+ sharedRead = null;
199
+ }
200
+ /**
201
+ * macOS implementation of {@link ResourceBackend}.
202
+ *
203
+ * `pressureAvailable` is `true` when the kernel memory signals were readable,
204
+ * so `evaluateState` uses the PSI path rather than degraded mode.
205
+ */
206
+ export class DarwinResourceBackend {
207
+ walPaths;
208
+ cacheTtlMs;
209
+ sysctlFn;
210
+ psRssFn;
211
+ statFileFn;
212
+ totalMemBytes;
213
+ now;
214
+ local = null;
215
+ constructor(opts = {}) {
216
+ this.walPaths = opts.walPaths ?? [];
217
+ this.cacheTtlMs = opts.cacheTtlMs ?? 2000;
218
+ this.sysctlFn = opts.sysctlFn ?? null;
219
+ this.psRssFn = opts.psRssFn ?? defaultPsRss;
220
+ this.statFileFn = opts.statFileFn ?? defaultStat;
221
+ this.totalMemBytes = opts.totalMemBytes ?? totalmem();
222
+ this.now = opts.now ?? Date.now;
223
+ }
224
+ /** At most one sysctl exec per TTL; on failure the sample is degraded. */
225
+ async sample() {
226
+ const sampledAtMs = this.now();
227
+ let signals = null;
228
+ try {
229
+ signals = parseDarwinSysctl(await this.readSysctl(sampledAtMs));
230
+ }
231
+ catch {
232
+ signals = null;
233
+ }
234
+ const { memory, cpu } = signals ? darwinPressure(signals) : { memory: null, cpu: null };
235
+ const memAvailableBytes = signals?.freePercent != null
236
+ ? Math.round((signals.freePercent / 100) * this.totalMemBytes)
237
+ : null;
238
+ const walObservations = [];
239
+ for (const walPath of this.walPaths) {
240
+ const info = await this.statFileFn(walPath);
241
+ walObservations.push({ walPath, sizeBytes: info?.size ?? null });
242
+ }
243
+ return {
244
+ sampledAtMs,
245
+ pressureAvailable: memory !== null,
246
+ memAvailableBytes,
247
+ globalPressure: memory,
248
+ slicePressure: null,
249
+ cpuPressure: cpu,
250
+ walObservations,
251
+ };
252
+ }
253
+ /** RSS via one `ps` exec (no PSS on macOS: `pssBytes` mirrors RSS). */
254
+ async sweepChildRss(pids) {
255
+ const sampledAtMs = this.now();
256
+ const wanted = pids.filter((p) => Number.isInteger(p) && p > 0);
257
+ if (wanted.length === 0)
258
+ return { sampledAtMs, entries: [] };
259
+ const entries = [];
260
+ for (const row of (await this.psRssFn(wanted)).split('\n')) {
261
+ const m = /^\s*(\d+)\s+(\d+)\s*$/.exec(row);
262
+ if (!m?.[1] || !m[2])
263
+ continue;
264
+ const rssBytes = Number.parseInt(m[2], 10) * 1024;
265
+ entries.push({ pid: Number.parseInt(m[1], 10), rssBytes, pssBytes: rssBytes });
266
+ }
267
+ return { sampledAtMs, entries };
268
+ }
269
+ readSysctl(at) {
270
+ const fresh = (c) => c !== null && at - c.at < this.cacheTtlMs && at >= c.at;
271
+ if (this.sysctlFn) {
272
+ if (!fresh(this.local))
273
+ this.local = { at, output: this.sysctlFn(DARWIN_SYSCTL_NAMES) };
274
+ return this.local.output;
275
+ }
276
+ if (!fresh(sharedRead)) {
277
+ const output = defaultSysctl(DARWIN_SYSCTL_NAMES);
278
+ // A failed read must not be cached for the whole TTL.
279
+ output.catch(() => {
280
+ if (sharedRead?.output === output)
281
+ sharedRead = null;
282
+ });
283
+ sharedRead = { at, output };
284
+ }
285
+ return sharedRead.output;
286
+ }
287
+ }
288
+ //# sourceMappingURL=darwin-backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"darwin-backend.js","sourceRoot":"","sources":["../../src/resources/darwin-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAYnC,sDAAsD;AACtD,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,qCAAqC;IACrC,yBAAyB;IACzB,cAAc;IACd,YAAY;IACZ,SAAS;IACT,0BAA0B;IAC1B,0BAA0B;CAClB,CAAC;AA6BX,MAAM,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAExB,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,CAAC,GAAG,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,GAAG,GAAG,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;IACvF,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,IAAI,CAAC;YAAE,SAAS;QACvB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,MAAM,GAAG,GAAG,CAAC,IAAY,EAAiB,EAAE;QAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3D,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC;IAEF,IAAI,cAAc,GAAkB,IAAI,CAAC;IACzC,IAAI,aAAa,GAAkB,IAAI,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACxC,IAAI,IAAI,EAAE,CAAC;QACT,cAAc,GAAG,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAClE,aAAa,GAAG,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,OAAO,GAAoC,IAAI,CAAC;IACpD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,IAAI,GAAG,IAAI;aACd,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;aACrB,IAAI,EAAE;aACN,KAAK,CAAC,KAAK,CAAC;aACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChE,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAW,EAAE,IAAI,CAAC,CAAC,CAAW,EAAE,IAAI,CAAC,CAAC,CAAW,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,OAAO;QACL,aAAa,EAAE,GAAG,CAAC,qCAAqC,CAAC;QACzD,WAAW,EAAE,GAAG,CAAC,yBAAyB,CAAC;QAC3C,cAAc;QACd,aAAa;QACb,OAAO;QACP,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC;QACpB,SAAS,EAAE,GAAG,CAAC,0BAA0B,CAAC;QAC1C,eAAe,EAAE,GAAG,CAAC,0BAA0B,CAAC;KACjD,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,CAAS;IACtB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAgB;IAC/C,IAAI,CAAC,CAAC,aAAa,KAAK,IAAI,IAAI,CAAC,CAAC,WAAW,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACpE,MAAM,UAAU,GAAG,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,SAAS,GAAG,CAAC,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;IACrF,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,CAAgB;IAC7C,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;QAC5C,OAAO,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,CAAC,CAAC,IAAI,CAAC;AAChB,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,IAAY;IACxD,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,IAAI,CAAC,KAAa,EAAE,KAAa,EAAE,MAAc;IACxD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AAC9C,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,cAAc,CAAC,CAAgB;IAI7C,MAAM,IAAI,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACjC,MAAM,MAAM,GACV,IAAI,KAAK,IAAI;QACX,CAAC,CAAC,IAAI;QACN,CAAC,CAAC;YACE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;YAC5B,IAAI,EAAE,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;SAC/D,CAAC;IACR,IAAI,GAAG,GAAmB,IAAI,CAAC;IAC/B,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;QAChC,GAAG,GAAG;YACJ,IAAI,EAAE,IAAI,CACR,eAAe,CAAC,EAAE,EAAE,KAAK,CAAC,EAC1B,eAAe,CAAC,EAAE,EAAE,KAAK,CAAC,EAC1B,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAC5B;YACD,IAAI,EAAE,IAAI;SACX,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,aAAa,GAAa,CAAC,KAAK,EAAE,EAAE,CACxC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC9B,QAAQ,CAAC,kBAAkB,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QAC1E,sEAAsE;QACtE,oCAAoC;QACpC,IAAI,MAAM;YAAE,OAAO,CAAC,MAAM,CAAC,CAAC;;YACvB,MAAM,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,MAAM,YAAY,GAAY,CAAC,IAAI,EAAE,EAAE,CACrC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;IACtB,QAAQ,CACN,SAAS,EACT,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EACzC,EAAE,OAAO,EAAE,IAAI,EAAE,EACjB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CACxC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,MAAM,WAAW,GAAe,KAAK,EAAE,IAAI,EAAE,EAAE;IAC7C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAoBF,qDAAqD;AACrD,IAAI,UAAU,GAAmD,IAAI,CAAC;AAEtE,6DAA6D;AAC7D,MAAM,UAAU,sBAAsB;IACpC,UAAU,GAAG,IAAI,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,qBAAqB;IACf,QAAQ,CAAoB;IAC5B,UAAU,CAAS;IACnB,QAAQ,CAAkB;IAC1B,OAAO,CAAU;IACjB,UAAU,CAAa;IACvB,aAAa,CAAS;IACtB,GAAG,CAAe;IAC3B,KAAK,GAAmD,IAAI,CAAC;IAErE,YAAY,OAA6B,EAAE;QACzC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;QAC1C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,YAAY,CAAC;QAC5C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,WAAW,CAAC;QACjD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,QAAQ,EAAE,CAAC;QACtD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IAClC,CAAC;IAED,0EAA0E;IAC1E,KAAK,CAAC,MAAM;QACV,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,IAAI,OAAO,GAAyB,IAAI,CAAC;QACzC,IAAI,CAAC;YACH,OAAO,GAAG,iBAAiB,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;QAClE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QACxF,MAAM,iBAAiB,GACrB,OAAO,EAAE,WAAW,IAAI,IAAI;YAC1B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC;YAC9D,CAAC,CAAC,IAAI,CAAC;QACX,MAAM,eAAe,GAAyB,EAAE,CAAC;QACjD,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAC5C,eAAe,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,OAAO;YACL,WAAW;YACX,iBAAiB,EAAE,MAAM,KAAK,IAAI;YAClC,iBAAiB;YACjB,cAAc,EAAE,MAAM;YACtB,aAAa,EAAE,IAAI;YACnB,WAAW,EAAE,GAAG;YAChB,eAAe;SAChB,CAAC;IACJ,CAAC;IAED,uEAAuE;IACvE,KAAK,CAAC,aAAa,CAAC,IAAuB;QACzC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC7D,MAAM,OAAO,GAAoB,EAAE,CAAC;QACpC,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,GAAG,uBAAuB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC5C,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAAE,SAAS;YAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;YAClD,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IAClC,CAAC;IAEO,UAAU,CAAC,EAAU;QAC3B,MAAM,KAAK,GAAG,CAAC,CAAwB,EAAW,EAAE,CAClD,CAAC,KAAK,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QAC1D,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;gBAAE,IAAI,CAAC,KAAK,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACxF,OAAQ,IAAI,CAAC,KAAqC,CAAC,MAAM,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,aAAa,CAAC,mBAAmB,CAAC,CAAC;YAClD,sDAAsD;YACtD,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;gBAChB,IAAI,UAAU,EAAE,MAAM,KAAK,MAAM;oBAAE,UAAU,GAAG,IAAI,CAAC;YACvD,CAAC,CAAC,CAAC;YACH,UAAU,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;QAC9B,CAAC;QACD,OAAQ,UAA0C,CAAC,MAAM,CAAC;IAC5D,CAAC;CACF"}
@@ -20,11 +20,16 @@
20
20
  * `interactive-cli` is NEVER gated; `full-build` is pinned to one machine-wide
21
21
  * slot regardless of pressure.
22
22
  *
23
+ * A local slot whose holder process is provably gone is reaped at once instead
24
+ * of waiting out the 10 min stale timeout (T12963), as the tool semaphore does
25
+ * for its slots (gh#1222).
26
+ *
23
27
  * @task T11999
28
+ * @task T12963
24
29
  * @epic T11992
25
30
  * @adr resource-governor-never-oom-architecture §3.4
26
31
  */
27
- import { type AdmissionResult, type GovernorMode, type ResourceClass } from '@cleocode/contracts';
32
+ import { type AdmissionResult, type GovernorMode, type ResourceClass, type ResourceGrant } from '@cleocode/contracts';
28
33
  import type { ResourceSample } from './backend.js';
29
34
  import { ResourceMonitor } from './monitor.js';
30
35
  /**
@@ -86,6 +91,38 @@ export declare function computeClassBudget(cls: ResourceClass, sample: ResourceS
86
91
  * and PIDs — exactly like the tool semaphore.
87
92
  */
88
93
  export declare function governorSlotDir(cls: ResourceClass): string;
94
+ export { SLOT_LOCK_STALE_MS, SLOT_LOCK_UPDATE_MS } from './slot-holder.js';
95
+ /** An ungated grant (no slot held, `slot: -1`): `off` mode, `interactive-cli`, a nested run, fail-open. */
96
+ export declare function passThroughGrant(cls: ResourceClass): ResourceGrant;
97
+ /** Why the governor could not keep its state: the errno code and the path, when known. */
98
+ export interface GovernorIoError {
99
+ readonly code: string;
100
+ readonly path: string | null;
101
+ }
102
+ /**
103
+ * The code and path of an error that means "the governor cannot keep state here" (a sandbox that
104
+ * blocks writes to the CLEO home, a read-only or full disk, a broken CLEO home), or null for any
105
+ * other error, which is a bug and must not be hidden.
106
+ */
107
+ export declare function governorIoError(err: unknown): GovernorIoError | null;
108
+ /**
109
+ * Run an admission, failing OPEN when the governor cannot write its state
110
+ * ({@link governorIoError}): the work proceeds ungated with a
111
+ * {@link passThroughGrant}, and `ungoverned` says why. A sandboxed or
112
+ * read-only CLEO home must never turn into a deferral that never clears.
113
+ * Any other error is a bug and propagates.
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * const { admission, ungoverned } = await admitFailOpen('agent-session', () =>
118
+ * governor.tryAcquire('agent-session'),
119
+ * );
120
+ * ```
121
+ */
122
+ export declare function admitFailOpen(cls: ResourceClass, acquire: () => Promise<AdmissionResult>): Promise<{
123
+ readonly admission: AdmissionResult;
124
+ readonly ungoverned: GovernorIoError | null;
125
+ }>;
89
126
  /** Options for {@link ResourceGovernor.acquire}. */
90
127
  export interface AcquireOptions extends BudgetOptions {
91
128
  /**
@@ -117,6 +154,12 @@ export declare class ResourceGovernor {
117
154
  * Acquire one slot of `cls`. Returns a {@link ResourceGrant} on success or a
118
155
  * {@link ResourceDeferral} on denial. Never throws for admission control;
119
156
  * only genuinely unexpected I/O errors propagate.
157
+ *
158
+ * Only a held lock (`ELOCKED`) counts as a busy slot. Any other lock error
159
+ * (EACCES from a sandbox that can't write the slot dir, EROFS, ENOSPC…) is
160
+ * thrown once a pass found no free slot, never read as "busy": a slot that
161
+ * can never be taken would otherwise defer every caller until it times out
162
+ * (#1777 round 8, R8-1). Callers fail open with {@link admitFailOpen}.
120
163
  */
121
164
  acquire(cls: ResourceClass, opts?: AcquireOptions): Promise<AdmissionResult>;
122
165
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"governor.d.ts","sourceRoot":"","sources":["../../src/resources/governor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAKH,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,YAAY,EACjB,KAAK,aAAa,EAGnB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAoB/C;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,YAAY,CAKlD;AAgBD;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAGjD;AAMD,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,kFAAkF;IAClF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAUD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,cAAc,EACtB,IAAI,GAAE,aAAkB,GACvB,MAAM,CA8CR;AAUD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAE1D;AA6CD,oDAAoD;AACpD,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,wDAAwD;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC;IACjC,yEAAyE;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC;CACpC;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B;;;;OAIG;IACG,OAAO,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,eAAe,CAAC;IAgFtF;;;;;;;OAOG;YACW,oBAAoB;IAkClC,8DAA8D;IACxD,UAAU,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,eAAe,CAAC;IAIzF;;;OAGG;IACG,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;CAWhF;AAqCD,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAIxD;AAED,uCAAuC;AACvC,eAAO,MAAM,QAAQ,kBAAyB,CAAC"}
1
+ {"version":3,"file":"governor.d.ts","sourceRoot":"","sources":["../../src/resources/governor.ts"],"names":[],"mappings":"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"}
@@ -20,7 +20,12 @@
20
20
  * `interactive-cli` is NEVER gated; `full-build` is pinned to one machine-wide
21
21
  * slot regardless of pressure.
22
22
  *
23
+ * A local slot whose holder process is provably gone is reaped at once instead
24
+ * of waiting out the 10 min stale timeout (T12963), as the tool semaphore does
25
+ * for its slots (gh#1222).
26
+ *
23
27
  * @task T11999
28
+ * @task T12963
24
29
  * @epic T11992
25
30
  * @adr resource-governor-never-oom-architecture §3.4
26
31
  */
@@ -28,10 +33,11 @@ import { existsSync, mkdirSync, readdirSync, writeFileSync } from 'node:fs';
28
33
  import { availableParallelism, totalmem } from 'node:os';
29
34
  import { join } from 'node:path';
30
35
  import { DEFAULT_RESOURCE_RETRY_AFTER_MS, } from '@cleocode/contracts';
31
- import lockfile from 'proper-lockfile';
32
36
  import { getLogger } from '../logger.js';
33
37
  import { getCleoHome } from '../paths.js';
34
- import { ResourceMonitor } from './monitor.js';
38
+ import { pressureScore, ResourceMonitor } from './monitor.js';
39
+ import { parentRunJob } from './run-admission.js';
40
+ import { _resetSlotHolderStateForTest, describeSlotHolders, lockSlot } from './slot-holder.js';
35
41
  import { resolveSupervisorSocketPath, sendResourceAdmit, sendResourceRelease, } from './supervisor-admit.js';
36
42
  let _log = null;
37
43
  function log() {
@@ -77,12 +83,13 @@ function logSupervisorDegradeOnce(reason) {
77
83
  export function _resetGovernorStateForTest() {
78
84
  _cachedMode = null;
79
85
  _supervisorDegradeLogged = false;
86
+ _resetSlotHolderStateForTest();
80
87
  }
81
88
  const MB = 1024 * 1024;
82
89
  /** Extract `some avg10` (0–100) from a sample; 0 when unavailable. */
83
90
  function someAvg10(sample) {
84
- const some = sample.globalPressure?.some ?? sample.slicePressure?.some;
85
- return some?.avg10 ?? 0;
91
+ // T12981: memory or CPU, whichever is worse (CPU rescaled to this scale).
92
+ return pressureScore(sample);
86
93
  }
87
94
  /**
88
95
  * Compute the slot budget for a class given a point-sample.
@@ -173,11 +180,14 @@ function ensureSlotFiles(dir, count) {
173
180
  }
174
181
  return paths;
175
182
  }
176
- const STALE_MS = 600_000;
183
+ // The slot timing constants live with the slot locks (T12963); re-exported
184
+ // for existing importers.
185
+ export { SLOT_LOCK_STALE_MS, SLOT_LOCK_UPDATE_MS } from './slot-holder.js';
177
186
  function sleep(ms) {
178
187
  return new Promise((r) => setTimeout(r, ms));
179
188
  }
180
- function passThroughGrant(cls) {
189
+ /** An ungated grant (no slot held, `slot: -1`): `off` mode, `interactive-cli`, a nested run, fail-open. */
190
+ export function passThroughGrant(cls) {
181
191
  return {
182
192
  deferred: false,
183
193
  class: cls,
@@ -189,6 +199,54 @@ function passThroughGrant(cls) {
189
199
  function deferral(cls, reason, retryAfterMs) {
190
200
  return { deferred: true, class: cls, retryAfterMs, reason };
191
201
  }
202
+ /** Filesystem errors meaning the governor's state can't be written here. */
203
+ const GOVERNOR_IO_CODES = new Set([
204
+ 'EACCES',
205
+ 'EPERM',
206
+ 'EROFS',
207
+ 'ENOSPC',
208
+ 'EDQUOT',
209
+ 'ENOTDIR',
210
+ 'ELOOP',
211
+ ]);
212
+ /**
213
+ * The code and path of an error that means "the governor cannot keep state here" (a sandbox that
214
+ * blocks writes to the CLEO home, a read-only or full disk, a broken CLEO home), or null for any
215
+ * other error, which is a bug and must not be hidden.
216
+ */
217
+ export function governorIoError(err) {
218
+ const e = err;
219
+ if (!e || typeof e !== 'object' || typeof e.code !== 'string')
220
+ return null;
221
+ if (!GOVERNOR_IO_CODES.has(e.code))
222
+ return null;
223
+ return { code: e.code, path: typeof e.path === 'string' ? e.path : null };
224
+ }
225
+ /**
226
+ * Run an admission, failing OPEN when the governor cannot write its state
227
+ * ({@link governorIoError}): the work proceeds ungated with a
228
+ * {@link passThroughGrant}, and `ungoverned` says why. A sandboxed or
229
+ * read-only CLEO home must never turn into a deferral that never clears.
230
+ * Any other error is a bug and propagates.
231
+ *
232
+ * @example
233
+ * ```ts
234
+ * const { admission, ungoverned } = await admitFailOpen('agent-session', () =>
235
+ * governor.tryAcquire('agent-session'),
236
+ * );
237
+ * ```
238
+ */
239
+ export async function admitFailOpen(cls, acquire) {
240
+ try {
241
+ return { admission: await acquire(), ungoverned: null };
242
+ }
243
+ catch (err) {
244
+ const io = governorIoError(err);
245
+ if (io === null)
246
+ throw err;
247
+ return { admission: passThroughGrant(cls), ungoverned: io };
248
+ }
249
+ }
192
250
  let _supervisorHolderSeq = 0;
193
251
  /**
194
252
  * A process-unique holder id for a supervisor `resource_admit`, so each acquire
@@ -209,6 +267,12 @@ export class ResourceGovernor {
209
267
  * Acquire one slot of `cls`. Returns a {@link ResourceGrant} on success or a
210
268
  * {@link ResourceDeferral} on denial. Never throws for admission control;
211
269
  * only genuinely unexpected I/O errors propagate.
270
+ *
271
+ * Only a held lock (`ELOCKED`) counts as a busy slot. Any other lock error
272
+ * (EACCES from a sandbox that can't write the slot dir, EROFS, ENOSPC…) is
273
+ * thrown once a pass found no free slot, never read as "busy": a slot that
274
+ * can never be taken would otherwise defer every caller until it times out
275
+ * (#1777 round 8, R8-1). Callers fail open with {@link admitFailOpen}.
212
276
  */
213
277
  async acquire(cls, opts = {}) {
214
278
  // Ungated fast paths: off mode + interactive-cli are pure pass-through.
@@ -216,6 +280,15 @@ export class ResourceGovernor {
216
280
  if (mode === 'off' || cls === 'interactive-cli') {
217
281
  return passThroughGrant(cls);
218
282
  }
283
+ // Inside a running `cleo run` job (e.g. `cleo run -- cleo verify`), the
284
+ // job's slot already covers this process tree: waiting for another slot
285
+ // of a budget-1 class would wait on ourselves (#1777 round 3, M-2). The
286
+ // env var only says "look"; parentRunJob's group + start-time check is
287
+ // what decides, so setting it by hand grants nothing.
288
+ // Only a parent holding THIS class covers it (#1777 round 4, MED-1).
289
+ if (process.env.CLEO_RUN_CLASS !== undefined && parentRunJob({ pid: process.pid, cls })) {
290
+ return passThroughGrant(cls);
291
+ }
219
292
  const sample = opts.sample ?? (await (opts.monitor ?? new ResourceMonitor()).sample());
220
293
  const budget = computeClassBudget(cls, sample, opts);
221
294
  if (!Number.isFinite(budget))
@@ -242,45 +315,32 @@ export class ResourceGovernor {
242
315
  do {
243
316
  // Re-shuffle each pass so concurrent acquirers don't collide on slot 0.
244
317
  const order = shuffledIndices(slots.length);
318
+ let lockError = null;
245
319
  for (const idx of order) {
246
320
  const path = slots[idx];
247
321
  if (!path)
248
322
  continue;
249
323
  try {
250
- const release = await lockfile.lock(path, {
251
- retries: 0,
252
- stale: STALE_MS,
253
- realpath: false,
254
- });
255
- let released = false;
256
- return {
257
- deferred: false,
258
- class: cls,
259
- slot: idx,
260
- acquiredAtMs: Date.now(),
261
- release: async () => {
262
- if (released)
263
- return;
264
- released = true;
265
- try {
266
- await release();
267
- }
268
- catch {
269
- // Already released (e.g. stale recovery) — post-condition holds.
270
- }
271
- },
272
- };
324
+ // T12963: a busy slot whose holder is provably dead is reaped here.
325
+ const release = await lockSlot(path, cls);
326
+ if (release) {
327
+ return { deferred: false, class: cls, slot: idx, acquiredAtMs: Date.now(), release };
328
+ }
273
329
  }
274
- catch {
275
- // slot busy — try next
330
+ catch (err) {
331
+ // Anything but a held lock is not "busy" (#1777 round 8, R8-1).
332
+ lockError ??= { err };
276
333
  }
277
334
  }
335
+ if (lockError !== null)
336
+ throw lockError.err;
278
337
  if (!blocking)
279
338
  break;
280
339
  await sleep(pollMs);
281
340
  } while (Date.now() - startedAt < timeoutMs);
282
341
  return deferral(cls, `class '${cls}' is at capacity (${budget} slot(s)); ` +
283
- (blocking ? `timed out after ${timeoutMs}ms` : 'no slot free'), Math.min(pollMs * 4, DEFAULT_RESOURCE_RETRY_AFTER_MS));
342
+ (blocking ? `timed out after ${timeoutMs}ms` : 'no slot free') +
343
+ describeSlotHolders(slots), Math.min(pollMs * 4, DEFAULT_RESOURCE_RETRY_AFTER_MS));
284
344
  }
285
345
  /**
286
346
  * Route an admission through the supervisor's central `resource_admit` verb.
@@ -355,7 +415,8 @@ function shuffledIndices(n) {
355
415
  /**
356
416
  * Count how many of `budget` slots are currently held, by probing each with a
357
417
  * non-blocking lock. A successful probe-lock is released immediately — it never
358
- * holds the slot, so it cannot starve a real acquirer.
418
+ * holds the slot, so it cannot starve a real acquirer. A slot held by a dead
419
+ * process is reaped, not counted (T12963).
359
420
  */
360
421
  async function countHeldSlots(cls, budget) {
361
422
  const dir = governorSlotDir(cls);
@@ -365,11 +426,14 @@ async function countHeldSlots(cls, budget) {
365
426
  let held = 0;
366
427
  for (const path of slots) {
367
428
  try {
368
- const release = await lockfile.lock(path, { retries: 0, stale: STALE_MS, realpath: false });
369
- await release();
429
+ const release = await lockSlot(path, cls);
430
+ if (release)
431
+ await release();
432
+ else
433
+ held++;
370
434
  }
371
435
  catch {
372
- held++;
436
+ // Only a held lock is a holder; an unwritable slot dir is not (R8-1).
373
437
  }
374
438
  }
375
439
  return held;