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,952 @@
1
+ import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync, } from 'node:fs';
2
+ import { basename, dirname, join } from 'node:path';
3
+ import { parseFrontmatter } from './frontmatter.js';
4
+ import { runAsync } from './git.js';
5
+ import { workFolderRel, workFolderPath, workItemPath, workItemRel, isWorkItemFile, } from './work-layout.js';
6
+ import { performIntegration, } from './integration-core.js';
7
+ import { resolveTaskingEligibility, } from './tasking-eligibility.js';
8
+ import { acquireTaskingLock, releaseTaskingLock, } from './tasking-lock.js';
9
+ import { releaseItemLock } from './item-lock.js';
10
+ import { NullHarness } from './harness.js';
11
+ import { launchWithOptionalWatch } from './agent-launch.js';
12
+ import { placementFolder, resolvePlacement } from './placement.js';
13
+ import { setNeedsAnswersMarker, propagateOrigin } from './frontmatter.js';
14
+ import { workBranchRef } from './slug-namespace.js';
15
+ import { runTaskReviewLoop, } from './tasker-review-loop.js';
16
+ const DEFAULT_LOCK_SEAM = {
17
+ acquire: acquireTaskingLock,
18
+ release: releaseTaskingLock,
19
+ };
20
+ const DEFAULT_ARBITER = 'origin';
21
+ /**
22
+ * **The STAGED-TASKS dir** (prd `staging-pool-position-gate-and-trust-model`,
23
+ * task `pre-backlog-staging-folder-and-promote-step-a`, governing ADR
24
+ * `placement-is-runner-deterministic-humanonly-is-agent-judgement`). The runner
25
+ * lands the tasker's emitted task files HERE, NOT in `work/tasks/ready/`: an item
26
+ * born in `pre-backlog/` is durable + readable but NOT in the agent-eligible
27
+ * pool (`work/tasks/ready/` STILL means the pool — every reader is byte-for-byte
28
+ * unchanged). A runner/human-owned promotion (`promoteFromPreBacklog` in
29
+ * `needs-attention.ts`) moves an approved item `pre-backlog/ → backlog/` to make
30
+ * it claimable. STEP A: ADDITIVE — no `work/tasks/ready/` reader changes here.
31
+ */
32
+ export const STAGED_TASKS_DIR = workFolderRel('tasks-backlog');
33
+ /**
34
+ * The POOL folder tasks land in when the runner-deterministic placement
35
+ * resolver chooses the pool side (`tasksLandIn: 'ready'` and a trusted
36
+ * origin, or an `--tasks-land-in ready` operator override). The agent NEVER
37
+ * writes here — it always writes to {@link STAGED_TASKS_DIR}; the runner
38
+ * redirects the emitted files to the resolved destination at integrate-stage
39
+ * time. prd US #4 / the governing ADR: the agent cannot self-place into the
40
+ * pool. Task `runner-deterministic-slice-placement-policy-and-precedence`.
41
+ */
42
+ const POOL_TASKS_DIR = workFolderRel('tasks-ready');
43
+ /** The placement slots for the TASK lifecycle (folder names). */
44
+ const TASK_PLACEMENT_SLOTS = {
45
+ staging: STAGED_TASKS_DIR,
46
+ pool: POOL_TASKS_DIR,
47
+ };
48
+ /**
49
+ * Map the `tasksLandIn` value spelling (`pre-backlog` | `ready`) onto the
50
+ * resolver's lifecycle-generic side enum (`staging` | `pool`). Returns
51
+ * `undefined` when no value is set, so the resolver's next precedence rung
52
+ * applies (the built-in floor). The legacy `'backlog'`/`'todo'` pool spellings
53
+ * are NOT accepted (clean break — the value was renamed `'backlog'` → `'todo'`
54
+ * → `'ready'`, ADR `rename-task-pool-folder-todo-to-ready`).
55
+ */
56
+ function landingToSide(landing) {
57
+ if (landing === 'pre-backlog')
58
+ return 'staging';
59
+ if (landing === 'ready')
60
+ return 'pool';
61
+ return undefined;
62
+ }
63
+ /** The repo-relative path of a staged task's `.md` (per {@link STAGED_TASKS_DIR}). */
64
+ function stagedTaskPath(name) {
65
+ return `${STAGED_TASKS_DIR}/${name}`;
66
+ }
67
+ /**
68
+ * Run the `do prd:<slug>` tasking path end-to-end. Never throws for the expected
69
+ * gate-refused / lock-lost / agent-failed / stale cases — those are returned with
70
+ * the appropriate exit code and outcome. The runner owns all git; the agent only
71
+ * writes task files.
72
+ */
73
+ export async function performTask(options) {
74
+ const note = options.note ?? (() => { });
75
+ const arbiter = options.arbiter ?? DEFAULT_ARBITER;
76
+ const cwd = options.cwd;
77
+ // `env` is the runner's GIT/provider env (identity-scoped). `agentEnv` is the
78
+ // AMBIENT env for AGENT launches (tasker agent, review/improver agents) — an
79
+ // agent must not act as the bot. Falls back to `env` when no identity.
80
+ const env = options.env;
81
+ const agentEnv = options.agentEnv ?? options.env;
82
+ const slug = options.slug;
83
+ const doer = options.doer ?? 'agent';
84
+ const lock = options.lock ?? DEFAULT_LOCK_SEAM;
85
+ // 0. The prd must exist in the checkout (`work/prds/ready/<slug>.md`) — it is the
86
+ // source the agent tasks + the file the lock holds.
87
+ const specPath = workItemPath(cwd, 'specs-ready', slug);
88
+ if (!existsSync(specPath)) {
89
+ const message = `no prd '${slug}' found at ${workFolderRel('specs-ready')}/${slug}.md.`;
90
+ note(message);
91
+ return { exitCode: 1, outcome: 'usage-error', slug, message };
92
+ }
93
+ const specContent = readFileSync(specPath, 'utf8');
94
+ const specFm = parseFrontmatter(specContent);
95
+ // 1. RESOLVE THE GATE (agent path only). The human path is UNBOUND — a human
96
+ // decides for themselves whether a prd is taskable.
97
+ if (doer === 'agent') {
98
+ const eligibility = resolveAgentGate(cwd, slug, specFm, options.autoTask, options.explicit ?? false);
99
+ if (!eligibility.taskable) {
100
+ const message = gateRefusalReason(slug, specFm, eligibility, options);
101
+ note(message);
102
+ return { exitCode: 1, outcome: 'gate-refused', slug, message };
103
+ }
104
+ }
105
+ // 2. ACQUIRE THE LOCK (agent path; concurrency serialisation). The human path
106
+ // with no contention may task on `main` directly WITHOUT the lock.
107
+ let lockedBlob;
108
+ const useLock = doer === 'agent';
109
+ if (useLock) {
110
+ const acquired = await lock.acquire({ slug, cwd, arbiter, env, note });
111
+ if (acquired.outcome === 'lost') {
112
+ return {
113
+ exitCode: 2,
114
+ outcome: 'lock-lost',
115
+ slug,
116
+ message: acquired.message,
117
+ };
118
+ }
119
+ if (acquired.outcome === 'contended') {
120
+ return {
121
+ exitCode: 3,
122
+ outcome: 'lock-lost',
123
+ slug,
124
+ message: acquired.message,
125
+ };
126
+ }
127
+ if (acquired.exitCode !== 0) {
128
+ return {
129
+ exitCode: 1,
130
+ outcome: 'usage-error',
131
+ slug,
132
+ message: acquired.message,
133
+ };
134
+ }
135
+ lockedBlob = acquired.lockedBlob;
136
+ }
137
+ // 2b. ONBOARD the agent's tasking work onto a `work/<slug>` BRANCH cut from the
138
+ // freshly-fetched `<arbiter>/main` (task `slice-output-through-integration`).
139
+ // The prd body rests in `work/prds/ready/<slug>.md` on `<arbiter>/main` (the lock no
140
+ // longer moves it), so the branch's base HOLDS the held prd — the lifecycle
141
+ // stage below moves it `prd/ → prd-tasked/` ON THIS BRANCH and the shared integrate core (`--propose`
142
+ // PR / `--merge` main) lands the whole transition, WITHOUT the lock release
143
+ // committing tasks straight to `main`. The agent runs IN-PLACE on this branch
144
+ // (branch ≠ worktree; the isolation seam upgrades it). The HUMAN path stays on
145
+ // its own branch and commits its output itself (no integrate, no branch cut).
146
+ if (useLock) {
147
+ await switchToWorkBranch(cwd, arbiter, slug, env);
148
+ }
149
+ // 3. INVOKE THE AGENT with the to-task prd. It WRITES
150
+ // `work/tasks/backlog/*.md` task files (the STAGED area — NOT `work/tasks/ready/`,
151
+ // which is the agent-eligible pool the runner owns the promotion into; task
152
+ // `pre-backlog-staging-folder-and-promote-step-a`); it does NO git. We
153
+ // snapshot the staged-tasks folder before/after so the runner (not the
154
+ // agent) captures + commits exactly what was produced.
155
+ const before = snapshotStagedTasks(cwd);
156
+ // Also snapshot the POOL `work/tasks/ready/` BEFORE the agent runs: the runner's
157
+ // final commit must scrub any agent writes there (an attempt to self-place into
158
+ // the pool, prd US #4) before `git add -A` would sweep them in.
159
+ const poolBefore = snapshotPool(cwd);
160
+ // MIGRATE step (prd `prd-to-spec-vocabulary-cutover-and-migration-command`):
161
+ // read the parent-spec self-pointer off `prdFm.spec` (populated beside
162
+ // `prdFm.prd` by the expand task).
163
+ const prompt = buildTaskingSpec(slug, specFm.spec);
164
+ let agent;
165
+ try {
166
+ agent = await runTaskAgent(options, cwd, prompt, slug);
167
+ }
168
+ catch (err) {
169
+ agent = {
170
+ ok: false,
171
+ detail: err instanceof Error ? err.message : String(err),
172
+ };
173
+ }
174
+ if (!agent.ok) {
175
+ const detail = agent.detail ?? `the agent failed to task '${slug}'.`;
176
+ const message = `Agent failed tasking '${slug}' (${detail}).`;
177
+ note(message);
178
+ // The lock stays held (the runner did not release it): a stuck tasking is
179
+ // recoverable / re-runnable. Surfacing it is the review/edit loop's job.
180
+ return { exitCode: 1, outcome: 'agent-failed', slug, message };
181
+ }
182
+ // 3.5 THE TASKER REVIEW→EDIT→CONVERGE LOOP (`slicer-review-edit-loop`, Shape 2 /
183
+ // insertion point A): when a loop seam is wired, run the `review` SKILL as a
184
+ // review→edit→re-review loop that IMPROVES the candidate tasks in place, then
185
+ // determines the disposition (the three outcomes). This plugs in AFTER the
186
+ // candidate tasks are produced and BEFORE they are finalised. The agent makes
187
+ // the review/edit JUDGEMENTS; the loop applies edits to the candidate files
188
+ // and routes the verdict; the runner (below) owns the git transition. Only the
189
+ // AGENT path runs the loop — the human tasking path is unaffected.
190
+ let loopDisposition;
191
+ if (options.reviewLoop && doer === 'agent') {
192
+ loopDisposition = await runTaskReviewLoop({
193
+ slug,
194
+ cwd,
195
+ gate: options.reviewLoop,
196
+ // SCOPING FENCE (the requeue fix): the loop reviews/edits/flags ONLY the
197
+ // tasks THIS run produced (new-or-changed vs `before`), never the
198
+ // pre-existing staged tasks that share `work/tasks/backlog/`.
199
+ before,
200
+ taskerLoopMax: options.taskerLoopMax ?? 3,
201
+ executions: options.reviewExecutions,
202
+ taskerLoopModel: options.taskerLoopModel,
203
+ sessionsDir: options.sessionsDir,
204
+ // The improver loop's review AGENT launches AMBIENT, never the identity.
205
+ env: agentEnv,
206
+ note,
207
+ });
208
+ // DECOMPOSITION UNCLEAR: emit NO guessed tasks — route the held prd to
209
+ // needs-attention with the questions as the reason. The lock release amends the
210
+ // `prd:<slug>` unified lock `active → stuck` (the tasking needs-attention surface
211
+ // is the stuck lock now — NO folder write; the prd body stays in `work/prds/ready/`).
212
+ if (loopDisposition.outcome === 'decomposition-unclear') {
213
+ const reason = decompositionUnclearReason(slug, loopDisposition.specQuestions);
214
+ if (useLock) {
215
+ const routed = await lock.release({
216
+ slug,
217
+ cwd,
218
+ arbiter,
219
+ lockedBlob,
220
+ routeToNeedsAttention: { reason },
221
+ env,
222
+ note,
223
+ });
224
+ if (routed.outcome !== 'released') {
225
+ return releaseFailureToResult(routed, slug);
226
+ }
227
+ }
228
+ note(loopDisposition.message);
229
+ return {
230
+ exitCode: 1,
231
+ outcome: 'needs-attention',
232
+ slug,
233
+ message: loopDisposition.message,
234
+ };
235
+ }
236
+ // UNCERTAIN TASKS: mark each named candidate `needsAnswers: true` + record
237
+ // its questions in the body, so it lands but is not agent-buildable. The
238
+ // runner writes the marker (the agent does no git/disk-escape).
239
+ if (loopDisposition.outcome === 'uncertain-tasks') {
240
+ for (const uncertain of loopDisposition.uncertainTasks) {
241
+ markTaskNeedsAnswers(cwd, uncertain.path, uncertain.questions, note);
242
+ }
243
+ }
244
+ }
245
+ // 4. The RUNNER commits the COMPLETING transition: drop the produced backlog
246
+ // tasks IN + move the prd tasking/ -> prd-tasked/ (residence = tasked-ness) — now
247
+ // through the SHARED integrate core (`--propose` PR / `--merge` main), NOT a
248
+ // direct commit to `main`. The agent never does git. (The backlog snapshot is
249
+ // taken AFTER any loop edits, so the runner integrates the IMPROVED tasks,
250
+ // not the pre-loop candidates.)
251
+ const stagedEmitted = newOrChangedStagedTasks(cwd, before);
252
+ const emitTasks = collectEmittedTasks(cwd, stagedEmitted);
253
+ // RUNNER-DETERMINISTIC PLACEMENT (task
254
+ // `runner-deterministic-slice-placement-policy-and-precedence`). Resolve which
255
+ // folder the runner lands the emitted tasks in BEFORE handing them to the
256
+ // shared integrate band: precedence `explicit > untrusted-origin ⇒ staging >
257
+ // tasksLandIn > built-in (staging)`, all from unforgeable inputs (the prd's
258
+ // stamped `originTrust:` + the resolved per-repo default + the operator's
259
+ // explicit flag). The agent NEVER influences this; it always writes to
260
+ // `work/tasks/backlog/`, and the runner redirects at `stage()` time.
261
+ const placementDecision = resolvePlacement({
262
+ explicit: landingToSide(options.explicitTasksLandIn),
263
+ originTrust: specFm.originTrust,
264
+ configuredDefault: landingToSide(options.tasksLandIn),
265
+ });
266
+ const placementDir = placementFolder(TASK_PLACEMENT_SLOTS, placementDecision.choice);
267
+ // REWRITE the emitted list to the RUNNER-RESOLVED destination so callers see
268
+ // where the runner actually placed the files (not where the agent wrote them).
269
+ const emitted = stagedEmitted.map((rel) => `${placementDir}/${basename(rel)}`);
270
+ const loopTag = loopDisposition?.outcome === 'converged'
271
+ ? 'converged'
272
+ : loopDisposition?.outcome === 'uncertain-tasks'
273
+ ? 'uncertain-tasks'
274
+ : undefined;
275
+ if (useLock) {
276
+ // READ-STABILITY BACKSTOP (the lock's content-identity check, now owned at the
277
+ // integrate seam): the OUTPUT no longer rides the lock release, so the band
278
+ // below would otherwise rebase a concurrent edit of the held prd body CLEANLY
279
+ // into prd/ (a rename+edit merge) while the tasks were cut from the OLD body —
280
+ // the exact silent stale-task drift the lock forbids
281
+ // (`work/notes/observations/tasking-lock-does-not-stabilise-prd-content.md`). So we
282
+ // compare the CURRENTLY held `work/prds/ready/<slug>.md` blob on the arbiter against
283
+ // the snapshot the lock TOOK (`lockedBlob`); ANY change ⇒ STALE ⇒ fail loud,
284
+ // touch NOTHING (the lock stays held; a human re-tasks or routes to
285
+ // needs-attention). It is the SAME content-identity check `releaseTaskingLock`
286
+ // runs — relocated here because this transition, not the release, owns the
287
+ // completing commit now.
288
+ const stale = await heldSpecIsStale(cwd, arbiter, slug, lockedBlob, env);
289
+ if (stale) {
290
+ const specRel = workItemRel('specs-ready', `${slug}.md`);
291
+ const message = `RELEASE CONFLICT for '${slug}': the prd was edited (${specRel} ` +
292
+ `changed on ${arbiter}/main) while the tasking lock was held. The tasking is ` +
293
+ `STALE — re-task from the edited prd or route it to needs-attention. ` +
294
+ `The arbiter was NOT modified (lock still held).`;
295
+ note(message);
296
+ return { exitCode: 4, outcome: 'stale', slug, message };
297
+ }
298
+ // Route the OUTPUT through the SHARED integrate back-half (task
299
+ // `slice-output-through-integration`): the produced backlog tasks + the prd
300
+ // lifecycle move (`work/prds/ready/ -> work/prds/tasked/`, residence = tasked-ness) integrate
301
+ // via `performIntegration` honoring `--propose` (push the work branch + open a
302
+ // PR, NO `main` touch) / `--merge` (land on `main`). Because the integrate-time
303
+ // args resolve ONCE in the shared core, every `do task:` arg applies here by
304
+ // construction. The agent did NO git; the runner (the band) owns the ONE commit.
305
+ const core = await performIntegration({
306
+ cwd,
307
+ arbiter,
308
+ slug,
309
+ // `source`/`recovering` are task-shaped and IGNORED when `lifecycle` is set
310
+ // (a tasking transition never recovers a surfaced needs-attention move).
311
+ source: 'in-progress',
312
+ recovering: false,
313
+ // Skip the build acceptance gate (Gate 1 / verify): a tasking transition has
314
+ // no `verify` floor (the tasker review loop above is its quality gate).
315
+ skipVerify: true,
316
+ // THE TASK-SET ACCEPTANCE GATE (task `slice-acceptance-gate`): the
317
+ // task-path mirror of the build Gate-2, riding THIS shared core's
318
+ // review-before-integrate block. When `review` resolves on, the wired
319
+ // `reviewGate` (production: `harnessTaskReviewGate` with the task-SET
320
+ // prompt) runs a FRESH-CONTEXT review of the produced task SET before it
321
+ // integrates: `approve` lands it, `block` routes the set to needs-attention
322
+ // via the SAME machinery the build block uses (mapped to the tasking
323
+ // `needs-attention` outcome below). It is ONE-SHOT: we pin
324
+ // `reviewMaxRounds: 1` so the gate is a SINGLE reviewer invocation → verdict
325
+ // (terminal pass/fail). The task path NEVER exposes/consults
326
+ // `--review-max-rounds` — a gate is terminal, the rounds bound is an orphan
327
+ // that belongs to a future revise↔review loop (see
328
+ // `work/notes/observations/reviewmaxrounds-on-wrong-concept.md`). This is
329
+ // independently controllable from the tasker improver loop (`reviewLoop` /
330
+ // the `--tasker-loop*` family); toggling one does not affect the other.
331
+ review: options.review,
332
+ reviewGate: options.reviewGate,
333
+ reviewModel: options.acceptanceReviewModel,
334
+ reviewMaxRounds: 1,
335
+ // The EXPLICITLY-chosen integrate mode proceeds AS-IS on an APPROVE — a
336
+ // `--merge` tasking run lands on main, `--propose` opens a PR. The tasking
337
+ // path's merge-vs-propose decision is the `integration` mode the user typed;
338
+ // `merge` IS the auto-land mode, so a resolved `merge` is never downgraded.
339
+ // The task gate family is `--review`/`--no-review`/`--review-model` only
340
+ // (prd US #6).
341
+ mode: options.integration ?? 'propose',
342
+ noPR: options.noPR,
343
+ providerInstance: options.providerInstance,
344
+ type: 'tasking',
345
+ lifecycle: {
346
+ // Read the PR title / commit summary from the held prd (before it moves).
347
+ titlePath: workItemPath(cwd, 'specs-ready', slug),
348
+ commitTag: 'tasked',
349
+ stage: () => stageTaskingLifecycle({
350
+ cwd,
351
+ slug,
352
+ emitTasks,
353
+ poolBefore,
354
+ placementDir,
355
+ placementReason: placementDecision.reason,
356
+ note,
357
+ env,
358
+ }),
359
+ },
360
+ env,
361
+ // The task-SET acceptance review AGENT launches AMBIENT, never the
362
+ // identity-scoped `env` (an agent must not act as the bot).
363
+ agentEnv,
364
+ note,
365
+ });
366
+ // THE TASK-SET ACCEPTANCE GATE BLOCKED (task `slice-acceptance-gate`): the
367
+ // fresh-context review of the produced SET returned `block`, so the core ran
368
+ // the review BEFORE the stage/integrate and did NOT integrate the tasks
369
+ // (correct). The CORRECT task-path destination is the SAME needs-attention
370
+ // route the lock release owns for the decomposition-unclear verdict: it amends
371
+ // the `prd:<slug>` unified lock `active -> stuck` with the block reason (the
372
+ // tasking needs-attention surface is the stuck lock now — NO folder write; the
373
+ // prd body stays in `work/prds/ready/`). So on a block we route the held prd to
374
+ // needs-attention THROUGH the lock release — the set never lands.
375
+ if (core.outcome === 'review-blocked') {
376
+ const reason = taskGateBlockedReason(slug, core.reviewBlockReason);
377
+ const routed = await lock.release({
378
+ slug,
379
+ cwd,
380
+ arbiter,
381
+ lockedBlob,
382
+ routeToNeedsAttention: { reason },
383
+ env,
384
+ note,
385
+ });
386
+ if (routed.outcome !== 'released') {
387
+ return releaseFailureToResult(routed, slug);
388
+ }
389
+ note(reason);
390
+ return {
391
+ exitCode: 1,
392
+ outcome: 'needs-attention',
393
+ slug,
394
+ message: `The task acceptance gate blocked the set produced for '${slug}'; ` +
395
+ `marked the per-item lock stuck (needs attention; no tasks landed).`,
396
+ };
397
+ }
398
+ if (core.outcome === 'review-unparseable') {
399
+ // The task-set acceptance gate RAN but its verdict was UNPARSEABLE (malformed
400
+ // JSON). Route the held prd to needs-attention through the SAME lock-release
401
+ // seam the block path uses (the tasking needs-attention surface is the stuck
402
+ // `prd:<slug>` lock; no folder write). It is NOT a block (the gate output was
403
+ // unreadable) — record it as the transient-infra-class re-run signal so the
404
+ // stuck reason reads correctly; nothing landed.
405
+ const reason = `The task acceptance gate for '${slug}' produced an UNPARSEABLE verdict ` +
406
+ `(re-run — transient): ${core.reason ?? ''}`;
407
+ const routed = await lock.release({
408
+ slug,
409
+ cwd,
410
+ arbiter,
411
+ lockedBlob,
412
+ routeToNeedsAttention: { reason },
413
+ env,
414
+ note,
415
+ });
416
+ if (routed.outcome !== 'released') {
417
+ return releaseFailureToResult(routed, slug);
418
+ }
419
+ note(reason);
420
+ return {
421
+ exitCode: 1,
422
+ outcome: 'needs-attention',
423
+ slug,
424
+ message: `The task acceptance gate produced an unparseable verdict for '${slug}'; ` +
425
+ `marked the per-item lock stuck (needs attention; no tasks landed; re-run).`,
426
+ };
427
+ }
428
+ if (core.outcome === 'completed') {
429
+ // The durable `prd → prd-tasked` `main` move landed through the shared integrate
430
+ // core (the body moved straight from `work/prds/ready/` — no transient `tasking/`
431
+ // marker). The completing commit is owned by the integrate band, NOT
432
+ // `releaseTaskingLock`, so the unified per-item lock that `acquireTaskingLock`
433
+ // took is released HERE (delete the ref). A
434
+ // `propose` (`mode: 'propose'`) is ALSO `completed` (the PR opened, the lock's
435
+ // hold over the in-flight tasking is done); the eventual hold-across-the-PR
436
+ // crash-safe ordering is the capstone task #7's concern, not this interim
437
+ // half. Best-effort + idempotent (`not-held` is fine).
438
+ // MIGRATE step: release under the `spec:<slug>` identity (keyed to the
439
+ // `spec-<slug>` lock entry the acquire now takes). Idempotent.
440
+ if (useLock) {
441
+ await releaseItemLock({ item: `spec:${slug}`, cwd, arbiter, env });
442
+ }
443
+ }
444
+ return integrationToTaskResult(core, { slug, emitted, loop: loopTag });
445
+ }
446
+ // HUMAN, no-lock path: the human commits on `main` directly (the runner does
447
+ // not own the human's git). We report the produced tasks; moving the prd into
448
+ // `work/prds/tasked/` (residence = tasked-ness) and committing is the human's to
449
+ // do, as with the human `complete`.
450
+ const message = `Tasked '${slug}' -> ${emitted.length} backlog task` +
451
+ `${emitted.length === 1 ? '' : 's'} (human path, no lock). Inspect + commit ` +
452
+ `the produced files (and move the prd into work/prds/tasked/) yourself.`;
453
+ note(message);
454
+ return {
455
+ exitCode: 0,
456
+ outcome: 'tasked',
457
+ slug,
458
+ emitted,
459
+ loop: loopTag,
460
+ message,
461
+ };
462
+ }
463
+ /**
464
+ * Map a non-`released` lock-release result onto the {@link TaskResult} contract
465
+ * (the decomposition-unclear routing reuses the SAME release seam, so it can also
466
+ * be `stale`/`lost`/`contended`/usage-error). Mirrors the step-4 release mapping.
467
+ */
468
+ function releaseFailureToResult(released, slug) {
469
+ if (released.outcome === 'stale') {
470
+ return { exitCode: 4, outcome: 'stale', slug, message: released.message };
471
+ }
472
+ if (released.outcome === 'lost' || released.outcome === 'contended') {
473
+ const code = released.outcome === 'lost' ? 2 : 3;
474
+ return {
475
+ exitCode: code,
476
+ outcome: 'lock-lost',
477
+ slug,
478
+ message: released.message,
479
+ };
480
+ }
481
+ return { exitCode: 1, outcome: 'usage-error', slug, message: released.message };
482
+ }
483
+ /**
484
+ * Map the shared integrate band's {@link IntegrationCoreResult} onto the tasking
485
+ * {@link TaskResult} (task `slice-output-through-integration`). On `completed`
486
+ * (propose pushed the work branch + opened a PR / merge landed on `main`) the
487
+ * tasking is `tasked`. The band's FAILURE outcomes are reported on the tasking
488
+ * contract: a `rebase-conflict` against a concurrently-advanced `main` maps to
489
+ * `stale` (exit 4) — the tasking analogue of "the held prd moved under us"; a
490
+ * a `gate-failed` cannot occur (the tasking path passes `skipVerify`) but maps to
491
+ * a usage error defensively. A `review-blocked` (the task-SET ACCEPTANCE GATE
492
+ * blocked the set, task `slice-acceptance-gate`) is handled by `performTask`
493
+ * BEFORE this mapper — it routes the held prd to needs-attention via
494
+ * the lock release (the task-path needs-attention route) — so it never reaches
495
+ * here; it is mapped defensively to a usage error if it ever does.
496
+ */
497
+ function integrationToTaskResult(core, ctx) {
498
+ const { slug, emitted, loop } = ctx;
499
+ if (core.outcome === 'completed') {
500
+ const landed = core.integration?.mode === 'merge'
501
+ ? 'landed them on the arbiter main'
502
+ : 'opened a PR carrying them (main untouched)';
503
+ const message = `Tasked '${slug}' -> ${emitted.length} backlog task` +
504
+ `${emitted.length === 1 ? '' : 's'}; the runner integrated the transition ` +
505
+ `through the shared core (moved work/prds/ready/ -> work/prds/tasked/, the ` +
506
+ `tasked resting state) and ${landed}.`;
507
+ return { exitCode: 0, outcome: 'tasked', slug, emitted, loop, message };
508
+ }
509
+ if (core.outcome === 'rebase-conflict') {
510
+ return {
511
+ exitCode: 4,
512
+ outcome: 'stale',
513
+ slug,
514
+ message: core.reason ??
515
+ `Integrating the tasking of '${slug}' conflicted against the latest ` +
516
+ `${slug} main — the tasking is stale; re-task from the current prd.`,
517
+ };
518
+ }
519
+ return {
520
+ exitCode: 1,
521
+ outcome: 'usage-error',
522
+ slug,
523
+ message: core.reason ??
524
+ `Integrating the tasking of '${slug}' failed unexpectedly.`,
525
+ };
526
+ }
527
+ /**
528
+ * ONBOARD the tasking work onto a `work/<slug>` branch cut from the freshly-
529
+ * fetched `<arbiter>/main` (task `slice-output-through-integration`). Called
530
+ * AFTER the tasking lock is held, so the branch's base HOLDS the prd in
531
+ * `work/prds/ready/` (the lock no longer moves the body) — the lifecycle stage then moves
532
+ * it `prd/ -> prd-tasked/` ON THIS BRANCH and the shared integrate core lands it. A
533
+ * pre-existing local `work/<slug>` (a re-run) is force-recreated off fresh main.
534
+ * The agent runs in-place on this branch (branch ≠ worktree).
535
+ */
536
+ async function switchToWorkBranch(cwd, arbiter, slug, env) {
537
+ // The tasking path is the parent-spec namespace (`do spec:<slug>`): the branch
538
+ // is `work/spec-<slug>`, distinct from a same-slug task-build's `work/task-<slug>`.
539
+ // MIGRATE step (prd `prd-to-spec-vocabulary-cutover-and-migration-command`):
540
+ // MINT the work-branch under the `spec` namespace token (`workBranchRef` still
541
+ // parses the legacy `work/prd-<slug>` form, so in-flight branches keep resolving).
542
+ const branch = workBranchRef('spec', slug);
543
+ await gitHard(['fetch', '--quiet', arbiter], cwd, env);
544
+ await gitHard(['switch', '--quiet', '-C', branch, `${arbiter}/main`], cwd, env);
545
+ }
546
+ /**
547
+ * The READ-STABILITY content-identity STALE CHECK (the lock's backstop, owned at
548
+ * the integrate seam now that the OUTPUT no longer rides the lock release): true
549
+ * iff the CURRENTLY held `work/prds/ready/<slug>.md` blob on `<arbiter>/main` DIFFERS
550
+ * from the snapshot the lock TOOK (`lockedBlob`, read from `work/prds/ready/<slug>.md` at
551
+ * acquire). ANY change = a concurrent edit under the lock = the tasking is STALE.
552
+ * Stronger than a textual rebase conflict (which a rename+edit merge can apply
553
+ * CLEANLY). When `lockedBlob` is absent (never, in production) it reads as
554
+ * not-stale (the lock acquire always returns it).
555
+ */
556
+ async function heldSpecIsStale(cwd, arbiter, slug, lockedBlob, env) {
557
+ if (lockedBlob === undefined) {
558
+ return false;
559
+ }
560
+ await gitHard(['fetch', '--quiet', arbiter], cwd, env);
561
+ const held = await gitSoft(['rev-parse', `${arbiter}/main:${workFolderRel('specs-ready')}/${slug}.md`], cwd, env);
562
+ // The prd being absent (already tasked/moved) is NOT this check's concern
563
+ // (the integrate's rebase/push surfaces that); only a CHANGED held blob is stale.
564
+ if (held.status !== 0) {
565
+ return false;
566
+ }
567
+ return held.stdout.trim() !== lockedBlob;
568
+ }
569
+ /**
570
+ * STAGE the tasking lifecycle into the index on the `work/<slug>` branch (the
571
+ * {@link performIntegration} lifecycle seam): move the held prd
572
+ * `git mv work/prds/ready/<slug>.md -> work/prds/tasked/<slug>.md` (the TASKED resting
573
+ * state — the build-machine `done/` analogue, the SOURCE OF TRUTH for tasked-ness),
574
+ * and write+`git add` the produced `work/tasks/backlog/*.md` files. The band's subsequent
575
+ * `git add -A` + atomic commit folds this AND the agent's uncommitted backlog writes
576
+ * into ONE runner-owned commit (the agent never does git).
577
+ *
578
+ * TASK `prd-sliced-folder-step-a` (prd `slicing-coherence` US #8): the lifecycle
579
+ * destination is `work/prds/tasked/` (NOT back to `work/prds/ready/`) — `prd-tasked/`
580
+ * residence IS tasked-ness (like `done/` for tasks, with no `done:` marker). The
581
+ * `tasked:` frontmatter marker was removed entirely in `remove-sliced-marker-step-b`
582
+ * (sequenced last): residence in `work/prds/tasked/` is now the sole signal.
583
+ */
584
+ async function stageTaskingLifecycle(params) {
585
+ const { cwd, slug, emitTasks, poolBefore, placementDir, placementReason, note, env, } = params;
586
+ const spec = workItemRel('specs-ready', `${slug}.md`);
587
+ const specTasked = workItemRel('specs-tasked', `${slug}.md`);
588
+ // PROPAGATE the origin-trust PROVENANCE (task
589
+ // `untrusted-origin-forces-build-propose`): read the held prd's `origin`/
590
+ // `originTrust` stamp BEFORE the move, so each emitted task can carry it. A
591
+ // task's risk is its BUILD; the stamp must reach the task so the build
592
+ // transition can force `propose` for untrusted-origin work. An UNSTAMPED prd (a
593
+ // human/local-authored one ⇒ trusted) propagates nothing — the normal path is
594
+ // untouched.
595
+ const specAbs = join(cwd, spec);
596
+ const specProvenance = existsSync(specAbs)
597
+ ? parseFrontmatter(readFileSync(specAbs, 'utf8'))
598
+ : { origin: undefined, originTrust: undefined };
599
+ if (placementReason === 'untrusted-origin') {
600
+ note(`Untrusted-origin prd '${slug}': forcing the emitted tasks STAGED ` +
601
+ `(${placementDir}/) regardless of tasksLandIn (a human promotes ` +
602
+ 'them into work/tasks/ready/). Pass --tasks-land-in <where> to override.');
603
+ }
604
+ // Move the held prd prd/ -> prd-tasked/ (the TASKED resting state — folder =
605
+ // source of truth, like done/ for tasks). This is the DURABLE `prd → prd-tasked`
606
+ // success move, owned by THIS transition's commit (the lock no longer moved the
607
+ // body, so the source is `work/prds/ready/`, never `work/tasking/`).
608
+ mkdirSync(dirname(join(cwd, specTasked)), { recursive: true });
609
+ await gitHard(['mv', spec, specTasked], cwd, env);
610
+ await gitHard(['add', '--', specTasked], cwd, env);
611
+ // **POOL-PLACEMENT FENCE (prd US #4 / governing ADR
612
+ // `placement-is-runner-deterministic-humanonly-is-agent-judgement`).** The
613
+ // agent ALWAYS writes to the STAGING folder (`work/tasks/backlog/`); the POOL
614
+ // (`work/tasks/ready/`) is the agent-eligible pool the runner owns the promotion
615
+ // into. Anything the agent dropped under the pool would otherwise be swept in
616
+ // by `performIntegration`'s subsequent `git add -A` — a self-placement into
617
+ // the pool. Scrub it FIRST (before the runner writes its resolved destination
618
+ // files below), so when the runner-deterministic placement resolves to the
619
+ // pool the runner's writes are the ONLY legitimate pool entries in the commit.
620
+ await scrubPoolDrift(cwd, poolBefore, env);
621
+ // Drop the produced backlog tasks IN at the RUNNER-RESOLVED destination
622
+ // (write + stage; the band's `git add -A` also catches them, but staging here
623
+ // keeps the transition explicit + atomic). The runner STAMPS the propagated
624
+ // provenance onto each task as it writes it (the agent does no git; the runner
625
+ // owns the file write here). When the resolved destination DIFFERS from where
626
+ // the agent wrote (the staging folder), remove the agent's source file too —
627
+ // otherwise `git add -A` would commit BOTH (staging twin + pool destination).
628
+ for (const [agentRel, content] of Object.entries(emitTasks)) {
629
+ const filename = basename(agentRel);
630
+ const destRel = `${placementDir}/${filename}`;
631
+ const destAbs = join(cwd, destRel);
632
+ mkdirSync(dirname(destAbs), { recursive: true });
633
+ writeFileSync(destAbs, propagateOrigin(specProvenance, content));
634
+ await gitHard(['add', '--', destRel], cwd, env);
635
+ if (destRel !== agentRel) {
636
+ const srcAbs = join(cwd, agentRel);
637
+ rmSync(srcAbs, { force: true });
638
+ // Also unstage if `git add --` from a previous run picked it up;
639
+ // untracked-and-now-gone is fine.
640
+ await gitSoft(['rm', '-f', '--quiet', '--', agentRel], cwd, env);
641
+ }
642
+ }
643
+ }
644
+ /**
645
+ * Revert any change/addition the agent made to the POOL `work/tasks/ready/` during a
646
+ * tasking run. The agent's STAGING folder is `work/tasks/backlog/`; a write to the
647
+ * pool is an attempt to self-place into the agent-eligible pool the runner owns
648
+ * the promotion into (prd US #4 / governing ADR). Compared to the `poolBefore`
649
+ * snapshot (the branch-base state of `work/tasks/ready/`, taken BEFORE the agent
650
+ * ran), any new file is removed from the worktree and any changed file is
651
+ * checked back out to HEAD — so the subsequent `git add -A` cannot land it. The
652
+ * runner's commit then carries ONLY the explicit `pre-backlog/` placement.
653
+ */
654
+ async function scrubPoolDrift(cwd, poolBefore, env) {
655
+ const dir = workFolderPath(cwd, 'tasks-ready');
656
+ let entries;
657
+ try {
658
+ entries = readdirSync(dir);
659
+ }
660
+ catch {
661
+ return;
662
+ }
663
+ for (const name of entries) {
664
+ if (!isWorkItemFile(name)) {
665
+ continue;
666
+ }
667
+ const abs = join(dir, name);
668
+ const content = readFileSync(abs, 'utf8');
669
+ if (poolBefore.has(name)) {
670
+ if (poolBefore.get(name) === content) {
671
+ continue;
672
+ }
673
+ // The agent edited a pre-existing pool task — restore it from HEAD.
674
+ await gitSoft(['checkout', 'HEAD', '--', workItemRel('tasks-ready', name)], cwd, env);
675
+ continue;
676
+ }
677
+ // The agent introduced a NEW file in the pool: drop it.
678
+ rmSync(abs, { force: true });
679
+ }
680
+ }
681
+ /** Run git, returning the raw result (no throw) — for soft checks. */
682
+ function gitSoft(args, cwd, env) {
683
+ return runAsync('git', args, cwd, { env });
684
+ }
685
+ /** Run git; throw on non-zero (genuinely unexpected plumbing failures). */
686
+ async function gitHard(args, cwd, env) {
687
+ const result = await runAsync('git', args, cwd, { env });
688
+ if (result.status !== 0) {
689
+ throw new Error(`git ${args.join(' ')} failed (exit ${result.status}): ${result.stderr.trim()}`);
690
+ }
691
+ return result;
692
+ }
693
+ /**
694
+ * Build the needs-attention REASON for a task-SET ACCEPTANCE GATE block (task
695
+ * `slice-acceptance-gate`): the fresh-context review of the produced set returned
696
+ * `block`, so the prd is routed to `work/needs-attention/` with the review's
697
+ * blocking findings as the body prose and NO tasks landed. Takes the core's
698
+ * structured `reviewBlockReason` (the gate's blocking findings); falls back to a
699
+ * generic line when absent. DISTINCT from the improver loop's
700
+ * {@link decompositionUnclearReason} (which carries the loop's open questions).
701
+ */
702
+ function taskGateBlockedReason(slug, findingsReason) {
703
+ const head = `The task acceptance gate (fresh-context review of the produced SET) blocked ` +
704
+ `'${slug}'. The prd is routed to needs-attention with no tasks landed; a human ` +
705
+ `must resolve the blocking findings, then re-task.`;
706
+ return findingsReason ? `${head}\n\n${findingsReason}` : head;
707
+ }
708
+ /**
709
+ * Build the needs-attention REASON for a decomposition-unclear loop verdict (the
710
+ * prd is routed to `work/needs-attention/` with these open questions, no guessed
711
+ * tasks). Prose only — recorded as the prd's needs-attention body block.
712
+ */
713
+ function decompositionUnclearReason(slug, questions) {
714
+ const head = `The tasker review→edit loop could not converge on a sound decomposition of ` +
715
+ `'${slug}' (--tasker-loop-max exhausted with unresolved blockers). The prd is routed ` +
716
+ `to needs-attention with no guessed tasks; a human must resolve:`;
717
+ const body = questions.length > 0
718
+ ? questions.map((q) => `- ${q}`).join('\n')
719
+ : '- (no specific questions surfaced; the decomposition is broadly unclear)';
720
+ return `${head}\n${body}`;
721
+ }
722
+ /**
723
+ * Mark a candidate task file `needsAnswers: true` and record its open questions in
724
+ * its body (the loop's uncertain-task routing outcome). The runner writes the
725
+ * file; the agent does no git/disk-escape. A path outside `work/tasks/backlog/`
726
+ * is skipped (defensive). A relative `work/tasks/backlog/<slug>.md` that does not
727
+ * exist is skipped with a note (never crash the transition).
728
+ */
729
+ function markTaskNeedsAnswers(cwd, relPath, questions, note) {
730
+ const normalized = relPath.replace(/\\/g, '/');
731
+ if (!normalized.startsWith(`${STAGED_TASKS_DIR}/`) ||
732
+ normalized.includes('..')) {
733
+ note(`Skipped a needsAnswers mark outside ${STAGED_TASKS_DIR}/ (${relPath}).`);
734
+ return;
735
+ }
736
+ const abs = join(cwd, normalized);
737
+ if (!existsSync(abs)) {
738
+ note(`Skipped a needsAnswers mark for missing candidate task ${relPath}.`);
739
+ return;
740
+ }
741
+ const current = readFileSync(abs, 'utf8');
742
+ const marked = setNeedsAnswersMarker(current, true);
743
+ writeFileSync(abs, appendQuestionsBlock(marked, questions));
744
+ }
745
+ /** The heading that opens the open-questions block in an uncertain task body. */
746
+ const OPEN_QUESTIONS_HEADING = '## Open questions';
747
+ /**
748
+ * Append an `## Open questions` block (prose, never a frontmatter field —
749
+ * WORK-CONTRACT rule 3) listing the loop's surfaced questions to an uncertain
750
+ * task's body. A human answers these before the task becomes agent-buildable.
751
+ */
752
+ function appendQuestionsBlock(content, questions) {
753
+ if (questions.length === 0) {
754
+ return content;
755
+ }
756
+ const base = content.replace(/\s*$/, '');
757
+ const items = questions.map((q) => `- ${q}`).join('\n');
758
+ return [base, '', OPEN_QUESTIONS_HEADING, '', items, ''].join('\n');
759
+ }
760
+ /**
761
+ * Resolve the AGENT tasking gate for `slug`: the pure predicate
762
+ * (`needsAnswers !== true && humanOnly !== true && autoTask`) plus the
763
+ * cross-prd `taskedAfter` ordering, resolved against `work/prds/tasked/` residence of
764
+ * the prds present in the checkout.
765
+ */
766
+ function resolveAgentGate(cwd, slug, specFm, autoTask, explicit) {
767
+ return resolveTaskingEligibility({
768
+ humanOnly: specFm.humanOnly,
769
+ needsAnswers: specFm.needsAnswers,
770
+ taskedAfter: specFm.taskedAfter,
771
+ taskedSlugs: readTaskedSlugs(cwd),
772
+ autoTask: autoTask ?? false,
773
+ explicit,
774
+ });
775
+ }
776
+ /** Build an HONEST gate-refusal message naming WHY the agent skipped the prd. */
777
+ function gateRefusalReason(slug, specFm, eligibility, options) {
778
+ const reasons = [];
779
+ if (specFm.humanOnly === true) {
780
+ reasons.push('the prd is humanOnly (a human must drive its tasking)');
781
+ }
782
+ if (specFm.needsAnswers === true) {
783
+ reasons.push('the prd has needsAnswers (open questions block auto-tasking)');
784
+ }
785
+ // The autoTask POLICY only refuses on the NON-explicit (auto-pick pool) path:
786
+ // an explicitly-named `do prd:<slug>` is authorized by the naming itself (the
787
+ // build path's autoBuild precedent), so the policy is never the reason there.
788
+ if (options.explicit !== true &&
789
+ specFm.humanOnly !== true &&
790
+ specFm.needsAnswers !== true &&
791
+ (options.autoTask ?? false) !== true) {
792
+ reasons.push("the repo's autoTask policy is off");
793
+ }
794
+ if (!eligibility.taskedAfter.satisfied) {
795
+ reasons.push(`taskedAfter prd(s) not yet tasked: ${eligibility.taskedAfter.missing.join(', ')}`);
796
+ }
797
+ const why = reasons.length > 0 ? reasons.join('; ') : 'the tasking gate refused';
798
+ return `Skipped tasking '${slug}': ${why}.`;
799
+ }
800
+ /**
801
+ * Read the set of slugs whose prds are already TASKED in this checkout — RESIDENCE
802
+ * in `work/prds/tasked/` (the tasked resting state, task `prd-sliced-folder-step-a`
803
+ * / prd `slicing-coherence` US #9), the build-machine `done/` analogue. The FOLDER
804
+ * is the source of truth; the `tasked:` frontmatter marker was removed entirely in
805
+ * `remove-sliced-marker-step-b` and is NOT consulted. So `taskedAfter` resolves
806
+ * against `prd-tasked/` residence
807
+ * (mirroring `blockedBy` -> `done/`). A missing folder reads as empty. The slug is
808
+ * read from each file's frontmatter `slug:`, falling back to the filename — the same
809
+ * shape the task readers use.
810
+ */
811
+ function readTaskedSlugs(cwd) {
812
+ const slugs = new Set();
813
+ const dir = workFolderPath(cwd, 'specs-tasked');
814
+ for (const file of listMarkdown(dir)) {
815
+ const content = readFileSync(join(dir, file), 'utf8');
816
+ const fm = parseFrontmatter(content);
817
+ slugs.add(fm.slug ?? file.replace(/\.md$/i, ''));
818
+ }
819
+ return slugs;
820
+ }
821
+ /**
822
+ * Build the tasking PROMPT: instruct a fresh-context agent to apply the
823
+ * **tasking discipline** (`work/protocol/TASKING-PROTOCOL.md`) to the held
824
+ * prd at `work/prds/ready/<slug>.md` and to EMIT tracer-bullet vertical
825
+ * tasks under `work/tasks/backlog/`. The discipline body (the tracer-bullet
826
+ * rules, the two-axis gate guidance, the confidence check, file-orthogonality,
827
+ * the emitted task shape) lives in `TASKING-PROTOCOL.md` — NOT inlined here
828
+ * (task `slicing-protocol-doc-and-vocabulary-fix`). The shape's source of
829
+ * truth is the frontmatter parser + the task template (`work/protocol/
830
+ * task-template.md`); the doc DESCRIBES it (D2).
831
+ *
832
+ * This builder owns ONLY the PER-BUILDER framing: who you are (a fresh-context
833
+ * tasker for ONE prd), where the held prd is, where the emitted task files
834
+ * MUST land (the staging folder, never the pool), and the runner-owns-git
835
+ * boundary on the agent path. The shared discipline body is NOT duplicated
836
+ * here.
837
+ */
838
+ function buildTaskingSpec(slug, _spec) {
839
+ return [
840
+ `You are a FRESH-CONTEXT tasker for the prd \`work/prds/ready/${slug}.md\`.`,
841
+ `Apply the tasking discipline defined in \`work/protocol/TASKING-PROTOCOL.md\``,
842
+ `(the in-band, protocol-native tasking protocol every set-up repo carries; the`,
843
+ `human-facing pointer is \`skills/to-task/SKILL.md\`) to this ONE prd:`,
844
+ `decompose it into independently-grabbable, tracer-bullet vertical tasks.`,
845
+ `Read the prd fully first.`,
846
+ ``,
847
+ `The discipline rules — the tracer-bullet test, the two-axis gate guidance`,
848
+ `(\`humanOnly\` is NARROW; \`needsAnswers\` flags genuine uncertainty), the`,
849
+ `confidence check that REPLACES the human-quiz step when no human is present,`,
850
+ `the file-orthogonality preference, the prd-vs-task gate disjointness, and`,
851
+ `the emitted task shape — ALL live in that doc. Read them there.`,
852
+ ``,
853
+ `No human is present, so apply the CONFIDENCE CHECK (\`TASKING-PROTOCOL.md\``,
854
+ `step 4): only emit tasks you would have gotten a human to approve. If`,
855
+ `granularity, dependency order, a gate, or a seam is genuinely unresolved, set`,
856
+ `\`needsAnswers: true\` on the specific uncertain task (questions in its body)`,
857
+ `rather than guessing — or, if the whole decomposition is unclear, stop and`,
858
+ `route the prd to needs-attention with the questions.`,
859
+ ``,
860
+ `WRITE EVERY emitted task file under \`${STAGED_TASKS_DIR}/\` (the STAGING folder)`,
861
+ `— NEVER \`work/tasks/ready/\`. \`work/tasks/ready/\` is the agent-eligible POOL and`,
862
+ `the runner owns the runner/human-only promotion into it; the tasker's staging`,
863
+ `folder is \`work/tasks/backlog/\`. A write outside the staging folder is dropped`,
864
+ `by the runner-deterministic placement resolver.`,
865
+ ``,
866
+ `Set each task's \`prd:\` field to the source prd slug (\`${slug}\`) so the`,
867
+ `link back to the prd survives.`,
868
+ ``,
869
+ `Do NOT perform any git operations — do not stage, commit, push, or move any`,
870
+ `files. The RUNNER owns every git-state transition (it commits the produced`,
871
+ `tasks, releases the tasking lock, and moves the prd into \`work/prds/tasked/\`).`,
872
+ ].join('\n');
873
+ }
874
+ /** Run the task agent. Prefers the injected runner; else the harness seam. */
875
+ async function runTaskAgent(options, cwd, prompt, slug) {
876
+ // The tasker AGENT launches with the AMBIENT env (`agentEnv`), never the
877
+ // identity-scoped `env` (an agent must not act as the bot). Falls back to `env`
878
+ // when no identity is configured.
879
+ const agentEnv = options.agentEnv ?? options.env;
880
+ if (options.dorfl) {
881
+ return options.dorfl({ cwd, prompt, slug, env: agentEnv });
882
+ }
883
+ const harness = options.harness ?? new NullHarness();
884
+ const launched = await launchWithOptionalWatch({
885
+ harness,
886
+ dir: cwd,
887
+ slug,
888
+ command: options.agentCmd ?? '',
889
+ prompt,
890
+ model: options.model,
891
+ sessionId: `task-${slug}`,
892
+ sessionsDir: options.sessionsDir,
893
+ env: agentEnv,
894
+ });
895
+ return { ok: launched.ok, detail: launched.detail };
896
+ }
897
+ /** A snapshot of {@link STAGED_TASKS_DIR}: filename → file content. */
898
+ function snapshotStagedTasks(cwd) {
899
+ const dir = join(cwd, STAGED_TASKS_DIR);
900
+ const snap = new Map();
901
+ for (const file of listMarkdown(dir)) {
902
+ snap.set(file, readFileSync(join(dir, file), 'utf8'));
903
+ }
904
+ return snap;
905
+ }
906
+ /**
907
+ * Repo-relative paths of the {@link STAGED_TASKS_DIR}`/*.md` files the agent
908
+ * NEWLY created or CHANGED vs the pre-run snapshot — exactly what the runner
909
+ * captures + commits. (An untouched pre-existing staged task is NOT
910
+ * re-committed.) The agent's staging folder is `work/tasks/backlog/`; writes to
911
+ * the pool `work/tasks/ready/` are scrubbed at stage time, never picked up here.
912
+ */
913
+ function newOrChangedStagedTasks(cwd, before) {
914
+ const dir = join(cwd, STAGED_TASKS_DIR);
915
+ const changed = [];
916
+ for (const file of listMarkdown(dir)) {
917
+ const content = readFileSync(join(dir, file), 'utf8');
918
+ if (before.get(file) !== content) {
919
+ changed.push(stagedTaskPath(file));
920
+ }
921
+ }
922
+ return changed.sort();
923
+ }
924
+ /** Snapshot the POOL `work/tasks/ready/` (for the agent-write fence at stage time). */
925
+ function snapshotPool(cwd) {
926
+ const dir = workFolderPath(cwd, 'tasks-ready');
927
+ const snap = new Map();
928
+ for (const file of listMarkdown(dir)) {
929
+ snap.set(file, readFileSync(join(dir, file), 'utf8'));
930
+ }
931
+ return snap;
932
+ }
933
+ /** Read the produced backlog tasks' content keyed by repo-relative path. */
934
+ function collectEmittedTasks(cwd, relPaths) {
935
+ const out = {};
936
+ for (const rel of relPaths) {
937
+ out[rel] = readFileSync(join(cwd, rel), 'utf8');
938
+ }
939
+ return out;
940
+ }
941
+ /** List `*.md` files in `dir`, sorted; an absent dir reads as empty. */
942
+ function listMarkdown(dir) {
943
+ let entries;
944
+ try {
945
+ entries = readdirSync(dir);
946
+ }
947
+ catch {
948
+ return [];
949
+ }
950
+ return entries.filter((name) => isWorkItemFile(name)).sort();
951
+ }
952
+ //# sourceMappingURL=tasking.js.map