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,276 @@
1
+ # The `work/` on-disk contract
2
+
3
+ The shared contract between the task PRODUCER (the tasking discipline) and the task CONSUMER (the runner / lifecycle). It is designed to be **conflict-safe for parallel agents**: every rule below avoids merge conflicts and lost updates.
4
+
5
+ ## Location
6
+
7
+ `work/` lives **inside the target project repo**, versioned with that repo's code. Tasks reference that repo's code; work happens in clones/worktrees of that repo.
8
+
9
+ ## Layout — three REGIME umbrellas: notes/ (capture) + tasks/ (build) + prds/ (spec lifecycle), plus questions/ + protocol/
10
+
11
+ The top level groups every tree by its GOVERNANCE REGIME, so a reader can tell what a folder MEANS without reading further: `notes/` are capture buckets (they do not flow), `tasks/` is the build board (status = folder), `prds/` is the spec lifecycle (status = folder), and `questions/` + `protocol/` are standalone top-level surfaces.
12
+
13
+ ```
14
+ work/
15
+ # ---- notes/ — CAPTURE BUCKETS: NOT status-governed; they do NOT flow/move ----
16
+ notes/
17
+ ideas/<slug>.md # proposed, pre-spec ideas — EDITABLE, deletable
18
+ observations/<slug>.md # spotted, unverified signals — APPEND-ONLY, deletable
19
+ findings/<slug>.md # VERIFIED external/domain ground truth — durable
20
+
21
+ # ---- tasks/ — the BUILD board: DURABLE status IS the folder; FLOW via `git mv` on `main` ----
22
+ # Task lifecycle (staging → pool → terminal):
23
+ tasks/
24
+ backlog/<slug>.md # STAGING: a task not yet admitted to the agent pool —
25
+ # review-first admission AND the human-control position
26
+ # (untrusted output lands here; a human promotes, OR drives
27
+ # it IN PLACE via `do --allow-backlog` — never promote-then-drive)
28
+ ready/<slug>.md # the AGENT POOL: built tasks, grabbable items eligible to claim
29
+ done/<slug>.md # completed (moved here durably on `main` at integration)
30
+ cancelled/<slug>.md # the task regime's "won't-proceed" terminal (lightweight ADR);
31
+ # the REASON (out-of-scope / superseded by <x> / duplicate /
32
+ # abandoned) lives in the item body as `reason:`
33
+
34
+ # ---- prds/ — the SPEC lifecycle: DURABLE status IS the folder; FLOW via `git mv` on `main` ----
35
+ # Spec lifecycle (staging → pool → tasked / terminal):
36
+ prds/
37
+ proposed/<slug>.md # STAGING: a spec not yet admitted to the auto-task pool —
38
+ # review-first admission AND the human-control position
39
+ # (untrusted/agent-authored output lands here; a human promotes,
40
+ # OR tasks it IN PLACE — TASKING-PROTOCOL.md §6 — never promote-then-task)
41
+ ready/<slug>.md # the AUTO-TASK POOL: specs eligible to be tasked into tasks
42
+ tasked/<slug>.md # TASKED, resting specs — the spec `done/` analogue; the
43
+ # SOURCE OF TRUTH for tasked-ness (see note below)
44
+ dropped/<slug>.md # the spec regime's "won't-proceed" terminal (REASON in the body)
45
+
46
+ # ---- questions/ — the "what needs me?" queue, kept TOP-LEVEL (NOT under notes/) ----
47
+ questions/<slug>.md # surfaced blockers a human must look at — glance-able top-level
48
+
49
+ # ---- protocol/ — the protocol reference docs ----
50
+ protocol/ # WORK-CONTRACT.md, CLAIM-PROTOCOL.md, the templates, VERSION
51
+
52
+ # ---- TRANSIENT STATUS + LOCKS: NOT on `main` — on per-item lock refs ----
53
+ # `in-progress` (claimed/building), `needs-attention` (stuck), `tasking` (a spec
54
+ # being tasked), and `advancing` (a tick holding an item) are NOT `main` folders.
55
+ # They collapse into ONE per-item lock on a hidden
56
+ # `refs/dorfl/lock/<type>-<slug>` ref: a two-axis entry
57
+ # `action: implement|task|advance` × `state: active|stuck` (+ holder/since,
58
+ # reason iff stuck). `in-progress` = lock held active for implement;
59
+ # `needs-attention` = lock held stuck. A human reads in-flight state via
60
+ # `dorfl status`/`scan` (which read the lock refs), NOT by `ls`-ing a folder.
61
+ ```
62
+
63
+ > **The two won't-proceed terminals use DIFFERENT words ON PURPOSE — `tasks/cancelled/` vs `prds/dropped/` — and it is a CORRECTNESS rule, not taste.** A task and a spec can share a slug, and a single shared bare-slug terminal (`work/dropped/<slug>.md`) would COLLIDE a dropped task and a dropped spec on the same path. Namespacing each regime's terminal under its own umbrella (`tasks/cancelled/<slug>.md`, `prds/dropped/<slug>.md`) gives each its own slug space, so the collision cannot happen. A dropped OBSERVATION needs no terminal — notes leave by deletion. (Every reader keys by `(umbrella, slug)`, never a bare slug, so `tasks/ready/foo.md` and `prds/ready/foo.md` legitimately co-exist.)
64
+
65
+ ### Three governance regimes + the substrate split (the key distinctions)
66
+
67
+ - **Work items' DURABLE positions are the folder** (specs: `prds/proposed`/`prds/ready`/`prds/tasked`/`prds/dropped`; tasks: `tasks/backlog`/`tasks/ready`/`tasks/done`/`tasks/cancelled`): **status = the folder**, transitions are `git mv` on `main`, each has one destiny. This is the conflict-safe core for the durable resting records. The ONLY moves ever made on `main` are these durable resting transitions: `tasks/ready → tasks/done`, `prds/ready → prds/tasked`, `tasks/ready → tasks/cancelled` (and `prds/ready → prds/dropped`). The per-regime terminals (`tasks/cancelled/`, `prds/dropped/`) are where an item that will not proceed for ANY reason (superseded, out-of-scope, duplicate, abandoned/obsolete) rests, with the REASON in the body (`reason:` line). They are deliberately NAMED differently per regime — see the slug-collision note above.
68
+ - **Transient status + locks are NOT on `main`** — they are per-item lock refs. `in-progress`/`needs-attention`/`tasking`/`advancing` are lock-ref state, not folders. A work branch cut from `main` therefore inherits NO transient status, so a continue/rebase is a plain rebase with nothing to drop. Eligibility/dependency resolution stay OFFLINE on `main` (`blockedBy → tasks/done/`, `taskedAfter → prds/tasked/`); only the operational "what's in flight" view (`status`/`scan`) reads the lock refs.
69
+ - **Capture buckets** (`notes/ideas`/`notes/observations`/`notes/findings`) are **NOT work items** and are **exempt from status = folder** — they are _notes_, not units of work. They do not move through statuses; they sit in their bucket, and the folder is the inbox (`ls work/notes/observations/` = the live signal list). They leave only by **deletion** (git history is the archive). A note may _spawn_ work (a task, an idea, an ADR) created independently — the note does not "become" or `git mv` into that work; it is simply deleted once it is no longer a useful signal. **Operational discharge test for a promoted note:** a note is dischargeable (deletable) the moment a **self-contained** artifact carries its signal — verify the spawned task/ADR actually contains the mechanism + fix shape (not just a back-pointer), then delete the note. Do NOT keep it until the spawned work lands in `tasks/done/`: a note stops being a live _signal_ the moment it is captured into actionable work, not when that work completes. If the spawned artifact is NOT self-contained, the bug is the artifact (fix it to carry the signal), not a reason to keep the note.
70
+ - **Deletion-on-apply is the SANCTIONED discharge — it is human-AUTHORED, so the capture-bucket rule below — a note "leaves the inbox **by deletion** the moment it stops being a live signal", a judgement only a human is authorised to make — does NOT bar it.** When the `advance` apply rung acts on a note whose question the human has ANSWERED, a decision agent reads that answer + the source note and emits a VERDICT, and the discharge DELETES the note in the SAME commit: a mint verdict (a new task / spec / ADR) rides the note's `git rm` in the same atomic commit as the new artifact's create; a delete-source verdict (the answer means "throw it away") is a standalone, revertible delete commit with the reason in the commit message. The cheap throw-away has a DIRECT path too — the human, the `answer-questions` skill, or the `dorfl` delete verb removes the source + its sidecar straight, no engine round-trip. Either way this is the human's ANSWER being EXECUTED, not the agent unilaterally destroying a live signal — that capture-bucket rule (the agent never deletes a live signal on its own judgement) only ever barred deleting an **un-answered** note; the human's answer IS the authorisation to delete. There is therefore **no `triaged:` / `needsAnswers:false` resting state** for a discharged note and **no `## Recommended: delete` recommend-and-retain hand-off** — a discharged note leaves the inbox, it does not rest there stamped "resolved". (Work ITEMS still leave via a terminal FOLDER, never by deletion; only notes discharge by deletion.)
71
+
72
+ > **Every capture-bucket note and every work item has a DIRECTION and a LIVENESS — never manufacture a backward artifact to look compliant.** Forward artifacts — a `tasks/ready/` task, an _open_ `notes/observations/` signal — describe work that is **pending or currently-signalled**, never the past. So: work that is **already done** does NOT get a task or observation back-filled to narrate it (a `tasks/ready/` task with pre-ticked acceptance criteria is a changelog wearing a spec's shape); completed work is recorded as a `tasks/done/` record landed _with_ the code plus the commit message, owned by whoever does the git transition. And a captured note is LIVE: it leaves the inbox **by deletion** the moment it stops being a live signal — a note annotated "resolved" and kept is a contradiction (there is no `resolved` status; discharge it by deleting it, its lasting product being the task/ADR/commit it spawned). This binds an agent invoked **outside** the runner too: building directly is fine when asked, but do not retroactively mint forward artifacts for it afterward.
73
+
74
+ ### The three capture buckets (different by polarity + mutability)
75
+
76
+ | Bucket | What | Mutability | Leaves by |
77
+ | --- | --- | --- | --- |
78
+ | `notes/ideas/` | a _proposed_, pre-spec opportunity ("we might want to build this") | **editable** (refine the proposal in place) | deletion (when built/abandoned) |
79
+ | `notes/observations/` | an _observed, unverified_ signal ("I noticed something maybe wrong") | **append-only** (add `## Update` notes; don't rewrite what was seen) | deletion (when no longer a useful signal) |
80
+ | `notes/findings/` | _verified external/domain_ ground truth (a reverse-engineered protocol, an external API's real behaviour) | accumulates; durable | rarely — it is reference knowledge |
81
+
82
+ > **`findings/` is for EXTERNAL/DOMAIN ground truth, NOT internal post-mortems.** A finding is durable knowledge about a _world the software integrates with_ (e.g. a Bluetooth/hardware protocol we reverse-engineered, a third-party API's undocumented behaviour) — it accumulates, it does not "resolve". An _internal_ investigation (why a test flakes, a perf regression) is NOT a finding: it is a transient `notes/observations/` signal that drives a fix task and/or an ADR. **ADRs — the durable _why_ of OUR technical decisions — live in `docs/adr/`** (format: `ADR-FORMAT.md`, alongside this contract), never in `work/notes/findings/`. So: observation = "spotted, unverified"; finding = "verified external ground truth"; ADR = "what WE decided and why".
83
+ >
84
+ > **Every finding MUST carry a `source:` (provenance) — how, and how _currently_, the finding came to be believed.** A finding is only as true as the source it was derived from, so the source is what makes it _correctable_: if the source is later shown wrong (or stale), the finding can be revised and you can trace _why_ it was believed. There is deliberately **no separate `confidence:` field** — a bare confidence label is redundant at best and misleading at worst ("doc-verified" sounds authoritative until you learn the doc was last touched ten years ago). The honest signal lives IN a rich `source:` string: state _what_ the source is AND _how current_ it is, specifically enough that a reader can judge its weight themselves. Examples (weakest → strongest, by their own description):
85
+ >
86
+ > - `"derived from reading src/<the-integrating-module> @ <commit>"` — weakest: it assumes our code is correct, so the finding inherits any bug in it. (A code-derived finding describes the _external behaviour our code assumes_, NOT our code's internal shape — that is `CONTEXT.md`/`docs/`.)
87
+ > - `"<external API/spec> docs, retrieved 2026-06-09"` — a dated external authority (the date is what stops it silently going stale).
88
+ > - `"captured live API response 2026-06-09, trace in <path>"` — strongest.
89
+ > - `"told by maintainer @<name>, 2026-06"` / `"inferred from the test asserting it at <path>"` — whatever it actually was; write it plainly.
90
+ >
91
+ > Put `source:` in the finding's frontmatter (see below) and, when the provenance is non-obvious, expand on it in the body. A finding without a source is a `notes/observations/` signal, not a finding.
92
+
93
+ **For work items, DURABLE status is the folder a file lives in — never a frontmatter field.** Finishing / dropping / tasking-complete = moving the file between durable folders with `git mv` on `main`. This is what makes concurrent durable updates safe: two agents moving _different_ files never conflict. (Transient status — claimed/stuck/being-tasked — is NOT a folder move; it is a per-item lock ref, see above. Capture buckets are exempt too.)
94
+
95
+ ### The spec lifecycle: `prds/ready/` (pool) → `prds/tasked/` on `main`; the tasking HOLD is a lock ref
96
+
97
+ A spec rests in `work/prds/ready/` (the auto-task pool) and, when tasked into tasks, moves durably to `work/prds/tasked/` on `main`. The **folder is the source of truth for tasked-ness**, exactly as `work/tasks/done/` is for tasks. Re-tasking a reshaped spec is `work/prds/tasked/ → work/prds/ready/` (reopen-to-ready, mirroring `tasks/done/ → tasks/ready/`).
98
+
99
+ **The tasking HOLD is a per-item lock, NOT a `work/tasking/` folder.** Tasking a spec acquires the unified per-item lock with `action: task` on `refs/dorfl/lock/prd-<slug>` — a create-only ref push that is self-arbitrating (winner creates it; a concurrent tasker loses the same CAS definitively, no retry budget), so a spec is never double-tasked. The spec body STAYS in `work/prds/ready/` while held (it does not move to a `tasking/` folder). On a **successful tasking** the release performs the durable `work/prds/ready/ → work/prds/tasked/` move on `main` in the SAME runner-owned commit that emits the `tasks/` items, then releases the lock. On an **aborted / unclear** tasking the lock is released with no `main` move (the spec already rests in `prds/ready/`), or the lock is marked `stuck` for a human.
100
+
101
+ - **Tasked-ness is RESIDENCE in `work/prds/tasked/` — the FOLDER, the SOLE signal.** There is no `tasked:` frontmatter marker; the folder is canonical. A spec whose lock is held `action: task` is _being tasked right now_; a spec in `prds/tasked/` _has been tasked_; a spec in `prds/ready/` is _to-task_.
102
+ - **Edit a spec when its tasking-lock is NOT held.** While the tasking lock is held the spec is mid-tasking; edit it before tasking starts or after it lands (in `prds/ready/` or `prds/tasked/`), not while the lock is held. (A human on a stale local checkout won't see the durable `git mv` until they fetch — the protocol guarantees no _silent corruption_, not no _human surprise_.)
103
+ - **Release fails loud on a concurrent edit (never a silent stale tasking).** If the held spec body was edited while the lock was held, the release detects it (the held content no longer matches the snapshot the lock took) and FAILS LOUD: the tasking is stale → re-task from the edited spec or mark the lock stuck. The release NEVER force-restores over the edit or emits tasks cut from a stale snapshot.
104
+ - **The human path needs no lock.** A human tasking locally with no agent running has no contention and may task on `main` directly — the lock is mandatory for the agent, optional for the human (parallel to "the runner never skips verify; the human may").
105
+
106
+ ### Land = rebase + re-verify + advance (the durable-move invariant)
107
+
108
+ Every durable `main` move (a task's `tasks/ready → tasks/done`, a spec's `prds/ready → prds/tasked`, a `tasks/ready → tasks/cancelled`) is a LAND, and every land is the same mode-agnostic primitive: **fetch current `main` → rebase the work onto it → re-run `verify` (and review) on the rebased tree → advance.** A lost CAS / moved-`main` between gate and push INVALIDATES any prior green and re-arms the gate (re-rebase, re-`verify`, retry — never a `--force`, never an auto-resolved conflict). Merge mode runs it inline at the serialised land; propose mode runs it at the human checkpoint. Human review is ADDITIVE (intent/design/security), NEVER a substitute for the re-verify on the rebased tree. The durable _why_ — a clean `git` merge validates the AUTHORED context, never the LIVED context — lives in ADR `land-primitive-rebase-reverify-advance`.
109
+
110
+ ### `needs-attention` — the post-claim "stuck" state (the lock `state: stuck`)
111
+
112
+ An item that was claimed and _attempted_ but could not complete is marked **stuck on its per-item lock** instead of reaching `tasks/done/`. This is the single home for every "couldn't finish, a human must look" outcome — a failed acceptance gate (red tests), a rebase/merge conflict, a task the agent found too ambiguous to build, a timeout, or a rejected review. It is NOT a `main` folder move: the bounce is a CAS amend of the held lock entry `active → stuck` (+ the reason and any agent-surfaced questions on the entry), with NO `main` write. The item's body never moves (it rests in `tasks/ready/`, since claim does not relocate it).
113
+
114
+ - **Who marks it:** the runner/human that owns the lock transitions — NOT the build agent (which never touches the lock ref). On a stuck job the runner amends the lock to `state: stuck` with the reason/questions, and SAVES the recoverable work as a wip commit on the kept `work/<type>-<slug>` branch (pushed to the arbiter so it travels cross-machine).
115
+ - **Not claimable:** a stuck item's lock is held, so it is not claimable (the create-only acquire loses); it IS surfaced — `dorfl status`/`scan` read the lock refs and list held (in-progress) + stuck (needs-attention) items with their reasons (this is the "look here" set). `tasks/done/` on `main` and a `stuck` lock may legitimately CO-EXIST (a rebase-conflict bounce of a just-completed item) without corruption.
116
+ - **Resolve / return path:** a human resolves the cause then either `resume`s the lock (`stuck → active`, pick the work up again) or `requeue`s it (`stuck → released`; the item is already resting in the pool `tasks/ready/`, so there is no folder bounce). A stuck/orphaned lock is nameable and clearable via `release-lock <item>` (+ a stuck-lock report in `gc --ledger`); there is no liveness heartbeat and no auto-sweep (a human asserts a lock is dead).
117
+ - This is a _post-claim_ state. (A separate _pre-claim_ "not ready" state is the STAGING folder `tasks/backlog/` — the position gate — not this.)
118
+ - **Branch self-conflicts cannot occur by construction.** Because NO transient status lands on `main` (a bounce is a lock amend, not a `git mv`), a work branch cut from `main` inherits no `needs-attention`/`tasking`/`advancing` markers, so a continue/rebase is a PLAIN rebase with nothing to drop. A genuine content conflict between two real lines of development still aborts → the item is marked stuck.
119
+
120
+ ### Drift is a needs-attention signal (check the doc against reality first)
121
+
122
+ A spec and a task are **launch snapshots** — they capture intent at creation and are deliberately NOT kept in sync (current truth lives in `docs/adr/` + the code in `tasks/done/`). So by the time you act on one, it MAY have **drifted**: a dependency landed differently than the doc assumed, an ADR superseded a decision the doc relies on, a sibling task changed the seam it builds against.
123
+
124
+ **Discipline (applies whenever you investigate / task / claim / build):** before acting, **check the doc against reality** — the code in `tasks/done/`, the relevant ADRs, and sibling tasks it depends on. If you find a discrepancy that would make you build/task against a false premise, that is a **needs-attention candidate — do NOT silently proceed on the stale spec.** Route it per the item's kind:
125
+
126
+ - **A TASK that contradicts current reality** → route to needs-attention (mark its lock `state: stuck`) with the discrepancy as the reason (the same mechanism as a red gate), rather than building on a stale assumption. A human reconciles the task, then returns it to the pool `tasks/ready/`. (Building on a stale task produces wrong-but-compiling work — the worst outcome.)
127
+ - **A SPEC that has drifted** (before tasking) → do NOT task it as-is. Set `needsAnswers: true` on the spec with the discrepancy in its body (or, if it is a small factual correction you are certain of, fix the spec first), so the tasker never emits tasks from a stale spec. A human reconciles, clears the flag, then it is tasked.
128
+ - **A SPEC that has drifted AFTER it was TASKED** (a mechanism it assumed got retired, a sibling decision superseded it) → do **NOT** move it back to `prds/proposed/`. `prds/proposed/` is the untrusted-admission STAGING position; moving an already-tasked spec there falsely un-records a tasking that really happened and ORPHANS the tasks it already emitted (they still sit in `tasks/backlog`/`tasks/ready` carrying `prd:`/`covers:` linkage to a spec that now claims it was never tasked). Tasked-ness is RESIDENCE in `prds/tasked/` and must never be silently rewound. Instead, two honest mechanisms (use the lighter one that fits):
129
+ - **Annotate in place (drifted, not yet re-decomposed).** Set `needsAnswers: true` on the spec **while it stays in `prds/tasked/`**, with the drift + what must be re-decomposed in its body, AND set `needsAnswers: true` on every emitted task that is now premised on the dead mechanism so no agent builds it. `needsAnswers: true` on a `prds/tasked/` spec is legal and means exactly _"tasked, but the spec has drifted — do not RE-task or rely on it until reconciled."_ The non-drifted emitted tasks are unaffected and stay promotable.
130
+ - **Reopen to re-decompose (the sanctioned move).** When you are ready to re-task from the reconciled spec, use the existing reopen path `prds/tasked/ → prds/ready/` (mirroring `tasks/done/ → tasks/ready/`), reconcile the spec, clear `needsAnswers`, then re-task — which emits corrected tasks. Supersede the stale emitted tasks into `tasks/cancelled/` (reason: superseded by the re-task). There is NO `prds/tasked/ → prds/proposed/` transition.
131
+
132
+ The rule is symmetric: _a discrepancy between a doc and reality is not something to paper over — it is exactly the "a human must look" signal `needs-attention` (tasks) / `needsAnswers` (specs) exists to carry._ Cheap to honour, and it stops drift from silently propagating into built work.
133
+
134
+ ## Conflict-safety rules (non-negotiable)
135
+
136
+ 1. **One file per item.** Never put two work items in one file. Disjoint files merge trivially.
137
+ 2. **No shared index / manifest.** Do not maintain a `work/INDEX.md`, `work/list.json`, or any file every item touches — it is a guaranteed conflict point. Derive lists on demand with `ls work/tasks/ready/` / `grep`. (A hand-maintained index just goes stale.)
138
+ 3. **An empty lifecycle folder is OPTIONAL — absence means "empty", never "broken".** The folders in the layout above (`tasks/backlog`/`ready`/`done`/`cancelled`, `prds/proposed`/`ready`/`tasked`/`dropped`, the `notes/*` buckets) describe the POSITIONS an item MAY rest in, not directories that must all exist at rest. Git does not track empty directories, so a position with no items in it simply has no folder on disk, and a reader/conductor MUST treat a missing lifecycle folder as the empty set (e.g. no `prds/proposed/` ⇒ "nothing awaiting promotion"), NOT as a misconfigured tree. A folder is CREATED implicitly the first time an item lands in it (the `git mv`/write that places the item), and may VANISH again when its last item leaves. So: never fail, warn, or auto-create-as-a-fixup on a missing lifecycle folder; derive each position's contents on demand (rule 2) and let an empty position be a no-op. (`setup` may scaffold a starter set for ergonomics, but the contract does not REQUIRE their continued existence — emptiness and absence are the same state.)
139
+ 4. **Status = location, not a field.** See above.
140
+ 5. **Content-derived slugs, never counters.** Use a URL-safe slug from the title (e.g. "Historical store schema" → `historical-store-schema`). NO monotonic integer IDs — two agents would both grab "next = 43". A short hash or date prefix is fine if disambiguation is needed (`historical-store-schema` or `2026-06-03-historical-store-schema`).
141
+ 6. **Dependencies by slug, read-only.** `blockedBy: [other-slug]` references other items; an item never writes another item's file. The blocker owns its own status (its folder).
142
+ 7. **Claim state is the per-item LOCK, never a frontmatter field (and not a folder move).** Claiming an item acquires its per-item lock (`refs/dorfl/lock/<type>-<slug>`, `action: implement`) — a create-only ref push that is self-arbitrating (the loser is definitively told "lost", no retry budget); the body STAYS in `tasks/ready/` (claim writes nothing to `main`, so an agent can claim even on a protected `main`). The holder/since ride the lock entry; `git` (the ref + its parentless commit) holds the authoritative record. There is NO `claimed_by` / `claimed_at` frontmatter, and no `git mv` into an `in-progress/` folder — the claimable predicate is "in the pool `tasks/ready/` on `main` AND no lock held on its ref".
143
+ 8. **An item MAY carry a co-located `<slug>/` asset sidecar folder.** The item is ALWAYS the `<slug>.md` file (that is its identity and the only thing scanned). When an item needs companion resources — a `.patch`, a mockup image, a diagram, a sample payload — put them in a sibling folder of the SAME slug, `<umbrella>/<slug>/` (e.g. `notes/ideas/my-idea.md` + `notes/ideas/my-idea/fix.patch`). This is safe and disturbs NOTHING because every scanner lists a bucket by `isWorkItemFile` (= name ends in `.md`), so a sidecar folder is silently skipped — it is never mistaken for an item, and `(umbrella, slug)` addressing is unchanged. Rules: the sidecar is OPTIONAL and most items have none; it is OWNED by its `<slug>.md` (the markdown references its assets by relative path, e.g. `[the patch](<slug>/fix.patch)`); it shares the item's lifecycle (when the item is deleted, delete its sidecar too — a note leaves by deletion, and an orphaned sidecar is litter); and it is NOT a second item, so never put another item's `<slug>.md` inside it (that would hide it from scanning). This applies to ANY bucket (`notes/*`, `tasks/*`, `prds/*`), not just ideas, though ideas are the common case. It does NOT violate rule 1 (one file per ITEM) or rule 2 (no shared index) — the sidecar holds an item's OWN assets, not a manifest over many items.
144
+
145
+ ## Task quality rule — tests must not touch the real environment
146
+
147
+ A task that makes code **write to a SHARED / GLOBAL location** — a real home/config dir, a system path, a shared service, or an **external tool's managed store** (e.g. another agent's session directory) — MUST, as an acceptance criterion, have its **tests ISOLATE that location** (point it at a temp/scratch dir via the relevant env var or config knob) **AND assert the real one is UNTOUCHED after the run**. State the _mechanism_, not just the outcome: name the env/config lever and note WHERE the path is resolved (in-process vs in a child), because that determines whether overriding a child's env is enough or the test process's own `process.env` must be set.
148
+
149
+ This is the generalisation of the git-config isolation tests already do (`GIT_CONFIG_GLOBAL=/dev/null`): the same discipline for ANY shared write target. A task that _moves_ a write into a shared location (e.g. "write sessions to the tool's default dir instead of the worktree") silently turns previously-isolated tests into ones that pollute — and a malformed fixture in a shared store can crash unrelated tools that read it. Corollary: a synthetic fixture written into any store an external tool reads MUST be VALID per that tool's contract (capture the contract as a `notes/findings/` doc).
150
+
151
+ ## Field-naming convention
152
+
153
+ All frontmatter and config field names are **camelCase** (`humanOnly`, `needsAnswers`, `blockedBy`, `taskedAfter`, `autoBuild`) — matching the JSON config and the TypeScript that parses them (1:1 property mapping, no snake↔camel translation layer). No exceptions.
154
+
155
+ ## Frontmatter (YAML)
156
+
157
+ ### Task frontmatter
158
+
159
+ ```yaml
160
+ ---
161
+ title: Human Readable Title
162
+ slug: historical-store-schema
163
+ prd: historical-store # slug of the work/prds/ready/<slug>.md this task derives from. REQUIRED iff `covers` is set; OMIT for a self-contained chore/refactor (covers: []).
164
+ humanOnly: true # gate axis 1 (DECIDED): a human must drive this. true | omitted. MOST OMIT IT.
165
+ needsAnswers: true # gate axis 2 (DISCOVERED): open questions block autonomous work. true | omitted.
166
+ blockedBy: [] # list of slugs that must reach tasks/done/ first; [] = startable now
167
+ covers: [] # optional: user-story numbers (within `prd`) this task covers
168
+ promptGuidance.testFirst: true # optional per-item NUDGE override: pin the test-first nudge ON or OFF for THIS task, regardless of the repo's resolved `promptGuidance.testFirst` policy. true | false | omitted (= inherit prd, else repo policy). NEVER an acceptance criterion — `verify` still decides pass/fail. See "`promptGuidance.*` per-item override" below.
169
+ ---
170
+ ```
171
+
172
+ ### Spec frontmatter
173
+
174
+ ```yaml
175
+ ---
176
+ title: Human Readable Title
177
+ slug: historical-store
178
+ issue: 123 # optional: the issue this spec was spawned from (the surviving thread)
179
+ humanOnly: true # optional: a human must drive the TASKING of this spec. true | omitted.
180
+ needsAnswers: true # optional: open questions block AUTO-tasking this spec. true | omitted.
181
+ taskedAfter: [] # optional: prd slugs that must be TASKED first (see below). [] = taskable now.
182
+ promptGuidance.testFirst: true # optional per-item NUDGE override: pin the test-first nudge ON or OFF for every task this spec fans out, regardless of the repo's resolved policy. A per-task override still wins over this. true | false | omitted (= inherit repo policy). See "`promptGuidance.*` per-item override" below.
183
+ # tasked-ness has NO frontmatter marker: it is RESIDENCE in work/prds/tasked/ (the release transition moves the spec there).
184
+ ---
185
+ ```
186
+
187
+ ### Finding frontmatter
188
+
189
+ A finding (`work/notes/findings/<slug>.md`) is a capture-bucket note (no status flow), but it MUST declare its **provenance** so it stays correctable (see the findings box above):
190
+
191
+ ```yaml
192
+ ---
193
+ title: Human Readable Title
194
+ slug: external-api-behaviour
195
+ source: 'derived from src/<the-integrating-module> @ <commit>' # REQUIRED: what the source is AND how current (a date for external sources). Be specific & honest — there is NO separate confidence field; the source string carries the weight.
196
+ ---
197
+ ```
198
+
199
+ - `source` is **required** — a finding without it is a `notes/observations/` signal, not a finding. State it specifically (a file+commit, a doc URL, a captured trace), so a later "the source was wrong" can revise the finding traceably.
200
+ - A **code-derived** finding describes the _external behaviour our code assumes_, never our code's internal architecture (that is `CONTEXT.md` / a `docs/` overview). If you find yourself describing our own package layout, it is not a finding.
201
+
202
+ ### The two autonomy axes: `humanOnly` (decided) × `needsAnswers` (discovered)
203
+
204
+ The autonomy gate is TWO orthogonal binary fields (both default to omitted = false), present on BOTH tasks and specs, plus the repo's `autoBuild` policy:
205
+
206
+ - **`humanOnly: true` — the DECIDED axis.** _Should a human drive this, regardless of how complete the spec is?_ A product/design/security/judgement call, or an `AGENTS.md`-type rule. Driven by a decision (in the spec conversation, or the tasker's own judgement). On a SPEC it means "a human must drive the tasking". On a TASK it is the NARROW "never-for-agents BY NATURE" guard (secrets/release/security) that **survives even when the task resides in the agent pool `work/tasks/ready/`**. Task `humanOnly` is NOT the tool for ordinary "a human should review this before the agent builds it" — that job belongs to POSITION (the runner births the task STAGED in `work/tasks/backlog/`; a human promotes the approved ones into the pool `work/tasks/ready/`). See "Task `humanOnly` is NARROW" below.
207
+ - **`needsAnswers: true` — the DISCOVERED axis.** _Are there unresolved questions blocking autonomous progress?_ The spec is incomplete; **the open questions live in the body**. Once answered, the flag is cleared and an agent may proceed.
208
+ - They are **orthogonal** — four honest states. e.g. `humanOnly:true, needsAnswers:false` = fully specified but a human must own it; `humanOnly:false, needsAnswers:true` = anyone can do it once the questions are answered.
209
+ - **Repo policy `autoBuild`** answers the question the _repo_ owns: _may agents auto-build undeclared items here?_ The build member of the symmetric per-action gate family (`autoBuild`/`autoTask`/`observationTriage`). Per-repo config key (`.dorfl.json`), resolved like `integration`: **CLI flag (`--auto-build` / `--no-auto-build`) > env (`DORFL_AUTO_BUILD`) > per-repo config > global config > built-in default (`false`)**.
210
+
211
+ **Predicate (same shape at both levels):** an item is **auto-eligible** iff `needsAnswers` is not `true` AND `humanOnly` is not `true` AND `autoBuild` is `true`. A human is never bound by it (a human may task/build a flagged item — the gate binds the agent, like the runner-vs-human stance on `verify`).
212
+
213
+ ### `promptGuidance.*` per-item override (the same precedence shape as `humanOnly`/`autoBuild`)
214
+
215
+ The `promptGuidance` NAMESPACE is a per-repo + per-item layer of PROMPT-TEXT NUDGES the runner folds into the worker's in-band prompt (currently one member, `testFirst`; the namespace is designed to grow). It is CATEGORICALLY SEPARATE from the gate family (`verify`/`autoBuild`/`humanOnly`): a nudge changes the agent's DISPOSITION, never the acceptance bar — the `verify` gate still decides pass/fail regardless of any value here.
216
+
217
+ The repo policy resolves like every other gate-family field: **CLI flag > env (`DORFL_PROMPT_GUIDANCE_TEST_FIRST`) > per-repo config > global config > built-in default (`false`)**. On top of THAT, a single task or spec may OVERRIDE the resolved repo policy for THAT item only by setting `promptGuidance.<member>: true | false` in its frontmatter — the same repo-default-plus-item-override shape `humanOnly`/`autoBuild` use. The per-item precedence chain (highest → lowest) is:
218
+
219
+ 1. **Per-task frontmatter** — the task's own `promptGuidance.<member>` line (when present).
220
+ 2. **Per-prd frontmatter** — the prd's `promptGuidance.<member>` line, consulted ONLY when the task carries a `prd:` and the prd file is found in `work/prds/ready/` or `work/prds/tasked/`.
221
+ 3. **Repo-resolved policy** — the value the chain above resolves to, with the built-in default `false`.
222
+
223
+ Each nudge member resolves INDEPENDENTLY — a task's `promptGuidance.testFirst` override never bleeds into a sibling member. A task with no `prd:` (a self-contained chore) MAY still carry the override; the prd layer is simply absent and the chain reads task ⇒ repo. A missing prd file is NOT an error: the override is OPTIONAL by design, so the chain silently falls through to the repo policy. Form: the frontmatter parser reads the DOTTED scalar form `promptGuidance.<member>: <bool>` (a single line, mirroring the flat shape `humanOnly`/`needsAnswers` use at the item level); a mistyped value (e.g. `"yes"`) reads as undefined — the same silent-on-malformed behaviour `humanOnly` has — never a silent coerce.
224
+
225
+ Authority: a per-item override binds the AGENT exactly like the gate-family overrides do. A human may always ignore it on a manual run (the prompt is generated; the human decides what to type).
226
+
227
+ ### Task `humanOnly` is NARROW — POSITION carries "review-first"; `humanOnly` carries "never-by-nature"
228
+
229
+ Three orthogonal axes, each meaning EXACTLY one thing:
230
+
231
+ - **POSITION (folder, runner-deterministic, STRUCTURAL).** Whether a task is in the agent POOL (`work/tasks/ready/`) or in STAGING (`work/tasks/backlog/`) is computed by the runner from unforgeable inputs (the `originTrust` stamp, the per-repo placement policy, explicit operator flags). "A human should review this before an agent acts on it" is encoded HERE — the task is BIRTHED in `work/tasks/backlog/` (not eligible) and a human promotes the approved ones into `work/tasks/ready/`. The agent CREATES only in the staging folder; the runner OWNS every move + promotion.
232
+ - **Staging is review-first admission AND the human-control position — the same folder carries BOTH.** A staging folder (`work/tasks/backlog/`, `work/prds/proposed/`) is not just "not-yet-reviewed"; it is also where an item rests so a HUMAN can drive it WITHOUT an autonomous claimer competing. Promoting an item into the POOL (`work/tasks/ready/`, `work/prds/ready/`) is EXACTLY what makes it claimable-by-anyone: the moment it lands in the pool, an autonomous claimer can grab it — a CI `advance` leg or a local `run` daemon (both are pool-only by construction). So **promote-then-drive opens a COMPETITION WINDOW** (the autonomous claimer races the human who meant to drive the work). The safe path is the inverse: a human who wants to drive an item themselves DRIVES IT IN PLACE from staging, and promotes only when (if ever) they want to hand it to the pool. The two drive-in-place mechanisms: a SPEC is **tasked in place** from `work/prds/proposed/` (TASKING-PROTOCOL.md §6), and a task is **built in place** from `work/tasks/backlog/` via `do --allow-backlog`. "I want to drive this myself" therefore means "drive it in place", never "promote, then race to claim it first".
233
+ - **NATURE (`humanOnly`, agent/human judgement, ADVISORY).** Task `humanOnly: true` means "an agent must NEVER AUTONOMOUSLY take this BY NATURE" — the rare hard case (release/secrets/security/AGENTS.md-rule) that **survives even when the task resides in the pool `work/tasks/ready/`**. The autonomy gate predicate above is exactly this: a `humanOnly: true` task is never AUTONOMOUSLY claimed (it drops out of `run`/`advance`/auto-pick selection and the conductor's READY set), even from `work/tasks/ready/`. It is NOT, however, unbuildable: an EXPLICIT human-driven `dorfl do task:<slug>` (or `claim`) STILL builds it — the readiness guard does not consult `humanOnly` on the human path (a human is never bound by `humanOnly`; it means "a human must DRIVE this"), and explicit dispatch gates on the item's own readiness, not the autonomy policy (the pool gates the policy, not the explicit claim). So the invariant is precise: `humanOnly` gates AUTONOMOUS SELECTION, never an explicit human action. Spec `humanOnly` gates auto-tasking; no folder substitute, because the tasker's input is a single spec — it must be flagged in-band.
234
+ - As a corollary, `humanOnly` CAN be used off-label as a "keep CI/`run`/auto-pick OFF this task while I drive it by hand" latch (it excludes the task from every autonomous claimer, while explicit `do task:<slug>` still builds it). PREFER POSITION (leave it in staging `work/tasks/backlog/`) for that intent; reserve the flag for the genuine never-by-nature case. If you do use it as a latch, strip it once the task lands so it does not falsely mark the done record never-by-nature.
235
+ - **DISCOVERED (`needsAnswers`, agent judgement, ADVISORY).** Open questions block autonomous work.
236
+
237
+ Consequences for the tasker heuristic (the `to-task` skill / the tasker review loop):
238
+
239
+ - For the COMMON "a human should review this task first" case, the tasker does NOT stamp `humanOnly: true` — it lets the runner birth the task STAGED in `work/tasks/backlog/` (the position carries the review-first signal).
240
+ - The tasker flags `humanOnly: true` on a task ONLY when building THAT task is genuinely never-for-agents-by-nature (release pipeline, secrets handling, hard security boundaries, AGENTS.md prohibitions). If in doubt, leave `humanOnly` off and rely on the position — a human can always refuse to promote.
241
+
242
+ ### Three honest integration modes for tasker output (`do prd:<slug>`)
243
+
244
+ The tasker-output integration combines `--propose`/`--merge` with the `tasksLandIn` placement default into three explicit, named modes:
245
+
246
+ | Mode | How to invoke | What lands where | When to use |
247
+ | --- | --- | --- | --- |
248
+ | **`--propose`** (PR path) | `do prd:<slug> --propose` (or the configured default) | A work branch pushed; a PR opened against `main`. Tasks land in the PR's tree (typically `work/tasks/backlog/`); review is the PR diff. | A repo with a host (GitHub, …) and a PR-based review culture. Code/implementation review ALWAYS uses this path — a diff cannot be folder-gated. |
249
+ | **`--merge` + land-in-staging** (PR-free review) | `do prd:<slug> --merge` with `tasksLandIn: pre-backlog` (or `--tasks-land-in pre-backlog`) | Tasks land DURABLY on `main` under `work/tasks/backlog/` (the staging folder, NOT eligible). A human promotes the approved ones `work/tasks/backlog/ → work/tasks/ready/`. | A bare / no-host / protected-`main` repo that still wants human review of ledger-file output. Review is a LEDGER POSITION a human moves, not an out-of-band PR. |
250
+ | **`--merge` + land-in-pool** (trusted no-review fast path) | `do prd:<slug> --merge` with `tasksLandIn: ready` (or `--tasks-land-in ready`) and a trusted origin | Tasks land on `main` directly in the agent POOL `work/tasks/ready/` — immediately eligible for `do` / auto-pick. | A trusted, fast-iteration repo where the tasker's output is trusted to enter the pool without ledger-position review. The runner-deterministic placement precedence still forces STAGING for an untrusted origin. |
251
+
252
+ Key rules:
253
+
254
+ - **Placement is runner-deterministic.** WHICH folder a task lands in is the runner's CALL from the `originTrust` stamp + `tasksLandIn` config + an explicit `--tasks-land-in` flag (precedence: explicit-flag > untrusted-forces-staging > configured default > built-in staging). The agent never sets it. (`tasksLandIn` names the TASK-side pool/staging slots, `ready`/`pre-backlog`.)
255
+ - **Code/implementation review is on the branch/PR path** — a code diff cannot be folder-gated. The position gate above is SCOPED to LEDGER-FILE output (tasking); the branch-based build review is unaffected.
256
+ - **`humanOnly` survives every mode.** A `humanOnly: true` task in the pool is still not agent-claimable — the position gate and the `humanOnly` gate are orthogonal.
257
+
258
+ ### `taskedAfter` — prd tasking-order (enforced against `work/prds/tasked/`, NOT `tasks/done/`)
259
+
260
+ `taskedAfter: [other-prd]` on a prd is **distinct from** task `blockedBy`, and named differently because it gates a different verb against a different signal:
261
+
262
+ - **task `blockedBy`** gates **building** a task, resolved against `tasks/done/`.
263
+ - **prd `taskedAfter`** gates **tasking** a prd, resolved against `work/prds/tasked/` residence (i.e. the listed prds must already be tasked — reside in `work/prds/tasked/` — so this prd's emitted tasks can reference the real slugs of those prds' tasks in their `blockedBy`). This mirrors `blockedBy` → `tasks/done/` exactly: ordering resolves against folder residence, not a frontmatter marker.
264
+
265
+ It waits on **tasked-ness (`work/prds/tasked/`), not `tasks/done/`** on purpose: the reason B waits for A is that B's tasks need A's slugs to _exist_, which happens the moment A is tasked — not when A is fully built. Build-ordering between A's and B's actual work is then expressed where it belongs, in B's individual tasks' `blockedBy` (against `tasks/done/`). Enforced for the auto-tasker (it skips a prd whose `taskedAfter` prds do not yet reside in `work/prds/tasked/`); a human may task anyway.
266
+
267
+ ### The `prd` link (required _when `covers` is set_)
268
+
269
+ `prd` names the source document this task was tasked from — the slug of a `work/prds/ready/<slug>.md` in the same repo. Its load-bearing job is to make `covers` unambiguous: `covers: [4]` means nothing without knowing _which_ prd's story 4. So the requirement tracks that job:
270
+
271
+ - **`prd` is REQUIRED iff `covers` is non-empty.** Any task that points into prd user stories MUST name the prd those numbers belong to (a task spanning multiple prds names its primary one in `prd` and references the others in prose).
272
+ - **`prd` MAY be omitted for a self-contained task** — a refactor, chore, build fix, or dependency bump that derives from no prd and covers no user stories (`covers: []`). Such a task MUST instead carry a clear, standalone _What to build_ + _Prompt_ (it is its own source of truth). This is **in contract** — not all work is feature work; only _feature_ work flows from a prd.
273
+
274
+ (Consequence, by design: a prd-less chore task is part of no prd's completion set — the "prd complete?" query counts only `prd:<slug>` tasks — which is correct, since a chore is not part of any feature's traceability.)
275
+
276
+ The body uses [task-template.md](task-template.md): What to build (end-to-end), Acceptance criteria (checkboxes), Blocked by (prose mirror of frontmatter), and a **Prompt** section — a self-contained instruction block that can be pasted into a fresh agent context, so an agent needs nothing but the file to start.
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: <Human Readable Title>
3
+ slug: <url-safe-slug>
4
+ # issue: 123 # optional: the issue this spec was spawned from (the surviving thread)
5
+ # humanOnly: true # optional: a HUMAN must drive the tasking of this spec (a decision). OMIT otherwise.
6
+ # needsAnswers: true # optional: open questions block AUTO-tasking (spec incomplete). OMIT otherwise. List the questions in the body.
7
+ # taskedAfter: [] # optional: prd slugs that must be TASKED first (so this spec's tasks can reference their slugs in blockedBy).
8
+ # promptGuidance.testFirst: true # optional per-item NUDGE override: pin the test-first nudge ON (true) or OFF (false) for every task this spec fans out, regardless of the repo's resolved policy. A per-task override still wins over this. OMIT to inherit the repo policy. NEVER an acceptance criterion — `verify` still decides pass/fail.
9
+ ---
10
+
11
+ > Launch snapshot — records intent at creation, NOT maintained. Current truth: `docs/adr/` (decisions) + the code; remaining work: `work/tasks/ready/` tasks. (The technical-detail sections below are trimmed by `to-task` once the work is tasked — they move into tasks/ADRs and this spec settles to its durable framing: Problem / Solution / User Stories / Out of Scope.)
12
+
13
+ <!-- open-questions -->
14
+ <!--
15
+ TRANSIENT BLOCK — stripped by the apply rung on full resolution.
16
+ While the spec has unresolved questions blocking autonomous tasking:
17
+ 1. Set `needsAnswers: true` in the frontmatter above.
18
+ 2. List the questions under the `## Open questions` heading below.
19
+ 3. Clear the flag (and let apply strip this block) once they are answered.
20
+ Delete the whole fenced block — markers and all — if the spec launches fully resolved.
21
+ -->
22
+
23
+ ## Open questions
24
+
25
+ 1. <question one>
26
+ 2. <question two>
27
+
28
+ <!-- /open-questions -->
29
+
30
+ ## Problem Statement
31
+
32
+ The problem the user faces, from the user's perspective.
33
+
34
+ ## Solution
35
+
36
+ The solution, from the user's perspective.
37
+
38
+ ## User Stories
39
+
40
+ A LONG, numbered list — the heart of the spec. Format:
41
+
42
+ 1. As a <actor>, I want <feature>, so that <benefit>.
43
+
44
+ Cover all aspects of the feature, extensively.
45
+
46
+ ### Autonomy notes (the two gate axes — set the frontmatter flags accordingly)
47
+
48
+ The spec now CARRIES the tasking gate (because an agent may auto-task it with no human in the loop). Record, in prose here AND as the frontmatter flags above:
49
+
50
+ - **`humanOnly` (DECIDED):** set `humanOnly: true` on the spec ONLY to mean "a human must drive the _tasking_ of this spec" (sole effect: an agent may not auto-task it). This is DISJOINT from task `humanOnly` — it does NOT propagate to or guide the tasks' gates (a `humanOnly` spec can yield fully agent-buildable tasks). The tasker sets each task's gate from that task's own build-nature.
51
+ - **`needsAnswers` (DISCOVERED):** are there open questions the spec has not yet resolved? If so, fill in the `## Open questions` block at the top of the spec (it carries the authoring instructions and the marker fence the apply rung uses to strip it on resolution) — the auto-tasker will refuse to task until they are answered and the flag cleared. Be HONEST: a flagged-incomplete spec is correct; a falsely-complete one produces wrongly-cut tasks. (Omit both flags if everything is resolved and straightforwardly agent-taskable.)
52
+
53
+ ## Implementation Decisions
54
+
55
+ Decisions made at launch (modules to build/modify, interfaces, architectural choices, schema, API contracts, specific interactions). No file paths or code snippets (they go stale) — except a decision-encoding snippet from a prototype (state machine, reducer, schema, type shape), trimmed to the decision-rich part.
56
+
57
+ > Trimmed at tasking-time: this detail moves into the tasks (what to build) and, where it's a durable rationale, into an ADR (`docs/adr/`). It is here only to seed the tasking.
58
+
59
+ ## Testing Decisions
60
+
61
+ What makes a good test (external behaviour, not implementation details); which modules/seams will be tested; prior art in the codebase.
62
+
63
+ > Also trimmed at tasking-time (moves into tasks' acceptance criteria / an ADR).
64
+
65
+ ## Out of Scope
66
+
67
+ What is deliberately not being done (and, where useful, where it lives instead — e.g. an incubating idea in `work/notes/ideas/`).
68
+
69
+ ## Further Notes
70
+
71
+ Anything else worth recording at launch.
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: <Human Readable Title>
3
+ slug: <url-safe-slug>
4
+ prd: <source-prd-slug> # slug of the work/prds/ready/<slug>.md this task derives from. REQUIRED iff `covers` is set; OMIT for a self-contained chore/refactor (covers: []).
5
+ # humanOnly: true # gate axis 1 (DECIDED, NARROW): NEVER-for-agents BY NATURE (secrets/release/security). Survives even in the pool work/tasks/ready/. OMIT otherwise — "review this before the agent builds" is the POSITION's job (the task is BIRTHED in work/tasks/backlog/), NOT humanOnly's.
6
+ # needsAnswers: true # gate axis 2 (DISCOVERED): open questions block autonomous work. OMIT otherwise. List them in the body.
7
+ # promptGuidance.testFirst: true # optional per-item NUDGE override: pin the test-first nudge ON (true) or OFF (false) for THIS task, regardless of the repo's resolved policy. OMIT to inherit (prd, else repo). NEVER an acceptance criterion — `verify` still decides pass/fail.
8
+ blockedBy: [] # slugs that must reach work/tasks/done/ first; [] = startable now
9
+ covers: [] # optional: user-story numbers within `prd` this task covers
10
+ ---
11
+
12
+ <!-- open-questions -->
13
+ <!--
14
+ TRANSIENT BLOCK — stripped by the apply rung on full resolution.
15
+ While the task has unresolved questions blocking autonomous build:
16
+ 1. Set `needsAnswers: true` in the frontmatter above.
17
+ 2. List the questions under the `## Open questions` heading below.
18
+ 3. Clear the flag (and let apply strip this block) once they are answered.
19
+ Delete the whole fenced block — markers and all — if the task launches fully resolved.
20
+ -->
21
+
22
+ ## Open questions
23
+
24
+ 1. <question one>
25
+ 2. <question two>
26
+
27
+ <!-- /open-questions -->
28
+
29
+ ## What to build
30
+
31
+ A concise description of this vertical task — the end-to-end behaviour (a thin path through every layer: schema → logic → API/UI → tests), NOT a layer-by-layer implementation plan. Avoid specific file paths / code snippets (they go stale).
32
+
33
+ Exception: if a prototype produced a snippet that encodes a decision more precisely than prose (state machine, reducer, schema, type shape), inline just the decision-rich part and note it came from a prototype.
34
+
35
+ ## Acceptance criteria
36
+
37
+ - [ ] Criterion 1 (verifiable / demoable on its own)
38
+ - [ ] Criterion 2
39
+ - [ ] Tests cover the new behaviour (mirror the repo's existing test style)
40
+ - [ ] **If this task makes code write to a SHARED / GLOBAL location** (a real home/config dir, a system path, a shared service, an external tool's managed store): tests ISOLATE that location (point it at a temp/scratch dir via the relevant env/config) AND assert the real one is UNTOUCHED after the run. Omit only if the task writes nothing outside its own temp fixtures.
41
+
42
+ ## Blocked by
43
+
44
+ - None — can start immediately. (or: list the blocking slugs, mirroring `blockedBy` in the frontmatter.)
45
+
46
+ ## Prompt
47
+
48
+ > Self-contained instructions to paste into a fresh agent context. An agent should be able to start from THIS FILE ALONE — no conversation history needed. State the goal, the relevant domain vocabulary, where to look in the codebase (by module/concept, not brittle paths), the seams to test at, and what "done" means. Reference any `work/notes/findings/*.md` or ADRs that constrain the work.
49
+ >
50
+ > FIRST, check this task against current reality (it is a launch snapshot and may have DRIFTED): does it still match the code in `tasks/done/`, the relevant ADRs, and the tasks it depends on? If a dependency landed differently than this task assumes, or an ADR superseded an assumption here, do NOT build on the stale premise — route the task to needs-attention with the discrepancy as the reason (WORK-CONTRACT.md "Drift is a needs-attention signal"). Building on a stale task produces wrong-but-compiling work.
51
+ >
52
+ > RECORD non-obvious in-scope decisions you make while building, DURABLY and LINKED from the done record. When the task did not specify some behaviour and you have to CHOOSE (a new refusal/exit code, a clamp that reaches a second code path, a fail-loud-vs-fail-safe asymmetry, keeping vs collapsing a now-redundant distinction), do not leave the choice silent for a reviewer to reverse-engineer. Surface it so it can be ratified: if it meets the ADR gate (hard to reverse + surprising without context + a real trade-off — see `ADR-FORMAT.md`), write the durable WHY as an ADR in `docs/adr/`; otherwise pick whichever durable home fits best — a module JSDoc at the choice site, an optional `## Decisions` block in the done record / PR description, or a dated observation note under `work/notes/observations/` — and link it from the done record so it is discoverable. An un-recorded in-scope decision is a review FINDING, not a silent default.
53
+
54
+ ---
55
+
56
+ ### Claiming this task
57
+
58
+ ```sh
59
+ # atomically claim it (works with a GitHub remote OR a local --bare remote):
60
+ dorfl claim <slug> --arbiter <remote> # default --arbiter origin
61
+ # then start work on the updated main:
62
+ git fetch <remote> && git switch -c work/<slug> <remote>/main
63
+ # on completion, in the work branch's PR/merge:
64
+ git mv work/tasks/ready/<slug>.md work/tasks/done/<slug>.md
65
+ ```
@@ -0,0 +1,66 @@
1
+ /**
2
+ * The pre-claim readiness guard for the HUMAN `start` / `claim` path. Today the
3
+ * human path decides purely on the FOLDER on `<arbiter>/main` (is the slug in
4
+ * `backlog/`?) and never parses the task's frontmatter — so it will happily
5
+ * claim a task whose `blockedBy` deps are not yet in `work/done/`, or one
6
+ * flagged `needsAnswers: true`. The autonomous `run --once` path already filters
7
+ * these out (scan → eligibility → select); this closes that asymmetry for the
8
+ * human path.
9
+ *
10
+ * It reads the SAME source of truth the folder check uses — the task file and
11
+ * the `work/done/` listing on `<arbiter>/main` — and resolves `blockedBy` with
12
+ * the shared {@link resolveBlockedBy} (no reimplemented dep resolution).
13
+ *
14
+ * The two axes are deliberately treated differently (see WORK-CONTRACT and the
15
+ * task prd):
16
+ *
17
+ * - `blockedBy` unmet is a FACTUAL prerequisite (the dep work does not exist
18
+ * yet) → REFUSE by default. An override flag is the human escape hatch.
19
+ * - `needsAnswers: true` is a softer, set-by-someone flag (the claimer may be
20
+ * the one about to resolve it) → WARN loudly but still claim. The same
21
+ * override silences the warning.
22
+ *
23
+ * `humanOnly` is NOT consulted here: `start`/`claim` is the human path, and a
24
+ * human is never bound by `humanOnly` (it means "a human must drive this", and
25
+ * the human is here).
26
+ */
27
+ export interface ReadinessVerdict {
28
+ /**
29
+ * `true` when the claim should be REFUSED before the CAS runs (an unmet
30
+ * `blockedBy`, not overridden). When `true`, the caller claims nothing.
31
+ */
32
+ refuse: boolean;
33
+ /** Blocker slugs not present in `work/done/` on the arbiter, in order. */
34
+ missing: string[];
35
+ /** Whether the task declares `needsAnswers: true`. */
36
+ needsAnswers: boolean;
37
+ /**
38
+ * `true` when an override flag was supplied (the refusal is bypassed and the
39
+ * `needsAnswers` warning is silenced — loudly).
40
+ */
41
+ overridden: boolean;
42
+ }
43
+ export interface ResolveReadinessOptions {
44
+ /** The slug being claimed (`work/backlog/<slug>.md`). */
45
+ slug: string;
46
+ /** Working clone the human path runs in. */
47
+ cwd: string;
48
+ /** Name of the arbiter git remote. */
49
+ arbiter: string;
50
+ /** Override flag (`--force` / `--ignore-not-ready`): bypass refusal + warning. */
51
+ override: boolean;
52
+ /** Environment for child git processes. */
53
+ env?: NodeJS.ProcessEnv;
54
+ }
55
+ /**
56
+ * Resolve the readiness of a task against `<arbiter>/main`. PURE w.r.t. the
57
+ * work tree — it reads only committed objects on the arbiter (the task file and
58
+ * the `work/done/` listing), the same source of truth the folder check uses.
59
+ *
60
+ * Assumes the caller has already fetched the arbiter (the human path fetches
61
+ * before deciding on the folder). Missing/unparseable task frontmatter degrades
62
+ * to "no blockers, no needsAnswers" — the folder check, not this guard, owns the
63
+ * "task exists / is in backlog" decision.
64
+ */
65
+ export declare function resolveReadiness(options: ResolveReadinessOptions): Promise<ReadinessVerdict>;
66
+ //# sourceMappingURL=readiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readiness.d.ts","sourceRoot":"","sources":["../src/readiness.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,MAAM,WAAW,gBAAgB;IAChC;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sDAAsD;IACtD,YAAY,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,UAAU,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACvC,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;IAClB,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,uBAAuB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAwB3B"}
@@ -0,0 +1,36 @@
1
+ import { parseFrontmatter } from './frontmatter.js';
2
+ import { resolveBlockedBy } from './eligibility.js';
3
+ import { ledgerRead } from './ledger-read.js';
4
+ /**
5
+ * Resolve the readiness of a task against `<arbiter>/main`. PURE w.r.t. the
6
+ * work tree — it reads only committed objects on the arbiter (the task file and
7
+ * the `work/done/` listing), the same source of truth the folder check uses.
8
+ *
9
+ * Assumes the caller has already fetched the arbiter (the human path fetches
10
+ * before deciding on the folder). Missing/unparseable task frontmatter degrades
11
+ * to "no blockers, no needsAnswers" — the folder check, not this guard, owns the
12
+ * "task exists / is in backlog" decision.
13
+ */
14
+ export async function resolveReadiness(options) {
15
+ const { slug, cwd, arbiter, override, env } = options;
16
+ // Resolve the task + `work/done/` from `<arbiter>/main` THROUGH the read
17
+ // seam's arbiter method — the single insertion point. Same source of truth the
18
+ // folder check uses; behaviour is byte-identical to the inline reads it
19
+ // replaced (task from `backlog/` or `in-progress/`, done slugs from the tree).
20
+ const { task, doneSlugs } = await ledgerRead.resolveArbiterState({
21
+ slug,
22
+ cwd,
23
+ arbiter,
24
+ env,
25
+ });
26
+ const fm = parseFrontmatter(task ?? '');
27
+ const needsAnswers = fm.needsAnswers === true;
28
+ const { missing } = resolveBlockedBy(fm.blockedBy, doneSlugs);
29
+ return {
30
+ refuse: missing.length > 0 && !override,
31
+ missing,
32
+ needsAnswers,
33
+ overridden: override,
34
+ };
35
+ }
36
+ //# sourceMappingURL=readiness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readiness.js","sourceRoot":"","sources":["../src/readiness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AA2D5C;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,OAAgC;IAEhC,MAAM,EAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAC,GAAG,OAAO,CAAC;IAEpD,yEAAyE;IACzE,+EAA+E;IAC/E,wEAAwE;IACxE,+EAA+E;IAC/E,MAAM,EAAC,IAAI,EAAE,SAAS,EAAC,GAAG,MAAM,UAAU,CAAC,mBAAmB,CAAC;QAC9D,IAAI;QACJ,GAAG;QACH,OAAO;QACP,GAAG;KACH,CAAC,CAAC;IACH,MAAM,EAAE,GAAG,gBAAgB,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,KAAK,IAAI,CAAC;IAE9C,MAAM,EAAC,OAAO,EAAC,GAAG,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAE5D,OAAO;QACN,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ;QACvC,OAAO;QACP,YAAY;QACZ,UAAU,EAAE,QAAQ;KACpB,CAAC;AACH,CAAC"}