dorfl 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/dist/advance-ci-template.d.ts +3 -3
  2. package/dist/advance-ci-template.js +1 -1
  3. package/dist/advance-ci-template.js.map +1 -1
  4. package/dist/advance-classify.d.ts +5 -5
  5. package/dist/advance-classify.d.ts.map +1 -1
  6. package/dist/advance-classify.js +4 -4
  7. package/dist/advance-drivers.d.ts +7 -7
  8. package/dist/advance-drivers.d.ts.map +1 -1
  9. package/dist/advance-drivers.js +5 -5
  10. package/dist/advance-drivers.js.map +1 -1
  11. package/dist/advance-isolated.d.ts +3 -3
  12. package/dist/advance-isolated.d.ts.map +1 -1
  13. package/dist/advance-isolated.js +1 -1
  14. package/dist/advance-lifecycle-template.d.ts +2 -2
  15. package/dist/advance-lifecycle-template.js +9 -9
  16. package/dist/advance-lifecycle-template.js.map +1 -1
  17. package/dist/advance-loop-driver.d.ts +3 -3
  18. package/dist/advance-loop-driver.d.ts.map +1 -1
  19. package/dist/advance-loop-driver.js +1 -1
  20. package/dist/advance-treeless-publish.d.ts +1 -1
  21. package/dist/advance.d.ts +11 -11
  22. package/dist/advance.d.ts.map +1 -1
  23. package/dist/advance.js +21 -21
  24. package/dist/advance.js.map +1 -1
  25. package/dist/advancing-lock.d.ts +1 -1
  26. package/dist/advancing-lock.js +5 -5
  27. package/dist/apply-decide.d.ts +2 -2
  28. package/dist/apply-decide.js +2 -2
  29. package/dist/apply-merge-action.d.ts +4 -4
  30. package/dist/apply-merge-action.js +2 -2
  31. package/dist/apply-persist.d.ts +5 -5
  32. package/dist/apply-persist.d.ts.map +1 -1
  33. package/dist/apply-persist.js +7 -7
  34. package/dist/apply-persist.js.map +1 -1
  35. package/dist/buildable-body.d.ts +14 -14
  36. package/dist/buildable-body.js +9 -9
  37. package/dist/claim-cas.d.ts +3 -3
  38. package/dist/claim-cas.js +1 -1
  39. package/dist/claim-cas.js.map +1 -1
  40. package/dist/cli.d.ts.map +1 -1
  41. package/dist/cli.js +83 -77
  42. package/dist/cli.js.map +1 -1
  43. package/dist/close-job-template.d.ts +3 -3
  44. package/dist/close-job-template.js +8 -8
  45. package/dist/close-job.d.ts +8 -8
  46. package/dist/close-job.js +25 -25
  47. package/dist/close-job.js.map +1 -1
  48. package/dist/complete.d.ts +3 -3
  49. package/dist/complete.js +8 -8
  50. package/dist/complete.js.map +1 -1
  51. package/dist/concurrency.d.ts +1 -1
  52. package/dist/concurrency.js +1 -1
  53. package/dist/config.d.ts +32 -32
  54. package/dist/config.js +5 -5
  55. package/dist/config.js.map +1 -1
  56. package/dist/continue-branch.d.ts +1 -1
  57. package/dist/continue-branch.js +1 -1
  58. package/dist/cwd-section.js +1 -1
  59. package/dist/cwd-section.js.map +1 -1
  60. package/dist/decision-engine.d.ts +2 -2
  61. package/dist/do-autopick.d.ts +6 -6
  62. package/dist/do-autopick.d.ts.map +1 -1
  63. package/dist/do-autopick.js +5 -5
  64. package/dist/do-autopick.js.map +1 -1
  65. package/dist/do-config.d.ts +3 -3
  66. package/dist/do-config.js +3 -3
  67. package/dist/do-config.js.map +1 -1
  68. package/dist/do-remote-auto.d.ts +2 -2
  69. package/dist/do-remote-auto.js +1 -1
  70. package/dist/do.d.ts +25 -25
  71. package/dist/do.d.ts.map +1 -1
  72. package/dist/do.js +22 -22
  73. package/dist/do.js.map +1 -1
  74. package/dist/drop-source.d.ts +2 -2
  75. package/dist/env-config.js +8 -8
  76. package/dist/env-config.js.map +1 -1
  77. package/dist/format.js +3 -3
  78. package/dist/format.js.map +1 -1
  79. package/dist/frontmatter.d.ts +33 -39
  80. package/dist/frontmatter.d.ts.map +1 -1
  81. package/dist/frontmatter.js +18 -31
  82. package/dist/frontmatter.js.map +1 -1
  83. package/dist/install-ci-branch-protection.d.ts +1 -1
  84. package/dist/install-ci-branch-protection.js +1 -1
  85. package/dist/install-ci-capabilities/advance-lifecycle.d.ts +1 -1
  86. package/dist/install-ci-capabilities/advance-lifecycle.js +1 -1
  87. package/dist/install-ci-capabilities/close-job.d.ts +1 -1
  88. package/dist/install-ci-capabilities/close-job.js +1 -1
  89. package/dist/install-ci-capabilities/example-noop.d.ts +1 -1
  90. package/dist/install-ci-capabilities/example-noop.js +1 -1
  91. package/dist/install-ci-capabilities/intake.d.ts +2 -2
  92. package/dist/install-ci-capabilities/intake.js +2 -2
  93. package/dist/install-ci-capabilities/verify.d.ts +1 -1
  94. package/dist/install-ci-capabilities/verify.js +1 -1
  95. package/dist/install-ci-core.d.ts +3 -3
  96. package/dist/install-ci-core.js +2 -2
  97. package/dist/install-ci-core.js.map +1 -1
  98. package/dist/install-ci-github.d.ts +1 -1
  99. package/dist/install-ci-github.js +1 -1
  100. package/dist/install-ci.d.ts +1 -1
  101. package/dist/install-ci.js +4 -4
  102. package/dist/install-ci.js.map +1 -1
  103. package/dist/intake-event.d.ts +6 -6
  104. package/dist/intake-event.js +6 -6
  105. package/dist/intake-marker.d.ts +3 -3
  106. package/dist/intake-marker.d.ts.map +1 -1
  107. package/dist/intake-triage.d.ts +1 -1
  108. package/dist/intake-triage.js +2 -2
  109. package/dist/intake-trigger-template.d.ts +8 -8
  110. package/dist/intake-trigger-template.d.ts.map +1 -1
  111. package/dist/intake-trigger-template.js +16 -16
  112. package/dist/intake-trigger-template.js.map +1 -1
  113. package/dist/intake.d.ts +50 -50
  114. package/dist/intake.d.ts.map +1 -1
  115. package/dist/intake.js +70 -70
  116. package/dist/intake.js.map +1 -1
  117. package/dist/integration-core.d.ts +17 -17
  118. package/dist/integration-core.js +17 -17
  119. package/dist/integration-core.js.map +1 -1
  120. package/dist/isolation.d.ts +3 -3
  121. package/dist/issue-provider.d.ts +4 -4
  122. package/dist/issue-provider.js +1 -1
  123. package/dist/item-lock.d.ts +21 -21
  124. package/dist/item-lock.d.ts.map +1 -1
  125. package/dist/item-lock.js +16 -16
  126. package/dist/item-path.d.ts +2 -2
  127. package/dist/item-path.js +2 -2
  128. package/dist/ledger-lint.d.ts +9 -9
  129. package/dist/ledger-lint.js +9 -9
  130. package/dist/ledger-read.d.ts +57 -57
  131. package/dist/ledger-read.d.ts.map +1 -1
  132. package/dist/ledger-read.js +24 -24
  133. package/dist/ledger-read.js.map +1 -1
  134. package/dist/ledger-write.d.ts +2 -2
  135. package/dist/ledger-write.js +1 -1
  136. package/dist/lifecycle-gather.d.ts +1 -1
  137. package/dist/lifecycle-gather.js +16 -16
  138. package/dist/lifecycle-gather.js.map +1 -1
  139. package/dist/lifecycle-pools.d.ts +4 -4
  140. package/dist/lifecycle-pools.js +1 -1
  141. package/dist/merge-question-surfacer.d.ts +3 -3
  142. package/dist/merge-question-surfacer.js +2 -2
  143. package/dist/merge-question-surfacer.js.map +1 -1
  144. package/dist/mint-adr.js +4 -4
  145. package/dist/mirror-pool-scan.d.ts +2 -2
  146. package/dist/mirror-pool-scan.js +3 -3
  147. package/dist/mirror-pool-scan.js.map +1 -1
  148. package/dist/needs-attention.d.ts +13 -13
  149. package/dist/needs-attention.d.ts.map +1 -1
  150. package/dist/needs-attention.js +11 -11
  151. package/dist/needs-attention.js.map +1 -1
  152. package/dist/orphan-sidecar.d.ts +2 -2
  153. package/dist/placement.d.ts +6 -6
  154. package/dist/placement.js +2 -2
  155. package/dist/prd-to-spec.d.ts +15 -1
  156. package/dist/prd-to-spec.d.ts.map +1 -1
  157. package/dist/prd-to-spec.js +36 -14
  158. package/dist/prd-to-spec.js.map +1 -1
  159. package/dist/prompt.d.ts +24 -24
  160. package/dist/prompt.d.ts.map +1 -1
  161. package/dist/prompt.js +29 -31
  162. package/dist/prompt.js.map +1 -1
  163. package/dist/protocol/CLAIM-PROTOCOL.md +4 -4
  164. package/dist/protocol/REVIEW-PROTOCOL.md +1 -1
  165. package/dist/protocol/TASKING-PROTOCOL.md +12 -12
  166. package/dist/protocol/WORK-CONTRACT.md +39 -39
  167. package/dist/protocol/spec-template.md +1 -1
  168. package/dist/protocol/task-template.md +3 -3
  169. package/dist/readiness.d.ts +1 -1
  170. package/dist/recover-isolated.js +1 -1
  171. package/dist/repo-config.js +12 -12
  172. package/dist/repo-config.js.map +1 -1
  173. package/dist/review-gate.d.ts +3 -3
  174. package/dist/review-gate.d.ts.map +1 -1
  175. package/dist/review-gate.js +11 -10
  176. package/dist/review-gate.js.map +1 -1
  177. package/dist/review-verdict.d.ts +2 -2
  178. package/dist/review-verdict.d.ts.map +1 -1
  179. package/dist/review-verdict.js +1 -1
  180. package/dist/run.d.ts +1 -1
  181. package/dist/run.js +5 -5
  182. package/dist/run.js.map +1 -1
  183. package/dist/scan.d.ts +10 -10
  184. package/dist/scan.d.ts.map +1 -1
  185. package/dist/scan.js +8 -8
  186. package/dist/scan.js.map +1 -1
  187. package/dist/select-order.d.ts +1 -1
  188. package/dist/select-priority.d.ts +12 -12
  189. package/dist/select-priority.d.ts.map +1 -1
  190. package/dist/select-priority.js +5 -5
  191. package/dist/select-priority.js.map +1 -1
  192. package/dist/sidecar.d.ts +2 -2
  193. package/dist/sidecar.js +2 -2
  194. package/dist/sidecar.js.map +1 -1
  195. package/dist/slug-namespace.d.ts +1 -1
  196. package/dist/slug-namespace.js +3 -3
  197. package/dist/slug-namespace.js.map +1 -1
  198. package/dist/spec-complete.js +2 -2
  199. package/dist/spec-complete.js.map +1 -1
  200. package/dist/start.d.ts +1 -1
  201. package/dist/start.js +3 -3
  202. package/dist/start.js.map +1 -1
  203. package/dist/status.d.ts +3 -3
  204. package/dist/status.js +4 -4
  205. package/dist/status.js.map +1 -1
  206. package/dist/surface-gate.d.ts +2 -2
  207. package/dist/surface-gate.d.ts.map +1 -1
  208. package/dist/surface-persist.d.ts +2 -2
  209. package/dist/surface-persist.d.ts.map +1 -1
  210. package/dist/tasker-review-loop.d.ts +8 -8
  211. package/dist/tasker-review-loop.d.ts.map +1 -1
  212. package/dist/tasker-review-loop.js +8 -8
  213. package/dist/tasker-review-loop.js.map +1 -1
  214. package/dist/tasking-eligibility.d.ts +21 -21
  215. package/dist/tasking-eligibility.d.ts.map +1 -1
  216. package/dist/tasking-eligibility.js +10 -10
  217. package/dist/tasking-lock.d.ts +8 -8
  218. package/dist/tasking-lock.d.ts.map +1 -1
  219. package/dist/tasking-lock.js +20 -21
  220. package/dist/tasking-lock.js.map +1 -1
  221. package/dist/tasking.d.ts +33 -33
  222. package/dist/tasking.d.ts.map +1 -1
  223. package/dist/tasking.js +89 -88
  224. package/dist/tasking.js.map +1 -1
  225. package/dist/triage-gate.d.ts +1 -1
  226. package/dist/triage-persist.d.ts +5 -5
  227. package/dist/triage-persist.js +15 -15
  228. package/dist/triage-persist.js.map +1 -1
  229. package/dist/verify-workflow-template.d.ts +1 -1
  230. package/dist/verify-workflow-template.js +2 -2
  231. package/dist/work-layout.d.ts +9 -7
  232. package/dist/work-layout.d.ts.map +1 -1
  233. package/dist/work-layout.js +9 -7
  234. package/dist/work-layout.js.map +1 -1
  235. package/dist/workspace.d.ts +1 -1
  236. package/package.json +1 -1
  237. package/src/advance-ci-template.ts +4 -4
  238. package/src/advance-classify.ts +5 -5
  239. package/src/advance-drivers.ts +10 -10
  240. package/src/advance-isolated.ts +3 -3
  241. package/src/advance-lifecycle-template.ts +9 -9
  242. package/src/advance-loop-driver.ts +3 -3
  243. package/src/advance-treeless-publish.ts +1 -1
  244. package/src/advance.ts +30 -30
  245. package/src/advancing-lock.ts +6 -6
  246. package/src/apply-decide.ts +2 -2
  247. package/src/apply-merge-action.ts +5 -5
  248. package/src/apply-persist.ts +8 -8
  249. package/src/buildable-body.ts +14 -14
  250. package/src/claim-cas.ts +4 -4
  251. package/src/cli.ts +94 -84
  252. package/src/close-job-template.ts +8 -8
  253. package/src/close-job.ts +26 -26
  254. package/src/complete.ts +11 -11
  255. package/src/concurrency.ts +1 -1
  256. package/src/config.ts +37 -37
  257. package/src/continue-branch.ts +1 -1
  258. package/src/cwd-section.ts +1 -1
  259. package/src/decision-engine.ts +3 -3
  260. package/src/do-autopick.ts +9 -9
  261. package/src/do-config.ts +6 -6
  262. package/src/do-remote-auto.ts +2 -2
  263. package/src/do.ts +49 -49
  264. package/src/drop-source.ts +2 -2
  265. package/src/env-config.ts +8 -8
  266. package/src/format.ts +3 -3
  267. package/src/frontmatter.ts +42 -60
  268. package/src/install-ci-branch-protection.ts +1 -1
  269. package/src/install-ci-capabilities/advance-lifecycle.ts +1 -1
  270. package/src/install-ci-capabilities/close-job.ts +1 -1
  271. package/src/install-ci-capabilities/example-noop.ts +1 -1
  272. package/src/install-ci-capabilities/intake.ts +2 -2
  273. package/src/install-ci-capabilities/verify.ts +1 -1
  274. package/src/install-ci-core.ts +4 -4
  275. package/src/install-ci-github.ts +1 -1
  276. package/src/install-ci.ts +4 -4
  277. package/src/intake-event.ts +6 -6
  278. package/src/intake-marker.ts +3 -3
  279. package/src/intake-triage.ts +2 -2
  280. package/src/intake-trigger-template.ts +17 -17
  281. package/src/intake.ts +97 -97
  282. package/src/integration-core.ts +35 -35
  283. package/src/isolation.ts +3 -3
  284. package/src/issue-provider.ts +4 -4
  285. package/src/item-lock.ts +21 -21
  286. package/src/item-path.ts +2 -2
  287. package/src/ledger-lint.ts +9 -9
  288. package/src/ledger-read.ts +81 -81
  289. package/src/ledger-write.ts +3 -3
  290. package/src/lifecycle-gather.ts +16 -16
  291. package/src/lifecycle-pools.ts +4 -4
  292. package/src/merge-question-surfacer.ts +4 -4
  293. package/src/mint-adr.ts +4 -4
  294. package/src/mirror-pool-scan.ts +5 -5
  295. package/src/needs-attention.ts +22 -22
  296. package/src/orphan-sidecar.ts +2 -2
  297. package/src/placement.ts +6 -6
  298. package/src/prd-to-spec.ts +51 -15
  299. package/src/prompt.ts +33 -35
  300. package/src/readiness.ts +1 -1
  301. package/src/recover-isolated.ts +1 -1
  302. package/src/repo-config.ts +12 -12
  303. package/src/review-gate.ts +12 -11
  304. package/src/review-verdict.ts +2 -2
  305. package/src/run.ts +6 -6
  306. package/src/scan.ts +15 -15
  307. package/src/select-order.ts +1 -1
  308. package/src/select-priority.ts +13 -13
  309. package/src/sidecar.ts +3 -3
  310. package/src/slug-namespace.ts +3 -3
  311. package/src/spec-complete.ts +2 -2
  312. package/src/start.ts +4 -4
  313. package/src/status.ts +7 -7
  314. package/src/surface-gate.ts +2 -2
  315. package/src/surface-persist.ts +2 -2
  316. package/src/tasker-review-loop.ts +15 -15
  317. package/src/tasking-eligibility.ts +21 -21
  318. package/src/tasking-lock.ts +27 -28
  319. package/src/tasking.ts +124 -123
  320. package/src/triage-gate.ts +1 -1
  321. package/src/triage-persist.ts +16 -16
  322. package/src/verify-workflow-template.ts +2 -2
  323. package/src/work-layout.ts +9 -7
  324. package/src/workspace.ts +1 -1
