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
@@ -30,7 +30,7 @@ import {
30
30
 
31
31
  /**
32
32
  * The **needs-attention mechanism** (ADR `ledger-status-on-per-item-lock-refs`;
33
- * prd `ledger-status-per-item-lock-refs`; ADR §12 for the original folder model).
33
+ * spec `ledger-status-per-item-lock-refs`; ADR §12 for the original folder model).
34
34
  * Every "couldn't finish, a human must look" outcome (a failed acceptance gate
35
35
  * (red `verify`), a rebase/merge conflict (ADR §10), a task the agent reported
36
36
  * too ambiguous to build, a timeout, or a rejected review) resolves to ONE
@@ -81,7 +81,7 @@ export interface RouteToNeedsAttentionOptions {
81
81
  /**
82
82
  * The work branch to push to the arbiter (the RECOVERABLE half — see the seam
83
83
  * docstring). DEFAULT `work/<slug>`: the build-bounce branch the wip/move
84
- * commits landed on. A tasking bounce passes its own branch (`work/prds/
84
+ * commits landed on. A tasking bounce passes its own branch (`work/specs/
85
85
  * ready-<slug>`). The supplied branch MUST be the one HEAD is on (the branch the
86
86
  * wip/move commits landed on) — NEVER a default that differs from HEAD; a
87
87
  * caller NOT checked out on the work branch (e.g. a temp branch off main) must
@@ -259,7 +259,7 @@ export interface SurfaceToNeedsAttentionResult {
259
259
  * (an unreachable arbiter leaves the local branch standing — recovery
260
260
  * degrades, never crashes the bounce; retried with bounded backoff on an
261
261
  * outage), BRANCH-PARAMETERISED (default `work/<slug>`; an explicit `branch`
262
- * overrides — the tasking bounce passes `work/prds/ready-<slug>`; `pushBranch: false`
262
+ * overrides — the tasking bounce passes `work/specs/ready-<slug>`; `pushBranch: false`
263
263
  * ⇒ push NOTHING), and EMPTINESS-GUARDED (a branch with no commits beyond
264
264
  * main, or an absent branch, is skipped). The branch MUST be the one HEAD is
265
265
  * on. The work-branch push is NOT a `main` write.
@@ -316,7 +316,7 @@ export async function routeToNeedsAttention(
316
316
  let pushError: string | undefined;
317
317
  if (options.arbiter && options.pushBranch !== false) {
318
318
  // DEFAULT to the task-namespaced build-bounce branch; a non-task caller
319
- // (the tasking bounce) passes its own `work/prds/ready-<slug>` via `branch`.
319
+ // (the tasking bounce) passes its own `work/specs/ready-<slug>` via `branch`.
320
320
  const branch = options.branch ?? workBranchRef('task', slug);
321
321
  if (branchAheadOf(cwd, branch, 'main', env)) {
322
322
  const arbiter = options.arbiter;
@@ -652,7 +652,7 @@ export async function returnToBacklog(
652
652
  }
653
653
 
654
654
  /**
655
- * **Promote a STAGED task into the agent-eligible pool** (prd
655
+ * **Promote a STAGED task into the agent-eligible pool** (spec
656
656
  * `staging-pool-position-gate-and-trust-model`, task
657
657
  * `pre-backlog-staging-folder-and-promote-step-a`, governing ADR
658
658
  * `placement-is-runner-deterministic-humanonly-is-agent-judgement`). Moves
@@ -733,7 +733,7 @@ export async function promoteFromPreBacklog(
733
733
  // arbiter's TRUTH. A fetch, not a checkout — the working tree is untouched.
734
734
  await gitSoftAsync(['fetch', '--quiet', arbiter], cwd, env);
735
735
 
736
- // UNIFIED PER-ITEM LOCK around the CAS window (prd
736
+ // UNIFIED PER-ITEM LOCK around the CAS window (spec
737
737
  // `staging-surface-and-apply-promote-safety`, task
738
738
  // `f3b-promote-takes-per-item-advancing-lock`): promote and apply BOTH key onto
739
739
  // the item's `refs/dorfl/lock/<entry>` ref with `action: advance` (the
@@ -850,34 +850,34 @@ export async function promoteFromPreBacklog(
850
850
  }
851
851
 
852
852
  /**
853
- * **Promote a STAGED prd into the auto-task pool** (prd
853
+ * **Promote a STAGED spec into the auto-task pool** (spec
854
854
  * `staging-pool-position-gate-and-trust-model`, task
855
855
  * `pre-prd-staging-pool-split-and-untrusted-prd-placement`, governing ADR
856
- * `placement-is-runner-deterministic-humanonly-is-agent-judgement`). The prd
856
+ * `placement-is-runner-deterministic-humanonly-is-agent-judgement`). The spec
857
857
  * twin of {@link promoteFromPreBacklog}: moves
858
- * `work/prds/proposed/<slug>.md → work/prds/ready/<slug>.md` as a durable `main` move
858
+ * `work/specs/proposed/<slug>.md → work/specs/ready/<slug>.md` as a durable `main` move
859
859
  * (tree-less CAS via {@link runTreelessLedgerMove}). After this transition
860
- * the prd is in the auto-task POOL and eligible to be auto-tasked (subject
860
+ * the spec is in the auto-task POOL and eligible to be auto-tasked (subject
861
861
  * to the existing `autoTask`/`humanOnly`/`needsAnswers`/`taskedAfter` gates,
862
862
  * which are UNCHANGED — the staging/pool split changes only WHICH folder is
863
863
  * the auto-task pool, not the gates).
864
864
  *
865
865
  * **RUNNER/human-owned.** There is no agent-facing path that performs this:
866
- * `intake`'s `prd` dispatch lands the prd STAGED in `work/prds/proposed/` (the
866
+ * `intake`'s `prd` dispatch lands the spec STAGED in `work/specs/proposed/` (the
867
867
  * runner's deterministic placement decision), and only a runner/human
868
868
  * invocation moves it into the pool. The agent does no git here, as
869
869
  * everywhere; this function is not reachable from any agent surface.
870
870
  *
871
871
  * Storage-agnostic + tree-less, exactly like {@link promoteFromPreBacklog}:
872
872
  * cwd index/HEAD/working tree are never touched, an arbiter remote is
873
- * REQUIRED, and "not in prds/proposed/" / contention-exhausted cases are returned
873
+ * REQUIRED, and "not in specs/proposed/" / contention-exhausted cases are returned
874
874
  * (NEVER thrown) via `{moved: false, reasonNotMoved}` so callers branch
875
875
  * cleanly. Idempotent: re-running after the move LANDED is a no-op success.
876
876
  */
877
877
  export interface PromoteFromPreSpecOptions {
878
878
  /** The working clone the move is originated from (origin source only; never written). */
879
879
  cwd: string;
880
- /** The slug of the staged prd to promote into the pool. */
880
+ /** The slug of the staged spec to promote into the pool. */
881
881
  slug: string;
882
882
  /** The arbiter remote the promotion is CAS-published to. REQUIRED. */
883
883
  arbiter: string;
@@ -888,11 +888,11 @@ export interface PromoteFromPreSpecOptions {
888
888
  }
889
889
 
890
890
  export interface PromoteFromPreSpecResult {
891
- /** True iff the staged prd was moved into the pool + committed. */
891
+ /** True iff the staged spec was moved into the pool + committed. */
892
892
  moved: boolean;
893
893
  /** When `moved`, the committed transition message. */
894
894
  commitMessage?: string;
895
- /** When NOT moved, why (no such prds/proposed item, already in prds/ready/, contention). */
895
+ /** When NOT moved, why (no such specs/proposed item, already in specs/ready/, contention). */
896
896
  reasonNotMoved?: string;
897
897
  }
898
898
 
@@ -927,14 +927,14 @@ export async function promoteFromPreSpec(
927
927
  await gitSoftAsync(['fetch', '--quiet', arbiter], cwd, env);
928
928
 
929
929
  // UNIFIED PER-ITEM LOCK around the CAS window — symmetric with
930
- // {@link promoteFromPreBacklog} (prd `staging-surface-and-apply-promote-safety`,
931
- // task `f3b-promote-takes-per-item-advancing-lock`, decisive prd q4 answer:
930
+ // {@link promoteFromPreBacklog} (spec `staging-surface-and-apply-promote-safety`,
931
+ // task `f3b-promote-takes-per-item-advancing-lock`, decisive spec q4 answer:
932
932
  // specs share the apply×promote mutual-exclusion fix with tasks). The lock
933
933
  // keys on `spec:${slug}` (a distinct ref from a task with the same slug, via
934
934
  // {@link lockEntryFor}'s `<type>-<slug>` encoding), with `action: advance` —
935
935
  // the SAME action an apply for a spec would take — so spec promote and spec
936
936
  // apply on the same item are mutually exclusive by construction. MIGRATE step
937
- // (prd `prd-to-spec-vocabulary-cutover-and-migration-command`): the lock
937
+ // (spec `prd-to-spec-vocabulary-cutover-and-migration-command`): the lock
938
938
  // identity is `spec:${slug}` to match the `spec-<slug>` entry the tasking/apply
939
939
  // path now acquires (`tasking.ts` releases under `spec:${slug}`); a stale
940
940
  // `prd:${slug}` here would key a DIFFERENT ref and break the mutual exclusion.
@@ -1009,7 +1009,7 @@ export async function promoteFromPreSpec(
1009
1009
  base,
1010
1010
  sourceRel,
1011
1011
  destRel,
1012
- // The body is carried byte-for-byte from prds/proposed into the pool —
1012
+ // The body is carried byte-for-byte from specs/proposed into the pool —
1013
1013
  // promotion is a placement decision, not a content transform.
1014
1014
  transformBody: (body) => body,
1015
1015
  commitMessage,
@@ -1020,14 +1020,14 @@ export async function promoteFromPreSpec(
1020
1020
  });
1021
1021
  if (moved) {
1022
1022
  note(
1023
- `Promoted prd '${slug}' from prds/proposed to prds/ready (auto-taskable).`,
1023
+ `Promoted spec '${slug}' from specs/proposed to specs/ready (auto-taskable).`,
1024
1024
  );
1025
1025
  return {moved: true, commitMessage};
1026
1026
  }
1027
1027
 
1028
1028
  const message =
1029
1029
  `promote for '${slug}': the arbiter's main kept moving (contended) ` +
1030
- `after ${TREELESS_CONTENTION_ATTEMPTS} attempts — item left in prds/proposed ` +
1030
+ `after ${TREELESS_CONTENTION_ATTEMPTS} attempts — item left in specs/proposed ` +
1031
1031
  '(no move). Try again shortly.';
1032
1032
  note(message);
1033
1033
  return {moved: false, reasonNotMoved: message};
@@ -1062,7 +1062,7 @@ export interface ListPromotableResult {
1062
1062
 
1063
1063
  /**
1064
1064
  * LIST every staged item awaiting a runner/human promotion — the tasks in
1065
- * `work/pre-backlog/` and the prds in `work/prds/proposed/` on `<arbiter>/main` (the
1065
+ * `work/pre-backlog/` and the prds in `work/specs/proposed/` on `<arbiter>/main` (the
1066
1066
  * discovery half of the `promote` verb, so `promote` with no argument answers
1067
1067
  * "what is staged waiting for me?"). It reads the ARBITER's truth (a fetch + a
1068
1068
  * tree read), NOT the local working tree (which may be stale) — the same source
@@ -8,12 +8,12 @@ import {workFolderPath, workFolderRel} from './work-layout.js';
8
8
  /**
9
9
  * The **orphan-sidecar reaper** — the WORKING-TREE counterpart of the job-worktree
10
10
  * and remote-branch reapers (`gc.ts` / `reap-branches.ts`), folded into `dorfl gc`
11
- * (prd `agentic-question-resolution-retire-disposition-vocabulary`, US #10).
11
+ * (spec `agentic-question-resolution-retire-disposition-vocabulary`, US #10).
12
12
  *
13
13
  * A question sidecar is a tooling-owned file `work/questions/<type>-<slug>.md`
14
14
  * keyed on its source item's `(type, slug)` identity (`sidecarPathFor`). The
15
15
  * contract is that notes/sidecars leave by DELETION (git history is the archive),
16
- * so when a human deletes the source observation (or task/prd) out-of-band, its
16
+ * so when a human deletes the source observation (or task/spec) out-of-band, its
17
17
  * sidecar is ORPHANED.
18
18
  *
19
19
  * WHY THIS IS A SWEEP, NOT AN APPLY STEP. An orphan's source item is GONE, so it
package/src/placement.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * **The shared STAGING/POOL placement resolver** (prd
2
+ * **The shared STAGING/POOL placement resolver** (spec
3
3
  * `staging-pool-position-gate-and-trust-model`, task
4
4
  * `runner-deterministic-slice-placement-policy-and-precedence`, governing ADR
5
5
  * `placement-is-runner-deterministic-humanonly-is-agent-judgement`).
@@ -32,18 +32,18 @@
32
32
  * onto the lifecycle's concrete folder name via {@link PlacementSlots}.
33
33
  *
34
34
  * - `'staging'` — land in the staging area (tasks: `pre-backlog/`; prds:
35
- * `prds/proposed/`). Not in the agent pool; a human/runner promotion is needed to make
35
+ * `specs/proposed/`). Not in the agent pool; a human/runner promotion is needed to make
36
36
  * the item eligible. Review-without-PR review surface.
37
37
  * - `'pool'` — land directly in the agent-eligible pool (tasks: `tasks/ready/`;
38
- * prds: `prds/ready/`). The trusted-fast-path landing.
38
+ * prds: `specs/ready/`). The trusted-fast-path landing.
39
39
  */
40
40
  export type PlacementSide = 'staging' | 'pool';
41
41
 
42
42
  /**
43
43
  * The two folder names a lifecycle uses for its staging/pool split. Supplied by
44
44
  * the caller so this resolver stays lifecycle-generic (the TASK caller passes
45
- * `{staging: 'pre-backlog', pool: 'tasks/ready'}`; the PRD-placement caller passes
46
- * `{staging: 'prds/proposed', pool: 'prds/ready'}`).
45
+ * `{staging: 'pre-backlog', pool: 'tasks/ready'}`; the SPEC-placement caller passes
46
+ * `{staging: 'specs/proposed', pool: 'specs/ready'}`).
47
47
  */
48
48
  export interface PlacementSlots {
49
49
  staging: string;
@@ -100,7 +100,7 @@ const BUILT_IN_FLOOR: PlacementSide = 'staging';
100
100
  * explicit > untrusted-origin ⇒ staging > configured default > built-in
101
101
  *
102
102
  * Pure: no I/O, no env reads — the caller resolves config + reads the
103
- * frontmatter and passes both in. Reused by every lifecycle (task + prd
103
+ * frontmatter and passes both in. Reused by every lifecycle (task + spec
104
104
  * placement + future intake variants) so a precedence change touches ONE place.
105
105
  */
106
106
  export function resolvePlacement(
@@ -276,6 +276,14 @@ export interface ResyncedDoc {
276
276
  dest: string;
277
277
  /** True when the target already had byte-identical content (a no-op copy). */
278
278
  unchanged: boolean;
279
+ /**
280
+ * True when the doc's SOURCE could not be resolved (the package/dev copy is
281
+ * missing), so NOTHING was copied to `dest`. A skipped doc is NEVER counted as
282
+ * a change (it must not bump `VERSION` — the latent bug this field guards) and
283
+ * is surfaced LOUDLY by the caller. Distinct from `unchanged` (which means the
284
+ * source WAS resolved and matched the dest byte-for-byte).
285
+ */
286
+ skipped: boolean;
279
287
  }
280
288
 
281
289
  /** What the protocol re-sync did (or would do). */
@@ -293,40 +301,68 @@ export interface ResyncResult {
293
301
  * (`skills/setup/protocol/`) copy — NEVER the target repo's own (old) copy. This
294
302
  * is how the migrated repo picks up the new `spec` contract before its data is
295
303
  * converted. Idempotent: a doc already byte-identical is reported `unchanged`.
304
+ * A doc whose SOURCE cannot be resolved is reported `skipped` (NOT copied, NEVER
305
+ * a VERSION-bump) rather than silently bumping VERSION with nothing copied.
296
306
  *
297
- * `dryRun` reports what WOULD be copied without writing.
307
+ * `dryRun` reports what WOULD be copied without writing. `resolveDoc` overrides
308
+ * how a doc's source path is resolved (defaults to {@link resolveProtocolDoc});
309
+ * it exists so a test can force a non-resolvable source (a path that does not
310
+ * exist) to exercise the skip path.
298
311
  */
299
312
  export function resyncProtocol(
300
313
  repoPath: string,
301
- options: {dryRun?: boolean} = {},
314
+ options: {
315
+ dryRun?: boolean;
316
+ resolveDoc?: (name: string) => string;
317
+ } = {},
302
318
  ): ResyncResult {
303
319
  const protocolDir = join(repoPath, WORK_ROOT, 'protocol');
320
+ const resolveDoc = options.resolveDoc ?? ((name) => resolveProtocolDoc(name));
304
321
  const docs: ResyncedDoc[] = [];
305
322
  for (const name of PROTOCOL_DOCS) {
306
323
  // Resolve the SOURCE (package/dev), never the target's adopted copy.
307
- const source = resolveProtocolDoc(name, undefined);
324
+ const source = resolveDoc(name);
308
325
  const destAbs = join(protocolDir, name);
309
326
  const destRel = relative(repoPath, destAbs);
310
- let unchanged = false;
311
- if (existsSync(source) && existsSync(destAbs)) {
312
- unchanged =
313
- readFileSync(source, 'utf8') === readFileSync(destAbs, 'utf8');
327
+ const sourceExists = existsSync(source);
328
+ if (!sourceExists) {
329
+ // The source doc could not be resolved: copy NOTHING and record the doc as
330
+ // SKIPPED (never a change). This is the latent-bug fix: a non-resolvable
331
+ // source must not count as `changed` and bump `VERSION` while copying no
332
+ // file. `unchanged: false` here is honest (the dest was not made to match a
333
+ // source), but `skipped: true` keeps it OUT of the VERSION-bump tally.
334
+ docs.push({name, dest: destRel, unchanged: false, skipped: true});
335
+ continue;
314
336
  }
315
- if (!options.dryRun && existsSync(source)) {
337
+ // Source resolved: a doc is CHANGED (VERSION-bump-worthy) only when the dest
338
+ // is absent OR its content differs from the source. An identical dest is a
339
+ // no-op copy (`unchanged`), so an already-synced re-run stays a true no-op.
340
+ const unchanged =
341
+ existsSync(destAbs) &&
342
+ readFileSync(source, 'utf8') === readFileSync(destAbs, 'utf8');
343
+ if (!options.dryRun) {
316
344
  mkdirSync(dirname(destAbs), {recursive: true});
317
345
  copyFileSync(source, destAbs);
318
346
  }
319
- docs.push({name, dest: destRel, unchanged});
347
+ docs.push({name, dest: destRel, unchanged, skipped: false});
320
348
  }
321
349
 
322
350
  const versionAbs = join(protocolDir, 'VERSION');
323
351
  const versionRel = relative(repoPath, versionAbs);
324
- // Bump VERSION only when a doc actually CHANGED (or VERSION is absent). A
325
- // re-run on an already-synced repo must stay a true no-op otherwise the
326
- // (always-fresh) `synced-at` timestamp would dirty the tree on every idempotent
327
- // re-run.
328
- const anyDocChanged = docs.some((d) => !d.unchanged);
329
- if (!options.dryRun && (anyDocChanged || !existsSync(versionAbs))) {
352
+ // Bump VERSION only when a doc was ACTUALLY COPIED with new content, or when
353
+ // VERSION is absent AND at least one doc was genuinely synced (copied). A
354
+ // SKIPPED doc (unresolvable source, nothing copied) is NEVER a change
355
+ // counting it would bump VERSION without copying a single doc (the latent bug),
356
+ // and the write-when-absent fallback must ALSO require a real copy so an
357
+ // all-skipped resync leaves no VERSION behind. A re-run on an already-synced
358
+ // repo must stay a true no-op — otherwise the (always-fresh) `synced-at`
359
+ // timestamp would dirty the tree on every idempotent re-run.
360
+ const anyDocChanged = docs.some((d) => !d.unchanged && !d.skipped);
361
+ const anyDocSynced = docs.some((d) => !d.skipped);
362
+ if (
363
+ !options.dryRun &&
364
+ (anyDocChanged || (anyDocSynced && !existsSync(versionAbs)))
365
+ ) {
330
366
  mkdirSync(dirname(versionAbs), {recursive: true});
331
367
  const today = new Date().toISOString().slice(0, 10);
332
368
  writeFileSync(
package/src/prompt.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * Builds the prompt the runner hands to `agentCmd`: a small CONSTANT wrapper
3
- * (only the `<slug>` / source-prd path vary) around the claimed task's own
3
+ * (only the `<slug>` / source-spec path vary) around the claimed task's own
4
4
  * `## Prompt` section. This is dual-use — the SAME assembly the autonomous
5
5
  * runner feeds `agentCmd` and the human `dorfl prompt [<slug>]` command.
6
6
  *
7
7
  * The wrapper is NOT hardcoded here: it is read VERBATIM from the work-contract
8
8
  * (`skills/setup/protocol/CLAIM-PROTOCOL.md` → "The prompt handed to the work agent"),
9
9
  * so the emitted text can never silently diverge from the canonical contract.
10
- * We only substitute the per-task placeholders (`<slug>`, `<prd>`).
10
+ * We only substitute the per-task placeholders (`<slug>`, `<spec>`).
11
11
  *
12
12
  * The wrapper draws the git boundary IN-BAND — the spawned agent does NO git ops
13
13
  * on the repo (no commit/push, no moving `work/` files); the RUNNER owns every
@@ -137,7 +137,7 @@ export function resolveProtocolDoc(
137
137
  /**
138
138
  * Pull the canonical wrapper TEMPLATE out of CLAIM-PROTOCOL.md: the first fenced
139
139
  * code block following the "The prompt handed to the work agent" heading. The
140
- * returned text still contains the `<slug>` / `<prd>` placeholders verbatim — it
140
+ * returned text still contains the `<slug>` / `<spec>` placeholders verbatim — it
141
141
  * is the single source of truth for the wrapper.
142
142
  */
143
143
  export function extractCanonicalWrapperTemplate(protocol: string): string {
@@ -208,7 +208,7 @@ export function extractCanonicalWrapperTemplate(protocol: string): string {
208
208
  *
209
209
  * Pure string transform; runs AFTER `extractCanonicalWrapperTemplate` (a pure
210
210
  * verbatim extractor stays a pure verbatim extractor) and BEFORE the
211
- * `<slug>`/`<prd>` substitution.
211
+ * `<slug>`/`<spec>` substitution.
212
212
  */
213
213
  export function applyPromptGuidance(
214
214
  template: string,
@@ -227,17 +227,17 @@ export function applyPromptGuidance(
227
227
  }
228
228
 
229
229
  /**
230
- * The constant wrapper, parameterised only by the task slug, its source prd
230
+ * The constant wrapper, parameterised only by the task slug, its source spec
231
231
  * slug, and (optionally) the resolved {@link PromptGuidance} nudges. Read
232
232
  * verbatim from the work-contract and substituted — never a divergent hardcoded
233
- * copy. `prd` may be `undefined` when the task has no `prd:` field. When
233
+ * copy. `spec` may be `undefined` when the task has no `spec:` field. When
234
234
  * `promptGuidance` is omitted (or every member resolves false) the output is
235
235
  * BYTE-IDENTICAL to today's wrapper (the ELSE-branch of every conditional is
236
236
  * the historic text).
237
237
  */
238
238
  export function wrapper(
239
239
  slug: string,
240
- prd: string | undefined,
240
+ spec: string | undefined,
241
241
  options: {
242
242
  protocolPath?: string;
243
243
  cwd?: string;
@@ -252,7 +252,7 @@ export function wrapper(
252
252
  const protocol = readFileSync(protocolPath, 'utf8');
253
253
  const template = extractCanonicalWrapperTemplate(protocol);
254
254
  const resolved = applyPromptGuidance(template, options.promptGuidance);
255
- return resolved.replace(/<slug>/g, slug).replace(/<prd>/g, prd ?? '<prd>');
255
+ return resolved.replace(/<slug>/g, slug).replace(/<spec>/g, spec ?? '<spec>');
256
256
  }
257
257
 
258
258
  /**
@@ -416,7 +416,7 @@ export function buildContinueBlock(slug: string, ctx: ContinueContext): string {
416
416
  }
417
417
 
418
418
  /**
419
- * Build the full prompt: the canonical wrapper for `slug` (with its source prd
419
+ * Build the full prompt: the canonical wrapper for `slug` (with its source spec
420
420
  * substituted) followed by the task's own `## Prompt` body, appended verbatim.
421
421
  *
422
422
  * In CONTINUE-mode (a {@link ContinueContext} is supplied), a CONTINUE block is
@@ -427,7 +427,7 @@ export function buildContinueBlock(slug: string, ctx: ContinueContext): string {
427
427
  */
428
428
  export function buildAgentPrompt(
429
429
  slug: string,
430
- prd: string | undefined,
430
+ spec: string | undefined,
431
431
  taskPrompt: string,
432
432
  options: {
433
433
  protocolPath?: string;
@@ -436,7 +436,7 @@ export function buildAgentPrompt(
436
436
  promptGuidance?: {testFirst?: boolean};
437
437
  } = {},
438
438
  ): string {
439
- const head = wrapper(slug, prd, options);
439
+ const head = wrapper(slug, spec, options);
440
440
  if (options.continueContext) {
441
441
  const block = buildContinueBlock(slug, options.continueContext);
442
442
  return `${head}\n\n${block}\n\n${taskPrompt}\n`;
@@ -459,8 +459,8 @@ export interface ResolvedTask {
459
459
  path: string;
460
460
  /** The folder the task was resolved from (in-progress wins over tasks-ready). */
461
461
  folder: TaskFolder;
462
- /** The task's source prd slug (frontmatter `prd:`), if any. */
463
- prd: string | undefined;
462
+ /** The task's source SPEC slug (frontmatter `spec:`), if any. */
463
+ spec: string | undefined;
464
464
  /** The extracted `## Prompt` body. */
465
465
  taskPrompt: string;
466
466
  }
@@ -490,7 +490,7 @@ export class PromptError extends Error {}
490
490
  /**
491
491
  * The CONTINUE-only gate that lets {@link resolveTask} reach a task that has
492
492
  * already been done-moved into `work/done/` — story 5 of the `ledger-integrity`
493
- * prd (defect 3). A continue/re-claim can legitimately land on a branch whose
493
+ * spec (defect 3). A continue/re-claim can legitimately land on a branch whose
494
494
  * task was ALREADY moved to `done/` (the green-but-unpushed STRAND state), and
495
495
  * onboard must find it; but a `done/` task is folder-indistinguishable between
496
496
  * two states and re-onboarding a genuinely-finished one would RE-RUN it. So
@@ -530,7 +530,7 @@ export interface ContinueResolutionGate {
530
530
 
531
531
  /**
532
532
  * Extra knobs for {@link resolveTask} beyond the continue gate. Today the only
533
- * member is `allowBacklog` (prd
533
+ * member is `allowBacklog` (spec
534
534
  * `do-allow-backlog-drive-staged-tasks-without-promotion`): the operator's
535
535
  * EXPLICIT `do … --allow-backlog`, which widens resolution to also search
536
536
  * `tasks-backlog` (staging) at LOWEST priority. Default off (omitted) \u21d2 the
@@ -571,7 +571,7 @@ function isStrandedDoneTip(gate: ContinueResolutionGate): boolean {
571
571
 
572
572
  /**
573
573
  * Resolve a task's file: prefer `work/in-progress/<slug>.md`, fall back to
574
- * `work/tasks/ready/<slug>.md` (the pool). Returns the parsed prd + extracted
574
+ * `work/tasks/ready/<slug>.md` (the pool). Returns the parsed spec + extracted
575
575
  * `## Prompt` body. Throws {@link PromptError} when neither file exists or it has
576
576
  * no prompt body.
577
577
  *
@@ -585,11 +585,11 @@ function isStrandedDoneTip(gate: ContinueResolutionGate): boolean {
585
585
  * the only addition, and it is gated. With no gate (a fresh claim) the behaviour
586
586
  * is byte-identical to the original `['in-progress','tasks-ready']`-only resolution.
587
587
  *
588
- * `--allow-backlog` (prd `do-allow-backlog-drive-staged-tasks-without-promotion`):
588
+ * `--allow-backlog` (spec `do-allow-backlog-drive-staged-tasks-without-promotion`):
589
589
  * when {@link ResolveTaskOptions.allowBacklog} is set, `tasks-backlog` (the staging
590
590
  * folder) is appended at the LOWEST priority — after `tasks-ready`, so a slug
591
591
  * present in BOTH the pool and staging resolves to the READY copy (the same-slug
592
- * precedence the prd's decision 5 fixes). Default off ⇒ byte-identical to today
592
+ * precedence the spec's decision 5 fixes). Default off ⇒ byte-identical to today
593
593
  * (no autonomous path sets it; staging stays unreachable to `run`/auto-pick).
594
594
  */
595
595
  export function resolveTask(
@@ -624,11 +624,10 @@ export function resolveTask(
624
624
  );
625
625
  }
626
626
  const fm = parseFrontmatter(content);
627
- // MIGRATE step (prd `prd-to-spec-vocabulary-cutover-and-migration-command`):
628
- // read the parent-spec pointer off the new `fm.spec` field (populated beside
629
- // `fm.prd` by the expand task). The `ResolvedTask.prd` field name is left
630
- // unchanged (a struct-field rename is out of this batch's scope).
631
- return {slug, path, folder, prd: fm.spec, taskPrompt};
627
+ // Read the parent-spec pointer off `fm.spec` (populated from the canonical
628
+ // `spec:` key) into the `spec`-only `ResolvedTask` (spec
629
+ // `prd-to-spec-vocabulary-cutover-and-migration-command`).
630
+ return {slug, path, folder, spec: fm.spec, taskPrompt};
632
631
  }
633
632
  const searched = order.map((f) => `${workFolderRel(f)}/`).join(', ');
634
633
  throw new PromptError(`no task '${slug}' found in ${searched}`);
@@ -662,13 +661,13 @@ export function inferSlugFromBranch(
662
661
  */
663
662
  /**
664
663
  * Resolve the EFFECTIVE `promptGuidance` for an item by walking the precedence
665
- * chain (highest → lowest): the per-task frontmatter override, the per-prd
666
- * frontmatter override (only when the task carries a `prd:`), then the
664
+ * chain (highest → lowest): the per-task frontmatter override, the per-spec
665
+ * frontmatter override (only when the task carries a `spec:`), then the
667
666
  * already-resolved repo policy. Each nudge member resolves independently — a
668
667
  * task's `promptGuidance.testFirst` override never bleeds into a sibling
669
668
  * member — mirroring the `humanOnly`/`autoBuild` per-item override shape.
670
669
  *
671
- * A task may carry the override even when it has NO `prd:` (a self-contained
670
+ * A task may carry the override even when it has NO `spec:` (a self-contained
672
671
  * chore), by symmetry with `humanOnly` at the item level; `specFrontmatter`
673
672
  * is then simply absent and the chain reads task ⇒ repo.
674
673
  */
@@ -685,11 +684,11 @@ export function resolveItemPromptGuidance(
685
684
  }
686
685
 
687
686
  /**
688
- * Locate a prd's file on disk: prefer `work/prds/ready/<slug>.md` (the
689
- * auto-slice pool), then fall back to `work/prds/tasked/<slug>.md` (tasked,
687
+ * Locate a spec's file on disk: prefer `work/specs/ready/<slug>.md` (the
688
+ * auto-slice pool), then fall back to `work/specs/tasked/<slug>.md` (tasked,
690
689
  * resting). Returns `undefined` when neither exists — the caller treats that
691
- * as "no prd-level override available" and the precedence chain falls
692
- * through to the repo policy (a missing prd is NOT an error at this seam;
690
+ * as "no spec-level override available" and the precedence chain falls
691
+ * through to the repo policy (a missing spec is NOT an error at this seam;
693
692
  * the per-item override is OPTIONAL by design).
694
693
  */
695
694
  export function findSpecPath(
@@ -711,7 +710,7 @@ export function findSpecPath(
711
710
  /**
712
711
  * The convenience seam every caller of {@link buildAgentPrompt} reuses to
713
712
  * resolve the per-item override: load the task frontmatter from its file +
714
- * (when the task carries `prd:`) the prd frontmatter, then walk
713
+ * (when the task carries `spec:`) the spec frontmatter, then walk
715
714
  * {@link resolveItemPromptGuidance}. Pure-ish (reads at most two files);
716
715
  * returns the repo policy verbatim when neither item layer overrides anything.
717
716
  */
@@ -722,8 +721,7 @@ export function resolvePromptGuidanceForItem(options: {
722
721
  }): PromptGuidance {
723
722
  const taskFm = parseFrontmatter(options.taskContent);
724
723
  let specFm: Frontmatter | undefined;
725
- // MIGRATE step (prd `prd-to-spec-vocabulary-cutover-and-migration-command`):
726
- // read the parent-spec pointer off `fm.spec` (populated beside `fm.prd`).
724
+ // Read the parent-spec pointer off `fm.spec` (populated from the `spec:` key).
727
725
  if (taskFm.spec !== undefined) {
728
726
  const specPath = findSpecPath(options.cwd, taskFm.spec);
729
727
  if (specPath !== undefined) {
@@ -742,7 +740,7 @@ export function renderPrompt(options: PromptOptions): string {
742
740
  );
743
741
  }
744
742
  const task = resolveTask(options.cwd, slug);
745
- // Per-item override layer: a task or prd may pin `promptGuidance.testFirst`
743
+ // Per-item override layer: a task or spec may pin `promptGuidance.testFirst`
746
744
  // in its frontmatter, superseding the resolved repo policy for THIS item.
747
745
  // We ALWAYS walk the resolver (even when no repo policy was threaded), so a
748
746
  // task can opt IN to the strengthened nudge even on a repo whose default is
@@ -752,7 +750,7 @@ export function renderPrompt(options: PromptOptions): string {
752
750
  repoResolved: {testFirst: options.promptGuidance?.testFirst === true},
753
751
  taskContent: readFileSync(task.path, 'utf8'),
754
752
  });
755
- return buildAgentPrompt(task.slug, task.prd, task.taskPrompt, {
753
+ return buildAgentPrompt(task.slug, task.spec, task.taskPrompt, {
756
754
  protocolPath: options.protocolPath,
757
755
  cwd: options.cwd,
758
756
  promptGuidance: resolvedGuidance,
package/src/readiness.ts CHANGED
@@ -16,7 +16,7 @@ import {ledgerRead} from './ledger-read.js';
16
16
  * the shared {@link resolveBlockedBy} (no reimplemented dep resolution).
17
17
  *
18
18
  * The two axes are deliberately treated differently (see WORK-CONTRACT and the
19
- * task prd):
19
+ * task spec):
20
20
  *
21
21
  * - `blockedBy` unmet is a FACTUAL prerequisite (the dep work does not exist
22
22
  * yet) → REFUSE by default. An override flag is the human escape hatch.
@@ -11,7 +11,7 @@ import type {ReviewProvider} from './integrator.js';
11
11
 
12
12
  /**
13
13
  * **`complete --isolated <slug>` — FINISH an already-committed, already-done-moved
14
- * STRANDED isolated worktree** (prd `ledger-integrity` story 6, the
14
+ * STRANDED isolated worktree** (spec `ledger-integrity` story 6, the
15
15
  * `finish-already-committed-branch` task). The LOCATE-EXISTING inverse of
16
16
  * `do --isolated` (which CREATES a worktree): it resolves the slug's RETAINED job
17
17
  * worktree via the existing arbiter-URL-keyed naming