dorfl 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (619) hide show
  1. package/dist/advance-ci-template.d.ts +73 -0
  2. package/dist/advance-ci-template.d.ts.map +1 -0
  3. package/dist/advance-ci-template.js +104 -0
  4. package/dist/advance-ci-template.js.map +1 -0
  5. package/dist/advance-classify.d.ts +132 -0
  6. package/dist/advance-classify.d.ts.map +1 -0
  7. package/dist/advance-classify.js +120 -0
  8. package/dist/advance-classify.js.map +1 -0
  9. package/dist/advance-drivers.d.ts +182 -0
  10. package/dist/advance-drivers.d.ts.map +1 -0
  11. package/dist/advance-drivers.js +231 -0
  12. package/dist/advance-drivers.js.map +1 -0
  13. package/dist/advance-isolated.d.ts +156 -0
  14. package/dist/advance-isolated.d.ts.map +1 -0
  15. package/dist/advance-isolated.js +256 -0
  16. package/dist/advance-isolated.js.map +1 -0
  17. package/dist/advance-lifecycle-template.d.ts +107 -0
  18. package/dist/advance-lifecycle-template.d.ts.map +1 -0
  19. package/dist/advance-lifecycle-template.js +668 -0
  20. package/dist/advance-lifecycle-template.js.map +1 -0
  21. package/dist/advance-loop-driver.d.ts +325 -0
  22. package/dist/advance-loop-driver.d.ts.map +1 -0
  23. package/dist/advance-loop-driver.js +437 -0
  24. package/dist/advance-loop-driver.js.map +1 -0
  25. package/dist/advance-treeless-publish.d.ts +108 -0
  26. package/dist/advance-treeless-publish.d.ts.map +1 -0
  27. package/dist/advance-treeless-publish.js +71 -0
  28. package/dist/advance-treeless-publish.js.map +1 -0
  29. package/dist/advance.d.ts +340 -0
  30. package/dist/advance.d.ts.map +1 -0
  31. package/dist/advance.js +1122 -0
  32. package/dist/advance.js.map +1 -0
  33. package/dist/advancing-lock.d.ts +294 -0
  34. package/dist/advancing-lock.d.ts.map +1 -0
  35. package/dist/advancing-lock.js +594 -0
  36. package/dist/advancing-lock.js.map +1 -0
  37. package/dist/agent-launch.d.ts +79 -0
  38. package/dist/agent-launch.d.ts.map +1 -0
  39. package/dist/agent-launch.js +61 -0
  40. package/dist/agent-launch.js.map +1 -0
  41. package/dist/agent-stop.d.ts +149 -0
  42. package/dist/agent-stop.d.ts.map +1 -0
  43. package/dist/agent-stop.js +307 -0
  44. package/dist/agent-stop.js.map +1 -0
  45. package/dist/apply-decide.d.ts +127 -0
  46. package/dist/apply-decide.d.ts.map +1 -0
  47. package/dist/apply-decide.js +176 -0
  48. package/dist/apply-decide.js.map +1 -0
  49. package/dist/apply-merge-action.d.ts +206 -0
  50. package/dist/apply-merge-action.d.ts.map +1 -0
  51. package/dist/apply-merge-action.js +307 -0
  52. package/dist/apply-merge-action.js.map +1 -0
  53. package/dist/apply-persist.d.ts +174 -0
  54. package/dist/apply-persist.d.ts.map +1 -0
  55. package/dist/apply-persist.js +359 -0
  56. package/dist/apply-persist.js.map +1 -0
  57. package/dist/arbiter.d.ts +120 -0
  58. package/dist/arbiter.d.ts.map +1 -0
  59. package/dist/arbiter.js +255 -0
  60. package/dist/arbiter.js.map +1 -0
  61. package/dist/brand.d.ts +70 -0
  62. package/dist/brand.d.ts.map +1 -0
  63. package/dist/brand.js +84 -0
  64. package/dist/brand.js.map +1 -0
  65. package/dist/buildable-body.d.ts +132 -0
  66. package/dist/buildable-body.d.ts.map +1 -0
  67. package/dist/buildable-body.js +131 -0
  68. package/dist/buildable-body.js.map +1 -0
  69. package/dist/categorise.d.ts +66 -0
  70. package/dist/categorise.d.ts.map +1 -0
  71. package/dist/categorise.js +106 -0
  72. package/dist/categorise.js.map +1 -0
  73. package/dist/claim-cas.d.ts +117 -0
  74. package/dist/claim-cas.d.ts.map +1 -0
  75. package/dist/claim-cas.js +312 -0
  76. package/dist/claim-cas.js.map +1 -0
  77. package/dist/cli-spinner.d.ts +112 -0
  78. package/dist/cli-spinner.d.ts.map +1 -0
  79. package/dist/cli-spinner.js +157 -0
  80. package/dist/cli-spinner.js.map +1 -0
  81. package/dist/cli.d.ts +11 -0
  82. package/dist/cli.d.ts.map +1 -0
  83. package/dist/cli.js +3094 -0
  84. package/dist/cli.js.map +1 -0
  85. package/dist/close-job-template.d.ts +70 -0
  86. package/dist/close-job-template.d.ts.map +1 -0
  87. package/dist/close-job-template.js +180 -0
  88. package/dist/close-job-template.js.map +1 -0
  89. package/dist/close-job.d.ts +95 -0
  90. package/dist/close-job.d.ts.map +1 -0
  91. package/dist/close-job.js +226 -0
  92. package/dist/close-job.js.map +1 -0
  93. package/dist/complete.d.ts +361 -0
  94. package/dist/complete.d.ts.map +1 -0
  95. package/dist/complete.js +885 -0
  96. package/dist/complete.js.map +1 -0
  97. package/dist/concurrency.d.ts +68 -0
  98. package/dist/concurrency.d.ts.map +1 -0
  99. package/dist/concurrency.js +112 -0
  100. package/dist/concurrency.js.map +1 -0
  101. package/dist/config-override.d.ts +76 -0
  102. package/dist/config-override.d.ts.map +1 -0
  103. package/dist/config-override.js +50 -0
  104. package/dist/config-override.js.map +1 -0
  105. package/dist/config.d.ts +668 -0
  106. package/dist/config.d.ts.map +1 -0
  107. package/dist/config.js +241 -0
  108. package/dist/config.js.map +1 -0
  109. package/dist/continue-branch.d.ts +249 -0
  110. package/dist/continue-branch.d.ts.map +1 -0
  111. package/dist/continue-branch.js +389 -0
  112. package/dist/continue-branch.js.map +1 -0
  113. package/dist/cwd-section.d.ts +186 -0
  114. package/dist/cwd-section.d.ts.map +1 -0
  115. package/dist/cwd-section.js +209 -0
  116. package/dist/cwd-section.js.map +1 -0
  117. package/dist/decision-engine.d.ts +170 -0
  118. package/dist/decision-engine.d.ts.map +1 -0
  119. package/dist/decision-engine.js +136 -0
  120. package/dist/decision-engine.js.map +1 -0
  121. package/dist/detect.d.ts +17 -0
  122. package/dist/detect.d.ts.map +1 -0
  123. package/dist/detect.js +118 -0
  124. package/dist/detect.js.map +1 -0
  125. package/dist/do-autopick.d.ts +85 -0
  126. package/dist/do-autopick.d.ts.map +1 -0
  127. package/dist/do-autopick.js +112 -0
  128. package/dist/do-autopick.js.map +1 -0
  129. package/dist/do-config.d.ts +312 -0
  130. package/dist/do-config.d.ts.map +1 -0
  131. package/dist/do-config.js +358 -0
  132. package/dist/do-config.js.map +1 -0
  133. package/dist/do-remote-auto.d.ts +75 -0
  134. package/dist/do-remote-auto.d.ts.map +1 -0
  135. package/dist/do-remote-auto.js +111 -0
  136. package/dist/do-remote-auto.js.map +1 -0
  137. package/dist/do.d.ts +621 -0
  138. package/dist/do.d.ts.map +1 -0
  139. package/dist/do.js +1882 -0
  140. package/dist/do.js.map +1 -0
  141. package/dist/drop-source.d.ts +96 -0
  142. package/dist/drop-source.d.ts.map +1 -0
  143. package/dist/drop-source.js +91 -0
  144. package/dist/drop-source.js.map +1 -0
  145. package/dist/eligibility.d.ts +46 -0
  146. package/dist/eligibility.d.ts.map +1 -0
  147. package/dist/eligibility.js +34 -0
  148. package/dist/eligibility.js.map +1 -0
  149. package/dist/env-config.d.ts +51 -0
  150. package/dist/env-config.d.ts.map +1 -0
  151. package/dist/env-config.js +272 -0
  152. package/dist/env-config.js.map +1 -0
  153. package/dist/failure-cause.d.ts +70 -0
  154. package/dist/failure-cause.d.ts.map +1 -0
  155. package/dist/failure-cause.js +126 -0
  156. package/dist/failure-cause.js.map +1 -0
  157. package/dist/format.d.ts +43 -0
  158. package/dist/format.d.ts.map +1 -0
  159. package/dist/format.js +256 -0
  160. package/dist/format.js.map +1 -0
  161. package/dist/frontmatter.d.ts +215 -0
  162. package/dist/frontmatter.d.ts.map +1 -0
  163. package/dist/frontmatter.js +345 -0
  164. package/dist/frontmatter.js.map +1 -0
  165. package/dist/gate-readiness.d.ts +84 -0
  166. package/dist/gate-readiness.d.ts.map +1 -0
  167. package/dist/gate-readiness.js +103 -0
  168. package/dist/gate-readiness.js.map +1 -0
  169. package/dist/gc.d.ts +165 -0
  170. package/dist/gc.d.ts.map +1 -0
  171. package/dist/gc.js +313 -0
  172. package/dist/gc.js.map +1 -0
  173. package/dist/gh-failure.d.ts +42 -0
  174. package/dist/gh-failure.d.ts.map +1 -0
  175. package/dist/gh-failure.js +49 -0
  176. package/dist/gh-failure.js.map +1 -0
  177. package/dist/git.d.ts +75 -0
  178. package/dist/git.d.ts.map +1 -0
  179. package/dist/git.js +130 -0
  180. package/dist/git.js.map +1 -0
  181. package/dist/github.d.ts +187 -0
  182. package/dist/github.d.ts.map +1 -0
  183. package/dist/github.js +343 -0
  184. package/dist/github.js.map +1 -0
  185. package/dist/harness.d.ts +242 -0
  186. package/dist/harness.d.ts.map +1 -0
  187. package/dist/harness.js +157 -0
  188. package/dist/harness.js.map +1 -0
  189. package/dist/identity.d.ts +167 -0
  190. package/dist/identity.d.ts.map +1 -0
  191. package/dist/identity.js +231 -0
  192. package/dist/identity.js.map +1 -0
  193. package/dist/index.d.ts +147 -0
  194. package/dist/index.d.ts.map +1 -0
  195. package/dist/index.js +76 -0
  196. package/dist/index.js.map +1 -0
  197. package/dist/install-ci-branch-protection.d.ts +147 -0
  198. package/dist/install-ci-branch-protection.d.ts.map +1 -0
  199. package/dist/install-ci-branch-protection.js +166 -0
  200. package/dist/install-ci-branch-protection.js.map +1 -0
  201. package/dist/install-ci-capabilities/advance-lifecycle.d.ts +15 -0
  202. package/dist/install-ci-capabilities/advance-lifecycle.d.ts.map +1 -0
  203. package/dist/install-ci-capabilities/advance-lifecycle.js +28 -0
  204. package/dist/install-ci-capabilities/advance-lifecycle.js.map +1 -0
  205. package/dist/install-ci-capabilities/close-job.d.ts +13 -0
  206. package/dist/install-ci-capabilities/close-job.d.ts.map +1 -0
  207. package/dist/install-ci-capabilities/close-job.js +26 -0
  208. package/dist/install-ci-capabilities/close-job.js.map +1 -0
  209. package/dist/install-ci-capabilities/example-noop.d.ts +16 -0
  210. package/dist/install-ci-capabilities/example-noop.d.ts.map +1 -0
  211. package/dist/install-ci-capabilities/example-noop.js +23 -0
  212. package/dist/install-ci-capabilities/example-noop.js.map +1 -0
  213. package/dist/install-ci-capabilities/intake.d.ts +15 -0
  214. package/dist/install-ci-capabilities/intake.d.ts.map +1 -0
  215. package/dist/install-ci-capabilities/intake.js +28 -0
  216. package/dist/install-ci-capabilities/intake.js.map +1 -0
  217. package/dist/install-ci-capabilities/verify.d.ts +14 -0
  218. package/dist/install-ci-capabilities/verify.d.ts.map +1 -0
  219. package/dist/install-ci-capabilities/verify.js +27 -0
  220. package/dist/install-ci-capabilities/verify.js.map +1 -0
  221. package/dist/install-ci-core.d.ts +446 -0
  222. package/dist/install-ci-core.d.ts.map +1 -0
  223. package/dist/install-ci-core.js +760 -0
  224. package/dist/install-ci-core.js.map +1 -0
  225. package/dist/install-ci-github.d.ts +167 -0
  226. package/dist/install-ci-github.d.ts.map +1 -0
  227. package/dist/install-ci-github.js +315 -0
  228. package/dist/install-ci-github.js.map +1 -0
  229. package/dist/install-ci.d.ts +105 -0
  230. package/dist/install-ci.d.ts.map +1 -0
  231. package/dist/install-ci.js +363 -0
  232. package/dist/install-ci.js.map +1 -0
  233. package/dist/intake-event.d.ts +88 -0
  234. package/dist/intake-event.d.ts.map +1 -0
  235. package/dist/intake-event.js +66 -0
  236. package/dist/intake-event.js.map +1 -0
  237. package/dist/intake-marker.d.ts +95 -0
  238. package/dist/intake-marker.d.ts.map +1 -0
  239. package/dist/intake-marker.js +127 -0
  240. package/dist/intake-marker.js.map +1 -0
  241. package/dist/intake-triage.d.ts +48 -0
  242. package/dist/intake-triage.d.ts.map +1 -0
  243. package/dist/intake-triage.js +95 -0
  244. package/dist/intake-triage.js.map +1 -0
  245. package/dist/intake-trigger-template.d.ts +185 -0
  246. package/dist/intake-trigger-template.d.ts.map +1 -0
  247. package/dist/intake-trigger-template.js +449 -0
  248. package/dist/intake-trigger-template.js.map +1 -0
  249. package/dist/intake.d.ts +569 -0
  250. package/dist/intake.d.ts.map +1 -0
  251. package/dist/intake.js +1628 -0
  252. package/dist/intake.js.map +1 -0
  253. package/dist/integration-core.d.ts +539 -0
  254. package/dist/integration-core.d.ts.map +1 -0
  255. package/dist/integration-core.js +2195 -0
  256. package/dist/integration-core.js.map +1 -0
  257. package/dist/integrator.d.ts +343 -0
  258. package/dist/integrator.d.ts.map +1 -0
  259. package/dist/integrator.js +400 -0
  260. package/dist/integrator.js.map +1 -0
  261. package/dist/isolation.d.ts +219 -0
  262. package/dist/isolation.d.ts.map +1 -0
  263. package/dist/isolation.js +261 -0
  264. package/dist/isolation.js.map +1 -0
  265. package/dist/issue-provider.d.ts +349 -0
  266. package/dist/issue-provider.d.ts.map +1 -0
  267. package/dist/issue-provider.js +360 -0
  268. package/dist/issue-provider.js.map +1 -0
  269. package/dist/item-lock.d.ts +626 -0
  270. package/dist/item-lock.d.ts.map +1 -0
  271. package/dist/item-lock.js +1381 -0
  272. package/dist/item-lock.js.map +1 -0
  273. package/dist/item-path.d.ts +49 -0
  274. package/dist/item-path.d.ts.map +1 -0
  275. package/dist/item-path.js +66 -0
  276. package/dist/item-path.js.map +1 -0
  277. package/dist/ledger-lint.d.ts +129 -0
  278. package/dist/ledger-lint.d.ts.map +1 -0
  279. package/dist/ledger-lint.js +249 -0
  280. package/dist/ledger-lint.js.map +1 -0
  281. package/dist/ledger-read.d.ts +357 -0
  282. package/dist/ledger-read.d.ts.map +1 -0
  283. package/dist/ledger-read.js +442 -0
  284. package/dist/ledger-read.js.map +1 -0
  285. package/dist/ledger-write.d.ts +330 -0
  286. package/dist/ledger-write.d.ts.map +1 -0
  287. package/dist/ledger-write.js +411 -0
  288. package/dist/ledger-write.js.map +1 -0
  289. package/dist/lifecycle-gather.d.ts +30 -0
  290. package/dist/lifecycle-gather.d.ts.map +1 -0
  291. package/dist/lifecycle-gather.js +205 -0
  292. package/dist/lifecycle-gather.js.map +1 -0
  293. package/dist/lifecycle-pools.d.ts +180 -0
  294. package/dist/lifecycle-pools.d.ts.map +1 -0
  295. package/dist/lifecycle-pools.js +78 -0
  296. package/dist/lifecycle-pools.js.map +1 -0
  297. package/dist/merge-question-surfacer.d.ts +166 -0
  298. package/dist/merge-question-surfacer.d.ts.map +1 -0
  299. package/dist/merge-question-surfacer.js +297 -0
  300. package/dist/merge-question-surfacer.js.map +1 -0
  301. package/dist/mint-adr.d.ts +126 -0
  302. package/dist/mint-adr.d.ts.map +1 -0
  303. package/dist/mint-adr.js +257 -0
  304. package/dist/mint-adr.js.map +1 -0
  305. package/dist/mirror-pool-scan.d.ts +125 -0
  306. package/dist/mirror-pool-scan.d.ts.map +1 -0
  307. package/dist/mirror-pool-scan.js +104 -0
  308. package/dist/mirror-pool-scan.js.map +1 -0
  309. package/dist/needs-attention.d.ts +341 -0
  310. package/dist/needs-attention.d.ts.map +1 -0
  311. package/dist/needs-attention.js +900 -0
  312. package/dist/needs-attention.js.map +1 -0
  313. package/dist/orphan-sidecar.d.ts +79 -0
  314. package/dist/orphan-sidecar.d.ts.map +1 -0
  315. package/dist/orphan-sidecar.js +71 -0
  316. package/dist/orphan-sidecar.js.map +1 -0
  317. package/dist/output.d.ts +48 -0
  318. package/dist/output.d.ts.map +1 -0
  319. package/dist/output.js +66 -0
  320. package/dist/output.js.map +1 -0
  321. package/dist/pi-harness.d.ts +179 -0
  322. package/dist/pi-harness.d.ts.map +1 -0
  323. package/dist/pi-harness.js +342 -0
  324. package/dist/pi-harness.js.map +1 -0
  325. package/dist/placement.d.ts +99 -0
  326. package/dist/placement.d.ts.map +1 -0
  327. package/dist/placement.js +67 -0
  328. package/dist/placement.js.map +1 -0
  329. package/dist/prd-to-spec.d.ts +315 -0
  330. package/dist/prd-to-spec.d.ts.map +1 -0
  331. package/dist/prd-to-spec.js +684 -0
  332. package/dist/prd-to-spec.js.map +1 -0
  333. package/dist/prepare.d.ts +121 -0
  334. package/dist/prepare.d.ts.map +1 -0
  335. package/dist/prepare.js +140 -0
  336. package/dist/prepare.js.map +1 -0
  337. package/dist/prompt.d.ts +360 -0
  338. package/dist/prompt.d.ts.map +1 -0
  339. package/dist/prompt.js +499 -0
  340. package/dist/prompt.js.map +1 -0
  341. package/dist/protocol/ADR-FORMAT.md +47 -0
  342. package/dist/protocol/CLAIM-PROTOCOL.md +217 -0
  343. package/dist/protocol/REVIEW-PROTOCOL.md +119 -0
  344. package/dist/protocol/SURFACE-PROTOCOL.md +121 -0
  345. package/dist/protocol/TASKING-PROTOCOL.md +122 -0
  346. package/dist/protocol/WORK-CONTRACT.md +276 -0
  347. package/dist/protocol/spec-template.md +71 -0
  348. package/dist/protocol/task-template.md +65 -0
  349. package/dist/readiness.d.ts +66 -0
  350. package/dist/readiness.d.ts.map +1 -0
  351. package/dist/readiness.js +36 -0
  352. package/dist/readiness.js.map +1 -0
  353. package/dist/reap-branches.d.ts +102 -0
  354. package/dist/reap-branches.d.ts.map +1 -0
  355. package/dist/reap-branches.js +149 -0
  356. package/dist/reap-branches.js.map +1 -0
  357. package/dist/recover-isolated.d.ts +72 -0
  358. package/dist/recover-isolated.d.ts.map +1 -0
  359. package/dist/recover-isolated.js +188 -0
  360. package/dist/recover-isolated.js.map +1 -0
  361. package/dist/registry.d.ts +172 -0
  362. package/dist/registry.d.ts.map +1 -0
  363. package/dist/registry.js +296 -0
  364. package/dist/registry.js.map +1 -0
  365. package/dist/repo-config.d.ts +201 -0
  366. package/dist/repo-config.d.ts.map +1 -0
  367. package/dist/repo-config.js +414 -0
  368. package/dist/repo-config.js.map +1 -0
  369. package/dist/repo-key.d.ts +20 -0
  370. package/dist/repo-key.d.ts.map +1 -0
  371. package/dist/repo-key.js +68 -0
  372. package/dist/repo-key.js.map +1 -0
  373. package/dist/repo-mirror.d.ts +177 -0
  374. package/dist/repo-mirror.d.ts.map +1 -0
  375. package/dist/repo-mirror.js +271 -0
  376. package/dist/repo-mirror.js.map +1 -0
  377. package/dist/retry-backoff.d.ts +90 -0
  378. package/dist/retry-backoff.d.ts.map +1 -0
  379. package/dist/retry-backoff.js +98 -0
  380. package/dist/retry-backoff.js.map +1 -0
  381. package/dist/review-gate.d.ts +173 -0
  382. package/dist/review-gate.d.ts.map +1 -0
  383. package/dist/review-gate.js +261 -0
  384. package/dist/review-gate.js.map +1 -0
  385. package/dist/review-verdict.d.ts +149 -0
  386. package/dist/review-verdict.d.ts.map +1 -0
  387. package/dist/review-verdict.js +332 -0
  388. package/dist/review-verdict.js.map +1 -0
  389. package/dist/run.d.ts +221 -0
  390. package/dist/run.d.ts.map +1 -0
  391. package/dist/run.js +963 -0
  392. package/dist/run.js.map +1 -0
  393. package/dist/scan.d.ts +308 -0
  394. package/dist/scan.d.ts.map +1 -0
  395. package/dist/scan.js +374 -0
  396. package/dist/scan.js.map +1 -0
  397. package/dist/select-order.d.ts +75 -0
  398. package/dist/select-order.d.ts.map +1 -0
  399. package/dist/select-order.js +108 -0
  400. package/dist/select-order.js.map +1 -0
  401. package/dist/select-priority.d.ts +188 -0
  402. package/dist/select-priority.d.ts.map +1 -0
  403. package/dist/select-priority.js +80 -0
  404. package/dist/select-priority.js.map +1 -0
  405. package/dist/select.d.ts +25 -0
  406. package/dist/select.d.ts.map +1 -0
  407. package/dist/select.js +43 -0
  408. package/dist/select.js.map +1 -0
  409. package/dist/session-path.d.ts +36 -0
  410. package/dist/session-path.d.ts.map +1 -0
  411. package/dist/session-path.js +129 -0
  412. package/dist/session-path.js.map +1 -0
  413. package/dist/sidecar-apply.d.ts +83 -0
  414. package/dist/sidecar-apply.d.ts.map +1 -0
  415. package/dist/sidecar-apply.js +111 -0
  416. package/dist/sidecar-apply.js.map +1 -0
  417. package/dist/sidecar.d.ts +245 -0
  418. package/dist/sidecar.d.ts.map +1 -0
  419. package/dist/sidecar.js +481 -0
  420. package/dist/sidecar.js.map +1 -0
  421. package/dist/slug-namespace.d.ts +204 -0
  422. package/dist/slug-namespace.d.ts.map +1 -0
  423. package/dist/slug-namespace.js +229 -0
  424. package/dist/slug-namespace.js.map +1 -0
  425. package/dist/spec-complete.d.ts +44 -0
  426. package/dist/spec-complete.d.ts.map +1 -0
  427. package/dist/spec-complete.js +69 -0
  428. package/dist/spec-complete.js.map +1 -0
  429. package/dist/start.d.ts +97 -0
  430. package/dist/start.d.ts.map +1 -0
  431. package/dist/start.js +633 -0
  432. package/dist/start.js.map +1 -0
  433. package/dist/status.d.ts +199 -0
  434. package/dist/status.d.ts.map +1 -0
  435. package/dist/status.js +228 -0
  436. package/dist/status.js.map +1 -0
  437. package/dist/surface-gate.d.ts +162 -0
  438. package/dist/surface-gate.d.ts.map +1 -0
  439. package/dist/surface-gate.js +206 -0
  440. package/dist/surface-gate.js.map +1 -0
  441. package/dist/surface-persist.d.ts +86 -0
  442. package/dist/surface-persist.d.ts.map +1 -0
  443. package/dist/surface-persist.js +129 -0
  444. package/dist/surface-persist.js.map +1 -0
  445. package/dist/tasker-review-loop.d.ts +249 -0
  446. package/dist/tasker-review-loop.d.ts.map +1 -0
  447. package/dist/tasker-review-loop.js +369 -0
  448. package/dist/tasker-review-loop.js.map +1 -0
  449. package/dist/tasking-eligibility.d.ts +74 -0
  450. package/dist/tasking-eligibility.d.ts.map +1 -0
  451. package/dist/tasking-eligibility.js +52 -0
  452. package/dist/tasking-eligibility.js.map +1 -0
  453. package/dist/tasking-lock.d.ts +111 -0
  454. package/dist/tasking-lock.d.ts.map +1 -0
  455. package/dist/tasking-lock.js +256 -0
  456. package/dist/tasking-lock.js.map +1 -0
  457. package/dist/tasking.d.ts +275 -0
  458. package/dist/tasking.d.ts.map +1 -0
  459. package/dist/tasking.js +952 -0
  460. package/dist/tasking.js.map +1 -0
  461. package/dist/triage-gate.d.ts +127 -0
  462. package/dist/triage-gate.d.ts.map +1 -0
  463. package/dist/triage-gate.js +139 -0
  464. package/dist/triage-gate.js.map +1 -0
  465. package/dist/triage-persist.d.ts +163 -0
  466. package/dist/triage-persist.d.ts.map +1 -0
  467. package/dist/triage-persist.js +387 -0
  468. package/dist/triage-persist.js.map +1 -0
  469. package/dist/verdict-json.d.ts +32 -0
  470. package/dist/verdict-json.d.ts.map +1 -0
  471. package/dist/verdict-json.js +74 -0
  472. package/dist/verdict-json.js.map +1 -0
  473. package/dist/verify-workflow-template.d.ts +60 -0
  474. package/dist/verify-workflow-template.d.ts.map +1 -0
  475. package/dist/verify-workflow-template.js +126 -0
  476. package/dist/verify-workflow-template.js.map +1 -0
  477. package/dist/verify.d.ts +60 -0
  478. package/dist/verify.d.ts.map +1 -0
  479. package/dist/verify.js +62 -0
  480. package/dist/verify.js.map +1 -0
  481. package/dist/watch-session.d.ts +112 -0
  482. package/dist/watch-session.d.ts.map +1 -0
  483. package/dist/watch-session.js +347 -0
  484. package/dist/watch-session.js.map +1 -0
  485. package/dist/work-layout.d.ts +198 -0
  486. package/dist/work-layout.d.ts.map +1 -0
  487. package/dist/work-layout.js +217 -0
  488. package/dist/work-layout.js.map +1 -0
  489. package/dist/work-on.d.ts +154 -0
  490. package/dist/work-on.d.ts.map +1 -0
  491. package/dist/work-on.js +387 -0
  492. package/dist/work-on.js.map +1 -0
  493. package/dist/workspace.d.ts +224 -0
  494. package/dist/workspace.d.ts.map +1 -0
  495. package/dist/workspace.js +325 -0
  496. package/dist/workspace.js.map +1 -0
  497. package/package.json +46 -2
  498. package/src/advance-ci-template.ts +203 -0
  499. package/src/advance-classify.ts +197 -0
  500. package/src/advance-drivers.ts +414 -0
  501. package/src/advance-isolated.ts +432 -0
  502. package/src/advance-lifecycle-template.ts +791 -0
  503. package/src/advance-loop-driver.ts +745 -0
  504. package/src/advance-treeless-publish.ts +177 -0
  505. package/src/advance.ts +1564 -0
  506. package/src/advancing-lock.ts +988 -0
  507. package/src/agent-launch.ts +137 -0
  508. package/src/agent-stop.ts +361 -0
  509. package/src/apply-decide.ts +242 -0
  510. package/src/apply-merge-action.ts +502 -0
  511. package/src/apply-persist.ts +518 -0
  512. package/src/arbiter.ts +372 -0
  513. package/src/brand.ts +111 -0
  514. package/src/buildable-body.ts +196 -0
  515. package/src/categorise.ts +158 -0
  516. package/src/claim-cas.ts +513 -0
  517. package/src/cli-spinner.ts +225 -0
  518. package/src/cli.ts +4369 -0
  519. package/src/close-job-template.ts +236 -0
  520. package/src/close-job.ts +319 -0
  521. package/src/complete.ts +1379 -0
  522. package/src/concurrency.ts +151 -0
  523. package/src/config-override.ts +116 -0
  524. package/src/config.ts +883 -0
  525. package/src/continue-branch.ts +542 -0
  526. package/src/cwd-section.ts +392 -0
  527. package/src/decision-engine.ts +272 -0
  528. package/src/detect.ts +124 -0
  529. package/src/do-autopick.ts +223 -0
  530. package/src/do-config.ts +589 -0
  531. package/src/do-remote-auto.ts +197 -0
  532. package/src/do.ts +2623 -0
  533. package/src/drop-source.ts +194 -0
  534. package/src/eligibility.ts +79 -0
  535. package/src/env-config.ts +305 -0
  536. package/src/failure-cause.ts +142 -0
  537. package/src/format.ts +313 -0
  538. package/src/frontmatter.ts +485 -0
  539. package/src/gate-readiness.ts +147 -0
  540. package/src/gc.ts +510 -0
  541. package/src/gh-failure.ts +53 -0
  542. package/src/git.ts +186 -0
  543. package/src/github.ts +468 -0
  544. package/src/harness.ts +355 -0
  545. package/src/identity.ts +322 -0
  546. package/src/index.ts +785 -0
  547. package/src/install-ci-branch-protection.ts +255 -0
  548. package/src/install-ci-capabilities/advance-lifecycle.ts +34 -0
  549. package/src/install-ci-capabilities/close-job.ts +32 -0
  550. package/src/install-ci-capabilities/example-noop.ts +24 -0
  551. package/src/install-ci-capabilities/intake.ts +34 -0
  552. package/src/install-ci-capabilities/verify.ts +33 -0
  553. package/src/install-ci-core.ts +1088 -0
  554. package/src/install-ci-github.ts +376 -0
  555. package/src/install-ci.ts +552 -0
  556. package/src/intake-event.ts +102 -0
  557. package/src/intake-marker.ts +195 -0
  558. package/src/intake-triage.ts +138 -0
  559. package/src/intake-trigger-template.ts +591 -0
  560. package/src/intake.ts +2445 -0
  561. package/src/integration-core.ts +3065 -0
  562. package/src/integrator.ts +771 -0
  563. package/src/isolation.ts +484 -0
  564. package/src/issue-provider.ts +733 -0
  565. package/src/item-lock.ts +1858 -0
  566. package/src/item-path.ts +75 -0
  567. package/src/ledger-lint.ts +332 -0
  568. package/src/ledger-read.ts +924 -0
  569. package/src/ledger-write.ts +865 -0
  570. package/src/lifecycle-gather.ts +298 -0
  571. package/src/lifecycle-pools.ts +250 -0
  572. package/src/merge-question-surfacer.ts +496 -0
  573. package/src/mint-adr.ts +362 -0
  574. package/src/mirror-pool-scan.ts +240 -0
  575. package/src/needs-attention.ts +1506 -0
  576. package/src/orphan-sidecar.ts +150 -0
  577. package/src/output.ts +89 -0
  578. package/src/pi-harness.ts +403 -0
  579. package/src/placement.ts +131 -0
  580. package/src/prd-to-spec.ts +1023 -0
  581. package/src/prepare.ts +230 -0
  582. package/src/prompt.ts +760 -0
  583. package/src/readiness.ts +98 -0
  584. package/src/reap-branches.ts +278 -0
  585. package/src/recover-isolated.ts +276 -0
  586. package/src/registry.ts +475 -0
  587. package/src/repo-config.ts +550 -0
  588. package/src/repo-key.ts +74 -0
  589. package/src/repo-mirror.ts +367 -0
  590. package/src/retry-backoff.ts +130 -0
  591. package/src/review-gate.ts +389 -0
  592. package/src/review-verdict.ts +422 -0
  593. package/src/run.ts +1430 -0
  594. package/src/scan.ts +611 -0
  595. package/src/select-order.ts +143 -0
  596. package/src/select-priority.ts +266 -0
  597. package/src/select.ts +62 -0
  598. package/src/session-path.ts +153 -0
  599. package/src/sidecar-apply.ts +216 -0
  600. package/src/sidecar.ts +700 -0
  601. package/src/slug-namespace.ts +367 -0
  602. package/src/spec-complete.ts +118 -0
  603. package/src/start.ts +974 -0
  604. package/src/status.ts +441 -0
  605. package/src/surface-gate.ts +337 -0
  606. package/src/surface-persist.ts +241 -0
  607. package/src/tasker-review-loop.ts +671 -0
  608. package/src/tasking-eligibility.ts +114 -0
  609. package/src/tasking-lock.ts +416 -0
  610. package/src/tasking.ts +1438 -0
  611. package/src/triage-gate.ts +248 -0
  612. package/src/triage-persist.ts +570 -0
  613. package/src/verdict-json.ts +73 -0
  614. package/src/verify-workflow-template.ts +159 -0
  615. package/src/verify.ts +123 -0
  616. package/src/watch-session.ts +397 -0
  617. package/src/work-layout.ts +262 -0
  618. package/src/work-on.ts +660 -0
  619. package/src/workspace.ts +502 -0