package/dist/cli.js CHANGED
@@ -218,10 +218,10 @@ function buildRegistrySetAdvanceTick(options) {
218
218
  lifecycleGates: {
219
219
  triage: config.observationTriage !== 'off',
220
220
  surface: config.surfaceBlockers,
221
- // `surfaceStaging` widens the SURFACE candidate set into STAGING (prd
221
+ // `surfaceStaging` widens the SURFACE candidate set into STAGING (spec
222
222
  // `staging-surface-and-apply-promote-safety` F2). Default `true` — a
223
- // tasked `needsAnswers` task in `tasks/backlog/` (or prd in
224
- // `prds/proposed/`) surfaces its questions BEFORE promotion. BUILD/claim
223
+ // tasked `needsAnswers` task in `tasks/backlog/` (or spec in
224
+ // `specs/proposed/`) surfaces its questions BEFORE promotion. BUILD/claim
225
225
  // stays pool-only either way.
226
226
  surfaceStaging: config.surfaceStaging,
227
227
  },
@@ -249,10 +249,10 @@ function buildRegistrySetAdvanceTick(options) {
249
249
  identity: config.identity,
250
250
  autoTask: config.autoTask,
251
251
  integration: config.integration,
252
- // The per-TRANSITION TASKING override: the `do prd:` tasking path threads
252
+ // The per-TRANSITION TASKING override: the `do spec:` tasking path threads
253
253
  // `taskingIntegration ?? integration`; the build path stays on `integration`.
254
254
  taskingIntegration: config.taskingIntegration,
255
- // The TASK-PLACEMENT configured default (`do prd:` tasking output:
255
+ // The TASK-PLACEMENT configured default (`do spec:` tasking output:
256
256
  // `pre-backlog` staged vs `ready` pool). No operator flag on this
257
257
  // registry-driven advance context, so only the configured default rung is
258
258
  // threaded (the resolver still layers untrusted-origin force + built-in floor).
@@ -261,7 +261,7 @@ function buildRegistrySetAdvanceTick(options) {
261
261
  verify: config.verify,
262
262
  // Single-job build path: gate the REBASED tip (the default) unconditionally.
263
263
  freshWorktreeGate: config.freshWorktreeGate,
264
- // Cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-
264
+ // Cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-
265
265
  // parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)) — resolved per-repo
266
266
  // and threaded so the registry-driven advance path's `do` inherits it.
267
267
  mergeRetries: config.mergeRetries,
@@ -300,7 +300,7 @@ function buildRegistrySetAdvanceTick(options) {
300
300
  triageGate: harnessTriageGate({ harness, agentCmd: config.agentCmd }),
301
301
  triageModel: config.model,
302
302
  // The ANSWERED-MERGE LAND DISPATCH context (task
303
- // `apply-rung-merge-disposition`, prd `land-time-reverify-and-parallel-
303
+ // `apply-rung-merge-disposition`, spec `land-time-reverify-and-parallel-
304
304
  // merge-ceiling`): the dispatcher cuts a per-job worktree via
305
305
  // `workspace.ts` `createJob` off the hub mirror (so we thread the resolved
306
306
  // `workspacesDir` + the real arbiter URL — the per-mirror tree-less
@@ -396,7 +396,7 @@ function runFlagOverrides(flags, command) {
396
396
  // fleet conditional lives in `runOnce`, not in this flag mapping).
397
397
  Object.assign(overrides, freshWorktreeGateFlagOverrides(flags));
398
398
  // `--merge-retries <n>` rides the SAME chain: the cross-job merge-serialiser
399
- // CAS-retry cap (prd `land-time-reverify-and-parallel-merge-ceiling` Story 5 /
399
+ // CAS-retry cap (spec `land-time-reverify-and-parallel-merge-ceiling` Story 5 /
400
400
  // Applied Answer q1 (a)). The `run` fleet inherits the resolved cap through
401
401
  // the converged `performIntegration` core (config.mergeRetries threads into
402
402
  // the merge loop, replacing the bare `DEFAULT_MERGE_RETRIES` fallback).
@@ -409,7 +409,7 @@ function formatItemLine(item) {
409
409
  }
410
410
  /**
411
411
  * Resolve the EXPLICIT operator placement override from `--tasks-land-in <where>`
412
- * (the top of the `do prd:` tasking-placement precedence — task
412
+ * (the top of the `do spec:` tasking-placement precedence — task
413
413
  * `runner-deterministic-slice-placement-policy-and-precedence`). Mirrors the
414
414
  * `flagMode === 'merge'` ⇒ `explicitMerge: true` shape: it contributes
415
415
  * `explicitTasksLandIn` ONLY when the operator actually typed the flag, so an
@@ -469,9 +469,15 @@ function printPrdToSpecReport(result) {
469
469
  ? '=== prd-to-spec (DRY RUN — nothing written) ==='
470
470
  : '=== prd-to-spec ===');
471
471
  if (result.resync) {
472
- const changed = result.resync.docs.filter((d) => !d.unchanged).length;
472
+ const changed = result.resync.docs.filter((d) => !d.unchanged && !d.skipped).length;
473
473
  console.log(`Contract re-sync: ${verb} sync ${result.resync.docs.length} protocol ` +
474
474
  `doc(s) (${changed} changed) + bump ${result.resync.versionPath}.`);
475
+ // Surface any doc whose SOURCE could not be resolved LOUDLY: it was NOT
476
+ // copied, so the contract in the target repo is incomplete for that doc.
477
+ for (const skipped of result.resync.docs.filter((d) => d.skipped)) {
478
+ console.warn(` !! ${skipped.name}: SOURCE could not be resolved — NOT copied ` +
479
+ `(the contract doc is missing/unchanged in the target repo).`);
480
+ }
475
481
  }
476
482
  console.log(`Folders: ${verb} move ${result.folderMoves.length} folder(s).`);
477
483
  for (const m of result.folderMoves) {
@@ -492,7 +498,7 @@ function printPrdToSpecReport(result) {
492
498
  return;
493
499
  }
494
500
  if (result.leaks.length === 0) {
495
- console.log('Leak scan: GREEN (no surviving prd data ref).');
501
+ console.log('Leak scan: GREEN (no surviving spec data ref).');
496
502
  }
497
503
  else {
498
504
  console.error(`Leak scan: FAILED (${result.leaks.length} leak(s)):`);
@@ -507,11 +513,12 @@ function printLeak(leak) {
507
513
  /**
508
514
  * Resolve a task-only command's slug argument through the §3a namespace guard
509
515
  * (`resolveTaskOnlyArg`): accept bare (= task) + `task:` (explicit alias),
510
- * REJECT `spec:` with a clear "operates on tasks, not specs" error (and the
511
- * legacy `prd:` with "operates on tasks, not prds", still accepted through the
512
- * cutover). On rejection it prints the error to stderr and exits 1 (the task-only
513
- * commands never act on a spec). An OMITTED slug (`start`/`complete`/`prompt`
514
- * infer it from the branch) passes through untouched.
516
+ * REJECT `spec:` with a clear "operates on tasks, not specs" error. On rejection
517
+ * it prints the error to stderr and exits 1 (the task-only commands never act on
518
+ * a spec). An OMITTED slug (`start`/`complete`/`prompt` infer it from the branch)
519
+ * passes through untouched. (The legacy `prd:` prefix is a DEAD namespace token
520
+ * after the hard cutover — it is neither special-cased nor rejected here; a
521
+ * `prd:<slug>` arg resolves as a bare literal task slug.)
515
522
  *
516
523
  * `do` is the ONE command that spans both namespaces; it consumes the full
517
524
  * `resolveSlug` (with the cross-namespace collision check) in the `do-in-place`
@@ -589,10 +596,10 @@ function buildInteractiveLauncher(flags, configPath, repoPath) {
589
596
  * switching to its `work/<slug>` branch WITHOUT claiming). The runtime
590
597
  * difference is exactly the `resume` flag — `resume` forces it on (its only mode
591
598
  * is to re-engage), while `start` honours the (now hidden) `--resume` alias.
592
- * Both are task-only (§3a: accept bare + `task:`, reject `prd:`).
599
+ * Both are task-only (§3a: accept bare + `task:`, reject `spec:`).
593
600
  */
594
601
  async function runStartAction(rawSlug, flags, resume) {
595
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
602
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
596
603
  const slug = resolveTaskOnlySlug(rawSlug);
597
604
  const cwd = process.cwd();
598
605
  // `resume --isolated <slug>`: re-engage the slug's RETAINED job worktree (the
@@ -908,7 +915,7 @@ export function buildProgram() {
908
915
  .option('--dry-run', 'show the intended push without mutating the arbiter')
909
916
  .option('--ignore-not-ready', 'override the readiness guard: claim despite an unmet blockedBy, and silence the needsAnswers warning (loud, never default)')
910
917
  .action(async (rawSlug, flags) => {
911
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
918
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
912
919
  const slug = resolveTaskOnlySlug(rawSlug);
913
920
  // Wrap ONLY this CLI surface's `performClaim` call with the spinner
914
921
  // helper (task `claim-cas-spinner`): the push can take seconds, so the
@@ -1016,7 +1023,7 @@ export function buildProgram() {
1016
1023
  const remote = flags.remote !== undefined && flags.remote.trim() !== ''
1017
1024
  ? flags.remote
1018
1025
  : undefined;
1019
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
1026
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
1020
1027
  const theSlug = resolveTaskOnlySlug(rawSlug);
1021
1028
  const configPath = flags.config ?? defaultConfigPath();
1022
1029
  const { dir: configuredRoot, config } = loadHumanWorktreesDir(configPath);
@@ -1060,10 +1067,10 @@ export function buildProgram() {
1060
1067
  program
1061
1068
  .command('prompt')
1062
1069
  .helpGroup(ADVANCED_GROUP)
1063
- .description("Print to stdout the work-agent prompt for a task: the canonical CLAIM-PROTOCOL wrapper + the task's own ## Prompt (with <slug> and source prd substituted). Resolves work/in-progress/<slug>.md then work/backlog/<slug>.md; infers <slug> from a work/<slug> branch when omitted. Read-only, stdout only — the same assembly the autonomous runner feeds agentCmd.")
1070
+ .description("Print to stdout the work-agent prompt for a task: the canonical CLAIM-PROTOCOL wrapper + the task's own ## Prompt (with <slug> and source spec substituted). Resolves work/in-progress/<slug>.md then work/backlog/<slug>.md; infers <slug> from a work/<slug> branch when omitted. Read-only, stdout only — the same assembly the autonomous runner feeds agentCmd.")
1064
1071
  .argument('[slug]', 'the slug to render (inferred from a work/<slug> branch if omitted)')
1065
1072
  .action((rawSlug) => {
1066
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
1073
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
1067
1074
  const slug = resolveTaskOnlySlug(rawSlug);
1068
1075
  // Resolve the `promptGuidance` NUDGE namespace through the SAME chain the
1069
1076
  // gate family uses (env > per-repo > global > default), so e.g. a
@@ -1106,7 +1113,7 @@ export function buildProgram() {
1106
1113
  .option('--no-fresh-worktree-gate', 'run the acceptance gate in the current checkout (the pre-rebase tree) — the opt-out for when the per-gate install cost is too high')
1107
1114
  .option('--merge-retries <n>', 'cross-job merge-serialiser CAS-retry cap (see `run --help`); resolved flag > env > per-repo > global > default 1000.')
1108
1115
  .action(async (rawSlug, flags) => {
1109
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
1116
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
1110
1117
  const slug = resolveTaskOnlySlug(rawSlug);
1111
1118
  const cwd = process.cwd();
1112
1119
  const { global, override } = loadGlobalAndOverride(flags.config);
@@ -1166,7 +1173,7 @@ export function buildProgram() {
1166
1173
  // `--fresh-worktree-gate`/`--no-fresh-worktree-gate` rides the SAME chain.
1167
1174
  ...freshWorktreeGateFlagOverrides(flags),
1168
1175
  // `--merge-retries <n>` rides the SAME chain: the cross-job merge-serialiser
1169
- // CAS-retry cap (prd `land-time-reverify-and-parallel-merge-ceiling` Story 5
1176
+ // CAS-retry cap (spec `land-time-reverify-and-parallel-merge-ceiling` Story 5
1170
1177
  // / Applied Answer q1 (a)).
1171
1178
  ...mergeRetriesFlagOverrides(flags),
1172
1179
  // `--no-pr` (the PR-INTENT axis) rides the SAME chain.
@@ -1206,7 +1213,7 @@ export function buildProgram() {
1206
1213
  // a single-job path, so the resolved flag is passed UNCONDITIONALLY (no
1207
1214
  // fleet downgrade).
1208
1215
  freshWorktreeGate: config.freshWorktreeGate,
1209
- // Cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-
1216
+ // Cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-
1210
1217
  // parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)) — the resolved
1211
1218
  // per-repo value reaches the merge loop via `performComplete`→
1212
1219
  // `performIntegration`.
@@ -1237,13 +1244,13 @@ export function buildProgram() {
1237
1244
  program
1238
1245
  .command('do')
1239
1246
  .helpGroup(HEADLINE_GROUP)
1240
- .description('The per-repo WORKER (the CI command): claim + onboard onto work/<slug>, run the agent, gate, integrate, and exit. In the CURRENT checkout by default (refuses on a dirty tree, integrates in-place). With --remote <r>: against a REGISTERED repo with NO checkout — materialise a hub mirror + job worktree in the agents\u2019 area, run the same pipeline there, then reap. do <slug> | do task:<slug> | do spec:<slug> (the tasking path; the legacy prd:<slug> is still accepted) | do (auto-pick one) | do <a> <b> (those, in sequence) | do -n <x> (x eligible, in sequence). Auto-pick draws TASKS-FIRST then SPECS-to-task by default (per-repo selectionOrder reorders the pools). --propose (default) / --merge resolved at integrate-time. Supersedes ar-run.sh.')
1247
+ .description('The per-repo WORKER (the CI command): claim + onboard onto work/<slug>, run the agent, gate, integrate, and exit. In the CURRENT checkout by default (refuses on a dirty tree, integrates in-place). With --remote <r>: against a REGISTERED repo with NO checkout — materialise a hub mirror + job worktree in the agents\u2019 area, run the same pipeline there, then reap. do <slug> | do task:<slug> | do spec:<slug> (the tasking path) | do (auto-pick one) | do <a> <b> (those, in sequence) | do -n <x> (x eligible, in sequence). Auto-pick draws TASKS-FIRST then SPECS-to-task by default (per-repo selectionOrder reorders the pools). --propose (default) / --merge resolved at integrate-time. Supersedes ar-run.sh.')
1241
1248
  // EXTENSIBLE argument grammar (the three do-* tasks grow this one block):
1242
1249
  // `do-autopick` widens the single optional positional into a VARIADIC one so
1243
1250
  // `do` (zero args = auto-pick), `do <a> <b> …` (named, in sequence), and
1244
1251
  // `do <slug>` (exactly one) all share the one command. `-n <x>` is the count
1245
1252
  // for the auto-pick form. `do` stays SEQUENTIAL (parallelism is `run`).
1246
- .argument('[slugs...]', 'the item(s) to do: bare (= the task), task:<slug>, or spec:<slug> (task the spec; the legacy prd:<slug> is still accepted). Zero args = auto-pick; multiple = do them in sequence.')
1253
+ .argument('[slugs...]', 'the item(s) to do: bare (= the task), task:<slug>, or spec:<slug> (task the spec). Zero args = auto-pick; multiple = do them in sequence.')
1247
1254
  .option('-c, --config <path>', 'config file path', defaultConfigPath())
1248
1255
  .option('--arbiter <remote>', 'name of the arbiter git remote (default: per-repo/global defaultArbiter)')
1249
1256
  .option('-n, --number <x>', 'AUTO-PICK x eligible items and do them IN SEQUENCE (ordered by selectionOrder, default drain = tasks-first then prds-to-task). Sequential — never a parallelism knob (that is `run`). Mutually exclusive with naming items.')
@@ -1252,7 +1259,7 @@ export function buildProgram() {
1252
1259
  .option('--isolated', "build in an ISOLATED job worktree off THIS repo's arbiter (inferred from cwd) instead of taking over the current checkout, then integrate + reap \u2014 the in-place-but-isolated form. Shares the same grammar as the no-checkout forms: a single named item, multiple named items (in sequence), AND -n/auto-pick over the mirror-side eligible-pool scan. Always SEQUENTIAL (parallelism is `run` / the CI matrix). Orthogonal to --remote (a foreign repo); with --remote, remote wins (isolation is already implied).")
1253
1260
  .option('--merge', 'integrate in merge mode this invocation (mutually exclusive with --propose; overrides config)')
1254
1261
  .option('--propose', 'integrate in propose mode this invocation (default; mutually exclusive with --merge; overrides config)')
1255
- .option('--tasks-land-in <where>', 'where `do prd:<slug>` tasking output lands: `pre-backlog` (staged, not agent-eligible) or `ready` (the agent POOL). The EXPLICIT operator override at the top of the placement precedence (explicit flag > untrusted-origin forces staging > tasksLandIn default > built-in). Resolved flag > env (DORFL_TASKS_LAND_IN) > per-repo > global > built-in.')
1262
+ .option('--tasks-land-in <where>', 'where `do spec:<slug>` tasking output lands: `pre-backlog` (staged, not agent-eligible) or `ready` (the agent POOL). The EXPLICIT operator override at the top of the placement precedence (explicit flag > untrusted-origin forces staging > tasksLandIn default > built-in). Resolved flag > env (DORFL_TASKS_LAND_IN) > per-repo > global > built-in.')
1256
1263
  .option('--no-pr', 'propose without opening a PR: push the branch but deliberately skip the review request, even on an authed GitHub arbiter (the explicit suppress-PR intent). Resolved flag > env > per-repo > global > default off.')
1257
1264
  .option('--ignore-diverged-main', 'override the in-place divergence guard: run even when local main is ahead of <arbiter>/main (unpushed). The work still lands on the arbiter; local main is left for you to `git rebase`. In-place only; loud, never default.')
1258
1265
  .option('--allow-backlog', 'do task:<slug> ONLY: also FIND, CLAIM, and COMPLETE a task that lives in tasks/backlog/ (staging), driving it in place WITHOUT promoting it to the pool (so no advance leg / run daemon can claim it out from under you). The done-move goes tasks/backlog/ -> tasks/done/ directly (your explicit drive IS the promotion). EXPLICIT-INVOCATION-ONLY: default off, never set by run/auto-pick/advance or config/env.')
@@ -1266,9 +1273,9 @@ export function buildProgram() {
1266
1273
  .option('--no-review', 'do NOT run Gate 2 this invocation (overrides config)')
1267
1274
  .option('--review-model <id>', 'model the Gate-2 review agent runs on (de-correlated from the builder; routing intent). Resolved flag > env > per-repo > global > default.')
1268
1275
  .option('--review-max-rounds <n>', 'bound the revise/review loop; on exhaustion force needs-attention (default 2)')
1269
- .option('--tasker-loop', 'run the tasker IMPROVER loop on `do prd:<slug>` (review→edit→converge over the produced task set). ON by default; --no-tasker-loop skips it. DISTINCT from the acceptance gate (--review).')
1270
- .option('--no-tasker-loop', 'skip the tasker improver loop on `do prd:<slug>`')
1271
- .option('--tasker-loop-max <n>', 'cap the tasker improver loop on `do prd:<slug>` (in-context review passes); on exhaustion with blockers, reject via needsAnswers / route the prd to needs-attention (default 3)')
1276
+ .option('--tasker-loop', 'run the tasker IMPROVER loop on `do spec:<slug>` (review→edit→converge over the produced task set). ON by default; --no-tasker-loop skips it. DISTINCT from the acceptance gate (--review).')
1277
+ .option('--no-tasker-loop', 'skip the tasker improver loop on `do spec:<slug>`')
1278
+ .option('--tasker-loop-max <n>', 'cap the tasker improver loop on `do spec:<slug>` (in-context review passes); on exhaustion with blockers, reject via needsAnswers / route the spec to needs-attention (default 3)')
1272
1279
  .option('--tasker-loop-model <id>', 'model the tasker improver loop review agent runs on (de-correlated from the tasker; routing intent). Resolved flag > env > per-repo > global > default. DISTINCT from --review-model.')
1273
1280
  .option('--fresh-worktree-gate', 'run the acceptance gate (prepare then verify) against the REBASED tip in a CLEAN throwaway worktree (the tree that actually integrates), so a green gate provably describes the merged artifact. ON by default. Resolved flag > env > per-repo > global > default on.')
1274
1281
  .option('--no-fresh-worktree-gate', "run the acceptance gate in the agent's build worktree (the pre-rebase tree) as before — the opt-out for when the per-gate install cost is too high")
@@ -1405,7 +1412,7 @@ export function buildProgram() {
1405
1412
  // Host-only runner IDENTITY — scopes git/provider ops only (not the
1406
1413
  // agent launch); absent ⇒ ambient.
1407
1414
  identity: remoteConfig.identity,
1408
- // `do --remote prd:<slug>` tasking-gate policy (task-build path ignores it).
1415
+ // `do --remote spec:<slug>` tasking-gate policy (task-build path ignores it).
1409
1416
  autoTask: remoteConfig.autoTask,
1410
1417
  // The resolved `promptGuidance` nudge — threaded into the remote worker
1411
1418
  // prompt (runRemotePipeline → buildAgentPrompt), mirroring in-place `do`.
@@ -1413,7 +1420,7 @@ export function buildProgram() {
1413
1420
  integration: remoteConfig.integration,
1414
1421
  // EXPLICIT `--merge` override for the untrusted-origin build-propose rule.
1415
1422
  explicitMerge: flagMode === 'merge',
1416
- // Per-TRANSITION TASKING override (the `do --remote prd:` tasking path).
1423
+ // Per-TRANSITION TASKING override (the `do --remote spec:` tasking path).
1417
1424
  taskingIntegration: remoteConfig.taskingIntegration,
1418
1425
  // TASK-PLACEMENT: the configured default + the EXPLICIT operator override
1419
1426
  // (`--tasks-land-in`), the top of the placement precedence — mirrors
@@ -1425,7 +1432,7 @@ export function buildProgram() {
1425
1432
  // Single-job build path: gate the REBASED tip (the default) unconditionally.
1426
1433
  freshWorktreeGate: remoteConfig.freshWorktreeGate,
1427
1434
  // Cross-job merge-serialiser CAS-retry cap (resolved through the per-repo
1428
- // chain on the arbiter-side `.dorfl.json` too) — prd
1435
+ // chain on the arbiter-side `.dorfl.json` too) — spec
1429
1436
  // `land-time-reverify-and-parallel-merge-ceiling` Story 5.
1430
1437
  mergeRetries: remoteConfig.mergeRetries,
1431
1438
  noPR: remoteConfig.noPR,
@@ -1442,7 +1449,7 @@ export function buildProgram() {
1442
1449
  agentCmd: remoteConfig.agentCmd,
1443
1450
  })
1444
1451
  : undefined,
1445
- // The tasker IMPROVER loop on the `do --remote prd:` path is ON by default
1452
+ // The tasker IMPROVER loop on the `do --remote spec:` path is ON by default
1446
1453
  // (auto-tasking has no `verify` floor, so the loop is the task path's
1447
1454
  // quality engine). `--tasker-loop`/`--no-tasker-loop` gates wiring the seam;
1448
1455
  // `taskerLoopMax`/`taskerLoopModel` resolve per-repo (flag > env > per-repo
@@ -1455,7 +1462,7 @@ export function buildProgram() {
1455
1462
  : undefined,
1456
1463
  taskerLoopMax: remoteConfig.taskerLoopMax,
1457
1464
  taskerLoopModel: remoteConfig.taskerLoopModel,
1458
- // The task-SET ACCEPTANCE GATE on the `do --remote prd:` path too.
1465
+ // The task-SET ACCEPTANCE GATE on the `do --remote spec:` path too.
1459
1466
  taskReviewGate: remoteConfig.review
1460
1467
  ? harnessTaskAcceptanceGate({
1461
1468
  harness: remoteHarness,
@@ -1559,7 +1566,7 @@ export function buildProgram() {
1559
1566
  // ops (claim, push, integrate, `gh`) — NEVER the agent launch. Absent ⇒
1560
1567
  // ambient (today's behaviour). Mapped Config → DoOptions like model/agentCmd.
1561
1568
  identity: config.identity,
1562
- // `do prd:<slug>` tasking-gate policy (the task-build path ignores it).
1569
+ // `do spec:<slug>` tasking-gate policy (the task-build path ignores it).
1563
1570
  autoTask: config.autoTask,
1564
1571
  // The resolved `promptGuidance` NUDGE namespace (e.g. `testFirst`),
1565
1572
  // threaded into the worker prompt by performDo → buildAgentPrompt so a
@@ -1572,11 +1579,11 @@ export function buildProgram() {
1572
1579
  // typed `--merge` (`flagMode`), never when `merge` came from config — so an
1573
1580
  // untrusted-origin task still forces propose under a config `merge`.
1574
1581
  explicitMerge: flagMode === 'merge',
1575
- // Per-TRANSITION TASKING override: the `do prd:` tasking path threads
1582
+ // Per-TRANSITION TASKING override: the `do spec:` tasking path threads
1576
1583
  // `taskingIntegration ?? integration`; the task-build path stays on
1577
1584
  // `integration`. Unset ⇒ tasking falls back to `integration` (today's behaviour).
1578
1585
  taskingIntegration: config.taskingIntegration,
1579
- // TASK-PLACEMENT (`do prd:` tasking output): the configured default rung +
1586
+ // TASK-PLACEMENT (`do spec:` tasking output): the configured default rung +
1580
1587
  // the EXPLICIT operator override `--tasks-land-in` (top of the precedence).
1581
1588
  // `explicitTasksLandIn` is set ONLY when the flag was typed (mirrors
1582
1589
  // `explicitMerge`), so an untrusted-origin staging force still wins under a
@@ -1589,7 +1596,7 @@ export function buildProgram() {
1589
1596
  verify: config.verify,
1590
1597
  // Single-job build path: gate the REBASED tip (the default) unconditionally.
1591
1598
  freshWorktreeGate: config.freshWorktreeGate,
1592
- // Cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-
1599
+ // Cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-
1593
1600
  // parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)) — resolved per-repo
1594
1601
  // and threaded to `performComplete`→`performIntegration`.
1595
1602
  mergeRetries: config.mergeRetries,
@@ -1613,7 +1620,7 @@ export function buildProgram() {
1613
1620
  reviewGate: config.review
1614
1621
  ? harnessReviewGate({ harness, agentCmd: config.agentCmd })
1615
1622
  : undefined,
1616
- // The tasker IMPROVER loop on the `do prd:` tasking path is ON by default
1623
+ // The tasker IMPROVER loop on the `do spec:` tasking path is ON by default
1617
1624
  // (auto-tasking has no `verify` floor — the loop is the task path's quality
1618
1625
  // engine). `--tasker-loop`/`--no-tasker-loop` gates wiring the seam;
1619
1626
  // `taskerLoopMax`/`taskerLoopModel` resolve per-repo (flag > env > per-repo
@@ -1640,7 +1647,7 @@ export function buildProgram() {
1640
1647
  note: (message) => console.error(`>> ${message}`),
1641
1648
  noteBlock: (message) => console.error(message),
1642
1649
  };
1643
- // `--allow-backlog` is EXPLICIT-SINGLE-TASK-ONLY (prd
1650
+ // `--allow-backlog` is EXPLICIT-SINGLE-TASK-ONLY (spec
1644
1651
  // `do-allow-backlog-drive-staged-tasks-without-promotion`, decision 4): it
1645
1652
  // drives ONE named staged task in place. It must NOT combine with the
1646
1653
  // AUTO-PICK (zero-args / -n) or MULTI-ITEM forms — those select FROM the
@@ -1694,33 +1701,33 @@ export function buildProgram() {
1694
1701
  process.exit(result.exitCode);
1695
1702
  });
1696
1703
  // `advance` — the SIBLING top-level verb (NOT a `do` subcommand; `do`
1697
- // subcommands + a standalone `task` verb are REJECTED in prd `advance-loop`).
1704
+ // subcommands + a standalone `task` verb are REJECTED in spec `advance-loop`).
1698
1705
  // It reuses the SAME shared `prefix:arg` resolver `do` uses, EXTENDED with the
1699
1706
  // `obs:` namespace, and wires the classify → lock → execute SKELETON: classify
1700
1707
  // the rung (read-only, no model, no lock), take the `advancing` CAS borrow, then
1701
- // dispatch winner-only — build/task rungs ORCHESTRATE `do`/`do prd:` (never a
1708
+ // dispatch winner-only — build/task rungs ORCHESTRATE `do`/`do spec:` (never a
1702
1709
  // duplicate), surface/apply/triage dispatch to a named executor seam later
1703
1710
  // tasks fill. The DRIVERS (one-shot/loop) + `-n` + per-action gates and the
1704
1711
  // rung BODIES are LATER tasks; the bare eligible-SET form errors clearly here.
1705
1712
  program
1706
1713
  .command('advance')
1707
1714
  .helpGroup(HEADLINE_GROUP)
1708
- .description('Advance work/ item(s) one lifecycle rung toward ready/built (PRD advance-loop), the SEQUENTIAL one-shot driver over the advance tick. advance <slug> (bare = the task) | advance spec:<slug> (the spec tasking rung; the legacy prd:<slug> is still accepted) | advance obs:<slug> (triage an observation) | advance (auto-pick one eligible) | advance <a> <b> (those, in sequence) | advance -n <x> (x eligible, in sequence). Each item: classify (read-only, no model, no lock) → take the `advancing` CAS lock → dispatch winner-only — build/task rungs ORCHESTRATE `do`/`do spec:`, surface/apply always run, triage respects observationTriage (off|ask|auto). The bare/`-n` selection respects the per-action gates (build→autoBuild, task→autoTask, triage→observationTriage); `-n` is ALWAYS sequential (parallelism is `run` / the CI matrix).')
1709
- .argument('[slugs...]', 'the item(s) to advance: bare (= the task), task:<slug>, spec:<slug> (the legacy prd:<slug> is still accepted), or obs:<slug> (an observation). Zero args = auto-pick one eligible; multiple = advance them in sequence.')
1715
+ .description('Advance work/ item(s) one lifecycle rung toward ready/built (SPEC advance-loop), the SEQUENTIAL one-shot driver over the advance tick. advance <slug> (bare = the task) | advance spec:<slug> (the spec tasking rung) | advance obs:<slug> (triage an observation) | advance (auto-pick one eligible) | advance <a> <b> (those, in sequence) | advance -n <x> (x eligible, in sequence). Each item: classify (read-only, no model, no lock) → take the `advancing` CAS lock → dispatch winner-only — build/task rungs ORCHESTRATE `do`/`do spec:`, surface/apply always run, triage respects observationTriage (off|ask|auto). The bare/`-n` selection respects the per-action gates (build→autoBuild, task→autoTask, triage→observationTriage); `-n` is ALWAYS sequential (parallelism is `run` / the CI matrix).')
1716
+ .argument('[slugs...]', 'the item(s) to advance: bare (= the task), task:<slug>, spec:<slug>, or obs:<slug> (an observation). Zero args = auto-pick one eligible; multiple = advance them in sequence.')
1710
1717
  .option('-c, --config <path>', 'config file path', defaultConfigPath())
1711
1718
  .option('--arbiter <remote>', 'name of the arbiter git remote (default: per-repo/global defaultArbiter)')
1712
1719
  .option('-n, --number <x>', 'AUTO-PICK x eligible items and advance them IN SEQUENCE (ordered by selectionOrder, default drain = tasks-first then prds-to-task). Sequential — never a parallelism knob (that is `run` / the CI matrix). Mutually exclusive with naming items.')
1713
1720
  .option('--isolated', "advance in an ISOLATED worktree off THIS repo's arbiter (inferred from cwd) instead of taking over the current checkout, then integrate + reap — the in-place-but-isolated form. Shares the same grammar: a single named item, multiple named items (in sequence), AND -n/auto-pick over the mirror-side eligible-pool scan. Always SEQUENTIAL (parallelism is `run` / the CI matrix). Lets you advance from a busy/dirty checkout or anywhere with a participating arbiter.")
1714
1721
  .option('--selection-order <order>', 'order the auto-pick pools (build/task/surface/triage; apply is always first): a preset keyword (drain (default) | groom) or an explicit comma-separated pool list. Resolved flag > env > per-repo > global > default.')
1715
1722
  .option('--observation-triage <mode>', 'the observation-inbox gate (off|ask|auto): off (default) leaves observations untouched (the triage pool is dropped from auto-pick); ask surfaces a promote/keep/delete question for each untriaged observation; auto auto-disposes the no-question cases (duplicate/map) and asks about the rest. Resolved flag > env > per-repo > global > default. An explicit `advance obs:<slug>` bypasses the selection gate and runs in ask-mode (auto-disposes only under `auto`).')
1716
- .option('--surface-blockers', 'the declared-blocked-work gate (the orthogonal peer of --observation-triage): render a task/prd carrying needsAnswers:true into an answerable question sidecar (the needsAnswers-blocked pool is enumerated into auto-pick). Resolved flag > env > per-repo > global > default off. An explicit `advance <slug>`/`advance prd:<slug>` bypasses this selection gate and surfaces regardless. Does NOT gate apply (an answered sidecar still applies) or needs-attention (always on).')
1717
- .option('--no-surface-blockers', 'leave a needsAnswers:true task/prd silently blocked (default; the blocked pool is dropped from auto-pick)')
1718
- .option('--strict-merge-approval', 'opt in to the host-agnostic "dismiss stale approvals on base change" discipline (prd `land-time-reverify-and-parallel-merge-ceiling` sidecar OQ6): when the merge-base CHANGED between the human’s merge-answer and the apply step, RE-SURFACE the merge-question (clear the answer back to no-answer; re-author the question on main/runner under the advancing lock) instead of auto-landing on a green re-verify. Default OFF (a green re-verify is trusted as sufficient; honour the prior answer). Story #16’s RED-re-verify refusal is UNCHANGED and independent of this flag. Resolved flag > env > per-repo > global > default off.')
1723
+ .option('--surface-blockers', 'the declared-blocked-work gate (the orthogonal peer of --observation-triage): render a task/spec carrying needsAnswers:true into an answerable question sidecar (the needsAnswers-blocked pool is enumerated into auto-pick). Resolved flag > env > per-repo > global > default off. An explicit `advance <slug>`/`advance spec:<slug>` bypasses this selection gate and surfaces regardless. Does NOT gate apply (an answered sidecar still applies) or needs-attention (always on).')
1724
+ .option('--no-surface-blockers', 'leave a needsAnswers:true task/spec silently blocked (default; the blocked pool is dropped from auto-pick)')
1725
+ .option('--strict-merge-approval', 'opt in to the host-agnostic "dismiss stale approvals on base change" discipline (spec `land-time-reverify-and-parallel-merge-ceiling` sidecar OQ6): when the merge-base CHANGED between the human’s merge-answer and the apply step, RE-SURFACE the merge-question (clear the answer back to no-answer; re-author the question on main/runner under the advancing lock) instead of auto-landing on a green re-verify. Default OFF (a green re-verify is trusted as sufficient; honour the prior answer). Story #16’s RED-re-verify refusal is UNCHANGED and independent of this flag. Resolved flag > env > per-repo > global > default off.')
1719
1726
  .option('--no-strict-merge-approval', 'honour the prior merge-answer and land when the rebased tip re-verifies GREEN even if the merge-base changed (default; the cheap green-re-verify-is-enough path)')
1720
1727
  .option('--merge-questions <mode>', 'the merge-question SURFACER gate (off|ask|auto): off drops the surfacer (only for a repo that lands by some other means); ask (default) enumerates unmerged `work/*` branches and surfaces a merge-question sidecar a human answers; auto self-supplies the `merge` answer and lands via the SAME deterministic apply-time re-verify (the merge-mode-like fast path). SEPARATE axis from --observation-triage with a HIGHER default (a dropped merge-question means pushed work never lands). Resolved flag > env > per-repo > global > default ask.')
1721
1728
  .option('--merge', 'integrate the advanced item(s) in merge mode this invocation (mutually exclusive with --propose; overrides config). The CI merge shape is a SINGLE SEQUENTIAL job, so this rides the `-n`/named-sequence path, never the matrix.')
1722
1729
  .option('--propose', 'integrate the advanced item(s) in propose mode this invocation (default; mutually exclusive with --merge; overrides config). The CI propose shape is the parallel matrix (one PR per item).')
1723
- .option('--tasks-land-in <where>', 'where `advance prd:<slug>` tasking output lands: `pre-backlog` (staged) or `ready` (the agent POOL). The EXPLICIT operator override at the top of the placement precedence. Resolved flag > env (DORFL_TASKS_LAND_IN) > per-repo > global > built-in.')
1730
+ .option('--tasks-land-in <where>', 'where `advance spec:<slug>` tasking output lands: `pre-backlog` (staged) or `ready` (the agent POOL). The EXPLICIT operator override at the top of the placement precedence. Resolved flag > env (DORFL_TASKS_LAND_IN) > per-repo > global > built-in.')
1724
1731
  .option('--watch', "stream the build agent's high-signal events live by tailing the pi session log (requires harness: pi; READ-ONLY observer — does not change outcome/gate/git). The same view `do --watch` gives, threaded through the build rung; CI uses it so the job log shows the agent working instead of freezing.")
1725
1732
  .action(async (rawSlugs, flags) => {
1726
1733
  // Variadic grammar (mirrors `do`): zero args = AUTO-PICK; one = the single
@@ -1836,7 +1843,7 @@ export function buildProgram() {
1836
1843
  integration: remoteConfig.integration,
1837
1844
  // EXPLICIT `--merge` override for the untrusted-origin build-propose rule.
1838
1845
  explicitMerge: flagMode === 'merge',
1839
- // Per-TRANSITION TASKING override (the isolated `do --remote prd:` path).
1846
+ // Per-TRANSITION TASKING override (the isolated `do --remote spec:` path).
1840
1847
  taskingIntegration: remoteConfig.taskingIntegration,
1841
1848
  // TASK-PLACEMENT: configured default + EXPLICIT `--tasks-land-in` override
1842
1849
  // (set only when typed, mirroring `explicitMerge`).
@@ -1846,7 +1853,7 @@ export function buildProgram() {
1846
1853
  verify: remoteConfig.verify,
1847
1854
  // Single-job build path: gate the REBASED tip (the default) unconditionally.
1848
1855
  freshWorktreeGate: remoteConfig.freshWorktreeGate,
1849
- // Cross-job merge-serialiser CAS-retry cap — prd
1856
+ // Cross-job merge-serialiser CAS-retry cap — spec
1850
1857
  // `land-time-reverify-and-parallel-merge-ceiling` Story 5.
1851
1858
  mergeRetries: remoteConfig.mergeRetries,
1852
1859
  noPR: remoteConfig.noPR,
@@ -1974,7 +1981,7 @@ export function buildProgram() {
1974
1981
  // EXPLICIT `--merge` override for the untrusted-origin build-propose rule (a
1975
1982
  // bare `advance` auto-pick passes no flag ⇒ unset ⇒ untrusted forces propose).
1976
1983
  explicitMerge: flagMode === 'merge',
1977
- // Per-TRANSITION TASKING override (the `do prd:` tasking path threads
1984
+ // Per-TRANSITION TASKING override (the `do spec:` tasking path threads
1978
1985
  // `taskingIntegration ?? integration`; the build path stays on `integration`).
1979
1986
  taskingIntegration: config.taskingIntegration,
1980
1987
  // TASK-PLACEMENT: configured default + EXPLICIT `--tasks-land-in` override
@@ -1985,7 +1992,7 @@ export function buildProgram() {
1985
1992
  verify: config.verify,
1986
1993
  // Single-job build path: gate the REBASED tip (the default) unconditionally.
1987
1994
  freshWorktreeGate: config.freshWorktreeGate,
1988
- // Cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-
1995
+ // Cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-
1989
1996
  // parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)).
1990
1997
  mergeRetries: config.mergeRetries,
1991
1998
  noPR: config.noPR,
@@ -2112,7 +2119,7 @@ export function buildProgram() {
2112
2119
  .action(async (flags) => {
2113
2120
  const config = resolveGlobalConfig(loadConfig(flags.config), {});
2114
2121
  const workspacesDir = flags.workspace ?? config.workspacesDir;
2115
- // The `gc`-STYLE ledger SWEEP (prd `ledger-integrity` story 3): a SEPARATE
2122
+ // The `gc`-STYLE ledger SWEEP (spec `ledger-integrity` story 3): a SEPARATE
2116
2123
  // surface from the worktree reaper below — it REPORTS one-slug-one-folder
2117
2124
  // violations in a repo's `work/` lifecycle ledger and NEVER deletes (a human
2118
2125
  // resolves each). Distinct `work/`: the ledger, not the execution substrate.
@@ -2120,7 +2127,7 @@ export function buildProgram() {
2120
2127
  const repoPath = typeof flags.ledger === 'string' ? flags.ledger : process.cwd();
2121
2128
  const result = sweepLedgerDuplicates(repoPath);
2122
2129
  // The UNIFIED-LOCK stuck/orphaned-lock REPORT (task
2123
- // `release-lock-verb-and-gc-stuck-report`, prd
2130
+ // `release-lock-verb-and-gc-stuck-report`, spec
2124
2131
  // `ledger-status-per-item-lock-refs` US #12/#13/#14): generalises the
2125
2132
  // advancing-marker report from advancing-only to the unified per-item
2126
2133
  // lock. The locks live on the ARBITER ref (`refs/dorfl/lock/*`),
@@ -2196,7 +2203,7 @@ export function buildProgram() {
2196
2203
  // ALL are REPORTED here (never auto-deleted — no automatic sweep exists; a
2197
2204
  // human clears a NAMED unified lock via `release-lock`).
2198
2205
  //
2199
- // SCOPED to the ATTENTION verdicts only (prd US#14/#21, ADR
2206
+ // SCOPED to the ATTENTION verdicts only (spec US#14/#21, ADR
2200
2207
  // `ledger-status-on-per-item-lock-refs`: this surface is the STUCK /
2201
2208
  // crash-orphaned lock, NOT every held one): a `kept-stuck` (terminal +
2202
2209
  // stuck) or a `cleared-stale`-eligible (terminal + stale active = orphaned)
@@ -2223,7 +2230,7 @@ export function buildProgram() {
2223
2230
  dryRun: flags.dryRun === true,
2224
2231
  note: (message) => console.error(`>> ${message}`),
2225
2232
  });
2226
- // The ORPHAN-SIDECAR sweep (prd
2233
+ // The ORPHAN-SIDECAR sweep (spec
2227
2234
  // `agentic-question-resolution-retire-disposition-vocabulary`, US #10) rides
2228
2235
  // the SAME `--remote-branches` invocation the SCHEDULED CI lifecycle workflow
2229
2236
  // runs (`dorfl gc --remote-branches --arbiter origin`) — so the reap of a
@@ -2421,7 +2428,7 @@ export function buildProgram() {
2421
2428
  .option('--reset', 'DISCARD the kept work: delete the remote work/<slug> branch FIRST, then move to backlog so the next claim starts FRESH (guarded; a deliberate departure from the never-delete-the-remote-branch invariant). Never the default.')
2422
2429
  .option('-m, --message <note>', 'append a dated handoff note to the item body for the next agent (append-only; applies to both default and --reset)')
2423
2430
  .action(async (rawSlug, flags) => {
2424
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
2431
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
2425
2432
  const slug = resolveTaskOnlySlug(rawSlug);
2426
2433
  const cwd = flags.cwd ?? process.cwd();
2427
2434
  // Route the requeue (default keep+continue / --reset discard / -m handoff)
@@ -2457,12 +2464,12 @@ export function buildProgram() {
2457
2464
  : ' (kept the work branch; next claim continues from its tip)';
2458
2465
  console.log(`Requeued '${slug}' to backlog for re-claiming.${how}`);
2459
2466
  });
2460
- // `promote [item]` (prd `staging-pool-position-gate-and-trust-model`, tasks
2467
+ // `promote [item]` (spec `staging-pool-position-gate-and-trust-model`, tasks
2461
2468
  // `pre-backlog-staging-folder-and-promote-step-a` /
2462
2469
  // `pre-prd-staging-pool-split-and-untrusted-prd-placement`): the HUMAN/runner-
2463
2470
  // owned verb that moves a STAGED item into its agent-eligible POOL — a task
2464
- // `work/pre-backlog/<slug>.md → work/backlog/<slug>.md`, a prd
2465
- // `work/prds/proposed/<slug>.md → work/prds/ready/<slug>.md` — as a tree-less CAS on the
2471
+ // `work/pre-backlog/<slug>.md → work/backlog/<slug>.md`, a spec
2472
+ // `work/specs/proposed/<slug>.md → work/specs/ready/<slug>.md` — as a tree-less CAS on the
2466
2473
  // arbiter, the SAME trust model + mechanism as `requeue`. The agent emits STAGED;
2467
2474
  // only this verb (a human, or the runner) admits it to the pool. With NO argument
2468
2475
  // it LISTS what is promotable (the "what is staged waiting for me?" discovery), so
@@ -2470,7 +2477,7 @@ export function buildProgram() {
2470
2477
  program
2471
2478
  .command('promote [item]')
2472
2479
  .helpGroup(HEADLINE_GROUP)
2473
- .description('Admit a STAGED item into its agent-eligible POOL (the runner/human side of the staging gate): a task `work/pre-backlog/<slug>.md → work/backlog/<slug>.md`, a prd `work/prds/proposed/<slug>.md → work/prds/ready/<slug>.md`, published as a TREE-LESS compare-and-swap to the arbiter ref (EXACTLY like requeue/claim — it never stages/commits in the cwd tree). The agent only ever CREATES staged; this verb is the gate a human (or the runner) opens. Accepts `task:<slug>` / `prd:<slug>` / a bare `<slug>` (= task). With NO argument, LISTS every promotable item (the tasks in pre-backlog/ + the prds in prds/proposed/ on the arbiter) so you can see what is staged waiting for promotion. Idempotent: promoting an already-pooled slug is a clean no-op success.')
2480
+ .description(`Admit a STAGED item into its agent-eligible POOL (the runner/human side of the staging gate): a task \`work/pre-backlog/<slug>.md → work/backlog/<slug>.md\`, a spec \`${workFolderPrefix('specs-proposed')}<slug>.md → ${workFolderPrefix('specs-ready')}<slug>.md\`, published as a TREE-LESS compare-and-swap to the arbiter ref (EXACTLY like requeue/claim — it never stages/commits in the cwd tree). The agent only ever CREATES staged; this verb is the gate a human (or the runner) opens. Accepts \`task:<slug>\` / \`spec:<slug>\` / a bare \`<slug>\` (= task). With NO argument, LISTS every promotable item (the tasks in pre-backlog/ + the specs in specs/proposed/ on the arbiter) so you can see what is staged waiting for promotion. Idempotent: promoting an already-pooled slug is a clean no-op success.`)
2474
2481
  .option('-c, --config <path>', 'config file path', defaultConfigPath())
2475
2482
  .option('--cwd <dir>', 'the repo/working clone whose arbiter remote the tree-less move is resolved FROM (default: cwd) — an ORIGIN SOURCE only; the move is published to the arbiter, never to this tree')
2476
2483
  .option('--arbiter <remote>', 'the arbiter git remote the promotion is CAS-published to / the staging folders are listed from (default: origin)')
@@ -2489,7 +2496,7 @@ export function buildProgram() {
2489
2496
  process.exit(1);
2490
2497
  }
2491
2498
  if (listed.items.length === 0) {
2492
- console.log(`Nothing staged to promote on ${arbiter}/main (work/pre-backlog/ and work/prds/proposed/ are empty).`);
2499
+ console.log(`Nothing staged to promote on ${arbiter}/main (work/pre-backlog/ and ${workFolderPrefix('specs-proposed')} are empty).`);
2493
2500
  return;
2494
2501
  }
2495
2502
  console.log('Staged, awaiting promotion (run `promote <item>`):');
@@ -2498,11 +2505,10 @@ export function buildProgram() {
2498
2505
  }
2499
2506
  return;
2500
2507
  }
2501
- // AN ITEM → promote it. `task:`/`spec:` are explicit (the legacy `prd:`
2502
- // prefix is still ACCEPTED as an input alias through the cutover — the
2503
- // contract task drops it); a bare slug defaults to a task (mirrors
2504
- // `requeue`). An `obs:`/`observation:` prefix is rejected (observations have
2505
- // no pool).
2508
+ // AN ITEM → promote it. `task:`/`spec:` are explicit; a bare slug defaults to
2509
+ // a task (mirrors `requeue`). An `obs:`/`observation:` prefix is rejected
2510
+ // (observations have no pool). A legacy `prd:` prefix is a DEAD namespace token
2511
+ // after the hard cutover it resolves as a bare literal task slug, not a spec.
2506
2512
  const parsed = parseSlugArg(rawItem);
2507
2513
  if (parsed.explicit === 'observation') {
2508
2514
  console.error(`error: promote takes a task or spec, not an observation ('${rawItem}'). Observations have no agent pool.`);
@@ -2529,7 +2535,7 @@ export function buildProgram() {
2529
2535
  // the `work/advancing/<entry>.md` marker is gone and an advance hold is now just
2530
2536
  // `action: advance` on the UNIFIED per-item lock, so `release-lock <item>` (below)
2531
2537
  // is the SOLE named human release for ALL holds (implement/task/advance).
2532
- // `release-lock <item>` (task `release-lock-verb-and-gc-stuck-report`, prd
2538
+ // `release-lock <item>` (task `release-lock-verb-and-gc-stuck-report`, spec
2533
2539
  // `ledger-status-per-item-lock-refs` US #14): the HUMAN-invoked named release of
2534
2540
  // a stuck/orphaned UNIFIED per-item lock (`refs/dorfl/lock/<entry>`) —
2535
2541
  // the GENERALISATION of `release-advancing` from the advancing-only marker to
@@ -2545,7 +2551,7 @@ export function buildProgram() {
2545
2551
  program
2546
2552
  .command('release-lock <item>')
2547
2553
  .helpGroup(HEADLINE_GROUP)
2548
- .description('Clear a NAMED stuck/orphaned UNIFIED per-item lock (refs/dorfl/lock/<entry>) by DELETING the ref on the arbiter — the recovery verb for a lock the system orphaned (a crashed build/task/advance that left the hold behind). The generalisation of `release-advancing` from the advancing marker to the ONE lock per item. Same trust model as `requeue`: a HUMAN asserts the lock is dead by NAMING it; the tool never guesses liveness (the lock has NO heartbeat, so there is NO automatic sweep / age-based reaper anywhere). Accepts the same item forms as the lock API: `task:<slug>` / `prd:<slug>` / `obs:<slug>` / a bare `<slug>` (= task). Idempotent — re-running on an already-cleared lock is a clean exit-0 no-op (deleting the lock ref is “all locks released”, recoverable). NEVER `--force`. Discoverable via `gc --ledger` (it REPORTS every lingering lock, never deletes).')
2554
+ .description('Clear a NAMED stuck/orphaned UNIFIED per-item lock (refs/dorfl/lock/<entry>) by DELETING the ref on the arbiter — the recovery verb for a lock the system orphaned (a crashed build/task/advance that left the hold behind). The generalisation of `release-advancing` from the advancing marker to the ONE lock per item. Same trust model as `requeue`: a HUMAN asserts the lock is dead by NAMING it; the tool never guesses liveness (the lock has NO heartbeat, so there is NO automatic sweep / age-based reaper anywhere). Accepts the same item forms as the lock API: `task:<slug>` / `spec:<slug>` / `obs:<slug>` / a bare `<slug>` (= task). Idempotent — re-running on an already-cleared lock is a clean exit-0 no-op (deleting the lock ref is “all locks released”, recoverable). NEVER `--force`. Discoverable via `gc --ledger` (it REPORTS every lingering lock, never deletes).')
2549
2555
  .option('-c, --config <path>', 'config file path', defaultConfigPath())
2550
2556
  .option('--cwd <dir>', 'the repo/working clone whose arbiter remote the lock ref is DELETED on (default: cwd)')
2551
2557
  .option('--arbiter <remote>', 'the arbiter git remote the lock ref is deleted on (default: origin)')
@@ -2574,7 +2580,7 @@ export function buildProgram() {
2574
2580
  console.error(`error: ${result.message}`);
2575
2581
  process.exit(1);
2576
2582
  });
2577
- // `drop <slug>` (prd `agentic-question-resolution-retire-disposition-vocabulary`,
2583
+ // `drop <slug>` (spec `agentic-question-resolution-retire-disposition-vocabulary`,
2578
2584
  // US #5/#11; task `direct-delete-question-cli-helper`): the DIRECT "throw it
2579
2585
  // away" verb — `git rm` a source item AND its question sidecar (when present) in
2580
2586
  // ONE revertible commit, the reason in the commit MESSAGE (git history is the
@@ -2588,7 +2594,7 @@ export function buildProgram() {
2588
2594
  program
2589
2595
  .command('drop <slug>')
2590
2596
  .helpGroup(HEADLINE_GROUP)
2591
- .description('DIRECTLY delete a source item + its question sidecar (when present) in ONE revertible commit — the "I just want to throw this away" path that does NOT round-trip through the decision engine or any agent. Resolves the source by its namespaced identity (`task:<slug>` / `prd:<slug>` / `obs:<slug>` / a bare `<slug>` = task), `git rm`s the source AND its sidecar together, and records your --reason in the commit MESSAGE (git history is the archive). A single revertible commit, so a wrong delete is recoverable via `git revert`. DISTINCT from `remote rm` (the hub-mirror deleter). A LOCAL working-tree commit (like the apply rung); it does not touch the arbiter — push/integrate it as you normally would. If the named source is already gone it is a clean no-op (nothing to throw away).')
2597
+ .description('DIRECTLY delete a source item + its question sidecar (when present) in ONE revertible commit — the "I just want to throw this away" path that does NOT round-trip through the decision engine or any agent. Resolves the source by its namespaced identity (`task:<slug>` / `spec:<slug>` / `obs:<slug>` / a bare `<slug>` = task), `git rm`s the source AND its sidecar together, and records your --reason in the commit MESSAGE (git history is the archive). A single revertible commit, so a wrong delete is recoverable via `git revert`. DISTINCT from `remote rm` (the hub-mirror deleter). A LOCAL working-tree commit (like the apply rung); it does not touch the arbiter — push/integrate it as you normally would. If the named source is already gone it is a clean no-op (nothing to throw away).')
2592
2598
  .option('-c, --config <path>', 'config file path', defaultConfigPath())
2593
2599
  .option('--cwd <dir>', 'the working clone the revertible delete commit is made in (default: cwd)')
2594
2600
  .option('--reason <text>', 'why you are throwing this away — recorded in the commit MESSAGE (git history is the archive). Optional; recorded as "(no reason given)" when omitted.')
@@ -2658,7 +2664,7 @@ export function buildProgram() {
2658
2664
  console.error(`>> ${resolved.message}`);
2659
2665
  }
2660
2666
  const config = resolved.config;
2661
- // Resolve the PER-OUTCOME integration modes (prd US #9): `intake` decides
2667
+ // Resolve the PER-OUTCOME integration modes (spec US #9): `intake` decides
2662
2668
  // the artifact TYPE at runtime, so a single --merge/--propose can't express
2663
2669
  // a type-conditional policy. The granular flags override the aggregate; an
2664
2670
  // UNSET type falls back to the per-repo/global `integration` (the SAME chain
@@ -2734,17 +2740,17 @@ export function buildProgram() {
2734
2740
  }
2735
2741
  process.exit(result.exitCode);
2736
2742
  });
2737
- // The CI CLOSE-JOB driver (prd `runner-in-ci`, capability E; task
2743
+ // The CI CLOSE-JOB driver (spec `runner-in-ci`, capability E; task
2738
2744
  // `install-ci-close-job-workflow`). The thin JOB the emitted close-job workflow
2739
2745
  // invokes on a merge to main: resolve which source issue(s) the landed work
2740
- // closes (resolveClosingIssue), run the "prd complete?" query for the prd case
2746
+ // closes (resolveClosingIssue), run the "spec complete?" query for the spec case
2741
2747
  // (prd-complete-query, done), and close via the IssueProvider seam — all
2742
2748
  // UNCHANGED engine pieces, CONSUMED not re-built (the Out-of-Scope fence). CI
2743
2749
  // owns ONLY the job + trigger. Local-runnable too (a manual catch-up close).
2744
2750
  program
2745
2751
  .command('close-merged-issues')
2746
2752
  .helpGroup(ADVANCED_GROUP)
2747
- .description('Close source issues whose work has landed on main (CI capability E, prd runner-in-ci). Resolves each closing issue from the work/ tree (resolveClosingIssue: a lone task closes its own `issue:`; a fanned task reaches the number via `task.prd: → prd issue:`), runs the existing "prd complete?" query for the prd case (closes ONLY when ALL its prd:<slug> tasks are in work/done/), and closes via the IssueProvider seam (atomic comment+close; NO direct gh). Re-implements NONE of the resolution/query/close — it WIRES them. Invoked by the emitted close-job workflow on a merge to main; DEGRADES (never crashes) on a missing/unauthenticated gh.')
2753
+ .description('Close source issues whose work has landed on main (CI capability E, spec runner-in-ci). Resolves each closing issue from the work/ tree (resolveClosingIssue: a lone task closes its own `issue:`; a fanned task reaches the number via `task.spec: → spec issue:`), runs the existing "spec complete?" query for the spec case (closes ONLY when ALL its spec:<slug> tasks are in work/done/), and closes via the IssueProvider seam (atomic comment+close; NO direct gh). Re-implements NONE of the resolution/query/close — it WIRES them. Invoked by the emitted close-job workflow on a merge to main; DEGRADES (never crashes) on a missing/unauthenticated gh.')
2748
2754
  .option('--cwd <dir>', 'the repo working dir whose work/ tree to scan (default: cwd)')
2749
2755
  .option('--gh-bin <bin>', 'the gh CLI binary (default: gh on PATH)')
2750
2756
  .option('--json', 'output the raw result as JSON')