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/src/cli.ts CHANGED
@@ -353,10 +353,10 @@ function buildRegistrySetAdvanceTick(options: {
353
353
  lifecycleGates: {
354
354
  triage: config.observationTriage !== 'off',
355
355
  surface: config.surfaceBlockers,
356
- // `surfaceStaging` widens the SURFACE candidate set into STAGING (prd
356
+ // `surfaceStaging` widens the SURFACE candidate set into STAGING (spec
357
357
  // `staging-surface-and-apply-promote-safety` F2). Default `true` — a
358
- // tasked `needsAnswers` task in `tasks/backlog/` (or prd in
359
- // `prds/proposed/`) surfaces its questions BEFORE promotion. BUILD/claim
358
+ // tasked `needsAnswers` task in `tasks/backlog/` (or spec in
359
+ // `specs/proposed/`) surfaces its questions BEFORE promotion. BUILD/claim
360
360
  // stays pool-only either way.
361
361
  surfaceStaging: config.surfaceStaging,
362
362
  },
@@ -388,10 +388,10 @@ function buildRegistrySetAdvanceTick(options: {
388
388
  identity: config.identity,
389
389
  autoTask: config.autoTask,
390
390
  integration: config.integration,
391
- // The per-TRANSITION TASKING override: the `do prd:` tasking path threads
391
+ // The per-TRANSITION TASKING override: the `do spec:` tasking path threads
392
392
  // `taskingIntegration ?? integration`; the build path stays on `integration`.
393
393
  taskingIntegration: config.taskingIntegration,
394
- // The TASK-PLACEMENT configured default (`do prd:` tasking output:
394
+ // The TASK-PLACEMENT configured default (`do spec:` tasking output:
395
395
  // `pre-backlog` staged vs `ready` pool). No operator flag on this
396
396
  // registry-driven advance context, so only the configured default rung is
397
397
  // threaded (the resolver still layers untrusted-origin force + built-in floor).
@@ -400,7 +400,7 @@ function buildRegistrySetAdvanceTick(options: {
400
400
  verify: config.verify,
401
401
  // Single-job build path: gate the REBASED tip (the default) unconditionally.
402
402
  freshWorktreeGate: config.freshWorktreeGate,
403
- // Cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-
403
+ // Cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-
404
404
  // parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)) — resolved per-repo
405
405
  // and threaded so the registry-driven advance path's `do` inherits it.
406
406
  mergeRetries: config.mergeRetries,
@@ -439,7 +439,7 @@ function buildRegistrySetAdvanceTick(options: {
439
439
  triageGate: harnessTriageGate({harness, agentCmd: config.agentCmd}),
440
440
  triageModel: config.model,
441
441
  // The ANSWERED-MERGE LAND DISPATCH context (task
442
- // `apply-rung-merge-disposition`, prd `land-time-reverify-and-parallel-
442
+ // `apply-rung-merge-disposition`, spec `land-time-reverify-and-parallel-
443
443
  // merge-ceiling`): the dispatcher cuts a per-job worktree via
444
444
  // `workspace.ts` `createJob` off the hub mirror (so we thread the resolved
445
445
  // `workspacesDir` + the real arbiter URL — the per-mirror tree-less
@@ -544,7 +544,7 @@ interface RunFlags extends ScanFlags {
544
544
  reviewMaxRounds?: string;
545
545
  /** `--fresh-worktree-gate` / `--no-fresh-worktree-gate` — gate the REBASED tip in a clean throwaway worktree (ON by default). */
546
546
  freshWorktreeGate?: boolean;
547
- /** `--merge-retries <n>` — the cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)). */
547
+ /** `--merge-retries <n>` — the cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)). */
548
548
  mergeRetries?: string;
549
549
  }
550
550
 
@@ -583,7 +583,7 @@ function runFlagOverrides(flags: RunFlags, command?: Commander): PartialConfig {
583
583
  // fleet conditional lives in `runOnce`, not in this flag mapping).
584
584
  Object.assign(overrides, freshWorktreeGateFlagOverrides(flags));
585
585
  // `--merge-retries <n>` rides the SAME chain: the cross-job merge-serialiser
586
- // CAS-retry cap (prd `land-time-reverify-and-parallel-merge-ceiling` Story 5 /
586
+ // CAS-retry cap (spec `land-time-reverify-and-parallel-merge-ceiling` Story 5 /
587
587
  // Applied Answer q1 (a)). The `run` fleet inherits the resolved cap through
588
588
  // the converged `performIntegration` core (config.mergeRetries threads into
589
589
  // the merge loop, replacing the bare `DEFAULT_MERGE_RETRIES` fallback).
@@ -661,7 +661,7 @@ interface CompleteFlags {
661
661
  reviewMaxRounds?: string;
662
662
  /** `--fresh-worktree-gate` / `--no-fresh-worktree-gate` — gate the REBASED tip in a clean throwaway worktree (ON by default). */
663
663
  freshWorktreeGate?: boolean;
664
- /** `--merge-retries <n>` — the cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)). */
664
+ /** `--merge-retries <n>` — the cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)). */
665
665
  mergeRetries?: string;
666
666
  /** `--isolated`: finish the slug's retained job worktree (the stranded-branch recover). */
667
667
  isolated?: boolean;
@@ -670,7 +670,7 @@ interface CompleteFlags {
670
670
 
671
671
  /**
672
672
  * Resolve the EXPLICIT operator placement override from `--tasks-land-in <where>`
673
- * (the top of the `do prd:` tasking-placement precedence — task
673
+ * (the top of the `do spec:` tasking-placement precedence — task
674
674
  * `runner-deterministic-slice-placement-policy-and-precedence`). Mirrors the
675
675
  * `flagMode === 'merge'` ⇒ `explicitMerge: true` shape: it contributes
676
676
  * `explicitTasksLandIn` ONLY when the operator actually typed the flag, so an
@@ -742,7 +742,7 @@ interface DoFlags {
742
742
  strictMergeApproval?: boolean;
743
743
  merge?: boolean;
744
744
  propose?: boolean;
745
- /** `--tasks-land-in <pre-backlog|ready>`: the explicit operator placement override for `do prd:` tasking output (top of the placement precedence). Resolves into the `tasksLandIn` config key. */
745
+ /** `--tasks-land-in <pre-backlog|ready>`: the explicit operator placement override for `do spec:` tasking output (top of the placement precedence). Resolves into the `tasksLandIn` config key. */
746
746
  tasksLandIn?: string;
747
747
  /** `--no-pr` ⇒ commander stores `pr === false` (the suppress-PR intent). */
748
748
  pr?: boolean;
@@ -758,15 +758,15 @@ interface DoFlags {
758
758
  review?: boolean;
759
759
  reviewModel?: string;
760
760
  reviewMaxRounds?: string;
761
- /** `--tasker-loop` / `--no-tasker-loop` — the tasker improver loop on/off toggle (`do prd:` path). Resolves into the `taskerLoop` config key. */
761
+ /** `--tasker-loop` / `--no-tasker-loop` — the tasker improver loop on/off toggle (`do spec:` path). Resolves into the `taskerLoop` config key. */
762
762
  taskerLoop?: boolean;
763
- /** `--tasker-loop-max <n>` — the tasker improver loop's in-context convergence cap (`do prd:` path). Resolves into the `taskerLoopMax` config key. */
763
+ /** `--tasker-loop-max <n>` — the tasker improver loop's in-context convergence cap (`do spec:` path). Resolves into the `taskerLoopMax` config key. */
764
764
  taskerLoopMax?: string;
765
- /** `--tasker-loop-model <id>` — the tasker improver loop reviewer's de-correlated model (`do prd:` path). Resolves into the `taskerLoopModel` config key. */
765
+ /** `--tasker-loop-model <id>` — the tasker improver loop reviewer's de-correlated model (`do spec:` path). Resolves into the `taskerLoopModel` config key. */
766
766
  taskerLoopModel?: string;
767
767
  /** `--fresh-worktree-gate` / `--no-fresh-worktree-gate` — gate the REBASED tip in a clean throwaway worktree (ON by default). */
768
768
  freshWorktreeGate?: boolean;
769
- /** `--merge-retries <n>` — the cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)). */
769
+ /** `--merge-retries <n>` — the cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)). */
770
770
  mergeRetries?: string;
771
771
  }
772
772
 
@@ -844,11 +844,21 @@ function printPrdToSpecReport(result: PrdToSpecResult): void {
844
844
  );
845
845
 
846
846
  if (result.resync) {
847
- const changed = result.resync.docs.filter((d) => !d.unchanged).length;
847
+ const changed = result.resync.docs.filter(
848
+ (d) => !d.unchanged && !d.skipped,
849
+ ).length;
848
850
  console.log(
849
851
  `Contract re-sync: ${verb} sync ${result.resync.docs.length} protocol ` +
850
852
  `doc(s) (${changed} changed) + bump ${result.resync.versionPath}.`,
851
853
  );
854
+ // Surface any doc whose SOURCE could not be resolved LOUDLY: it was NOT
855
+ // copied, so the contract in the target repo is incomplete for that doc.
856
+ for (const skipped of result.resync.docs.filter((d) => d.skipped)) {
857
+ console.warn(
858
+ ` !! ${skipped.name}: SOURCE could not be resolved — NOT copied ` +
859
+ `(the contract doc is missing/unchanged in the target repo).`,
860
+ );
861
+ }
852
862
  }
853
863
  console.log(`Folders: ${verb} move ${result.folderMoves.length} folder(s).`);
854
864
  for (const m of result.folderMoves) {
@@ -876,7 +886,7 @@ function printPrdToSpecReport(result: PrdToSpecResult): void {
876
886
  return;
877
887
  }
878
888
  if (result.leaks.length === 0) {
879
- console.log('Leak scan: GREEN (no surviving prd data ref).');
889
+ console.log('Leak scan: GREEN (no surviving spec data ref).');
880
890
  } else {
881
891
  console.error(`Leak scan: FAILED (${result.leaks.length} leak(s)):`);
882
892
  for (const leak of result.leaks) {
@@ -969,11 +979,12 @@ interface CloseMergedIssuesFlags {
969
979
  /**
970
980
  * Resolve a task-only command's slug argument through the §3a namespace guard
971
981
  * (`resolveTaskOnlyArg`): accept bare (= task) + `task:` (explicit alias),
972
- * REJECT `spec:` with a clear "operates on tasks, not specs" error (and the
973
- * legacy `prd:` with "operates on tasks, not prds", still accepted through the
974
- * cutover). On rejection it prints the error to stderr and exits 1 (the task-only
975
- * commands never act on a spec). An OMITTED slug (`start`/`complete`/`prompt`
976
- * infer it from the branch) passes through untouched.
982
+ * REJECT `spec:` with a clear "operates on tasks, not specs" error. On rejection
983
+ * it prints the error to stderr and exits 1 (the task-only commands never act on
984
+ * a spec). An OMITTED slug (`start`/`complete`/`prompt` infer it from the branch)
985
+ * passes through untouched. (The legacy `prd:` prefix is a DEAD namespace token
986
+ * after the hard cutover — it is neither special-cased nor rejected here; a
987
+ * `prd:<slug>` arg resolves as a bare literal task slug.)
977
988
  *
978
989
  * `do` is the ONE command that spans both namespaces; it consumes the full
979
990
  * `resolveSlug` (with the cross-namespace collision check) in the `do-in-place`
@@ -1057,14 +1068,14 @@ function buildInteractiveLauncher(
1057
1068
  * switching to its `work/<slug>` branch WITHOUT claiming). The runtime
1058
1069
  * difference is exactly the `resume` flag — `resume` forces it on (its only mode
1059
1070
  * is to re-engage), while `start` honours the (now hidden) `--resume` alias.
1060
- * Both are task-only (§3a: accept bare + `task:`, reject `prd:`).
1071
+ * Both are task-only (§3a: accept bare + `task:`, reject `spec:`).
1061
1072
  */
1062
1073
  async function runStartAction(
1063
1074
  rawSlug: string | undefined,
1064
1075
  flags: StartFlags,
1065
1076
  resume: boolean,
1066
1077
  ): Promise<void> {
1067
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
1078
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
1068
1079
  const slug = resolveTaskOnlySlug(rawSlug);
1069
1080
  const cwd = process.cwd();
1070
1081
 
@@ -1520,7 +1531,7 @@ export function buildProgram(): Command {
1520
1531
  'override the readiness guard: claim despite an unmet blockedBy, and silence the needsAnswers warning (loud, never default)',
1521
1532
  )
1522
1533
  .action(async (rawSlug: string, flags: ClaimFlags) => {
1523
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
1534
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
1524
1535
  const slug = resolveTaskOnlySlug(rawSlug) as string;
1525
1536
  // Wrap ONLY this CLI surface's `performClaim` call with the spinner
1526
1537
  // helper (task `claim-cas-spinner`): the push can take seconds, so the
@@ -1726,7 +1737,7 @@ export function buildProgram(): Command {
1726
1737
  flags.remote !== undefined && flags.remote.trim() !== ''
1727
1738
  ? flags.remote
1728
1739
  : undefined;
1729
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
1740
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
1730
1741
  const theSlug = resolveTaskOnlySlug(rawSlug) as string;
1731
1742
 
1732
1743
  const configPath = flags.config ?? defaultConfigPath();
@@ -1778,14 +1789,14 @@ export function buildProgram(): Command {
1778
1789
  .command('prompt')
1779
1790
  .helpGroup(ADVANCED_GROUP)
1780
1791
  .description(
1781
- "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.",
1792
+ "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.",
1782
1793
  )
1783
1794
  .argument(
1784
1795
  '[slug]',
1785
1796
  'the slug to render (inferred from a work/<slug> branch if omitted)',
1786
1797
  )
1787
1798
  .action((rawSlug: string | undefined) => {
1788
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
1799
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
1789
1800
  const slug = resolveTaskOnlySlug(rawSlug);
1790
1801
  // Resolve the `promptGuidance` NUDGE namespace through the SAME chain the
1791
1802
  // gate family uses (env > per-repo > global > default), so e.g. a
@@ -1892,7 +1903,7 @@ export function buildProgram(): Command {
1892
1903
  'cross-job merge-serialiser CAS-retry cap (see `run --help`); resolved flag > env > per-repo > global > default 1000.',
1893
1904
  )
1894
1905
  .action(async (rawSlug: string | undefined, flags: CompleteFlags) => {
1895
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
1906
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
1896
1907
  const slug = resolveTaskOnlySlug(rawSlug);
1897
1908
  const cwd = process.cwd();
1898
1909
  const {global, override} = loadGlobalAndOverride(flags.config);
@@ -1956,7 +1967,7 @@ export function buildProgram(): Command {
1956
1967
  // `--fresh-worktree-gate`/`--no-fresh-worktree-gate` rides the SAME chain.
1957
1968
  ...freshWorktreeGateFlagOverrides(flags),
1958
1969
  // `--merge-retries <n>` rides the SAME chain: the cross-job merge-serialiser
1959
- // CAS-retry cap (prd `land-time-reverify-and-parallel-merge-ceiling` Story 5
1970
+ // CAS-retry cap (spec `land-time-reverify-and-parallel-merge-ceiling` Story 5
1960
1971
  // / Applied Answer q1 (a)).
1961
1972
  ...mergeRetriesFlagOverrides(flags),
1962
1973
  // `--no-pr` (the PR-INTENT axis) rides the SAME chain.
@@ -1996,7 +2007,7 @@ export function buildProgram(): Command {
1996
2007
  // a single-job path, so the resolved flag is passed UNCONDITIONALLY (no
1997
2008
  // fleet downgrade).
1998
2009
  freshWorktreeGate: config.freshWorktreeGate,
1999
- // Cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-
2010
+ // Cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-
2000
2011
  // parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)) — the resolved
2001
2012
  // per-repo value reaches the merge loop via `performComplete`→
2002
2013
  // `performIntegration`.
@@ -2029,7 +2040,7 @@ export function buildProgram(): Command {
2029
2040
  .command('do')
2030
2041
  .helpGroup(HEADLINE_GROUP)
2031
2042
  .description(
2032
- '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.',
2043
+ '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.',
2033
2044
  )
2034
2045
  // EXTENSIBLE argument grammar (the three do-* tasks grow this one block):
2035
2046
  // `do-autopick` widens the single optional positional into a VARIADIC one so
@@ -2038,7 +2049,7 @@ export function buildProgram(): Command {
2038
2049
  // for the auto-pick form. `do` stays SEQUENTIAL (parallelism is `run`).
2039
2050
  .argument(
2040
2051
  '[slugs...]',
2041
- '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.',
2052
+ '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.',
2042
2053
  )
2043
2054
  .option('-c, --config <path>', 'config file path', defaultConfigPath())
2044
2055
  .option(
@@ -2071,7 +2082,7 @@ export function buildProgram(): Command {
2071
2082
  )
2072
2083
  .option(
2073
2084
  '--tasks-land-in <where>',
2074
- '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.',
2085
+ '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.',
2075
2086
  )
2076
2087
  .option(
2077
2088
  '--no-pr',
@@ -2124,15 +2135,15 @@ export function buildProgram(): Command {
2124
2135
  )
2125
2136
  .option(
2126
2137
  '--tasker-loop',
2127
- '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).',
2138
+ '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).',
2128
2139
  )
2129
2140
  .option(
2130
2141
  '--no-tasker-loop',
2131
- 'skip the tasker improver loop on `do prd:<slug>`',
2142
+ 'skip the tasker improver loop on `do spec:<slug>`',
2132
2143
  )
2133
2144
  .option(
2134
2145
  '--tasker-loop-max <n>',
2135
- '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)',
2146
+ '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)',
2136
2147
  )
2137
2148
  .option(
2138
2149
  '--tasker-loop-model <id>',
@@ -2300,7 +2311,7 @@ export function buildProgram(): Command {
2300
2311
  // Host-only runner IDENTITY — scopes git/provider ops only (not the
2301
2312
  // agent launch); absent ⇒ ambient.
2302
2313
  identity: remoteConfig.identity,
2303
- // `do --remote prd:<slug>` tasking-gate policy (task-build path ignores it).
2314
+ // `do --remote spec:<slug>` tasking-gate policy (task-build path ignores it).
2304
2315
  autoTask: remoteConfig.autoTask,
2305
2316
  // The resolved `promptGuidance` nudge — threaded into the remote worker
2306
2317
  // prompt (runRemotePipeline → buildAgentPrompt), mirroring in-place `do`.
@@ -2308,7 +2319,7 @@ export function buildProgram(): Command {
2308
2319
  integration: remoteConfig.integration,
2309
2320
  // EXPLICIT `--merge` override for the untrusted-origin build-propose rule.
2310
2321
  explicitMerge: flagMode === 'merge',
2311
- // Per-TRANSITION TASKING override (the `do --remote prd:` tasking path).
2322
+ // Per-TRANSITION TASKING override (the `do --remote spec:` tasking path).
2312
2323
  taskingIntegration: remoteConfig.taskingIntegration,
2313
2324
  // TASK-PLACEMENT: the configured default + the EXPLICIT operator override
2314
2325
  // (`--tasks-land-in`), the top of the placement precedence — mirrors
@@ -2320,7 +2331,7 @@ export function buildProgram(): Command {
2320
2331
  // Single-job build path: gate the REBASED tip (the default) unconditionally.
2321
2332
  freshWorktreeGate: remoteConfig.freshWorktreeGate,
2322
2333
  // Cross-job merge-serialiser CAS-retry cap (resolved through the per-repo
2323
- // chain on the arbiter-side `.dorfl.json` too) — prd
2334
+ // chain on the arbiter-side `.dorfl.json` too) — spec
2324
2335
  // `land-time-reverify-and-parallel-merge-ceiling` Story 5.
2325
2336
  mergeRetries: remoteConfig.mergeRetries,
2326
2337
  noPR: remoteConfig.noPR,
@@ -2337,7 +2348,7 @@ export function buildProgram(): Command {
2337
2348
  agentCmd: remoteConfig.agentCmd,
2338
2349
  })
2339
2350
  : undefined,
2340
- // The tasker IMPROVER loop on the `do --remote prd:` path is ON by default
2351
+ // The tasker IMPROVER loop on the `do --remote spec:` path is ON by default
2341
2352
  // (auto-tasking has no `verify` floor, so the loop is the task path's
2342
2353
  // quality engine). `--tasker-loop`/`--no-tasker-loop` gates wiring the seam;
2343
2354
  // `taskerLoopMax`/`taskerLoopModel` resolve per-repo (flag > env > per-repo
@@ -2350,7 +2361,7 @@ export function buildProgram(): Command {
2350
2361
  : undefined,
2351
2362
  taskerLoopMax: remoteConfig.taskerLoopMax,
2352
2363
  taskerLoopModel: remoteConfig.taskerLoopModel,
2353
- // The task-SET ACCEPTANCE GATE on the `do --remote prd:` path too.
2364
+ // The task-SET ACCEPTANCE GATE on the `do --remote spec:` path too.
2354
2365
  taskReviewGate: remoteConfig.review
2355
2366
  ? harnessTaskAcceptanceGate({
2356
2367
  harness: remoteHarness,
@@ -2462,7 +2473,7 @@ export function buildProgram(): Command {
2462
2473
  // ops (claim, push, integrate, `gh`) — NEVER the agent launch. Absent ⇒
2463
2474
  // ambient (today's behaviour). Mapped Config → DoOptions like model/agentCmd.
2464
2475
  identity: config.identity,
2465
- // `do prd:<slug>` tasking-gate policy (the task-build path ignores it).
2476
+ // `do spec:<slug>` tasking-gate policy (the task-build path ignores it).
2466
2477
  autoTask: config.autoTask,
2467
2478
  // The resolved `promptGuidance` NUDGE namespace (e.g. `testFirst`),
2468
2479
  // threaded into the worker prompt by performDo → buildAgentPrompt so a
@@ -2475,11 +2486,11 @@ export function buildProgram(): Command {
2475
2486
  // typed `--merge` (`flagMode`), never when `merge` came from config — so an
2476
2487
  // untrusted-origin task still forces propose under a config `merge`.
2477
2488
  explicitMerge: flagMode === 'merge',
2478
- // Per-TRANSITION TASKING override: the `do prd:` tasking path threads
2489
+ // Per-TRANSITION TASKING override: the `do spec:` tasking path threads
2479
2490
  // `taskingIntegration ?? integration`; the task-build path stays on
2480
2491
  // `integration`. Unset ⇒ tasking falls back to `integration` (today's behaviour).
2481
2492
  taskingIntegration: config.taskingIntegration,
2482
- // TASK-PLACEMENT (`do prd:` tasking output): the configured default rung +
2493
+ // TASK-PLACEMENT (`do spec:` tasking output): the configured default rung +
2483
2494
  // the EXPLICIT operator override `--tasks-land-in` (top of the precedence).
2484
2495
  // `explicitTasksLandIn` is set ONLY when the flag was typed (mirrors
2485
2496
  // `explicitMerge`), so an untrusted-origin staging force still wins under a
@@ -2492,7 +2503,7 @@ export function buildProgram(): Command {
2492
2503
  verify: config.verify,
2493
2504
  // Single-job build path: gate the REBASED tip (the default) unconditionally.
2494
2505
  freshWorktreeGate: config.freshWorktreeGate,
2495
- // Cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-
2506
+ // Cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-
2496
2507
  // parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)) — resolved per-repo
2497
2508
  // and threaded to `performComplete`→`performIntegration`.
2498
2509
  mergeRetries: config.mergeRetries,
@@ -2516,7 +2527,7 @@ export function buildProgram(): Command {
2516
2527
  reviewGate: config.review
2517
2528
  ? harnessReviewGate({harness, agentCmd: config.agentCmd})
2518
2529
  : undefined,
2519
- // The tasker IMPROVER loop on the `do prd:` tasking path is ON by default
2530
+ // The tasker IMPROVER loop on the `do spec:` tasking path is ON by default
2520
2531
  // (auto-tasking has no `verify` floor — the loop is the task path's quality
2521
2532
  // engine). `--tasker-loop`/`--no-tasker-loop` gates wiring the seam;
2522
2533
  // `taskerLoopMax`/`taskerLoopModel` resolve per-repo (flag > env > per-repo
@@ -2544,7 +2555,7 @@ export function buildProgram(): Command {
2544
2555
  noteBlock: (message) => console.error(message),
2545
2556
  };
2546
2557
 
2547
- // `--allow-backlog` is EXPLICIT-SINGLE-TASK-ONLY (prd
2558
+ // `--allow-backlog` is EXPLICIT-SINGLE-TASK-ONLY (spec
2548
2559
  // `do-allow-backlog-drive-staged-tasks-without-promotion`, decision 4): it
2549
2560
  // drives ONE named staged task in place. It must NOT combine with the
2550
2561
  // AUTO-PICK (zero-args / -n) or MULTI-ITEM forms — those select FROM the
@@ -2605,11 +2616,11 @@ export function buildProgram(): Command {
2605
2616
  });
2606
2617
 
2607
2618
  // `advance` — the SIBLING top-level verb (NOT a `do` subcommand; `do`
2608
- // subcommands + a standalone `task` verb are REJECTED in prd `advance-loop`).
2619
+ // subcommands + a standalone `task` verb are REJECTED in spec `advance-loop`).
2609
2620
  // It reuses the SAME shared `prefix:arg` resolver `do` uses, EXTENDED with the
2610
2621
  // `obs:` namespace, and wires the classify → lock → execute SKELETON: classify
2611
2622
  // the rung (read-only, no model, no lock), take the `advancing` CAS borrow, then
2612
- // dispatch winner-only — build/task rungs ORCHESTRATE `do`/`do prd:` (never a
2623
+ // dispatch winner-only — build/task rungs ORCHESTRATE `do`/`do spec:` (never a
2613
2624
  // duplicate), surface/apply/triage dispatch to a named executor seam later
2614
2625
  // tasks fill. The DRIVERS (one-shot/loop) + `-n` + per-action gates and the
2615
2626
  // rung BODIES are LATER tasks; the bare eligible-SET form errors clearly here.
@@ -2617,11 +2628,11 @@ export function buildProgram(): Command {
2617
2628
  .command('advance')
2618
2629
  .helpGroup(HEADLINE_GROUP)
2619
2630
  .description(
2620
- '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).',
2631
+ '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).',
2621
2632
  )
2622
2633
  .argument(
2623
2634
  '[slugs...]',
2624
- '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.',
2635
+ '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.',
2625
2636
  )
2626
2637
  .option('-c, --config <path>', 'config file path', defaultConfigPath())
2627
2638
  .option(
@@ -2646,15 +2657,15 @@ export function buildProgram(): Command {
2646
2657
  )
2647
2658
  .option(
2648
2659
  '--surface-blockers',
2649
- '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).',
2660
+ '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).',
2650
2661
  )
2651
2662
  .option(
2652
2663
  '--no-surface-blockers',
2653
- 'leave a needsAnswers:true task/prd silently blocked (default; the blocked pool is dropped from auto-pick)',
2664
+ 'leave a needsAnswers:true task/spec silently blocked (default; the blocked pool is dropped from auto-pick)',
2654
2665
  )
2655
2666
  .option(
2656
2667
  '--strict-merge-approval',
2657
- '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.',
2668
+ '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.',
2658
2669
  )
2659
2670
  .option(
2660
2671
  '--no-strict-merge-approval',
@@ -2674,7 +2685,7 @@ export function buildProgram(): Command {
2674
2685
  )
2675
2686
  .option(
2676
2687
  '--tasks-land-in <where>',
2677
- '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.',
2688
+ '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.',
2678
2689
  )
2679
2690
  .option(
2680
2691
  '--watch',
@@ -2810,7 +2821,7 @@ export function buildProgram(): Command {
2810
2821
  integration: remoteConfig.integration,
2811
2822
  // EXPLICIT `--merge` override for the untrusted-origin build-propose rule.
2812
2823
  explicitMerge: flagMode === 'merge',
2813
- // Per-TRANSITION TASKING override (the isolated `do --remote prd:` path).
2824
+ // Per-TRANSITION TASKING override (the isolated `do --remote spec:` path).
2814
2825
  taskingIntegration: remoteConfig.taskingIntegration,
2815
2826
  // TASK-PLACEMENT: configured default + EXPLICIT `--tasks-land-in` override
2816
2827
  // (set only when typed, mirroring `explicitMerge`).
@@ -2820,7 +2831,7 @@ export function buildProgram(): Command {
2820
2831
  verify: remoteConfig.verify,
2821
2832
  // Single-job build path: gate the REBASED tip (the default) unconditionally.
2822
2833
  freshWorktreeGate: remoteConfig.freshWorktreeGate,
2823
- // Cross-job merge-serialiser CAS-retry cap — prd
2834
+ // Cross-job merge-serialiser CAS-retry cap — spec
2824
2835
  // `land-time-reverify-and-parallel-merge-ceiling` Story 5.
2825
2836
  mergeRetries: remoteConfig.mergeRetries,
2826
2837
  noPR: remoteConfig.noPR,
@@ -2952,7 +2963,7 @@ export function buildProgram(): Command {
2952
2963
  // EXPLICIT `--merge` override for the untrusted-origin build-propose rule (a
2953
2964
  // bare `advance` auto-pick passes no flag ⇒ unset ⇒ untrusted forces propose).
2954
2965
  explicitMerge: flagMode === 'merge',
2955
- // Per-TRANSITION TASKING override (the `do prd:` tasking path threads
2966
+ // Per-TRANSITION TASKING override (the `do spec:` tasking path threads
2956
2967
  // `taskingIntegration ?? integration`; the build path stays on `integration`).
2957
2968
  taskingIntegration: config.taskingIntegration,
2958
2969
  // TASK-PLACEMENT: configured default + EXPLICIT `--tasks-land-in` override
@@ -2963,7 +2974,7 @@ export function buildProgram(): Command {
2963
2974
  verify: config.verify,
2964
2975
  // Single-job build path: gate the REBASED tip (the default) unconditionally.
2965
2976
  freshWorktreeGate: config.freshWorktreeGate,
2966
- // Cross-job merge-serialiser CAS-retry cap (prd `land-time-reverify-and-
2977
+ // Cross-job merge-serialiser CAS-retry cap (spec `land-time-reverify-and-
2967
2978
  // parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)).
2968
2979
  mergeRetries: config.mergeRetries,
2969
2980
  noPR: config.noPR,
@@ -3127,7 +3138,7 @@ export function buildProgram(): Command {
3127
3138
  const config = resolveGlobalConfig(loadConfig(flags.config), {});
3128
3139
  const workspacesDir = flags.workspace ?? config.workspacesDir;
3129
3140
 
3130
- // The `gc`-STYLE ledger SWEEP (prd `ledger-integrity` story 3): a SEPARATE
3141
+ // The `gc`-STYLE ledger SWEEP (spec `ledger-integrity` story 3): a SEPARATE
3131
3142
  // surface from the worktree reaper below — it REPORTS one-slug-one-folder
3132
3143
  // violations in a repo's `work/` lifecycle ledger and NEVER deletes (a human
3133
3144
  // resolves each). Distinct `work/`: the ledger, not the execution substrate.
@@ -3136,7 +3147,7 @@ export function buildProgram(): Command {
3136
3147
  typeof flags.ledger === 'string' ? flags.ledger : process.cwd();
3137
3148
  const result = sweepLedgerDuplicates(repoPath);
3138
3149
  // The UNIFIED-LOCK stuck/orphaned-lock REPORT (task
3139
- // `release-lock-verb-and-gc-stuck-report`, prd
3150
+ // `release-lock-verb-and-gc-stuck-report`, spec
3140
3151
  // `ledger-status-per-item-lock-refs` US #12/#13/#14): generalises the
3141
3152
  // advancing-marker report from advancing-only to the unified per-item
3142
3153
  // lock. The locks live on the ARBITER ref (`refs/dorfl/lock/*`),
@@ -3221,7 +3232,7 @@ export function buildProgram(): Command {
3221
3232
  // ALL are REPORTED here (never auto-deleted — no automatic sweep exists; a
3222
3233
  // human clears a NAMED unified lock via `release-lock`).
3223
3234
  //
3224
- // SCOPED to the ATTENTION verdicts only (prd US#14/#21, ADR
3235
+ // SCOPED to the ATTENTION verdicts only (spec US#14/#21, ADR
3225
3236
  // `ledger-status-on-per-item-lock-refs`: this surface is the STUCK /
3226
3237
  // crash-orphaned lock, NOT every held one): a `kept-stuck` (terminal +
3227
3238
  // stuck) or a `cleared-stale`-eligible (terminal + stale active = orphaned)
@@ -3251,7 +3262,7 @@ export function buildProgram(): Command {
3251
3262
  dryRun: flags.dryRun === true,
3252
3263
  note: (message) => console.error(`>> ${message}`),
3253
3264
  });
3254
- // The ORPHAN-SIDECAR sweep (prd
3265
+ // The ORPHAN-SIDECAR sweep (spec
3255
3266
  // `agentic-question-resolution-retire-disposition-vocabulary`, US #10) rides
3256
3267
  // the SAME `--remote-branches` invocation the SCHEDULED CI lifecycle workflow
3257
3268
  // runs (`dorfl gc --remote-branches --arbiter origin`) — so the reap of a
@@ -3507,7 +3518,7 @@ export function buildProgram(): Command {
3507
3518
  'append a dated handoff note to the item body for the next agent (append-only; applies to both default and --reset)',
3508
3519
  )
3509
3520
  .action(async (rawSlug: string, flags: RequeueFlags) => {
3510
- // Task-only command (§3a): accept bare + `task:`, reject `prd:`.
3521
+ // Task-only command (§3a): accept bare + `task:`, reject `spec:`.
3511
3522
  const slug = resolveTaskOnlySlug(rawSlug) as string;
3512
3523
  const cwd = flags.cwd ?? process.cwd();
3513
3524
  // Route the requeue (default keep+continue / --reset discard / -m handoff)
@@ -3544,12 +3555,12 @@ export function buildProgram(): Command {
3544
3555
  console.log(`Requeued '${slug}' to backlog for re-claiming.${how}`);
3545
3556
  });
3546
3557
 
3547
- // `promote [item]` (prd `staging-pool-position-gate-and-trust-model`, tasks
3558
+ // `promote [item]` (spec `staging-pool-position-gate-and-trust-model`, tasks
3548
3559
  // `pre-backlog-staging-folder-and-promote-step-a` /
3549
3560
  // `pre-prd-staging-pool-split-and-untrusted-prd-placement`): the HUMAN/runner-
3550
3561
  // owned verb that moves a STAGED item into its agent-eligible POOL — a task
3551
- // `work/pre-backlog/<slug>.md → work/backlog/<slug>.md`, a prd
3552
- // `work/prds/proposed/<slug>.md → work/prds/ready/<slug>.md` — as a tree-less CAS on the
3562
+ // `work/pre-backlog/<slug>.md → work/backlog/<slug>.md`, a spec
3563
+ // `work/specs/proposed/<slug>.md → work/specs/ready/<slug>.md` — as a tree-less CAS on the
3553
3564
  // arbiter, the SAME trust model + mechanism as `requeue`. The agent emits STAGED;
3554
3565
  // only this verb (a human, or the runner) admits it to the pool. With NO argument
3555
3566
  // it LISTS what is promotable (the "what is staged waiting for me?" discovery), so
@@ -3558,7 +3569,7 @@ export function buildProgram(): Command {
3558
3569
  .command('promote [item]')
3559
3570
  .helpGroup(HEADLINE_GROUP)
3560
3571
  .description(
3561
- '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.',
3572
+ `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.`,
3562
3573
  )
3563
3574
  .option('-c, --config <path>', 'config file path', defaultConfigPath())
3564
3575
  .option(
@@ -3586,7 +3597,7 @@ export function buildProgram(): Command {
3586
3597
  }
3587
3598
  if (listed.items.length === 0) {
3588
3599
  console.log(
3589
- `Nothing staged to promote on ${arbiter}/main (work/pre-backlog/ and work/prds/proposed/ are empty).`,
3600
+ `Nothing staged to promote on ${arbiter}/main (work/pre-backlog/ and ${workFolderPrefix('specs-proposed')} are empty).`,
3590
3601
  );
3591
3602
  return;
3592
3603
  }
@@ -3597,11 +3608,10 @@ export function buildProgram(): Command {
3597
3608
  return;
3598
3609
  }
3599
3610
 
3600
- // AN ITEM → promote it. `task:`/`spec:` are explicit (the legacy `prd:`
3601
- // prefix is still ACCEPTED as an input alias through the cutover — the
3602
- // contract task drops it); a bare slug defaults to a task (mirrors
3603
- // `requeue`). An `obs:`/`observation:` prefix is rejected (observations have
3604
- // no pool).
3611
+ // AN ITEM → promote it. `task:`/`spec:` are explicit; a bare slug defaults to
3612
+ // a task (mirrors `requeue`). An `obs:`/`observation:` prefix is rejected
3613
+ // (observations have no pool). A legacy `prd:` prefix is a DEAD namespace token
3614
+ // after the hard cutover it resolves as a bare literal task slug, not a spec.
3605
3615
  const parsed = parseSlugArg(rawItem);
3606
3616
  if (parsed.explicit === 'observation') {
3607
3617
  console.error(
@@ -3638,7 +3648,7 @@ export function buildProgram(): Command {
3638
3648
  // `action: advance` on the UNIFIED per-item lock, so `release-lock <item>` (below)
3639
3649
  // is the SOLE named human release for ALL holds (implement/task/advance).
3640
3650
 
3641
- // `release-lock <item>` (task `release-lock-verb-and-gc-stuck-report`, prd
3651
+ // `release-lock <item>` (task `release-lock-verb-and-gc-stuck-report`, spec
3642
3652
  // `ledger-status-per-item-lock-refs` US #14): the HUMAN-invoked named release of
3643
3653
  // a stuck/orphaned UNIFIED per-item lock (`refs/dorfl/lock/<entry>`) —
3644
3654
  // the GENERALISATION of `release-advancing` from the advancing-only marker to
@@ -3655,7 +3665,7 @@ export function buildProgram(): Command {
3655
3665
  .command('release-lock <item>')
3656
3666
  .helpGroup(HEADLINE_GROUP)
3657
3667
  .description(
3658
- '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).',
3668
+ '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).',
3659
3669
  )
3660
3670
  .option('-c, --config <path>', 'config file path', defaultConfigPath())
3661
3671
  .option(
@@ -3696,7 +3706,7 @@ export function buildProgram(): Command {
3696
3706
  process.exit(1);
3697
3707
  });
3698
3708
 
3699
- // `drop <slug>` (prd `agentic-question-resolution-retire-disposition-vocabulary`,
3709
+ // `drop <slug>` (spec `agentic-question-resolution-retire-disposition-vocabulary`,
3700
3710
  // US #5/#11; task `direct-delete-question-cli-helper`): the DIRECT "throw it
3701
3711
  // away" verb — `git rm` a source item AND its question sidecar (when present) in
3702
3712
  // ONE revertible commit, the reason in the commit MESSAGE (git history is the
@@ -3711,7 +3721,7 @@ export function buildProgram(): Command {
3711
3721
  .command('drop <slug>')
3712
3722
  .helpGroup(HEADLINE_GROUP)
3713
3723
  .description(
3714
- '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).',
3724
+ '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).',
3715
3725
  )
3716
3726
  .option('-c, --config <path>', 'config file path', defaultConfigPath())
3717
3727
  .option(
@@ -3849,7 +3859,7 @@ export function buildProgram(): Command {
3849
3859
  console.error(`>> ${resolved.message}`);
3850
3860
  }
3851
3861
  const config = resolved.config;
3852
- // Resolve the PER-OUTCOME integration modes (prd US #9): `intake` decides
3862
+ // Resolve the PER-OUTCOME integration modes (spec US #9): `intake` decides
3853
3863
  // the artifact TYPE at runtime, so a single --merge/--propose can't express
3854
3864
  // a type-conditional policy. The granular flags override the aggregate; an
3855
3865
  // UNSET type falls back to the per-repo/global `integration` (the SAME chain
@@ -3931,10 +3941,10 @@ export function buildProgram(): Command {
3931
3941
  process.exit(result.exitCode);
3932
3942
  });
3933
3943
 
3934
- // The CI CLOSE-JOB driver (prd `runner-in-ci`, capability E; task
3944
+ // The CI CLOSE-JOB driver (spec `runner-in-ci`, capability E; task
3935
3945
  // `install-ci-close-job-workflow`). The thin JOB the emitted close-job workflow
3936
3946
  // invokes on a merge to main: resolve which source issue(s) the landed work
3937
- // closes (resolveClosingIssue), run the "prd complete?" query for the prd case
3947
+ // closes (resolveClosingIssue), run the "spec complete?" query for the spec case
3938
3948
  // (prd-complete-query, done), and close via the IssueProvider seam — all
3939
3949
  // UNCHANGED engine pieces, CONSUMED not re-built (the Out-of-Scope fence). CI
3940
3950
  // owns ONLY the job + trigger. Local-runnable too (a manual catch-up close).
@@ -3942,7 +3952,7 @@ export function buildProgram(): Command {
3942
3952
  .command('close-merged-issues')
3943
3953
  .helpGroup(ADVANCED_GROUP)
3944
3954
  .description(
3945
- '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.',
3955
+ '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.',
3946
3956
  )
3947
3957
  .option(
3948
3958
  '--cwd <dir>',