@@ -0,0 +1,1122 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { workItemPath, workItemRel } from './work-layout.js';
4
+ import { resolveAdvanceArg, SlugResolutionError, } from './slug-namespace.js';
5
+ import { ledgerRead } from './ledger-read.js';
6
+ import { parseFrontmatter } from './frontmatter.js';
7
+ import { parseSidecar, sidecarPathFor, } from './sidecar.js';
8
+ import { classifyTick } from './advance-classify.js';
9
+ import { acquireAdvancingLock, releaseAdvancingLock, } from './advancing-lock.js';
10
+ import { performDo } from './do.js';
11
+ import { harnessSurfaceGate, toNewQuestions, } from './surface-gate.js';
12
+ import { harnessTriageGate } from './triage-gate.js';
13
+ import { autoDispositionObservation, promoteObservation, } from './triage-persist.js';
14
+ import { mintAdr } from './mint-adr.js';
15
+ import { LIFECYCLE_CAS_CONTENTION } from './advancing-lock.js';
16
+ import { decide, DisallowedOutcomeError, } from './decision-engine.js';
17
+ import { APPLY_ALLOWED_OUTCOMES, buildApplyDecisionInput, harnessApplyDecider, } from './apply-decide.js';
18
+ import { persistSurfacedQuestions, } from './surface-persist.js';
19
+ import { applyAnsweredQuestions, } from './apply-persist.js';
20
+ import { detectAnsweredMergeAction, performMergeAction, } from './apply-merge-action.js';
21
+ /**
22
+ * The **`advance` verb SKELETON** (prd `advance-loop`, task
23
+ * `advance-verb-resolver`, US #1/5/6/18). `advance` is the SIBLING top-level verb
24
+ * (NOT a `do` subcommand — `do` subcommands are REJECTED in the prd) that drives
25
+ * a `work/` item ONE lifecycle rung toward "ready/built", reusing the SAME shared
26
+ * `prefix:arg` resolver `do` uses (extended with the `obs:` namespace, see
27
+ * {@link resolveAdvanceArg}).
28
+ *
29
+ * This module delivers the **classify → lock → execute SKELETON** — the contract
30
+ * both drivers (the later one-shot/loop tasks) wrap:
31
+ *
32
+ * 1. **classify** — read-only, NO model, NO lock: read the item's two signals
33
+ * (`needsAnswers` + the sidecar's answered-state) and call the pure
34
+ * {@link classifyTick} to get the rung kind. A CAS loser will have spent ONLY
35
+ * this free classification.
36
+ * 2. **lock** — take the `advancing` CAS borrow ({@link acquireAdvancingLock})
37
+ * for the classified rung, keyed on the item's `<type>-<slug>` identity. The
38
+ * expensive (agent/model) phase is ALWAYS post-lock, so a loser backs off
39
+ * having done ~nothing (a TOCTOU between classify and CAS is harmless — only
40
+ * the free classification is wasted, and the loser never starts model work).
41
+ * 3. **execute** — WINNER ONLY: dispatch the classified rung to the
42
+ * {@link RungExecutor} seam, then release the borrow.
43
+ *
44
+ * The **rung BODIES** are now ALL filled (their own tasks): `surface`
45
+ * (`advance-rung-surface`), `apply` (`advance-rung-apply`), and
46
+ * `triage-observation` (`advance-rung-triage`) dispatch through the clearly-named
47
+ * executor SEAM ({@link RungExecutor}); the build/task rungs ORCHESTRATE
48
+ * `do`/`do prd:`. What this verb does NOT do (LATER tasks):
49
+ * - The two **DRIVERS** (one-shot sequential / loop) + `-n` + the gate-FAMILY
50
+ * WIRING that resolves `autoBuild`/`autoTask`/`observationTriage` and threads
51
+ * them into the build/task gate composition — task `advance-drivers-and-gates`.
52
+ * (This verb already RESPECTS `observationTriage` in the triage rung — the gate's
53
+ * resolution chain + the build/task gate composition is the drivers task.)
54
+ * - The bare `advance` (eligible-SET) form — it needs the pool scan / driver, so
55
+ * the verb here is a SINGLE named-item tick; the bare form errors clearly
56
+ * ("needs the driver task"). See the `## Decisions` block in the task.
57
+ *
58
+ * The build-task / task-spec rungs ORCHESTRATE the existing `do` / `do spec:`
59
+ * machinery ({@link performDo}) — `advance` is a driver layered ON TOP, NEVER a
60
+ * peer that duplicates the build/task path (ONE build path, ONE task path —
61
+ * US #6).
62
+ */
63
+ const DEFAULT_ARBITER = 'origin';
64
+ /**
65
+ * Map the resolver's namespace onto the sidecar type. The `spec` namespace maps
66
+ * to the `spec` sidecar type, so `advance spec:<slug>` resolves its
67
+ * signals/folders (`FOLDERS_FOR_TYPE['spec']`) and orchestrates `do spec:<slug>`.
68
+ */
69
+ function sidecarTypeFor(namespace) {
70
+ return namespace === 'observation'
71
+ ? 'observation'
72
+ : namespace === 'spec'
73
+ ? 'spec'
74
+ : 'task';
75
+ }
76
+ /**
77
+ * Read an item's two CLASSIFY signals off disk (read-only, NO model, NO lock):
78
+ * - `needsAnswers` from the item-body frontmatter (searching the lifecycle
79
+ * folders the type may rest in), and
80
+ * - the ACTIVE sidecar (`work/questions/<type>-<slug>.md`) parsed when present.
81
+ *
82
+ * Identity-keyed: the sidecar path derives PURELY from `<type>-<slug>` (it
83
+ * survives the item's `git mv`s with no lock-step move). Returns
84
+ * `needsAnswers:undefined` when no item file is found (the classifier treats it
85
+ * as "not gated", an ANALYSE rung) — the verb's job here is to wire the two
86
+ * signals, not to assert the item exists (that is the rung's concern).
87
+ */
88
+ export function readItemSignals(input) {
89
+ const { repoPath, type, slug, item } = input;
90
+ const needsAnswers = readNeedsAnswers(repoPath, type, slug);
91
+ const sidecarRel = sidecarPathFor(item);
92
+ const sidecarAbs = join(repoPath, sidecarRel);
93
+ let sidecar;
94
+ if (existsSync(sidecarAbs)) {
95
+ sidecar = parseSidecar(readFileSync(sidecarAbs, 'utf8'));
96
+ }
97
+ return { needsAnswers, sidecar };
98
+ }
99
+ /**
100
+ * The lifecycle folders each item type may rest in (frontmatter source). After
101
+ * the capstone cut-over (task
102
+ * `cutover-retire-slicing-advancing-markers-and-trim-folder-sets`) the transient
103
+ * `tasking/` folder is GONE — a prd rests in `prds/ready` (source) or
104
+ * `prds/tasked` (tasked); while it is being tasked the body STAYS in
105
+ * `prds/ready` (the lock no longer moves it), so `tasking/` is never a
106
+ * frontmatter source.
107
+ *
108
+ * STAGING IS INCLUDED (`tasks-backlog` / `prds-proposed`): with `surfaceStaging`
109
+ * on (the user-visible default) the lifecycle surface pool enumerates
110
+ * `needsAnswers` items resting in STAGING as `task:`/`prd:` legs
111
+ * (`lifecycle-gather.ts`). The rung CLASSIFIER's signal read MUST see those
112
+ * staged bodies, or `needsAnswers` reads back `undefined`, the classifier
113
+ * mis-routes the item to the BUILD rung, and claim dies with "not found on
114
+ * origin/main" (observation
115
+ * `advance-task-folder-set-omits-tasks-backlog-staged-surface-items-misroute-to-build`).
116
+ * This is the staging-inclusive set its sibling `apply-persist.ts`
117
+ * (`APPLY_LIFECYCLE_FOLDERS`) already uses — kept in step here. BUILD/claim
118
+ * eligibility is UNCHANGED (still pool-only; staging items stay non-claimable):
119
+ * only the rung-classifier's frontmatter-source folders widen.
120
+ */
121
+ const FOLDERS_FOR_TYPE = {
122
+ task: ['tasks-backlog', 'tasks-ready', 'in-progress', 'done'],
123
+ // `spec` rests in the parent-spec regime folders (a `spec:<slug>` legs
124
+ // frontmatter-source read resolves against these).
125
+ spec: ['specs-proposed', 'specs-ready', 'specs-tasked'],
126
+ observation: ['observations'],
127
+ };
128
+ /** Read `needsAnswers` off the FIRST `work/<folder>/<slug>.md` that exists. */
129
+ function readNeedsAnswers(repoPath, type, slug) {
130
+ for (const folder of FOLDERS_FOR_TYPE[type]) {
131
+ const abs = workItemPath(repoPath, folder, slug);
132
+ if (existsSync(abs)) {
133
+ return parseFrontmatter(readFileSync(abs, 'utf8')).needsAnswers;
134
+ }
135
+ }
136
+ return undefined;
137
+ }
138
+ /**
139
+ * The PRODUCTION rung executor: build/task rungs ORCHESTRATE the existing
140
+ * `do`/`do prd:` machinery ({@link performDo}); the `surface`/`apply`/
141
+ * `triage-observation` rung bodies are filled by their own tasks
142
+ * ({@link surfaceRung} / {@link applyRung} / {@link triageRung}). It NEVER
143
+ * re-implements the build/task path — it hands the resolved arg to `performDo`,
144
+ * which spans both namespaces (the task path is the `do prd:` rung the prd's
145
+ * 2026-06-09 UPDATE confirms routes through `performIntegration`).
146
+ */
147
+ export const defaultRungExecutor = {
148
+ async buildTask(input) {
149
+ return orchestrateDo(input);
150
+ },
151
+ async taskSpec(input) {
152
+ return orchestrateDo(input);
153
+ },
154
+ async triageObservation(input) {
155
+ return triageRung(input);
156
+ },
157
+ async surface(input) {
158
+ return surfaceRung(input);
159
+ },
160
+ async apply(input) {
161
+ return applyRung(input);
162
+ },
163
+ };
164
+ /**
165
+ * ORCHESTRATE `do`/`do spec:` for the build-task / task-spec rungs: hand the
166
+ * resolved namespaced identity to {@link performDo} (the ONE build path / ONE
167
+ * task path). `advance` is a driver ON TOP — it does NOT duplicate `do`. The
168
+ * `do` outcome is mapped back onto the tick's outcome surface.
169
+ */
170
+ async function orchestrateDo(input) {
171
+ const { item, context } = input;
172
+ const base = context.doOptions;
173
+ if (base === undefined) {
174
+ // The skeleton can classify + lock + DISPATCH without `do` options wired
175
+ // (the driver task threads them). Report it honestly rather than crash —
176
+ // the orchestration TARGET is `performDo`, named here, not re-implemented.
177
+ return {
178
+ exitCode: 1,
179
+ outcome: 'usage-error',
180
+ message: `advance would ORCHESTRATE \`do ${item}\` for this rung, but no \`do\` ` +
181
+ `options were threaded into the tick (the driver task wires them).`,
182
+ };
183
+ }
184
+ // The ORCHESTRATION TARGET is `performDo` by DEFAULT (in-place, the cwd checkout
185
+ // IS the isolation), or the injected {@link AdvanceContext.doDriver} — the
186
+ // registry-set advance driver threads a PER-MIRROR JOB-WORKTREE driver so the
187
+ // daemon/CI build runs isolated off the mirror's arbiter. Either way `advance`
188
+ // ORCHESTRATES `do` (the ONE build path / ONE task path) — it does NOT duplicate it.
189
+ const driver = context.doDriver ?? performDo;
190
+ const result = await driver({ ...base, arg: item });
191
+ return {
192
+ exitCode: result.exitCode,
193
+ outcome: result.exitCode === 0 ? 'advanced' : mapDoOutcome(result),
194
+ message: result.message,
195
+ };
196
+ }
197
+ /** Map a non-zero `do` result onto the tick's outcome vocabulary. */
198
+ function mapDoOutcome(result) {
199
+ switch (result.outcome) {
200
+ case 'lost':
201
+ return 'lost';
202
+ case 'contended':
203
+ return 'contended';
204
+ default:
205
+ return 'usage-error';
206
+ }
207
+ }
208
+ /**
209
+ * The SURFACE rung BODY (task `advance-rung-surface`, US #32/33): the FIRST rung
210
+ * filling the executor seam, establishing the spawn→emit→persist pattern the
211
+ * other rung bodies reuse. Under the `advancing` CAS lock (held by
212
+ * {@link performAdvance} BEFORE this runs — so the expensive spawn is POST-lock,
213
+ * winner-only), it:
214
+ *
215
+ * 1. spawns a FRESH-CONTEXT agent with `surface-questions` loaded (the
216
+ * {@link SurfaceGate} seam, mirroring the review gate's `review` spawn) and
217
+ * collects the EMITTED questions — the skill JUDGES, writes nothing; and
218
+ * 2. has the ENGINE ITSELF write/append them to the sidecar CAS-atomically AND
219
+ * set `needsAnswers:true` in the SAME commit
220
+ * ({@link persistSurfacedQuestions}) — the engine PERSISTS.
221
+ *
222
+ * Append-never-overwrite: a re-surface ADDS `qN+1` and flips a previously-all-
223
+ * answered sidecar back to not-all-answered (the persist owns that). An EMPTY
224
+ * emit (the skill's honest "no open judgement") writes nothing and reports it.
225
+ */
226
+ async function surfaceRung(input) {
227
+ const { item, context } = input;
228
+ const note = context.note ?? (() => { });
229
+ const cwd = context.cwd;
230
+ // Locate the item file (the only thing the persist needs beyond the questions:
231
+ // the file to set `needsAnswers:true` on). The sidecar path is identity-derived,
232
+ // not folder-derived, so only the ITEM file's folder must be found.
233
+ const itemPath = findItemPath(cwd, input.namespace, input.slug);
234
+ if (itemPath === undefined) {
235
+ return vanishedSkip({ rung: 'surface', item });
236
+ }
237
+ // 1. SPAWN the fresh-context `surface-questions` agent (the skill JUDGES). The
238
+ // expensive model work is POST-lock (the lock is held by `performAdvance`).
239
+ const gate = context.surfaceGate ?? harnessSurfaceGate();
240
+ let emit;
241
+ try {
242
+ emit = await gate({
243
+ item,
244
+ cwd,
245
+ surfaceModel: context.surfaceModel,
246
+ });
247
+ }
248
+ catch (err) {
249
+ const detail = err instanceof Error ? err.message : String(err);
250
+ return {
251
+ exitCode: 1,
252
+ outcome: 'usage-error',
253
+ message: `surface ${item}: the surface-questions agent produced no usable emit (${detail}).`,
254
+ };
255
+ }
256
+ // 2. The ENGINE persists (the skill wrote nothing): append-or-create the sidecar
257
+ // + set `needsAnswers:true` in ONE commit (CAS-atomic under the held lock).
258
+ const persist = context.surfacePersist ?? persistSurfacedQuestions;
259
+ const result = persist({
260
+ cwd,
261
+ item,
262
+ itemPath,
263
+ questions: toNewQuestions(emit),
264
+ note,
265
+ });
266
+ if (result.outcome === 'nothing') {
267
+ // LIMBO DETECTION (task `advance-surface-limbo-observation-loudly-instead-of-
268
+ // silent-no-op`): an untriaged observation with NO sidecar whose surfacer had
269
+ // nothing to ask is a TRAP — the human's triage answer may have been recorded
270
+ // in an in-BODY "Applied answers" block, but the engine reads triage-vs-
271
+ // settled only from the `triaged:` frontmatter marker (`ledger-read.ts`) and
272
+ // the promote path only from an answered `disposition: promote` SIDECAR
273
+ // (`triage-persist.ts`). Without either, the item is untriaged (re-enumerated
274
+ // every tick), un-surfaceable (nothing to ask), un-promotable (no sidecar) —
275
+ // a silent exit-0 no-op forever. Surface it LOUDLY instead.
276
+ const limbo = detectObservationLimbo(input);
277
+ if (limbo !== undefined) {
278
+ note(limbo);
279
+ return { exitCode: 1, outcome: 'usage-error', message: limbo };
280
+ }
281
+ return {
282
+ exitCode: 0,
283
+ outcome: 'no-op',
284
+ message: `surface ${item}: no open judgement — nothing surfaced.`,
285
+ };
286
+ }
287
+ return {
288
+ exitCode: 0,
289
+ outcome: 'advanced',
290
+ message: `surfaced ${result.entryCount} question(s) for ${item} → ${result.sidecarPath} ` +
291
+ `(needsAnswers:true, CAS-atomic).`,
292
+ };
293
+ }
294
+ /**
295
+ * Detect the OBSERVATION LIMBO shape (task `advance-surface-limbo-observation-
296
+ * loudly-instead-of-silent-no-op`): an observation whose triage answer was
297
+ * (mis-)authored in an in-body "Applied answers" block instead of the sidecar/
298
+ * frontmatter channels the engine reads. All four conditions must hold:
299
+ *
300
+ * 1. the item is an OBSERVATION;
301
+ * 2. its frontmatter has NO `triaged:` marker (untriaged per `ledger-read.ts`);
302
+ * 3. there is NO active question sidecar at `work/questions/observation-<slug>.md`;
303
+ * 4. the surfacer just returned empty (the caller — {@link surfaceRung} — only
304
+ * calls this on the persist's `nothing` branch).
305
+ *
306
+ * Returns the loud diagnostic to emit (naming BOTH valid channels), or `undefined`
307
+ * when the shape does not match (the surfacer's empty is then the normal calm no-op).
308
+ * The engine does NOT (and will not) honour in-body disposition prose — one channel
309
+ * (the sidecar + `triaged:` frontmatter) keeps the loop honest.
310
+ */
311
+ function detectObservationLimbo(input) {
312
+ if (input.namespace !== 'observation')
313
+ return undefined;
314
+ const { item, slug, context } = input;
315
+ const cwd = context.cwd;
316
+ const itemRel = findItemPath(cwd, input.namespace, slug);
317
+ if (itemRel === undefined)
318
+ return undefined;
319
+ const fm = parseFrontmatter(readFileSync(join(cwd, itemRel), 'utf8'));
320
+ if (fm.triaged !== undefined && fm.triaged !== '')
321
+ return undefined;
322
+ const sidecarRel = sidecarPathFor(item);
323
+ if (existsSync(join(cwd, sidecarRel)))
324
+ return undefined;
325
+ return (`observation \`${slug}\` is in a limbo: no \`triaged:\` frontmatter marker ` +
326
+ `AND no answered question sidecar at \`${sidecarRel}\`, but the surfacer has ` +
327
+ `nothing to ask. If a human triage decision (promote-slice / keep / duplicate) ` +
328
+ `has been recorded in the observation BODY, that channel is INVISIBLE to the ` +
329
+ `runner — author the sidecar, or set \`triaged:\` in frontmatter. The engine ` +
330
+ `does not (and will not) honour in-body disposition prose.`);
331
+ }
332
+ /**
333
+ * The observation TRIAGE rung BODY (task `advance-rung-triage`, US #16/17/23):
334
+ * the rung the classifier picks for an UNTRIAGED observation (`needsAnswers` not
335
+ * set, no sidecar). It is QUESTION-GATED BY DEFAULT: it surfaces a promote/keep/
336
+ * delete question and WAITS — so "is this worth building?" is NEVER decided
337
+ * autonomously. A CONSERVATIVE `observationTriage: 'auto'`-gated EXCEPTION (US #17,
338
+ * high bar) may auto-disposition ONLY the no-question cases:
339
+ *
340
+ * - **default (question-gated):** delegate to {@link surfaceRung} — spawn the
341
+ * `surface-questions` agent (it emits a PLAIN "what becomes of this signal?"
342
+ * question — NO disposition token any more, task
343
+ * `agentic-apply-retire-disposition-vocabulary`) and the ENGINE persists the
344
+ * sidecar + `needsAnswers`. When the human answers, the AGENTIC apply decision
345
+ * (not a stamped token) reads the answer + source and chooses what to DO.
346
+ * Surface stays ALWAYS allowed (US #23) — this path runs under `ask`/`off`
347
+ * (and `off` + an explicit `obs:` runs in this `ask`-mode).
348
+ * - **`auto` exception:** ONLY under `observationTriage: 'auto'`, ask the
349
+ * {@link TriageGate} whether the observation is a no-question case. If it emits
350
+ * `auto: true` (`duplicate` → DELETE the redundant note; `map` → unambiguous
351
+ * map onto an existing item), the engine auto-dispositions it WITHOUT a
352
+ * question ({@link autoDispositionObservation}). It NEVER auto-deletes a
353
+ * NON-duplicate (a `duplicate` discharges by deletion because it is a
354
+ * redundant copy of an already-captured signal — nothing is lost) and NEVER
355
+ * auto-promotes a judgement call (`auto: false` ⇒ fall back to the surface
356
+ * question). Promotion is ALWAYS a human answer (the apply path).
357
+ *
358
+ * Under the `advancing` CAS lock (held by {@link performAdvance} BEFORE this runs),
359
+ * so the expensive spawn is POST-lock, winner-only.
360
+ */
361
+ async function triageRung(input) {
362
+ const { item, context } = input;
363
+ const note = context.note ?? (() => { });
364
+ const cwd = context.cwd;
365
+ // The CONSERVATIVE auto-disposition EXCEPTION — ONLY under `observationTriage:
366
+ // 'auto'`. Under `'ask'`/`'off'`/unset (including `off` + an EXPLICIT obs:<slug>
367
+ // that bypassed the selection gate), EVERY untriaged observation surfaces the
368
+ // question (the always-allowed path), so "worth building?" is never decided
369
+ // autonomously — `off` + explicit runs in the conservative `ask`-mode.
370
+ if (context.observationTriage === 'auto') {
371
+ const itemPath = findItemPath(cwd, input.namespace, input.slug);
372
+ if (itemPath === undefined) {
373
+ return vanishedSkip({ rung: 'triage', item });
374
+ }
375
+ const gate = context.triageGate ?? harnessTriageGate();
376
+ let decision;
377
+ try {
378
+ decision = await gate({ item, cwd, triageModel: context.triageModel });
379
+ }
380
+ catch (err) {
381
+ // A gate failure is NOT a reason to auto-dispose — fall back to the SAFE
382
+ // question-gated path (surface the question), never the reverse.
383
+ const detail = err instanceof Error ? err.message : String(err);
384
+ note(`triage ${item}: the auto-triage gate produced no usable emit (${detail}); ` +
385
+ 'falling back to the question-gated surface path.');
386
+ decision = { auto: false };
387
+ }
388
+ if (decision.auto === true) {
389
+ // A no-question case (duplicate / map) — auto-disposition WITHOUT a
390
+ // question. BOTH discharge the redundant note BY DELETION (a duplicate is a
391
+ // redundant copy; a map is already covered by the item it maps onto). There
392
+ // is no resting `triaged:keep` state any more. NEVER auto-deletes a
393
+ // NON-redundant signal; NEVER auto-promotes.
394
+ const dispose = context.autoDisposition ?? autoDispositionObservation;
395
+ const result = dispose({
396
+ cwd,
397
+ item,
398
+ itemPath,
399
+ kind: decision.kind,
400
+ existing: decision.existing,
401
+ reason: decision.reason,
402
+ note,
403
+ });
404
+ return { exitCode: 0, outcome: 'advanced', message: result.message };
405
+ }
406
+ // `auto: false` ⇒ a judgement call. Fall through to the surface question.
407
+ }
408
+ // DEFAULT (question-gated): surface a PLAIN "what becomes of this signal?"
409
+ // question + WAIT. This REUSES the surface rung verbatim (the `surface-questions`
410
+ // skill emits the triage question — NO disposition token any more, task
411
+ // `agentic-apply-retire-disposition-vocabulary`); the AGENTIC apply decision
412
+ // reads the human's answer + source and decides what to DO when it is answered.
413
+ return surfaceRung(input);
414
+ }
415
+ /**
416
+ * The APPLY rung BODY (task `advance-rung-apply`; AGENTIC apply, task
417
+ * `agentic-apply-retire-disposition-vocabulary`): when the classifier says `apply`
418
+ * (ALL sidecar entries answered), apply the HUMAN's answers.
419
+ *
420
+ * For a fully-answered OBSERVATION (and no caller-supplied follow-up batch), the
421
+ * apply rung is now AGENT-DRIVEN: it runs the shared `decide(input, allowedOutcomes)`
422
+ * engine ({@link decide}) over `(the answered question(s) + the SOURCE item + its
423
+ * type/context)` via the injected {@link ApplyDecider}, allowing the set
424
+ * `{task | prd | adr | delete | ask}` (= `{mint-task | mint-prd | mint-adr |
425
+ * delete-source | ask-follow-up}`; `adr` is now WIRED by task
426
+ * `agentic-apply-mint-adr-route`, which added the {@link mintAdr} route). The
427
+ * verdict ROUTES:
428
+ * - `ask` → the EXISTING append/re-pause loop ({@link applyAnsweredQuestions}
429
+ * with the follow-up appended; `needsAnswers:true` stays, re-pause in one
430
+ * commit);
431
+ * - `adr` → {@link mintAdr} (mint a SELF-CONTAINED ADR into `docs/adr/` + `git
432
+ * rm` the source + sidecar in the SAME atomic commit; the SIBLING route for the
433
+ * off-board target);
434
+ * - `task` / `prd` → {@link promoteObservation} (mint a SELF-CONTAINED artifact +
435
+ * `git rm` the source + sidecar in the SAME atomic commit); the artifact type
436
+ * comes from the agent's VERDICT, NOT a human `promote-*` field;
437
+ * - `delete` → {@link applyAnsweredQuestions} discharge-by-deletion (`git rm`
438
+ * source + sidecar in one revertible commit, the reason in the commit message).
439
+ *
440
+ * For a TASK/PRD (answering its OWN open questions) or a caller-supplied follow-up
441
+ * batch, it delegates straight to {@link applyAnsweredQuestions} (resolve fully /
442
+ * re-pause) — the lifecycle path is untouched (a task/prd is dropped by its own
443
+ * lifecycle, not by a question answer).
444
+ *
445
+ * Under the `advancing` CAS lock (held by {@link performAdvance} BEFORE this runs
446
+ * — so the work is POST-lock, winner-only). ALWAYS allowed (no gate). NEVER
447
+ * invents an answer — it applies ONLY the human-authored `answer:` text; a
448
+ * subset-answered sidecar is not even classified `apply` (the classifier NO-OPs),
449
+ * asserted in the persist.
450
+ */
451
+ async function applyRung(input) {
452
+ const { item, context } = input;
453
+ const note = context.note ?? (() => { });
454
+ const cwd = context.cwd;
455
+ const itemPath = findItemPath(cwd, input.namespace, input.slug);
456
+ if (itemPath === undefined) {
457
+ return vanishedSkip({ rung: 'apply', item });
458
+ }
459
+ // RUNNER-ACTION KIND-CHECK (task `apply-rung-merge-disposition`, prd
460
+ // `land-time-reverify-and-parallel-merge-ceiling`): an answered `kind: merge`
461
+ // sidecar entry is a DETERMINISTIC land action, NOT a content decision. It
462
+ // dispatches HERE (a sibling of the agentic `decide()`), keyed off the
463
+ // question kind + the human's plain `merge | hold | drop` answer, BEFORE the
464
+ // agentic decider runs. The dispatcher invokes the EXISTING land primitive
465
+ // (`performIntegration` with `committedRecovery: true` + `freshWorktreeGate:
466
+ // true`) through the EXISTING per-job worktree seam (`workspace.ts`
467
+ // `createJob` off the hub mirror) — it does NOT re-implement rebase / verify
468
+ // / advance and does NOT improvise a worktree or clone.
469
+ const mergeRoute = await maybeRunMergeAction(input, itemPath);
470
+ if (mergeRoute !== undefined) {
471
+ return mergeRoute;
472
+ }
473
+ // AGENTIC APPLY for an answered OBSERVATION (the subsumed triage rung): run the
474
+ // shared decision engine over the answer(s) + source, route the verdict. A
475
+ // caller-supplied follow-up batch (`applyFollowups`) bypasses the decision and
476
+ // re-pauses directly (a test/driver hook). TASK/PRD items resolve in place
477
+ // (their own lifecycle), so they skip the decision and fall through to the
478
+ // persist below.
479
+ const runAgenticDecision = input.namespace === 'observation' &&
480
+ !(context.applyFollowups && context.applyFollowups.length > 0);
481
+ if (runAgenticDecision) {
482
+ return applyAgenticDecision(input, itemPath);
483
+ }
484
+ const apply = context.applyPersist ?? applyAnsweredQuestions;
485
+ try {
486
+ const result = apply({
487
+ cwd,
488
+ item,
489
+ itemPath,
490
+ appendQuestions: context.applyFollowups,
491
+ note,
492
+ });
493
+ // Map the apply persist's outcome to the rung's outcome. `vanished` is the
494
+ // F3a clean-exit case (item was gone between capture and write, e.g. a
495
+ // concurrent promote); benign skip, exitCode 0, distinct from `no-op`.
496
+ const mapped = result.outcome === 'repaused'
497
+ ? 'no-op'
498
+ : result.outcome === 'vanished'
499
+ ? 'vanished'
500
+ : 'advanced';
501
+ return {
502
+ exitCode: 0,
503
+ outcome: mapped,
504
+ message: result.message,
505
+ };
506
+ }
507
+ catch (err) {
508
+ const detail = err instanceof Error ? err.message : String(err);
509
+ return {
510
+ exitCode: 1,
511
+ outcome: 'usage-error',
512
+ message: `apply ${item}: ${detail}`,
513
+ };
514
+ }
515
+ }
516
+ /**
517
+ * Dispatch an answered MERGE-QUESTION (a sidecar entry stamped `kind: merge` by
518
+ * the merge-question surfacer) through the EXISTING land primitive
519
+ * (`performIntegration` with `committedRecovery: true` + `freshWorktreeGate:
520
+ * true`) via the EXISTING per-job worktree seam (`workspace.ts` `createJob`).
521
+ * The deterministic SIBLING of the agentic `decide()` content-decision (PRD
522
+ * `land-time-reverify-and-parallel-merge-ceiling`, task
523
+ * `apply-rung-merge-disposition`; Stories #15, #16): a merge-acceptance has no
524
+ * judgement content (the human's plain `merge | hold | drop` answer IS the
525
+ * decision; the apply-time re-verify on the rebased tip is the real correctness
526
+ * gate), so the apply rung KIND-CHECKS the sidecar BEFORE the agentic decider.
527
+ *
528
+ * Returns `undefined` when there is no answered `kind: merge` entry to dispatch
529
+ * (the apply rung then proceeds to the existing path — agentic for
530
+ * observations, normal `applyAnsweredQuestions` for task/prd content questions).
531
+ * Returns a {@link RungExecResult} when the dispatcher handled the rung:
532
+ *
533
+ * - `landed` / `already-integrated` ⇒ the kept commit landed on `main` (or
534
+ * was already there); the dispatcher FALLS THROUGH to the normal apply path
535
+ * so the answer is recorded in the item body + the sidecar is resolved.
536
+ * - `refused` ⇒ the LAND was refused (RED re-verify on the rebased tip,
537
+ * rebase conflict, or pre-checkout failure); `performIntegration` routed
538
+ * the item to needs-attention through its own shared seam, so `main` never
539
+ * received a failing tree. The apply rung SHORT-CIRCUITS — the sidecar is
540
+ * LEFT IN PLACE so the open answer stays surfaced for a human follow-up.
541
+ * - `restale` ⇒ `strictMergeApproval` was ON and the merge-base moved
542
+ * between the surfacer's question and this apply; the apply rung appends
543
+ * a follow-up question + re-pauses (the human re-confirms against the new
544
+ * base).
545
+ * - `hold` / `drop` ⇒ no land; fall through to the normal apply path so the
546
+ * answer is recorded in body. The branch stays unmerged; a future
547
+ * surfacer pass may re-emit a merge-question.
548
+ */
549
+ async function maybeRunMergeAction(input, itemPath) {
550
+ const { item, context } = input;
551
+ const cwd = context.cwd;
552
+ const note = context.note ?? (() => { });
553
+ const detected = detectAnsweredMergeAction(cwd, item);
554
+ if (detected === undefined)
555
+ return undefined;
556
+ const handler = context.mergeAction ?? performMergeAction;
557
+ // The dispatcher needs a `workspacesDir` to cut a per-job worktree (the
558
+ // `createJob` seam). When unset (a caller that has not threaded it) we
559
+ // REFUSE cleanly rather than guess: a land without isolation is not the
560
+ // shape this dispatcher promises.
561
+ const workspacesDir = context.workspacesDir;
562
+ if (workspacesDir === undefined && context.mergeAction === undefined) {
563
+ const message = `apply ${item}: answered merge-question detected (kind=merge, answer=` +
564
+ `${detected.verb}) but no \`workspacesDir\` is threaded into the apply ` +
565
+ `rung — the dispatcher needs one to cut the per-job worktree via ` +
566
+ `\`workspace.ts\` \`createJob\`. NOT landing; the answer stays surfaced.`;
567
+ note(message);
568
+ return { exitCode: 1, outcome: 'usage-error', message };
569
+ }
570
+ let result;
571
+ try {
572
+ result = await handler({
573
+ action: detected,
574
+ item,
575
+ slug: input.slug,
576
+ cwd,
577
+ arbiter: context.arbiter ?? DEFAULT_ARBITER,
578
+ arbiterUrl: context.arbiterUrl,
579
+ workspacesDir: workspacesDir ?? '',
580
+ prepare: context.prepare,
581
+ verify: context.verify,
582
+ strictMergeApproval: context.strictMergeApproval,
583
+ note,
584
+ });
585
+ }
586
+ catch (err) {
587
+ const detail = err instanceof Error ? err.message : String(err);
588
+ const message = `apply ${item}: answered merge-question dispatch raised (${detail}); NOT ` +
589
+ `landing; the answer stays surfaced.`;
590
+ note(message);
591
+ return { exitCode: 1, outcome: 'usage-error', message };
592
+ }
593
+ if (result.outcome === 'refused') {
594
+ // `main` never received a failing tree (performIntegration routed the
595
+ // bounce to needs-attention through its own shared seam). SHORT-CIRCUIT:
596
+ // leave the sidecar so the open answer stays surfaced — the apply rung
597
+ // MUST NOT also resolve it (the next surfacer / human will follow up).
598
+ note(result.message);
599
+ return { exitCode: 1, outcome: 'usage-error', message: result.message };
600
+ }
601
+ if (result.outcome === 'restale') {
602
+ // `strictMergeApproval` re-surface: append a follow-up question and
603
+ // re-pause. The previous answer stays recorded in the entry; the human
604
+ // re-confirms against the new merge-base in the appended question.
605
+ const apply = context.applyPersist ?? applyAnsweredQuestions;
606
+ try {
607
+ const applied = apply({
608
+ cwd,
609
+ item,
610
+ itemPath,
611
+ appendQuestions: [
612
+ {
613
+ question: `Merge-base for \`work/${input.slug}\` moved since your last ` +
614
+ `answer (strictMergeApproval is ON). Re-confirm: still land?`,
615
+ context: result.message,
616
+ default: 'merge | hold | drop',
617
+ kind: 'merge',
618
+ },
619
+ ],
620
+ note,
621
+ });
622
+ return {
623
+ exitCode: 0,
624
+ outcome: 'no-op',
625
+ message: applied.message,
626
+ };
627
+ }
628
+ catch (err) {
629
+ const detail = err instanceof Error ? err.message : String(err);
630
+ return {
631
+ exitCode: 1,
632
+ outcome: 'usage-error',
633
+ message: `apply ${item}: re-surfacing the merge-question failed (${detail}).`,
634
+ };
635
+ }
636
+ }
637
+ // landed | already-integrated | hold | drop: the dispatcher's action is
638
+ // done; FALL THROUGH to the normal apply path so the answer is recorded in
639
+ // the item body + the sidecar is resolved.
640
+ note(result.message);
641
+ const apply = context.applyPersist ?? applyAnsweredQuestions;
642
+ try {
643
+ const applied = apply({ cwd, item, itemPath, note });
644
+ const mapped = applied.outcome === 'repaused'
645
+ ? 'no-op'
646
+ : applied.outcome === 'vanished'
647
+ ? 'vanished'
648
+ : 'advanced';
649
+ return {
650
+ exitCode: 0,
651
+ outcome: mapped,
652
+ message: `${result.message} ${applied.message}`,
653
+ };
654
+ }
655
+ catch (err) {
656
+ const detail = err instanceof Error ? err.message : String(err);
657
+ return {
658
+ exitCode: 1,
659
+ outcome: 'usage-error',
660
+ message: `apply ${item}: ${detail}`,
661
+ };
662
+ }
663
+ }
664
+ /**
665
+ * The cross-tick-window BENIGN SKIP shared by all three rungs that need to
666
+ * resolve an item file (surface / triage / apply). The lifecycle pool enumerated
667
+ * the item at scan-time, but by the time this leg ran a sibling parallel leg had
668
+ * already triaged/settled/deleted it. At the ~33-way CI matrix scale this is a
669
+ * CALM, EXPECTED condition — making it an exit-1 "a human must reconcile" turned
670
+ * the matrix into a wall of red. It is now a `vanished` outcome (`exitCode: 0`,
671
+ * distinguishable from `no-op`) carrying a clear message naming the rung + item.
672
+ * (See task `observation-identity-is-its-filename-not-a-foreign-slug`.)
673
+ */
674
+ function vanishedSkip(input) {
675
+ return {
676
+ exitCode: 0,
677
+ outcome: 'vanished',
678
+ message: `advance classified the '${input.rung}' rung for ${input.item} but its ` +
679
+ `item file was gone from work/ by the time the leg ran (a sibling leg ` +
680
+ `likely triaged/settled/deleted it between enumerate and run) — benign ` +
681
+ `skip.`,
682
+ };
683
+ }
684
+ /**
685
+ * Find the item file `work/<folder>/<slug>.md` for a type, across the lifecycle
686
+ * folders it may rest in (the SAME folder set {@link readNeedsAnswers} searches).
687
+ * Returns the path RELATIVE to `cwd`, or `undefined` when no file exists.
688
+ */
689
+ function findItemPath(cwd, namespace, slug) {
690
+ const type = sidecarTypeFor(namespace);
691
+ for (const folder of FOLDERS_FOR_TYPE[type]) {
692
+ const rel = workItemRel(folder, `${slug}.md`);
693
+ if (existsSync(join(cwd, rel))) {
694
+ return rel;
695
+ }
696
+ }
697
+ return undefined;
698
+ }
699
+ /**
700
+ * The AGENTIC apply DECISION for a fully-answered OBSERVATION (task
701
+ * `agentic-apply-retire-disposition-vocabulary`): run the shared
702
+ * `decide(input, allowedOutcomes)` engine over the answer(s) + source, then ROUTE
703
+ * the verdict. The artifact-type selection (task vs prd) comes from the agent's
704
+ * VERDICT, NOT a human `promote-*` field (which is retired). Replaces the old
705
+ * `answeredPromoteArtifact` + disposition picker.
706
+ *
707
+ * - `ask` → append the follow-up question(s) + re-pause (the EXISTING loop, via
708
+ * {@link applyAnsweredQuestions}'s `appendQuestions`);
709
+ * - `task` / `prd` → {@link promoteObservation} (mint self-contained + delete
710
+ * source in the same atomic commit);
711
+ * - `adr` → {@link mintAdr} (mint a self-contained ADR into `docs/adr/` + delete
712
+ * source in the same atomic commit; the SIBLING route for the off-board target,
713
+ * task `agentic-apply-mint-adr-route`);
714
+ * - `delete` → {@link applyAnsweredQuestions}'s discharge-by-deletion (`git rm`
715
+ * source + sidecar in one revertible commit, the reason in the message).
716
+ *
717
+ * The allowed set is `{task | prd | adr | delete | ask}`; a verdict outside it is
718
+ * rejected by the engine's allowed-outcome guard ({@link DisallowedOutcomeError})
719
+ * and mapped onto a usage-error — never dispatched.
720
+ */
721
+ async function applyAgenticDecision(input, itemPath) {
722
+ const { item, context } = input;
723
+ const note = context.note ?? (() => { });
724
+ const cwd = context.cwd;
725
+ const decisionInput = buildApplyDecisionInput({
726
+ item,
727
+ type: sidecarTypeFor(input.namespace),
728
+ itemPath,
729
+ cwd,
730
+ model: context.applyModel,
731
+ });
732
+ if (decisionInput === undefined) {
733
+ // No sidecar / item to decide over (a sibling leg removed it between classify
734
+ // and run) — the same benign clean-exit the persist's vanished branch gives.
735
+ return vanishedSkip({ rung: 'apply', item });
736
+ }
737
+ const decider = context.applyDecide ?? harnessApplyDecider();
738
+ let verdict;
739
+ try {
740
+ verdict = await decide(decisionInput, decider, APPLY_ALLOWED_OUTCOMES);
741
+ }
742
+ catch (err) {
743
+ const detail = err instanceof Error ? err.message : String(err);
744
+ // A DisallowedOutcomeError (e.g. a stubbed `adr` verdict) and an agent-failed
745
+ // parse both degrade HONESTLY onto a usage-error — never a silent dispatch.
746
+ const label = err instanceof DisallowedOutcomeError
747
+ ? `apply ${item}: the decision verdict is not an allowed outcome (${detail})`
748
+ : `apply ${item}: the decision agent produced no usable verdict (${detail})`;
749
+ return { exitCode: 1, outcome: 'usage-error', message: label };
750
+ }
751
+ if (verdict.outcome === 'ask') {
752
+ // ask-follow-up → the EXISTING append/re-pause loop. One BATCH of follow-ups.
753
+ const apply = context.applyPersist ?? applyAnsweredQuestions;
754
+ const question = (verdict.question ?? '').trim();
755
+ if (question === '') {
756
+ return {
757
+ exitCode: 1,
758
+ outcome: 'usage-error',
759
+ message: `apply ${item}: the decision agent chose 'ask' but emitted no follow-up question.`,
760
+ };
761
+ }
762
+ try {
763
+ const result = apply({
764
+ cwd,
765
+ item,
766
+ itemPath,
767
+ appendQuestions: [{ question }],
768
+ note,
769
+ });
770
+ return {
771
+ exitCode: 0,
772
+ outcome: result.outcome === 'vanished' ? 'vanished' : 'no-op',
773
+ message: result.message,
774
+ };
775
+ }
776
+ catch (err) {
777
+ const detail = err instanceof Error ? err.message : String(err);
778
+ return {
779
+ exitCode: 1,
780
+ outcome: 'usage-error',
781
+ message: `apply ${item}: ${detail}`,
782
+ };
783
+ }
784
+ }
785
+ if (verdict.outcome === 'task' || verdict.outcome === 'spec') {
786
+ // mint-task / mint-spec → CAS-create a SELF-CONTAINED artifact + delete the
787
+ // source + sidecar in the SAME commit (delete-on-promote, preserved). The
788
+ // verdict's drafted body (when present) seeds the new item; else the writer
789
+ // builds a self-contained body FROM the observation (carrying the answers +
790
+ // open-question scoping). The artifact type is the agent's VERDICT.
791
+ const promote = context.promote ?? promoteObservation;
792
+ const draftedBody = verdict.outcome === 'task' ? verdict.taskBody : verdict.specBody;
793
+ const draftedSlug = verdict.outcome === 'task' ? verdict.taskSlug : verdict.specSlug;
794
+ try {
795
+ const result = await promote({
796
+ cwd,
797
+ item,
798
+ itemPath,
799
+ artifact: verdict.outcome,
800
+ newSlug: context.promoteSlug ?? draftedSlug,
801
+ ...(draftedBody !== undefined && draftedBody.trim() !== ''
802
+ ? { stubContent: draftedBody }
803
+ : {}),
804
+ arbiter: context.arbiter,
805
+ // Lifecycle FAN-OUT: widen the CAS contention budget + jitter the retries
806
+ // so N parallel promote legs desync (task
807
+ // `jitter-and-widen-cas-contention-retry-for-lifecycle-fanout`).
808
+ contention: LIFECYCLE_CAS_CONTENTION,
809
+ note,
810
+ });
811
+ return {
812
+ exitCode: result.exitCode,
813
+ outcome: result.outcome === 'promoted'
814
+ ? 'advanced'
815
+ : result.outcome === 'lost'
816
+ ? 'lost'
817
+ : result.outcome === 'contended'
818
+ ? 'contended'
819
+ : 'usage-error',
820
+ message: result.message,
821
+ };
822
+ }
823
+ catch (err) {
824
+ const detail = err instanceof Error ? err.message : String(err);
825
+ return {
826
+ exitCode: 1,
827
+ outcome: 'usage-error',
828
+ message: `apply ${item}: ${detail}`,
829
+ };
830
+ }
831
+ }
832
+ if (verdict.outcome === 'adr') {
833
+ // mint-adr → CAS-create a SELF-CONTAINED ADR into `docs/adr/` + delete the
834
+ // source + sidecar in the SAME commit (delete-on-promote, preserved via the
835
+ // shared create-CAS). An ADR lives OUTSIDE the work board, so this is the
836
+ // SIBLING route (NOT a `promoteObservation` artifact type). The verdict's
837
+ // drafted body (when present) seeds the ADR; else `mintAdr` builds a
838
+ // self-contained body FROM the observation + the answered question(s).
839
+ const mint = context.mintAdr ?? mintAdr;
840
+ const answers = decisionInput.sidecar.entries.map((e) => ({
841
+ question: e.question,
842
+ answer: e.answer,
843
+ }));
844
+ try {
845
+ const result = await mint({
846
+ cwd,
847
+ item,
848
+ itemPath,
849
+ adrSlug: context.promoteSlug ?? verdict.adrSlug,
850
+ ...(verdict.adrTitle !== undefined ? { adrTitle: verdict.adrTitle } : {}),
851
+ ...(verdict.adrBody !== undefined && verdict.adrBody.trim() !== ''
852
+ ? { adrBody: verdict.adrBody }
853
+ : {}),
854
+ answers,
855
+ arbiter: context.arbiter,
856
+ // Lifecycle FAN-OUT: widen the CAS contention budget + jitter the retries
857
+ // so N parallel mint-adr legs desync (task
858
+ // `jitter-and-widen-cas-contention-retry-for-lifecycle-fanout`).
859
+ contention: LIFECYCLE_CAS_CONTENTION,
860
+ note,
861
+ });
862
+ return {
863
+ exitCode: result.exitCode,
864
+ outcome: result.outcome === 'minted'
865
+ ? 'advanced'
866
+ : result.outcome === 'lost'
867
+ ? 'lost'
868
+ : result.outcome === 'contended'
869
+ ? 'contended'
870
+ : 'usage-error',
871
+ message: result.message,
872
+ };
873
+ }
874
+ catch (err) {
875
+ const detail = err instanceof Error ? err.message : String(err);
876
+ return {
877
+ exitCode: 1,
878
+ outcome: 'usage-error',
879
+ message: `apply ${item}: ${detail}`,
880
+ };
881
+ }
882
+ }
883
+ // delete-source → discharge by deletion (DIRECT, no confirm — decision 12). The
884
+ // human's answer is the source of truth; the deletion is a single revertible
885
+ // commit with the reason in the message.
886
+ const apply = context.applyPersist ?? applyAnsweredQuestions;
887
+ try {
888
+ const result = apply({
889
+ cwd,
890
+ item,
891
+ itemPath,
892
+ discharge: { reason: verdict.deleteReason ?? '' },
893
+ note,
894
+ });
895
+ return {
896
+ exitCode: 0,
897
+ outcome: result.outcome === 'vanished' ? 'vanished' : 'advanced',
898
+ message: result.message,
899
+ };
900
+ }
901
+ catch (err) {
902
+ const detail = err instanceof Error ? err.message : String(err);
903
+ return {
904
+ exitCode: 1,
905
+ outcome: 'usage-error',
906
+ message: `apply ${item}: ${detail}`,
907
+ };
908
+ }
909
+ }
910
+ /**
911
+ * Run ONE `advance` tick over a SINGLE named item: classify → lock → dispatch →
912
+ * release. The pure tick the drivers (later tasks) wrap. The expensive phase is
913
+ * ALWAYS post-lock — a CAS loser backs off having done ONLY the free
914
+ * classification (it never reaches the executor).
915
+ */
916
+ export async function performAdvance(options) {
917
+ const note = options.note ?? (() => { });
918
+ const cwd = options.cwd;
919
+ const repoPath = options.repoPath ?? cwd;
920
+ const arbiter = options.arbiter ?? DEFAULT_ARBITER;
921
+ // {@link performAdvance} is the SINGLE-item tick. The bare `advance`
922
+ // (eligible-SET) form is the DRIVER's job ({@link performAdvanceAuto} in
923
+ // `advance-drivers.ts`, which selects over the pool + runs THIS tick per item) —
924
+ // the tick itself REQUIRES a named item, so an empty arg here is a usage error
925
+ // (the CLI dispatches the bare form to the driver before reaching here).
926
+ if (options.arg === undefined || options.arg.trim() === '') {
927
+ const message = '`advance` with no item is the eligible-SET form (the one-shot driver). ' +
928
+ 'The single-item tick needs a named item: ' +
929
+ '`advance <slug>` / `advance prd:<slug>` / `advance obs:<slug>`.';
930
+ note(message);
931
+ return { exitCode: 1, outcome: 'usage-error', message };
932
+ }
933
+ // 1. RESOLVE the arg via the SHARED resolver (extended with `obs:`). `advance`
934
+ // spans task / prd / observation; a collision / bad arg is a loud usage error.
935
+ let resolved;
936
+ try {
937
+ resolved = resolveAdvanceArg({
938
+ arg: options.arg,
939
+ repoPath,
940
+ read: options.read ?? ledgerRead,
941
+ });
942
+ }
943
+ catch (err) {
944
+ if (err instanceof SlugResolutionError) {
945
+ return { exitCode: 1, outcome: 'usage-error', message: err.message };
946
+ }
947
+ const message = err instanceof Error ? err.message : String(err);
948
+ return { exitCode: 1, outcome: 'usage-error', message };
949
+ }
950
+ const type = sidecarTypeFor(resolved.namespace);
951
+ const item = `${resolved.namespace}:${resolved.slug}`;
952
+ // 2. CLASSIFY — read-only, NO model, NO lock. Read the two signals + run the
953
+ // pure classifier. This is the ONLY work a CAS loser will have spent.
954
+ const readSignals = options.readSignals ?? readItemSignals;
955
+ const signals = readSignals({ repoPath, type, slug: resolved.slug, item });
956
+ const classification = classifyTick({
957
+ type,
958
+ needsAnswers: signals.needsAnswers,
959
+ sidecar: signals.sidecar,
960
+ });
961
+ // A NO-OP (pending sidecar / nothing eligible) or an invariant violation never
962
+ // takes the lock — there is nothing to execute, so do NOT pay the CAS.
963
+ if (classification.kind === 'no-op') {
964
+ const message = `no-op for ${item} (${classification.reason ?? 'nothing to advance'}).`;
965
+ note(message);
966
+ return {
967
+ exitCode: 0,
968
+ outcome: 'no-op',
969
+ rung: 'no-op',
970
+ slug: resolved.slug,
971
+ message,
972
+ };
973
+ }
974
+ if (classification.kind === 'invariant-violation') {
975
+ const message = `refusing to advance ${item}: the \`needsAnswers\` flag and the sidecar ` +
976
+ `disagree (${classification.reason ?? 'invariant violation'}). ` +
977
+ `A human must reconcile them.`;
978
+ note(message);
979
+ return {
980
+ exitCode: 1,
981
+ outcome: 'invariant-violation',
982
+ rung: 'invariant-violation',
983
+ slug: resolved.slug,
984
+ message,
985
+ };
986
+ }
987
+ // 3. LOCK — take the `advancing` CAS borrow for the classified rung, keyed on
988
+ // the item's `<type>-<slug>` identity. The expensive phase is POST-lock.
989
+ //
990
+ // UNIFIED PER-ITEM LOCK, TREE-LESS RUNGS ONLY (prd
991
+ // `ledger-status-per-item-lock-refs` US #1/#3/#18; ADR
992
+ // `ledger-status-on-per-item-lock-refs`). The rung kind is KNOWN here
993
+ // (`classification.kind`, classified pre-lock), so the tree-less-only policy
994
+ // lives HERE — where the rung is known — and `advancing-lock.ts` stays
995
+ // rung-agnostic (it only learns "unified or not" via `acquireUnified`). For a
996
+ // TREE-LESS rung (`surface`/`apply`/`triage-observation`) the advancing acquire
997
+ // ALSO takes the item's unified lock (`action: advance`) — these rungs have NO
998
+ // inner `do`, so the unified hold is what realises advance∥claim / advance∥task
999
+ // exclusion. For a BUILD-TASK / TASK-PRD rung we do NOT take the unified lock
1000
+ // at the advance layer: `performAdvance` ORCHESTRATES an inner `performDo` that
1001
+ // ITSELF acquires the SAME `task-<slug>`/`prd-<slug>` ref (the create-only CAS
1002
+ // with NO re-entrancy/auto-steal, per the ADR), so taking it here too would
1003
+ // DEADLOCK the tick against itself. The inner `do`'s claim/task lock IS the
1004
+ // single exclusion point for those rungs. The `work/advancing/<entry>.md` marker
1005
+ // CAS is KEPT for ALL rungs (its removal is the capstone task #9).
1006
+ const unifiedForRung = isTreeLessRung(classification.kind);
1007
+ const acquire = options.acquireLock ??
1008
+ ((lockItem) => acquireAdvancingLock({
1009
+ item: lockItem,
1010
+ cwd,
1011
+ arbiter,
1012
+ acquireUnified: unifiedForRung,
1013
+ note,
1014
+ }));
1015
+ const lock = await acquire(item);
1016
+ if (lock.exitCode !== 0) {
1017
+ // A CAS LOSER (exit 2) or contended (exit 3) backs off having spent ONLY the
1018
+ // free classification above — it never reaches the executor.
1019
+ return {
1020
+ exitCode: lock.exitCode,
1021
+ outcome: lock.outcome === 'lost' ? 'lost' : 'contended',
1022
+ rung: classification.kind,
1023
+ slug: resolved.slug,
1024
+ message: lock.message,
1025
+ };
1026
+ }
1027
+ // 4. EXECUTE — WINNER ONLY: dispatch the classified rung to the executor seam,
1028
+ // then ALWAYS release the borrow (the item never moved; release is clean).
1029
+ const executor = options.executor ?? defaultRungExecutor;
1030
+ const release = options.releaseLock ??
1031
+ ((lockItem) => releaseAdvancingLock({
1032
+ item: lockItem,
1033
+ cwd,
1034
+ arbiter,
1035
+ releaseUnified: unifiedForRung,
1036
+ note,
1037
+ }));
1038
+ try {
1039
+ const exec = await dispatchRung(executor, {
1040
+ item,
1041
+ namespace: resolved.namespace,
1042
+ slug: resolved.slug,
1043
+ classification,
1044
+ context: {
1045
+ cwd,
1046
+ arbiter,
1047
+ doOptions: options.doOptions,
1048
+ doDriver: options.doDriver,
1049
+ surfaceGate: options.surfaceGate,
1050
+ surfaceModel: options.surfaceModel,
1051
+ surfacePersist: options.surfacePersist,
1052
+ applyPersist: options.applyPersist,
1053
+ applyFollowups: options.applyFollowups,
1054
+ applyDecide: options.applyDecide,
1055
+ applyModel: options.applyModel,
1056
+ observationTriage: options.observationTriage,
1057
+ triageGate: options.triageGate,
1058
+ triageModel: options.triageModel,
1059
+ autoDisposition: options.autoDisposition,
1060
+ promote: options.promote,
1061
+ mintAdr: options.mintAdr,
1062
+ promoteSlug: options.promoteSlug,
1063
+ // The answered-merge LAND dispatch context (task
1064
+ // `apply-rung-merge-disposition`): threaded into the apply rung's
1065
+ // kind-check for a `kind: merge` runner-action.
1066
+ workspacesDir: options.workspacesDir,
1067
+ arbiterUrl: options.arbiterUrl,
1068
+ prepare: options.prepare,
1069
+ verify: options.verify,
1070
+ strictMergeApproval: options.strictMergeApproval,
1071
+ mergeAction: options.mergeAction,
1072
+ note,
1073
+ },
1074
+ });
1075
+ return {
1076
+ exitCode: exec.exitCode,
1077
+ outcome: exec.outcome,
1078
+ rung: classification.kind,
1079
+ slug: resolved.slug,
1080
+ message: exec.message,
1081
+ };
1082
+ }
1083
+ finally {
1084
+ await release(item);
1085
+ }
1086
+ }
1087
+ /**
1088
+ * Is this a TREE-LESS rung (`surface`/`apply`/`triage-observation`) — the rungs
1089
+ * that have NO inner `performDo`, so the advancing acquire must ALSO take the
1090
+ * unified per-item lock (`action: advance`) to realise advance∥claim / advance∥task
1091
+ * exclusion? The build/task rungs (`build-task`/`task-spec`) are the inverse:
1092
+ * their inner `do` holds the SAME unified ref, so the advance layer must NOT take
1093
+ * it (it would deadlock the tick against itself). `no-op`/`invariant-violation`
1094
+ * never reach the lock step. This is the single place the tree-less-only policy
1095
+ * is expressed (the rung is known here); `advancing-lock.ts` stays rung-agnostic.
1096
+ */
1097
+ function isTreeLessRung(kind) {
1098
+ return (kind === 'surface' || kind === 'apply' || kind === 'triage-observation');
1099
+ }
1100
+ /** Dispatch the classified rung to the executor seam (winner-only). */
1101
+ function dispatchRung(executor, input) {
1102
+ switch (input.classification.kind) {
1103
+ case 'build-task':
1104
+ return executor.buildTask(input);
1105
+ case 'task-spec':
1106
+ return executor.taskSpec(input);
1107
+ case 'triage-observation':
1108
+ return executor.triageObservation(input);
1109
+ case 'surface':
1110
+ return executor.surface(input);
1111
+ case 'apply':
1112
+ return executor.apply(input);
1113
+ default:
1114
+ // `no-op` / `invariant-violation` never reach here (handled pre-lock).
1115
+ return Promise.resolve({
1116
+ exitCode: 1,
1117
+ outcome: 'usage-error',
1118
+ message: `unexpected rung kind '${input.classification.kind}' at dispatch.`,
1119
+ });
1120
+ }
1121
+ }
1122
+ //# sourceMappingURL=advance.js.map