dorfl 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (619) hide show
  1. package/dist/advance-ci-template.d.ts +73 -0
  2. package/dist/advance-ci-template.d.ts.map +1 -0
  3. package/dist/advance-ci-template.js +104 -0
  4. package/dist/advance-ci-template.js.map +1 -0
  5. package/dist/advance-classify.d.ts +132 -0
  6. package/dist/advance-classify.d.ts.map +1 -0
  7. package/dist/advance-classify.js +120 -0
  8. package/dist/advance-classify.js.map +1 -0
  9. package/dist/advance-drivers.d.ts +182 -0
  10. package/dist/advance-drivers.d.ts.map +1 -0
  11. package/dist/advance-drivers.js +231 -0
  12. package/dist/advance-drivers.js.map +1 -0
  13. package/dist/advance-isolated.d.ts +156 -0
  14. package/dist/advance-isolated.d.ts.map +1 -0
  15. package/dist/advance-isolated.js +256 -0
  16. package/dist/advance-isolated.js.map +1 -0
  17. package/dist/advance-lifecycle-template.d.ts +107 -0
  18. package/dist/advance-lifecycle-template.d.ts.map +1 -0
  19. package/dist/advance-lifecycle-template.js +668 -0
  20. package/dist/advance-lifecycle-template.js.map +1 -0
  21. package/dist/advance-loop-driver.d.ts +325 -0
  22. package/dist/advance-loop-driver.d.ts.map +1 -0
  23. package/dist/advance-loop-driver.js +437 -0
  24. package/dist/advance-loop-driver.js.map +1 -0
  25. package/dist/advance-treeless-publish.d.ts +108 -0
  26. package/dist/advance-treeless-publish.d.ts.map +1 -0
  27. package/dist/advance-treeless-publish.js +71 -0
  28. package/dist/advance-treeless-publish.js.map +1 -0
  29. package/dist/advance.d.ts +340 -0
  30. package/dist/advance.d.ts.map +1 -0
  31. package/dist/advance.js +1122 -0
  32. package/dist/advance.js.map +1 -0
  33. package/dist/advancing-lock.d.ts +294 -0
  34. package/dist/advancing-lock.d.ts.map +1 -0
  35. package/dist/advancing-lock.js +594 -0
  36. package/dist/advancing-lock.js.map +1 -0
  37. package/dist/agent-launch.d.ts +79 -0
  38. package/dist/agent-launch.d.ts.map +1 -0
  39. package/dist/agent-launch.js +61 -0
  40. package/dist/agent-launch.js.map +1 -0
  41. package/dist/agent-stop.d.ts +149 -0
  42. package/dist/agent-stop.d.ts.map +1 -0
  43. package/dist/agent-stop.js +307 -0
  44. package/dist/agent-stop.js.map +1 -0
  45. package/dist/apply-decide.d.ts +127 -0
  46. package/dist/apply-decide.d.ts.map +1 -0
  47. package/dist/apply-decide.js +176 -0
  48. package/dist/apply-decide.js.map +1 -0
  49. package/dist/apply-merge-action.d.ts +206 -0
  50. package/dist/apply-merge-action.d.ts.map +1 -0
  51. package/dist/apply-merge-action.js +307 -0
  52. package/dist/apply-merge-action.js.map +1 -0
  53. package/dist/apply-persist.d.ts +174 -0
  54. package/dist/apply-persist.d.ts.map +1 -0
  55. package/dist/apply-persist.js +359 -0
  56. package/dist/apply-persist.js.map +1 -0
  57. package/dist/arbiter.d.ts +120 -0
  58. package/dist/arbiter.d.ts.map +1 -0
  59. package/dist/arbiter.js +255 -0
  60. package/dist/arbiter.js.map +1 -0
  61. package/dist/brand.d.ts +70 -0
  62. package/dist/brand.d.ts.map +1 -0
  63. package/dist/brand.js +84 -0
  64. package/dist/brand.js.map +1 -0
  65. package/dist/buildable-body.d.ts +132 -0
  66. package/dist/buildable-body.d.ts.map +1 -0
  67. package/dist/buildable-body.js +131 -0
  68. package/dist/buildable-body.js.map +1 -0
  69. package/dist/categorise.d.ts +66 -0
  70. package/dist/categorise.d.ts.map +1 -0
  71. package/dist/categorise.js +106 -0
  72. package/dist/categorise.js.map +1 -0
  73. package/dist/claim-cas.d.ts +117 -0
  74. package/dist/claim-cas.d.ts.map +1 -0
  75. package/dist/claim-cas.js +312 -0
  76. package/dist/claim-cas.js.map +1 -0
  77. package/dist/cli-spinner.d.ts +112 -0
  78. package/dist/cli-spinner.d.ts.map +1 -0
  79. package/dist/cli-spinner.js +157 -0
  80. package/dist/cli-spinner.js.map +1 -0
  81. package/dist/cli.d.ts +11 -0
  82. package/dist/cli.d.ts.map +1 -0
  83. package/dist/cli.js +3094 -0
  84. package/dist/cli.js.map +1 -0
  85. package/dist/close-job-template.d.ts +70 -0
  86. package/dist/close-job-template.d.ts.map +1 -0
  87. package/dist/close-job-template.js +180 -0
  88. package/dist/close-job-template.js.map +1 -0
  89. package/dist/close-job.d.ts +95 -0
  90. package/dist/close-job.d.ts.map +1 -0
  91. package/dist/close-job.js +226 -0
  92. package/dist/close-job.js.map +1 -0
  93. package/dist/complete.d.ts +361 -0
  94. package/dist/complete.d.ts.map +1 -0
  95. package/dist/complete.js +885 -0
  96. package/dist/complete.js.map +1 -0
  97. package/dist/concurrency.d.ts +68 -0
  98. package/dist/concurrency.d.ts.map +1 -0
  99. package/dist/concurrency.js +112 -0
  100. package/dist/concurrency.js.map +1 -0
  101. package/dist/config-override.d.ts +76 -0
  102. package/dist/config-override.d.ts.map +1 -0
  103. package/dist/config-override.js +50 -0
  104. package/dist/config-override.js.map +1 -0
  105. package/dist/config.d.ts +668 -0
  106. package/dist/config.d.ts.map +1 -0
  107. package/dist/config.js +241 -0
  108. package/dist/config.js.map +1 -0
  109. package/dist/continue-branch.d.ts +249 -0
  110. package/dist/continue-branch.d.ts.map +1 -0
  111. package/dist/continue-branch.js +389 -0
  112. package/dist/continue-branch.js.map +1 -0
  113. package/dist/cwd-section.d.ts +186 -0
  114. package/dist/cwd-section.d.ts.map +1 -0
  115. package/dist/cwd-section.js +209 -0
  116. package/dist/cwd-section.js.map +1 -0
  117. package/dist/decision-engine.d.ts +170 -0
  118. package/dist/decision-engine.d.ts.map +1 -0
  119. package/dist/decision-engine.js +136 -0
  120. package/dist/decision-engine.js.map +1 -0
  121. package/dist/detect.d.ts +17 -0
  122. package/dist/detect.d.ts.map +1 -0
  123. package/dist/detect.js +118 -0
  124. package/dist/detect.js.map +1 -0
  125. package/dist/do-autopick.d.ts +85 -0
  126. package/dist/do-autopick.d.ts.map +1 -0
  127. package/dist/do-autopick.js +112 -0
  128. package/dist/do-autopick.js.map +1 -0
  129. package/dist/do-config.d.ts +312 -0
  130. package/dist/do-config.d.ts.map +1 -0
  131. package/dist/do-config.js +358 -0
  132. package/dist/do-config.js.map +1 -0
  133. package/dist/do-remote-auto.d.ts +75 -0
  134. package/dist/do-remote-auto.d.ts.map +1 -0
  135. package/dist/do-remote-auto.js +111 -0
  136. package/dist/do-remote-auto.js.map +1 -0
  137. package/dist/do.d.ts +621 -0
  138. package/dist/do.d.ts.map +1 -0
  139. package/dist/do.js +1882 -0
  140. package/dist/do.js.map +1 -0
  141. package/dist/drop-source.d.ts +96 -0
  142. package/dist/drop-source.d.ts.map +1 -0
  143. package/dist/drop-source.js +91 -0
  144. package/dist/drop-source.js.map +1 -0
  145. package/dist/eligibility.d.ts +46 -0
  146. package/dist/eligibility.d.ts.map +1 -0
  147. package/dist/eligibility.js +34 -0
  148. package/dist/eligibility.js.map +1 -0
  149. package/dist/env-config.d.ts +51 -0
  150. package/dist/env-config.d.ts.map +1 -0
  151. package/dist/env-config.js +272 -0
  152. package/dist/env-config.js.map +1 -0
  153. package/dist/failure-cause.d.ts +70 -0
  154. package/dist/failure-cause.d.ts.map +1 -0
  155. package/dist/failure-cause.js +126 -0
  156. package/dist/failure-cause.js.map +1 -0
  157. package/dist/format.d.ts +43 -0
  158. package/dist/format.d.ts.map +1 -0
  159. package/dist/format.js +256 -0
  160. package/dist/format.js.map +1 -0
  161. package/dist/frontmatter.d.ts +215 -0
  162. package/dist/frontmatter.d.ts.map +1 -0
  163. package/dist/frontmatter.js +345 -0
  164. package/dist/frontmatter.js.map +1 -0
  165. package/dist/gate-readiness.d.ts +84 -0
  166. package/dist/gate-readiness.d.ts.map +1 -0
  167. package/dist/gate-readiness.js +103 -0
  168. package/dist/gate-readiness.js.map +1 -0
  169. package/dist/gc.d.ts +165 -0
  170. package/dist/gc.d.ts.map +1 -0
  171. package/dist/gc.js +313 -0
  172. package/dist/gc.js.map +1 -0
  173. package/dist/gh-failure.d.ts +42 -0
  174. package/dist/gh-failure.d.ts.map +1 -0
  175. package/dist/gh-failure.js +49 -0
  176. package/dist/gh-failure.js.map +1 -0
  177. package/dist/git.d.ts +75 -0
  178. package/dist/git.d.ts.map +1 -0
  179. package/dist/git.js +130 -0
  180. package/dist/git.js.map +1 -0
  181. package/dist/github.d.ts +187 -0
  182. package/dist/github.d.ts.map +1 -0
  183. package/dist/github.js +343 -0
  184. package/dist/github.js.map +1 -0
  185. package/dist/harness.d.ts +242 -0
  186. package/dist/harness.d.ts.map +1 -0
  187. package/dist/harness.js +157 -0
  188. package/dist/harness.js.map +1 -0
  189. package/dist/identity.d.ts +167 -0
  190. package/dist/identity.d.ts.map +1 -0
  191. package/dist/identity.js +231 -0
  192. package/dist/identity.js.map +1 -0
  193. package/dist/index.d.ts +147 -0
  194. package/dist/index.d.ts.map +1 -0
  195. package/dist/index.js +76 -0
  196. package/dist/index.js.map +1 -0
  197. package/dist/install-ci-branch-protection.d.ts +147 -0
  198. package/dist/install-ci-branch-protection.d.ts.map +1 -0
  199. package/dist/install-ci-branch-protection.js +166 -0
  200. package/dist/install-ci-branch-protection.js.map +1 -0
  201. package/dist/install-ci-capabilities/advance-lifecycle.d.ts +15 -0
  202. package/dist/install-ci-capabilities/advance-lifecycle.d.ts.map +1 -0
  203. package/dist/install-ci-capabilities/advance-lifecycle.js +28 -0
  204. package/dist/install-ci-capabilities/advance-lifecycle.js.map +1 -0
  205. package/dist/install-ci-capabilities/close-job.d.ts +13 -0
  206. package/dist/install-ci-capabilities/close-job.d.ts.map +1 -0
  207. package/dist/install-ci-capabilities/close-job.js +26 -0
  208. package/dist/install-ci-capabilities/close-job.js.map +1 -0
  209. package/dist/install-ci-capabilities/example-noop.d.ts +16 -0
  210. package/dist/install-ci-capabilities/example-noop.d.ts.map +1 -0
  211. package/dist/install-ci-capabilities/example-noop.js +23 -0
  212. package/dist/install-ci-capabilities/example-noop.js.map +1 -0
  213. package/dist/install-ci-capabilities/intake.d.ts +15 -0
  214. package/dist/install-ci-capabilities/intake.d.ts.map +1 -0
  215. package/dist/install-ci-capabilities/intake.js +28 -0
  216. package/dist/install-ci-capabilities/intake.js.map +1 -0
  217. package/dist/install-ci-capabilities/verify.d.ts +14 -0
  218. package/dist/install-ci-capabilities/verify.d.ts.map +1 -0
  219. package/dist/install-ci-capabilities/verify.js +27 -0
  220. package/dist/install-ci-capabilities/verify.js.map +1 -0
  221. package/dist/install-ci-core.d.ts +446 -0
  222. package/dist/install-ci-core.d.ts.map +1 -0
  223. package/dist/install-ci-core.js +760 -0
  224. package/dist/install-ci-core.js.map +1 -0
  225. package/dist/install-ci-github.d.ts +167 -0
  226. package/dist/install-ci-github.d.ts.map +1 -0
  227. package/dist/install-ci-github.js +315 -0
  228. package/dist/install-ci-github.js.map +1 -0
  229. package/dist/install-ci.d.ts +105 -0
  230. package/dist/install-ci.d.ts.map +1 -0
  231. package/dist/install-ci.js +363 -0
  232. package/dist/install-ci.js.map +1 -0
  233. package/dist/intake-event.d.ts +88 -0
  234. package/dist/intake-event.d.ts.map +1 -0
  235. package/dist/intake-event.js +66 -0
  236. package/dist/intake-event.js.map +1 -0
  237. package/dist/intake-marker.d.ts +95 -0
  238. package/dist/intake-marker.d.ts.map +1 -0
  239. package/dist/intake-marker.js +127 -0
  240. package/dist/intake-marker.js.map +1 -0
  241. package/dist/intake-triage.d.ts +48 -0
  242. package/dist/intake-triage.d.ts.map +1 -0
  243. package/dist/intake-triage.js +95 -0
  244. package/dist/intake-triage.js.map +1 -0
  245. package/dist/intake-trigger-template.d.ts +185 -0
  246. package/dist/intake-trigger-template.d.ts.map +1 -0
  247. package/dist/intake-trigger-template.js +449 -0
  248. package/dist/intake-trigger-template.js.map +1 -0
  249. package/dist/intake.d.ts +569 -0
  250. package/dist/intake.d.ts.map +1 -0
  251. package/dist/intake.js +1628 -0
  252. package/dist/intake.js.map +1 -0
  253. package/dist/integration-core.d.ts +539 -0
  254. package/dist/integration-core.d.ts.map +1 -0
  255. package/dist/integration-core.js +2195 -0
  256. package/dist/integration-core.js.map +1 -0
  257. package/dist/integrator.d.ts +343 -0
  258. package/dist/integrator.d.ts.map +1 -0
  259. package/dist/integrator.js +400 -0
  260. package/dist/integrator.js.map +1 -0
  261. package/dist/isolation.d.ts +219 -0
  262. package/dist/isolation.d.ts.map +1 -0
  263. package/dist/isolation.js +261 -0
  264. package/dist/isolation.js.map +1 -0
  265. package/dist/issue-provider.d.ts +349 -0
  266. package/dist/issue-provider.d.ts.map +1 -0
  267. package/dist/issue-provider.js +360 -0
  268. package/dist/issue-provider.js.map +1 -0
  269. package/dist/item-lock.d.ts +626 -0
  270. package/dist/item-lock.d.ts.map +1 -0
  271. package/dist/item-lock.js +1381 -0
  272. package/dist/item-lock.js.map +1 -0
  273. package/dist/item-path.d.ts +49 -0
  274. package/dist/item-path.d.ts.map +1 -0
  275. package/dist/item-path.js +66 -0
  276. package/dist/item-path.js.map +1 -0
  277. package/dist/ledger-lint.d.ts +129 -0
  278. package/dist/ledger-lint.d.ts.map +1 -0
  279. package/dist/ledger-lint.js +249 -0
  280. package/dist/ledger-lint.js.map +1 -0
  281. package/dist/ledger-read.d.ts +357 -0
  282. package/dist/ledger-read.d.ts.map +1 -0
  283. package/dist/ledger-read.js +442 -0
  284. package/dist/ledger-read.js.map +1 -0
  285. package/dist/ledger-write.d.ts +330 -0
  286. package/dist/ledger-write.d.ts.map +1 -0
  287. package/dist/ledger-write.js +411 -0
  288. package/dist/ledger-write.js.map +1 -0
  289. package/dist/lifecycle-gather.d.ts +30 -0
  290. package/dist/lifecycle-gather.d.ts.map +1 -0
  291. package/dist/lifecycle-gather.js +205 -0
  292. package/dist/lifecycle-gather.js.map +1 -0
  293. package/dist/lifecycle-pools.d.ts +180 -0
  294. package/dist/lifecycle-pools.d.ts.map +1 -0
  295. package/dist/lifecycle-pools.js +78 -0
  296. package/dist/lifecycle-pools.js.map +1 -0
  297. package/dist/merge-question-surfacer.d.ts +166 -0
  298. package/dist/merge-question-surfacer.d.ts.map +1 -0
  299. package/dist/merge-question-surfacer.js +297 -0
  300. package/dist/merge-question-surfacer.js.map +1 -0
  301. package/dist/mint-adr.d.ts +126 -0
  302. package/dist/mint-adr.d.ts.map +1 -0
  303. package/dist/mint-adr.js +257 -0
  304. package/dist/mint-adr.js.map +1 -0
  305. package/dist/mirror-pool-scan.d.ts +125 -0
  306. package/dist/mirror-pool-scan.d.ts.map +1 -0
  307. package/dist/mirror-pool-scan.js +104 -0
  308. package/dist/mirror-pool-scan.js.map +1 -0
  309. package/dist/needs-attention.d.ts +341 -0
  310. package/dist/needs-attention.d.ts.map +1 -0
  311. package/dist/needs-attention.js +900 -0
  312. package/dist/needs-attention.js.map +1 -0
  313. package/dist/orphan-sidecar.d.ts +79 -0
  314. package/dist/orphan-sidecar.d.ts.map +1 -0
  315. package/dist/orphan-sidecar.js +71 -0
  316. package/dist/orphan-sidecar.js.map +1 -0
  317. package/dist/output.d.ts +48 -0
  318. package/dist/output.d.ts.map +1 -0
  319. package/dist/output.js +66 -0
  320. package/dist/output.js.map +1 -0
  321. package/dist/pi-harness.d.ts +179 -0
  322. package/dist/pi-harness.d.ts.map +1 -0
  323. package/dist/pi-harness.js +342 -0
  324. package/dist/pi-harness.js.map +1 -0
  325. package/dist/placement.d.ts +99 -0
  326. package/dist/placement.d.ts.map +1 -0
  327. package/dist/placement.js +67 -0
  328. package/dist/placement.js.map +1 -0
  329. package/dist/prd-to-spec.d.ts +315 -0
  330. package/dist/prd-to-spec.d.ts.map +1 -0
  331. package/dist/prd-to-spec.js +684 -0
  332. package/dist/prd-to-spec.js.map +1 -0
  333. package/dist/prepare.d.ts +121 -0
  334. package/dist/prepare.d.ts.map +1 -0
  335. package/dist/prepare.js +140 -0
  336. package/dist/prepare.js.map +1 -0
  337. package/dist/prompt.d.ts +360 -0
  338. package/dist/prompt.d.ts.map +1 -0
  339. package/dist/prompt.js +499 -0
  340. package/dist/prompt.js.map +1 -0
  341. package/dist/protocol/ADR-FORMAT.md +47 -0
  342. package/dist/protocol/CLAIM-PROTOCOL.md +217 -0
  343. package/dist/protocol/REVIEW-PROTOCOL.md +119 -0
  344. package/dist/protocol/SURFACE-PROTOCOL.md +121 -0
  345. package/dist/protocol/TASKING-PROTOCOL.md +122 -0
  346. package/dist/protocol/WORK-CONTRACT.md +276 -0
  347. package/dist/protocol/spec-template.md +71 -0
  348. package/dist/protocol/task-template.md +65 -0
  349. package/dist/readiness.d.ts +66 -0
  350. package/dist/readiness.d.ts.map +1 -0
  351. package/dist/readiness.js +36 -0
  352. package/dist/readiness.js.map +1 -0
  353. package/dist/reap-branches.d.ts +102 -0
  354. package/dist/reap-branches.d.ts.map +1 -0
  355. package/dist/reap-branches.js +149 -0
  356. package/dist/reap-branches.js.map +1 -0
  357. package/dist/recover-isolated.d.ts +72 -0
  358. package/dist/recover-isolated.d.ts.map +1 -0
  359. package/dist/recover-isolated.js +188 -0
  360. package/dist/recover-isolated.js.map +1 -0
  361. package/dist/registry.d.ts +172 -0
  362. package/dist/registry.d.ts.map +1 -0
  363. package/dist/registry.js +296 -0
  364. package/dist/registry.js.map +1 -0
  365. package/dist/repo-config.d.ts +201 -0
  366. package/dist/repo-config.d.ts.map +1 -0
  367. package/dist/repo-config.js +414 -0
  368. package/dist/repo-config.js.map +1 -0
  369. package/dist/repo-key.d.ts +20 -0
  370. package/dist/repo-key.d.ts.map +1 -0
  371. package/dist/repo-key.js +68 -0
  372. package/dist/repo-key.js.map +1 -0
  373. package/dist/repo-mirror.d.ts +177 -0
  374. package/dist/repo-mirror.d.ts.map +1 -0
  375. package/dist/repo-mirror.js +271 -0
  376. package/dist/repo-mirror.js.map +1 -0
  377. package/dist/retry-backoff.d.ts +90 -0
  378. package/dist/retry-backoff.d.ts.map +1 -0
  379. package/dist/retry-backoff.js +98 -0
  380. package/dist/retry-backoff.js.map +1 -0
  381. package/dist/review-gate.d.ts +173 -0
  382. package/dist/review-gate.d.ts.map +1 -0
  383. package/dist/review-gate.js +261 -0
  384. package/dist/review-gate.js.map +1 -0
  385. package/dist/review-verdict.d.ts +149 -0
  386. package/dist/review-verdict.d.ts.map +1 -0
  387. package/dist/review-verdict.js +332 -0
  388. package/dist/review-verdict.js.map +1 -0
  389. package/dist/run.d.ts +221 -0
  390. package/dist/run.d.ts.map +1 -0
  391. package/dist/run.js +963 -0
  392. package/dist/run.js.map +1 -0
  393. package/dist/scan.d.ts +308 -0
  394. package/dist/scan.d.ts.map +1 -0
  395. package/dist/scan.js +374 -0
  396. package/dist/scan.js.map +1 -0
  397. package/dist/select-order.d.ts +75 -0
  398. package/dist/select-order.d.ts.map +1 -0
  399. package/dist/select-order.js +108 -0
  400. package/dist/select-order.js.map +1 -0
  401. package/dist/select-priority.d.ts +188 -0
  402. package/dist/select-priority.d.ts.map +1 -0
  403. package/dist/select-priority.js +80 -0
  404. package/dist/select-priority.js.map +1 -0
  405. package/dist/select.d.ts +25 -0
  406. package/dist/select.d.ts.map +1 -0
  407. package/dist/select.js +43 -0
  408. package/dist/select.js.map +1 -0
  409. package/dist/session-path.d.ts +36 -0
  410. package/dist/session-path.d.ts.map +1 -0
  411. package/dist/session-path.js +129 -0
  412. package/dist/session-path.js.map +1 -0
  413. package/dist/sidecar-apply.d.ts +83 -0
  414. package/dist/sidecar-apply.d.ts.map +1 -0
  415. package/dist/sidecar-apply.js +111 -0
  416. package/dist/sidecar-apply.js.map +1 -0
  417. package/dist/sidecar.d.ts +245 -0
  418. package/dist/sidecar.d.ts.map +1 -0
  419. package/dist/sidecar.js +481 -0
  420. package/dist/sidecar.js.map +1 -0
  421. package/dist/slug-namespace.d.ts +204 -0
  422. package/dist/slug-namespace.d.ts.map +1 -0
  423. package/dist/slug-namespace.js +229 -0
  424. package/dist/slug-namespace.js.map +1 -0
  425. package/dist/spec-complete.d.ts +44 -0
  426. package/dist/spec-complete.d.ts.map +1 -0
  427. package/dist/spec-complete.js +69 -0
  428. package/dist/spec-complete.js.map +1 -0
  429. package/dist/start.d.ts +97 -0
  430. package/dist/start.d.ts.map +1 -0
  431. package/dist/start.js +633 -0
  432. package/dist/start.js.map +1 -0
  433. package/dist/status.d.ts +199 -0
  434. package/dist/status.d.ts.map +1 -0
  435. package/dist/status.js +228 -0
  436. package/dist/status.js.map +1 -0
  437. package/dist/surface-gate.d.ts +162 -0
  438. package/dist/surface-gate.d.ts.map +1 -0
  439. package/dist/surface-gate.js +206 -0
  440. package/dist/surface-gate.js.map +1 -0
  441. package/dist/surface-persist.d.ts +86 -0
  442. package/dist/surface-persist.d.ts.map +1 -0
  443. package/dist/surface-persist.js +129 -0
  444. package/dist/surface-persist.js.map +1 -0
  445. package/dist/tasker-review-loop.d.ts +249 -0
  446. package/dist/tasker-review-loop.d.ts.map +1 -0
  447. package/dist/tasker-review-loop.js +369 -0
  448. package/dist/tasker-review-loop.js.map +1 -0
  449. package/dist/tasking-eligibility.d.ts +74 -0
  450. package/dist/tasking-eligibility.d.ts.map +1 -0
  451. package/dist/tasking-eligibility.js +52 -0
  452. package/dist/tasking-eligibility.js.map +1 -0
  453. package/dist/tasking-lock.d.ts +111 -0
  454. package/dist/tasking-lock.d.ts.map +1 -0
  455. package/dist/tasking-lock.js +256 -0
  456. package/dist/tasking-lock.js.map +1 -0
  457. package/dist/tasking.d.ts +275 -0
  458. package/dist/tasking.d.ts.map +1 -0
  459. package/dist/tasking.js +952 -0
  460. package/dist/tasking.js.map +1 -0
  461. package/dist/triage-gate.d.ts +127 -0
  462. package/dist/triage-gate.d.ts.map +1 -0
  463. package/dist/triage-gate.js +139 -0
  464. package/dist/triage-gate.js.map +1 -0
  465. package/dist/triage-persist.d.ts +163 -0
  466. package/dist/triage-persist.d.ts.map +1 -0
  467. package/dist/triage-persist.js +387 -0
  468. package/dist/triage-persist.js.map +1 -0
  469. package/dist/verdict-json.d.ts +32 -0
  470. package/dist/verdict-json.d.ts.map +1 -0
  471. package/dist/verdict-json.js +74 -0
  472. package/dist/verdict-json.js.map +1 -0
  473. package/dist/verify-workflow-template.d.ts +60 -0
  474. package/dist/verify-workflow-template.d.ts.map +1 -0
  475. package/dist/verify-workflow-template.js +126 -0
  476. package/dist/verify-workflow-template.js.map +1 -0
  477. package/dist/verify.d.ts +60 -0
  478. package/dist/verify.d.ts.map +1 -0
  479. package/dist/verify.js +62 -0
  480. package/dist/verify.js.map +1 -0
  481. package/dist/watch-session.d.ts +112 -0
  482. package/dist/watch-session.d.ts.map +1 -0
  483. package/dist/watch-session.js +347 -0
  484. package/dist/watch-session.js.map +1 -0
  485. package/dist/work-layout.d.ts +198 -0
  486. package/dist/work-layout.d.ts.map +1 -0
  487. package/dist/work-layout.js +217 -0
  488. package/dist/work-layout.js.map +1 -0
  489. package/dist/work-on.d.ts +154 -0
  490. package/dist/work-on.d.ts.map +1 -0
  491. package/dist/work-on.js +387 -0
  492. package/dist/work-on.js.map +1 -0
  493. package/dist/workspace.d.ts +224 -0
  494. package/dist/workspace.d.ts.map +1 -0
  495. package/dist/workspace.js +325 -0
  496. package/dist/workspace.js.map +1 -0
  497. package/package.json +46 -2
  498. package/src/advance-ci-template.ts +203 -0
  499. package/src/advance-classify.ts +197 -0
  500. package/src/advance-drivers.ts +414 -0
  501. package/src/advance-isolated.ts +432 -0
  502. package/src/advance-lifecycle-template.ts +791 -0
  503. package/src/advance-loop-driver.ts +745 -0
  504. package/src/advance-treeless-publish.ts +177 -0
  505. package/src/advance.ts +1564 -0
  506. package/src/advancing-lock.ts +988 -0
  507. package/src/agent-launch.ts +137 -0
  508. package/src/agent-stop.ts +361 -0
  509. package/src/apply-decide.ts +242 -0
  510. package/src/apply-merge-action.ts +502 -0
  511. package/src/apply-persist.ts +518 -0
  512. package/src/arbiter.ts +372 -0
  513. package/src/brand.ts +111 -0
  514. package/src/buildable-body.ts +196 -0
  515. package/src/categorise.ts +158 -0
  516. package/src/claim-cas.ts +513 -0
  517. package/src/cli-spinner.ts +225 -0
  518. package/src/cli.ts +4369 -0
  519. package/src/close-job-template.ts +236 -0
  520. package/src/close-job.ts +319 -0
  521. package/src/complete.ts +1379 -0
  522. package/src/concurrency.ts +151 -0
  523. package/src/config-override.ts +116 -0
  524. package/src/config.ts +883 -0
  525. package/src/continue-branch.ts +542 -0
  526. package/src/cwd-section.ts +392 -0
  527. package/src/decision-engine.ts +272 -0
  528. package/src/detect.ts +124 -0
  529. package/src/do-autopick.ts +223 -0
  530. package/src/do-config.ts +589 -0
  531. package/src/do-remote-auto.ts +197 -0
  532. package/src/do.ts +2623 -0
  533. package/src/drop-source.ts +194 -0
  534. package/src/eligibility.ts +79 -0
  535. package/src/env-config.ts +305 -0
  536. package/src/failure-cause.ts +142 -0
  537. package/src/format.ts +313 -0
  538. package/src/frontmatter.ts +485 -0
  539. package/src/gate-readiness.ts +147 -0
  540. package/src/gc.ts +510 -0
  541. package/src/gh-failure.ts +53 -0
  542. package/src/git.ts +186 -0
  543. package/src/github.ts +468 -0
  544. package/src/harness.ts +355 -0
  545. package/src/identity.ts +322 -0
  546. package/src/index.ts +785 -0
  547. package/src/install-ci-branch-protection.ts +255 -0
  548. package/src/install-ci-capabilities/advance-lifecycle.ts +34 -0
  549. package/src/install-ci-capabilities/close-job.ts +32 -0
  550. package/src/install-ci-capabilities/example-noop.ts +24 -0
  551. package/src/install-ci-capabilities/intake.ts +34 -0
  552. package/src/install-ci-capabilities/verify.ts +33 -0
  553. package/src/install-ci-core.ts +1088 -0
  554. package/src/install-ci-github.ts +376 -0
  555. package/src/install-ci.ts +552 -0
  556. package/src/intake-event.ts +102 -0
  557. package/src/intake-marker.ts +195 -0
  558. package/src/intake-triage.ts +138 -0
  559. package/src/intake-trigger-template.ts +591 -0
  560. package/src/intake.ts +2445 -0
  561. package/src/integration-core.ts +3065 -0
  562. package/src/integrator.ts +771 -0
  563. package/src/isolation.ts +484 -0
  564. package/src/issue-provider.ts +733 -0
  565. package/src/item-lock.ts +1858 -0
  566. package/src/item-path.ts +75 -0
  567. package/src/ledger-lint.ts +332 -0
  568. package/src/ledger-read.ts +924 -0
  569. package/src/ledger-write.ts +865 -0
  570. package/src/lifecycle-gather.ts +298 -0
  571. package/src/lifecycle-pools.ts +250 -0
  572. package/src/merge-question-surfacer.ts +496 -0
  573. package/src/mint-adr.ts +362 -0
  574. package/src/mirror-pool-scan.ts +240 -0
  575. package/src/needs-attention.ts +1506 -0
  576. package/src/orphan-sidecar.ts +150 -0
  577. package/src/output.ts +89 -0
  578. package/src/pi-harness.ts +403 -0
  579. package/src/placement.ts +131 -0
  580. package/src/prd-to-spec.ts +1023 -0
  581. package/src/prepare.ts +230 -0
  582. package/src/prompt.ts +760 -0
  583. package/src/readiness.ts +98 -0
  584. package/src/reap-branches.ts +278 -0
  585. package/src/recover-isolated.ts +276 -0
  586. package/src/registry.ts +475 -0
  587. package/src/repo-config.ts +550 -0
  588. package/src/repo-key.ts +74 -0
  589. package/src/repo-mirror.ts +367 -0
  590. package/src/retry-backoff.ts +130 -0
  591. package/src/review-gate.ts +389 -0
  592. package/src/review-verdict.ts +422 -0
  593. package/src/run.ts +1430 -0
  594. package/src/scan.ts +611 -0
  595. package/src/select-order.ts +143 -0
  596. package/src/select-priority.ts +266 -0
  597. package/src/select.ts +62 -0
  598. package/src/session-path.ts +153 -0
  599. package/src/sidecar-apply.ts +216 -0
  600. package/src/sidecar.ts +700 -0
  601. package/src/slug-namespace.ts +367 -0
  602. package/src/spec-complete.ts +118 -0
  603. package/src/start.ts +974 -0
  604. package/src/status.ts +441 -0
  605. package/src/surface-gate.ts +337 -0
  606. package/src/surface-persist.ts +241 -0
  607. package/src/tasker-review-loop.ts +671 -0
  608. package/src/tasking-eligibility.ts +114 -0
  609. package/src/tasking-lock.ts +416 -0
  610. package/src/tasking.ts +1438 -0
  611. package/src/triage-gate.ts +248 -0
  612. package/src/triage-persist.ts +570 -0
  613. package/src/verdict-json.ts +73 -0
  614. package/src/verify-workflow-template.ts +159 -0
  615. package/src/verify.ts +123 -0
  616. package/src/watch-session.ts +397 -0
  617. package/src/work-layout.ts +262 -0
  618. package/src/work-on.ts +660 -0
  619. package/src/workspace.ts +502 -0
@@ -0,0 +1,924 @@
1
+ import {readdirSync, readFileSync} from 'node:fs';
2
+ import {basename, join} from 'node:path';
3
+ import {parseFrontmatter} from './frontmatter.js';
4
+ import {runAsync, type RunResult} from './git.js';
5
+ import {
6
+ type WorkFolderKey,
7
+ type SpecFolder,
8
+ workFolderPath,
9
+ workFolderRel,
10
+ isWorkItemFile,
11
+ } from './work-layout.js';
12
+
13
+ /**
14
+ * The **read half** of the ledger-transition seam (ADR
15
+ * `docs/adr/claim-ledger-vs-protected-main.md`, status: accepted — the "Read
16
+ * seam"). ONE entry point — "resolve the live `work/` state for a repo" — that
17
+ * every reader goes through, so a FUTURE strategy could resolve some states from
18
+ * elsewhere (e.g. work-branch tips, a dedicated ledger ref) without each reader
19
+ * (`scan`, eligibility's data, readiness, the claim CAS) learning a new
20
+ * mechanism.
21
+ *
22
+ * It is a PURE REFACTOR: there is exactly ONE strategy ({@link currentLedgerRead})
23
+ * and it does EXACTLY what the code did before — the local method reads the
24
+ * working tree (offline, cross-repo); the arbiter method reads `<arbiter>/main`
25
+ * via `git show`/`ls-tree`. No mode, no config, no `ledgerMode`, no new ref, no
26
+ * new network read.
27
+ *
28
+ * The seam is honest about the real read sources rather than pretending they are
29
+ * one (per the ADR — do not collapse them):
30
+ *
31
+ * - **local working tree** — a working clone reads `work/tasks/ready|tasks/done`
32
+ * from its checkout (pool = `tasks/ready`; staging = `tasks/backlog`, surfaced
33
+ * elsewhere). OFFLINE. (Pre-registry `scan`/`status` used this; `run`'s in-place
34
+ * checkouts still do.)
35
+ * - **arbiter `main`** — the human claim guard (`readiness`) and the claim CAS
36
+ * read the task + `work/done/` from `<arbiter>/main`.
37
+ * - **hub mirror `main`** — `scan`/`status` (registry model, ADR §1) read the
38
+ * full `work/` lifecycle from each BARE hub mirror's `main` ref. A mirror has
39
+ * no working tree, so this reads the committed tree via `git ls-tree`/`git
40
+ * show` (the SAME mechanism the arbiter `done/` read uses, widened to the
41
+ * full backlog set). This read itself is offline; the
42
+ * fetch-first contract (ADR §5/§6 — the old "scan is always offline" invariant
43
+ * is retired) lives ONE layer up in `scan`/`status`, which refresh the
44
+ * mirror's `main` before calling this method. The read STRATEGY here is
45
+ * unchanged either way.
46
+ *
47
+ * The signatures stay at the SEMANTIC level ("resolve live state") and storage-
48
+ * agnostic: the ONLY public distinction is local-vs-arbiter (no `main`/path is
49
+ * baked into the public shape beyond that). `gc` is NOT a consumer — its `work/`
50
+ * reads are job-WORKTREE discovery under `<workspacesDir>/work/*` (the execution
51
+ * substrate), not the `work/` lifecycle ledger this seam resolves, so it has no
52
+ * applicable read to route here.
53
+ */
54
+
55
+ /**
56
+ * One agent-POOL task's parsed gate/deps, as resolved from the live `work/`
57
+ * state. The pool lives in `work/tasks/ready/` in the new layout (staging is
58
+ * `work/tasks/backlog/`); the type name follows the pool noun (`ready`) so a
59
+ * later reader cannot misread `backlog` as the pool.
60
+ */
61
+ export interface LedgerReadyItem {
62
+ /** Filename within `work/tasks/ready/` (e.g. `scan.md`). */
63
+ file: string;
64
+ /** Resolved slug (frontmatter `slug:`, falling back to the filename). */
65
+ slug: string;
66
+ /** Autonomy axis 1 (DECIDED): `true` (human-only) | `undefined` (undeclared). */
67
+ humanOnly: boolean | undefined;
68
+ /** Autonomy axis 2 (DISCOVERED): `true` (open questions) | `undefined`. */
69
+ needsAnswers: boolean | undefined;
70
+ /** Slugs this item is blocked by. */
71
+ blockedBy: string[];
72
+ }
73
+
74
+ /**
75
+ * The result of a prd-existence read (ADR §3a): does a prd named `<slug>` exist,
76
+ * and where. A prd lives at `work/prds/ready/<slug>.md`; once TASKED it rests at
77
+ * `work/prds/tasked/<slug>.md` (the tasked resting state, the source of truth for
78
+ * tasked-ness — task `prd-sliced-folder-step-a`). BOTH folders are consulted (any
79
+ * is enough): a prd that is up-for-tasking OR already tasked still occupies its
80
+ * slug, so collision detection must see it. While a prd IS being tasked its body
81
+ * STAYS in `work/prds/ready/` (the tasking lock no longer moves it — task
82
+ * `cutover-retire-slicing-advancing-markers-and-trim-folder-sets`; the transient
83
+ * `tasking/` folder is retired, the in-flight state is the per-item lock ref), so a
84
+ * mid-tasking prd is detected via its `work/prds/ready/` residence. The slug is resolved
85
+ * from frontmatter `slug:`, falling back to the filename — the SAME shape the task
86
+ * readers use.
87
+ */
88
+ export interface SpecExistence {
89
+ /**
90
+ * Whether a prd named `<slug>` exists in `work/prds/ready/` and/or `work/prds/tasked/`
91
+ * (up-for-tasking OR already tasked — either still claims the slug).
92
+ */
93
+ exists: boolean;
94
+ /** The spec source file, when present (`work/prds/ready/<slug>.md`). */
95
+ specFile: string | undefined;
96
+ /**
97
+ * The tasked resting file, when present (`work/prds/tasked/<slug>.md`) — i.e. the
98
+ * spec HAS BEEN tasked (the source of truth for tasked-ness, task
99
+ * `prd-sliced-folder-step-a`). A re-task moves it back `prds/tasked/ -> prds/ready/`.
100
+ */
101
+ specTaskedFile: string | undefined;
102
+ }
103
+
104
+ /**
105
+ * One prd enumerated for the AUTO-TASK selection pool (ADR §3 — the
106
+ * "tasks-first then specs to task" priority). A prd is NOT in the task
107
+ * scan/candidate model, so the auto-pick pool is built HERE from `work/prds/ready/`
108
+ * through this single shared prd read path (the same path
109
+ * {@link SpecExistence} uses, widened from existence to the gate axes the tasking
110
+ * predicate needs). The tasking-eligibility predicate (`autoslice-gate`'s
111
+ * `resolveTaskingEligibility`) is applied to these by the selection layer; this
112
+ * reader does NOT itself decide eligibility (it just surfaces the inputs).
113
+ */
114
+ export interface LedgerSpecItem {
115
+ /** Filename within `work/prds/ready/` (e.g. `auto-slice.md`). */
116
+ file: string;
117
+ /** Resolved slug (frontmatter `slug:`, falling back to the filename). */
118
+ slug: string;
119
+ /** Autonomy axis 1 (DECIDED): `true` (human-only) | `undefined`. */
120
+ humanOnly: boolean | undefined;
121
+ /** Autonomy axis 2 (DISCOVERED): `true` (open questions) | `undefined`. */
122
+ needsAnswers: boolean | undefined;
123
+ /** Spec-only cross-prd order: prd slugs that must already be TASKED first. */
124
+ taskedAfter: string[];
125
+ }
126
+
127
+ /**
128
+ * The prd pool of ONE repo, resolved from `work/prds/ready/` (the auto-task candidate
129
+ * source). Carries every prd's gate axes PLUS the set of already-TASKED slugs so
130
+ * the selection layer can resolve each prd's `taskedAfter` against `work/prds/tasked/`
131
+ * RESIDENCE (task `prd-sliced-folder-step-a` / prd `slicing-coherence` US #9): the
132
+ * FOLDER is the source of truth, like `done/` for tasks (the auto-tasker reads
133
+ * folder-residence; the `tasked:` marker was removed in
134
+ * `remove-sliced-marker-step-b`). Built
135
+ * through the SAME prd read path as {@link SpecExistence}; there is no second prd
136
+ * reader.
137
+ */
138
+ export interface LedgerSpecPool {
139
+ /** Every prd in `work/prds/ready/`, sorted by slug. */
140
+ specs: LedgerSpecItem[];
141
+ /** Slugs whose spec resides in `work/prds/tasked/` (resolves `taskedAfter`). */
142
+ taskedSlugs: Set<string>;
143
+ }
144
+
145
+ /**
146
+ * One OBSERVATION's lifecycle-pool fields, as resolved from `work/notes/observations/`
147
+ * (the triage candidate source for the advance auto-pick lifecycle pools, task
148
+ * `advance-autopick-lifecycle-pools`). An observation with NO `triaged:` marker is
149
+ * UNTRIAGED (still in the triage pool); a non-empty `triaged:` value (`keep` /
150
+ * `duplicate`) means it is SETTLED and DROPS OUT of the pool (US #30). This is the
151
+ * FIRST read of `work/notes/observations/` in the seam — `scan`/eligibility read only
152
+ * `backlog`/`done`/`specs*`.
153
+ */
154
+ export interface LedgerObservationItem {
155
+ /** Filename within `work/notes/observations/` (e.g. `stray-note.md`). */
156
+ file: string;
157
+ /** Resolved slug (frontmatter `slug:`, falling back to the filename). */
158
+ slug: string;
159
+ /**
160
+ * The SETTLED marker (`triaged:` frontmatter): a non-empty value (`keep` /
161
+ * `duplicate`) drops the observation out of the triage pool; `undefined` ⇒
162
+ * UNTRIAGED (still a triage candidate).
163
+ */
164
+ triaged: string | undefined;
165
+ }
166
+
167
+ /**
168
+ * The live `work/` lifecycle state of ONE repo as resolved from the LOCAL
169
+ * working tree. Storage-agnostic in shape: it is "the resolved state", not "the
170
+ * files on disk".
171
+ */
172
+ export interface LocalLedgerState {
173
+ /** Parsed `work/tasks/ready/*.md` (the agent POOL), sorted by slug. */
174
+ ready: LedgerReadyItem[];
175
+ /** Slugs present in `work/done/` (per-repo; resolves `blockedBy`). */
176
+ doneSlugs: Set<string>;
177
+ /**
178
+ * `work/notes/observations/*.md` items (sorted by slug) — the triage candidate source
179
+ * for the advance auto-pick lifecycle pools (task
180
+ * `advance-autopick-lifecycle-pools`). UNTRIAGED observations (no `triaged:`
181
+ * marker) are the triage pool; SETTLED ones (`triaged:` non-empty) drop out.
182
+ */
183
+ observations: LedgerObservationItem[];
184
+ }
185
+
186
+ /** The live `work/` state of ONE repo as resolved from the arbiter. */
187
+ export interface ArbiterLedgerState {
188
+ /**
189
+ * The requested task's raw file contents from the arbiter (it may live in
190
+ * the POOL `tasks/ready/` or in `in-progress/`), or `undefined` when not found
191
+ * there.
192
+ */
193
+ task: string | undefined;
194
+ /** Slugs present in `work/done/` on the arbiter (per-repo; resolves `blockedBy`). */
195
+ doneSlugs: Set<string>;
196
+ }
197
+
198
+ /** What the LOCAL-tree resolve method needs: which repo checkout to read. */
199
+ export interface ResolveLocalStateInput {
200
+ /** The repo working-tree root whose `work/` state to resolve. */
201
+ repoPath: string;
202
+ }
203
+
204
+ /** What the prd-existence resolve method needs: which repo + which slug. */
205
+ export interface ResolveSpecExistenceInput {
206
+ /** The repo root whose `work/prds/ready/`+`work/prds/tasked/` to read. */
207
+ repoPath: string;
208
+ /** The slug to look up (matched against frontmatter `slug:`, then filename). */
209
+ slug: string;
210
+ }
211
+
212
+ /** What the prd-pool resolve method needs: which repo's `work/prds/ready/` to enumerate. */
213
+ export interface ResolveSpecPoolInput {
214
+ /** The repo working-tree root whose `work/prds/ready/` to read. */
215
+ repoPath: string;
216
+ }
217
+
218
+ /**
219
+ * What the MIRROR-ref resolve method needs to read the full `work/` lifecycle
220
+ * from a BARE hub mirror's committed tree.
221
+ */
222
+ export interface ResolveMirrorStateInput {
223
+ /** The bare hub mirror directory (`<workspacesDir>/repos/<key>.git`). */
224
+ mirrorPath: string;
225
+ /**
226
+ * The mirror-LOCAL ref whose `work/` tree to read (default `main`). A hub
227
+ * mirror is bare, so `main` is a LOCAL branch — read `main:work/...`, NOT
228
+ * `origin/main:work/...`.
229
+ */
230
+ ref?: string;
231
+ /** Environment for child git processes. */
232
+ env?: NodeJS.ProcessEnv;
233
+ }
234
+
235
+ /**
236
+ * What the MIRROR-ref prd-pool method needs: which bare hub mirror's committed
237
+ * `work/prds/ready/`+`work/prds/tasked/` tree to enumerate.
238
+ */
239
+ export interface ResolveMirrorSpecPoolInput {
240
+ /** The bare hub mirror directory (`<workspacesDir>/repos/<key>.git`). */
241
+ mirrorPath: string;
242
+ /** The mirror-LOCAL ref whose `work/prds*` tree to read (default `main`). */
243
+ ref?: string;
244
+ /** Environment for child git processes. */
245
+ env?: NodeJS.ProcessEnv;
246
+ }
247
+
248
+ /** What the ARBITER resolve method needs to read committed `work/` state. */
249
+ export interface ResolveArbiterStateInput {
250
+ /** The slug whose task file to resolve (`work/{backlog,in-progress}/<slug>.md`). */
251
+ slug: string;
252
+ /** A working clone whose remotes include the arbiter (the reads run here). */
253
+ cwd: string;
254
+ /** Name of the arbiter git remote (its `main` is the source of truth). */
255
+ arbiter: string;
256
+ /** Environment for child git processes. */
257
+ env?: NodeJS.ProcessEnv;
258
+ }
259
+
260
+ /**
261
+ * The read-seam interface: ONE entry with THREE resolve-methods. The local
262
+ * method is synchronous and OFFLINE; the arbiter and mirror methods are async
263
+ * (they shell out to git). A future strategy implements this same interface to
264
+ * resolve some states elsewhere — without any reader changing.
265
+ */
266
+ export interface LedgerReadStrategy {
267
+ /** Resolve a repo's live `work/` state from its LOCAL working tree (offline). */
268
+ resolveLocalState(input: ResolveLocalStateInput): LocalLedgerState;
269
+ /** Resolve a repo's live `work/` state from the ARBITER (`<arbiter>/main`). */
270
+ resolveArbiterState(
271
+ input: ResolveArbiterStateInput,
272
+ ): Promise<ArbiterLedgerState>;
273
+ /**
274
+ * Resolve the FULL live `work/` lifecycle (backlog + done + observations) of
275
+ * a repo from its BARE hub mirror's `main` ref. Mirrors have no working
276
+ * tree, so `resolveLocalState`'s `readdirSync`/`readFileSync` cannot read them
277
+ * — this reads the committed tree via `git ls-tree`/`git show` (the same
278
+ * mechanism the arbiter method uses for `done/`, widened to the full set).
279
+ */
280
+ resolveMirrorState(input: ResolveMirrorStateInput): Promise<LocalLedgerState>;
281
+ /**
282
+ * Enumerate the repo's prd pool from a BARE hub mirror's committed `work/prds/ready/`
283
+ * tree (+ already-TASKED slugs from `work/prds/tasked/` residence) — the
284
+ * mirror-ref counterpart of {@link LedgerReadStrategy.resolveSpecPool}, for the
285
+ * NO-CHECKOUT mirror-side auto-pick (`run`'s isolated loop + the one-shot/CI
286
+ * `advance --remote -n`). A mirror is bare, so this reads the committed tree via
287
+ * `git ls-tree`/`git show` (the SAME mechanism {@link resolveMirrorState} uses),
288
+ * not a working-tree `readdirSync`. Returns the SAME {@link LedgerSpecPool} shape
289
+ * the working-tree reader returns, so the tasking-eligibility predicate
290
+ * (`taskableSpecs`) applies byte-identically to either source.
291
+ */
292
+ resolveMirrorSpecPool(
293
+ input: ResolveMirrorSpecPoolInput,
294
+ ): Promise<LedgerSpecPool>;
295
+ /**
296
+ * Resolve whether a prd named `<slug>` exists in the LOCAL working tree's
297
+ * `work/prds/ready/` (the prd source — where a mid-tasking prd ALSO rests now that the
298
+ * `tasking/` folder is retired) and/or `work/prds/tasked/` (the tasked resting
299
+ * state). The slug is resolved from each candidate file's frontmatter `slug:`,
300
+ * falling back to the filename — the SAME shape the task readers use.
301
+ *
302
+ * This is the FIRST prd read path in the seam: `ledger-read.ts`/`scan.ts` read
303
+ * only `backlog`/`done`, NEVER `work/prds/ready/`. It is added here
304
+ * so the §3a slug-namespace resolver, and later the auto-tasking / `do prd:` work,
305
+ * share ONE prd read path rather than each growing a bespoke scan. Synchronous
306
+ * and OFFLINE (a working-tree read), like {@link resolveLocalState}.
307
+ */
308
+ resolveSpecExistence(input: ResolveSpecExistenceInput): SpecExistence;
309
+ /**
310
+ * Enumerate the repo's prd pool from `work/prds/ready/` (the auto-task candidate
311
+ * source for the `do`/`run` "tasks-first then specs to task" priority, ADR
312
+ * §3). Returns every prd's gate axes (`humanOnly`/`needsAnswers`/`taskedAfter`)
313
+ * PLUS the set of already-TASKED slugs so the selection layer can resolve
314
+ * `taskedAfter` against `work/prds/tasked/` residence (the FOLDER is the source of
315
+ * truth) and apply `autoslice-gate`'s
316
+ * predicate. This is the SAME prd read path {@link resolveSpecExistence} uses,
317
+ * widened from a single-slug existence check to a full enumeration — NOT a
318
+ * second prd reader. Synchronous and OFFLINE (a working-tree read), like
319
+ * {@link resolveLocalState}.
320
+ */
321
+ resolveSpecPool(input: ResolveSpecPoolInput): LedgerSpecPool;
322
+ /**
323
+ * Enumerate `work/tasks/backlog/*.md` (the TASK STAGING folder) into the SAME
324
+ * {@link LedgerReadyItem} shape `resolveLocalState().ready` returns for the pool
325
+ * — the SURFACE-on-staging widening (prd
326
+ * `staging-surface-and-apply-promote-safety` F2). Synchronous + OFFLINE
327
+ * (working-tree read), like {@link resolveLocalState}. The pool / staging
328
+ * folders are distinct durable status folders (one-slug-one-folder — a slug
329
+ * is in at most one), so the two reads compose without de-duplication
330
+ * gymnastics. Missing folder reads as empty. CONSUMED ONLY by the lifecycle
331
+ * GATHER under the `surfaceStaging` gate — the BUILD/claim pool stays
332
+ * pool-only (`resolveLocalState().ready`), untouched by this read.
333
+ */
334
+ resolveLocalTaskStaging(input: ResolveLocalStateInput): LedgerReadyItem[];
335
+ /**
336
+ * Enumerate `work/prds/proposed/*.md` (the PRD STAGING folder) into the
337
+ * SAME {@link LedgerSpecItem} shape `resolveSpecPool().specs` returns for the
338
+ * pool — the PRD-symmetric `surfaceStaging` widening (prd
339
+ * `staging-surface-and-apply-promote-safety` F2, prd q4 answer). Sync + OFFLINE.
340
+ */
341
+ resolveLocalSpecStaging(input: ResolveSpecPoolInput): LedgerSpecItem[];
342
+ /**
343
+ * Enumerate `work/prds/tasked/*.md` (the TASKED resting folder) into the SAME
344
+ * {@link LedgerSpecItem} shape `resolveSpecPool().specs` returns. UNLIKE the pool
345
+ * (`prds/ready/`) and staging (`prds/proposed/`) readers, this exists so the
346
+ * lifecycle GATHER can surface/apply a `needsAnswers:true` prd that drifted
347
+ * AFTER it was tasked and rests IN PLACE in `prds/tasked/` (WORK-CONTRACT
348
+ * "A PRD that has drifted AFTER it was TASKED"). Without it, such a prd's
349
+ * ANSWERED sidecar is enumerated by no pool and the human's answer is STRANDED
350
+ * (observation `tasked-prd-needsanswers-sidecar-stranded-no-apply-pool`).
351
+ * `resolveSpecPool` deliberately returns tasked specs only as `taskedSlugs`
352
+ * (residence, for `taskedAfter`), NOT as enumerable gate-bearing items, so this
353
+ * is a SEPARATE read. Sync + OFFLINE.
354
+ */
355
+ resolveLocalSpecTasked(input: ResolveSpecPoolInput): LedgerSpecItem[];
356
+ /**
357
+ * Mirror-ref counterpart of {@link resolveLocalTaskStaging}: read
358
+ * `<ref>:work/tasks/backlog/*.md` from a BARE hub mirror via `git ls-tree` +
359
+ * `git show` (the SAME mechanism `resolveMirrorState` uses for the pool).
360
+ */
361
+ resolveMirrorTaskStaging(
362
+ input: ResolveMirrorStateInput,
363
+ ): Promise<LedgerReadyItem[]>;
364
+ /**
365
+ * Mirror-ref counterpart of {@link resolveLocalSpecStaging}: read
366
+ * `<ref>:work/prds/proposed/*.md` from a bare mirror.
367
+ */
368
+ resolveMirrorSpecStaging(
369
+ input: ResolveMirrorSpecPoolInput,
370
+ ): Promise<LedgerSpecItem[]>;
371
+ /**
372
+ * Mirror-ref counterpart of {@link resolveLocalSpecTasked}: read
373
+ * `<ref>:work/prds/tasked/*.md` from a bare mirror, so a `needsAnswers` tasked
374
+ * prd's answered sidecar is never stranded on the mirror-side advance path
375
+ * either.
376
+ */
377
+ resolveMirrorSpecTasked(
378
+ input: ResolveMirrorSpecPoolInput,
379
+ ): Promise<LedgerSpecItem[]>;
380
+ }
381
+
382
+ // --- The sole strategy: exactly today's behaviour -------------------------
383
+
384
+ function listMarkdown(dir: string): string[] {
385
+ let entries: string[];
386
+ try {
387
+ entries = readdirSync(dir);
388
+ } catch {
389
+ return [];
390
+ }
391
+ return entries.filter((name) => isWorkItemFile(name)).sort();
392
+ }
393
+
394
+ function slugForFile(dir: string, file: string): string {
395
+ const content = readFileSync(join(dir, file), 'utf8');
396
+ const fm = parseFrontmatter(content);
397
+ return fm.slug ?? basename(file, '.md');
398
+ }
399
+
400
+ /**
401
+ * Read a folder of TASK items (`tasks-ready` or `tasks-backlog`) from the local
402
+ * tree into the {@link LedgerReadyItem[]} shape. Factored so the POOL reader
403
+ * (`tasks/ready`) and the STAGING reader (`tasks/backlog`, the `surfaceStaging`
404
+ * widening) share one parse path — the two folders carry the SAME item shape
405
+ * (frontmatter + body), only the trust polarity differs.
406
+ */
407
+ function readLocalTaskFolder(
408
+ repoPath: string,
409
+ folder: 'tasks-ready' | 'tasks-backlog',
410
+ ): LedgerReadyItem[] {
411
+ const dir = workFolderPath(repoPath, folder);
412
+ const items: LedgerReadyItem[] = [];
413
+ for (const file of listMarkdown(dir)) {
414
+ const content = readFileSync(join(dir, file), 'utf8');
415
+ const fm = parseFrontmatter(content);
416
+ items.push({
417
+ file,
418
+ slug: fm.slug ?? basename(file, '.md'),
419
+ humanOnly: fm.humanOnly,
420
+ needsAnswers: fm.needsAnswers,
421
+ blockedBy: fm.blockedBy,
422
+ });
423
+ }
424
+ return items.sort((a, b) => a.slug.localeCompare(b.slug));
425
+ }
426
+
427
+ /** Read `work/tasks/ready/*.md` (the agent POOL) from the local tree, parsed and sorted by slug. */
428
+ function readLocalReady(repoPath: string): LedgerReadyItem[] {
429
+ return readLocalTaskFolder(repoPath, 'tasks-ready');
430
+ }
431
+
432
+ /**
433
+ * Read `work/tasks/backlog/*.md` (the TASK STAGING folder, prd
434
+ * `staging-surface-and-apply-promote-safety` F2) from the local tree. Same
435
+ * {@link LedgerReadyItem} shape as the pool reader — the SURFACE-on-staging
436
+ * widening only enumerates items; it does NOT promote them.
437
+ */
438
+ function readLocalTaskStaging(repoPath: string): LedgerReadyItem[] {
439
+ return readLocalTaskFolder(repoPath, 'tasks-backlog');
440
+ }
441
+
442
+ /**
443
+ * Read `work/prds/proposed/*.md` (the PRD STAGING folder, the prd twin
444
+ * of {@link readLocalTaskStaging}, prd q4 answer) from the local tree. Returns
445
+ * the SAME {@link LedgerSpecItem} shape `resolveSpecPool().specs` returns.
446
+ */
447
+ function readLocalSpecStaging(repoPath: string): LedgerSpecItem[] {
448
+ return readLocalSpecFolder(repoPath, 'specs-proposed');
449
+ }
450
+
451
+ /**
452
+ * Read `work/prds/tasked/*.md` (the TASKED resting folder) into the SAME
453
+ * {@link LedgerSpecItem} shape. Used by the lifecycle gather to surface/apply a
454
+ * `needsAnswers` prd that drifted after tasking and rests in place in
455
+ * `prds/tasked/` — so its answered sidecar is never stranded.
456
+ */
457
+ function readLocalSpecTasked(repoPath: string): LedgerSpecItem[] {
458
+ return readLocalSpecFolder(repoPath, 'specs-tasked');
459
+ }
460
+
461
+ /** Shared body for the local prd-FOLDER readers (proposed/tasked) — same item shape. */
462
+ function readLocalSpecFolder(
463
+ repoPath: string,
464
+ folder: 'specs-proposed' | 'specs-tasked',
465
+ ): LedgerSpecItem[] {
466
+ const dir = workFolderPath(repoPath, folder);
467
+ const specs: LedgerSpecItem[] = [];
468
+ for (const file of listMarkdown(dir)) {
469
+ const content = readFileSync(join(dir, file), 'utf8');
470
+ const fm = parseFrontmatter(content);
471
+ specs.push({
472
+ file,
473
+ slug: fm.slug ?? basename(file, '.md'),
474
+ humanOnly: fm.humanOnly,
475
+ needsAnswers: fm.needsAnswers,
476
+ taskedAfter: fm.taskedAfter,
477
+ });
478
+ }
479
+ return specs.sort((a, b) => a.slug.localeCompare(b.slug));
480
+ }
481
+
482
+ /** Collect the slugs present in `work/done/` on the local tree. */
483
+ function readLocalDoneSlugs(repoPath: string): Set<string> {
484
+ const dir = workFolderPath(repoPath, 'done');
485
+ const slugs = new Set<string>();
486
+ for (const file of listMarkdown(dir)) {
487
+ slugs.add(slugForFile(dir, file));
488
+ }
489
+ return slugs;
490
+ }
491
+
492
+ /**
493
+ * Read `work/notes/observations/*.md` (slug-sorted) from the local tree.
494
+ *
495
+ * Identity rule (task `observation-identity-is-its-filename-not-a-foreign-slug`):
496
+ * an observation's IDENTITY is its FILENAME, NEVER a foreign frontmatter `slug:`.
497
+ * Earlier this read `fm.slug ?? basename(file)`, which let the review-nits minting
498
+ * (which wrote the REVIEWED TASK's slug into `slug:` as a back-pointer) drive the
499
+ * lifecycle pool to emit `obs:<reviewed-slug>` — a key that did not round-trip
500
+ * through `findItemPath` (filename-only) and collided with the reviewed task in
501
+ * `work/done/`. Identity is now ALWAYS the basename, so the enumerate→resolve
502
+ * round-trip is total by construction and a stray frontmatter `slug:` cannot
503
+ * re-break it. The back-pointer lives in `reviewOf:` instead.
504
+ */
505
+ function readLocalObservations(repoPath: string): LedgerObservationItem[] {
506
+ const dir = workFolderPath(repoPath, 'observations');
507
+ const items: LedgerObservationItem[] = [];
508
+ for (const file of listMarkdown(dir)) {
509
+ const content = readFileSync(join(dir, file), 'utf8');
510
+ const fm = parseFrontmatter(content);
511
+ items.push({
512
+ file,
513
+ slug: basename(file, '.md'),
514
+ triaged: fm.triaged,
515
+ });
516
+ }
517
+ return items.sort((a, b) => a.slug.localeCompare(b.slug));
518
+ }
519
+
520
+ /**
521
+ * Does a prd named `slug` exist in `<repoPath>/work/<folder>/`? A prd source file
522
+ * is `work/prds/ready/*.md` (where a mid-tasking prd also rests — the `tasking/` folder is
523
+ * retired); a tasked prd rests at `work/prds/tasked/*.md` (the source of truth for
524
+ * tasked-ness). We match the slug against each file's
525
+ * frontmatter `slug:` (falling back to the filename) — the SAME shape the task
526
+ * readers use — so a renamed file whose frontmatter slug matches still resolves.
527
+ * Returns the matching filename, or `undefined`.
528
+ */
529
+ function findSpecFileBySlug(
530
+ repoPath: string,
531
+ folder: SpecFolder,
532
+ slug: string,
533
+ ): string | undefined {
534
+ const dir = workFolderPath(repoPath, folder);
535
+ for (const file of listMarkdown(dir)) {
536
+ if (slugForFile(dir, file) === slug) {
537
+ return file;
538
+ }
539
+ }
540
+ return undefined;
541
+ }
542
+
543
+ /**
544
+ * Enumerate `work/prds/ready/*.md` into the auto-task prd pool (the tasks-first/prd
545
+ * priority's prd source) — the SAME prd read path {@link findSpecFileBySlug} uses,
546
+ * widened from a single-slug existence check to a full enumeration. Each prd's
547
+ * slug is resolved from frontmatter `slug:` (falling back to the filename) and
548
+ * its gate axes (`humanOnly`/`needsAnswers`/`taskedAfter`) parsed. The
549
+ * already-TASKED set is RESIDENCE in `work/prds/tasked/` (task
550
+ * `prd-sliced-folder-step-a` / prd `slicing-coherence` US #9): the FOLDER is the
551
+ * source of truth (the build-machine `done/` analogue), so `taskedAfter` resolves
552
+ * against `prds/tasked/` residence (mirroring `blockedBy` -> `done/`). The `tasked:`
553
+ * frontmatter marker was removed entirely in `remove-sliced-marker-step-b`. This
554
+ * matches `tasking.ts`'s `readTaskedSlugs`. Missing folders read as empty.
555
+ */
556
+ function readLocalSpecPool(repoPath: string): LocalSpecPool {
557
+ const dir = workFolderPath(repoPath, 'specs-ready');
558
+ const specs: LedgerSpecItem[] = [];
559
+ for (const file of listMarkdown(dir)) {
560
+ const content = readFileSync(join(dir, file), 'utf8');
561
+ const fm = parseFrontmatter(content);
562
+ specs.push({
563
+ file,
564
+ slug: fm.slug ?? basename(file, '.md'),
565
+ humanOnly: fm.humanOnly,
566
+ needsAnswers: fm.needsAnswers,
567
+ taskedAfter: fm.taskedAfter,
568
+ });
569
+ }
570
+ specs.sort((a, b) => a.slug.localeCompare(b.slug));
571
+
572
+ // Tasked-ness is RESIDENCE in `work/prds/tasked/` — the FOLDER is the source of
573
+ // truth, like `done/` for tasks (the `tasked:` marker was removed in
574
+ // `remove-sliced-marker-step-b`), mirroring tasking.ts's readTaskedSlugs. Missing
575
+ // folder reads as empty.
576
+ const taskedSlugs = new Set<string>();
577
+ const taskedDir = workFolderPath(repoPath, 'specs-tasked');
578
+ for (const file of listMarkdown(taskedDir)) {
579
+ const content = readFileSync(join(taskedDir, file), 'utf8');
580
+ const fm = parseFrontmatter(content);
581
+ taskedSlugs.add(fm.slug ?? basename(file, '.md'));
582
+ }
583
+ return {specs, taskedSlugs};
584
+ }
585
+
586
+ /** Internal alias for {@link LedgerSpecPool} (kept local to the reader). */
587
+ type LocalSpecPool = LedgerSpecPool;
588
+
589
+ /** Run git, returning the raw result (no throw) — for soft checks. */
590
+ function gitSoft(
591
+ args: string[],
592
+ cwd: string,
593
+ env: NodeJS.ProcessEnv | undefined,
594
+ ): Promise<RunResult> {
595
+ return runAsync('git', args, cwd, {env});
596
+ }
597
+
598
+ /**
599
+ * Read the task file's contents from `<arbiter>/main`. It may live in `backlog/`
600
+ * (the normal claim case) or `in-progress/` (start --resume); read whichever
601
+ * exists. Returns `undefined` when the task is not found there.
602
+ */
603
+ async function readTaskOnArbiter(
604
+ slug: string,
605
+ arbiter: string,
606
+ cwd: string,
607
+ env: NodeJS.ProcessEnv | undefined,
608
+ ): Promise<string | undefined> {
609
+ for (const folder of ['tasks-ready', 'in-progress'] as const) {
610
+ const object = `${arbiter}/main:${workFolderRel(folder)}/${slug}.md`;
611
+ const show = await gitSoft(['show', object], cwd, env);
612
+ if (show.status === 0) {
613
+ return show.stdout;
614
+ }
615
+ }
616
+ return undefined;
617
+ }
618
+
619
+ /**
620
+ * Collect the slugs present in `work/done/` on `<arbiter>/main`, read from the
621
+ * committed arbiter tree (`ls-tree`). The slug is the filename minus `.md`
622
+ * (matching how claim/done moves name the file after its slug).
623
+ */
624
+ async function readDoneSlugsOnArbiter(
625
+ arbiter: string,
626
+ cwd: string,
627
+ env: NodeJS.ProcessEnv | undefined,
628
+ ): Promise<Set<string>> {
629
+ return readDoneSlugsFromTree(`${arbiter}/main`, cwd, env);
630
+ }
631
+
632
+ // --- Reading a committed `work/` tree (ref-based; bare-mirror or arbiter) ----
633
+ //
634
+ // These helpers read `work/{backlog,done}` from a git REF via
635
+ // `git ls-tree`/`git show` — the ONLY mechanism that works against a BARE repo
636
+ // (no working tree). `treeBase` is the `<ref>:work/<folder>` prefix; `cwd` is
637
+ // the repo the `git -C <cwd>` commands run in (the mirror itself for the mirror
638
+ // method, a working clone for the arbiter method).
639
+
640
+ /** `git ls-tree --name-only <base>` → the `.md` filenames (sorted), or `[]`. */
641
+ async function listMarkdownInTree(
642
+ base: string,
643
+ cwd: string,
644
+ env: NodeJS.ProcessEnv | undefined,
645
+ ): Promise<string[]> {
646
+ const tree = await gitSoft(['ls-tree', '--name-only', base], cwd, env);
647
+ if (tree.status !== 0) {
648
+ // The folder does not exist on this ref — nothing there.
649
+ return [];
650
+ }
651
+ return tree.stdout
652
+ .split('\n')
653
+ .map((s) => s.trim())
654
+ .filter((name) => isWorkItemFile(name))
655
+ .sort();
656
+ }
657
+
658
+ /** `git show <base>/<file>` → the file's raw contents, or `undefined`. */
659
+ async function showInTree(
660
+ base: string,
661
+ file: string,
662
+ cwd: string,
663
+ env: NodeJS.ProcessEnv | undefined,
664
+ ): Promise<string | undefined> {
665
+ const show = await gitSoft(['show', `${base}/${file}`], cwd, env);
666
+ return show.status === 0 ? show.stdout : undefined;
667
+ }
668
+
669
+ /** Collect the slugs in `<ref>:work/done` (filename minus `.md`). */
670
+ async function readDoneSlugsFromTree(
671
+ ref: string,
672
+ cwd: string,
673
+ env: NodeJS.ProcessEnv | undefined,
674
+ ): Promise<Set<string>> {
675
+ const slugs = new Set<string>();
676
+ for (const file of await listMarkdownInTree(
677
+ `${ref}:${workFolderRel('done')}`,
678
+ cwd,
679
+ env,
680
+ )) {
681
+ slugs.add(file.slice(0, -'.md'.length));
682
+ }
683
+ return slugs;
684
+ }
685
+
686
+ /**
687
+ * Parse `<ref>:work/tasks/<folder>/*.md` from a committed tree into
688
+ * {@link LedgerReadyItem[]}, sorted by slug. Factored so the POOL + STAGING
689
+ * mirror reads share ONE parse path (mirrors `readLocalTaskFolder`).
690
+ */
691
+ async function readTaskFolderFromTree(
692
+ folder: 'tasks-ready' | 'tasks-backlog',
693
+ ref: string,
694
+ cwd: string,
695
+ env: NodeJS.ProcessEnv | undefined,
696
+ ): Promise<LedgerReadyItem[]> {
697
+ const base = `${ref}:${workFolderRel(folder)}`;
698
+ const items: LedgerReadyItem[] = [];
699
+ for (const file of await listMarkdownInTree(base, cwd, env)) {
700
+ const content = await showInTree(base, file, cwd, env);
701
+ if (content === undefined) {
702
+ continue;
703
+ }
704
+ const fm = parseFrontmatter(content);
705
+ items.push({
706
+ file,
707
+ slug: fm.slug ?? basename(file, '.md'),
708
+ humanOnly: fm.humanOnly,
709
+ needsAnswers: fm.needsAnswers,
710
+ blockedBy: fm.blockedBy,
711
+ });
712
+ }
713
+ return items.sort((a, b) => a.slug.localeCompare(b.slug));
714
+ }
715
+
716
+ /** Parse `<ref>:work/tasks/ready/*.md` into pool items, sorted by slug. */
717
+ async function readReadyFromTree(
718
+ ref: string,
719
+ cwd: string,
720
+ env: NodeJS.ProcessEnv | undefined,
721
+ ): Promise<LedgerReadyItem[]> {
722
+ return readTaskFolderFromTree('tasks-ready', ref, cwd, env);
723
+ }
724
+
725
+ /** Parse `<ref>:work/tasks/backlog/*.md` (TASK STAGING) into items, sorted by slug. */
726
+ async function readTaskStagingFromTree(
727
+ ref: string,
728
+ cwd: string,
729
+ env: NodeJS.ProcessEnv | undefined,
730
+ ): Promise<LedgerReadyItem[]> {
731
+ return readTaskFolderFromTree('tasks-backlog', ref, cwd, env);
732
+ }
733
+
734
+ /** Parse `<ref>:work/prds/proposed/*.md` (PRD STAGING) into prd items, sorted by slug. */
735
+ async function readSpecStagingFromTree(
736
+ ref: string,
737
+ cwd: string,
738
+ env: NodeJS.ProcessEnv | undefined,
739
+ ): Promise<LedgerSpecItem[]> {
740
+ return readSpecFolderFromTree('specs-proposed', ref, cwd, env);
741
+ }
742
+
743
+ /** Parse `<ref>:work/prds/tasked/*.md` (TASKED resting) into prd items, sorted by slug. */
744
+ async function readSpecTaskedFromTree(
745
+ ref: string,
746
+ cwd: string,
747
+ env: NodeJS.ProcessEnv | undefined,
748
+ ): Promise<LedgerSpecItem[]> {
749
+ return readSpecFolderFromTree('specs-tasked', ref, cwd, env);
750
+ }
751
+
752
+ /** Shared body for the mirror-ref prd-FOLDER readers (proposed/tasked) — same item shape. */
753
+ async function readSpecFolderFromTree(
754
+ folder: 'specs-proposed' | 'specs-tasked',
755
+ ref: string,
756
+ cwd: string,
757
+ env: NodeJS.ProcessEnv | undefined,
758
+ ): Promise<LedgerSpecItem[]> {
759
+ const base = `${ref}:${workFolderRel(folder)}`;
760
+ const specs: LedgerSpecItem[] = [];
761
+ for (const file of await listMarkdownInTree(base, cwd, env)) {
762
+ const content = await showInTree(base, file, cwd, env);
763
+ if (content === undefined) {
764
+ continue;
765
+ }
766
+ const fm = parseFrontmatter(content);
767
+ specs.push({
768
+ file,
769
+ slug: fm.slug ?? basename(file, '.md'),
770
+ humanOnly: fm.humanOnly,
771
+ needsAnswers: fm.needsAnswers,
772
+ taskedAfter: fm.taskedAfter,
773
+ });
774
+ }
775
+ return specs.sort((a, b) => a.slug.localeCompare(b.slug));
776
+ }
777
+
778
+ /**
779
+ * Parse `<ref>:work/prds/ready/*.md` into the auto-task prd pool, sorted by slug, plus
780
+ * the already-TASKED slugs from `<ref>:work/prds/tasked/` RESIDENCE (the folder is
781
+ * the source of truth, mirroring the working-tree {@link readLocalSpecPool}). Reads
782
+ * a committed tree (bare-mirror or any ref) via `ls-tree`/`show`. Missing folders
783
+ * read as empty.
784
+ */
785
+ async function readSpecPoolFromTree(
786
+ ref: string,
787
+ cwd: string,
788
+ env: NodeJS.ProcessEnv | undefined,
789
+ ): Promise<LedgerSpecPool> {
790
+ const specBase = `${ref}:${workFolderRel('specs-ready')}`;
791
+ const specs: LedgerSpecItem[] = [];
792
+ for (const file of await listMarkdownInTree(specBase, cwd, env)) {
793
+ const content = await showInTree(specBase, file, cwd, env);
794
+ if (content === undefined) {
795
+ continue;
796
+ }
797
+ const fm = parseFrontmatter(content);
798
+ specs.push({
799
+ file,
800
+ slug: fm.slug ?? basename(file, '.md'),
801
+ humanOnly: fm.humanOnly,
802
+ needsAnswers: fm.needsAnswers,
803
+ taskedAfter: fm.taskedAfter,
804
+ });
805
+ }
806
+ specs.sort((a, b) => a.slug.localeCompare(b.slug));
807
+
808
+ // Tasked-ness is RESIDENCE in `work/prds/tasked/` — the FOLDER is the source of
809
+ // truth (the `tasked:` marker was removed in `remove-sliced-marker-step-b`),
810
+ // exactly as the working-tree reader resolves it.
811
+ const taskedBase = `${ref}:${workFolderRel('specs-tasked')}`;
812
+ const taskedSlugs = new Set<string>();
813
+ for (const file of await listMarkdownInTree(taskedBase, cwd, env)) {
814
+ const content = await showInTree(taskedBase, file, cwd, env);
815
+ if (content === undefined) {
816
+ continue;
817
+ }
818
+ const fm = parseFrontmatter(content);
819
+ taskedSlugs.add(fm.slug ?? basename(file, '.md'));
820
+ }
821
+ return {specs, taskedSlugs};
822
+ }
823
+
824
+ /**
825
+ * Parse `<ref>:work/notes/observations/*.md` into items, sorted by slug. Identity is the
826
+ * FILENAME (mirrors {@link readLocalObservations}) so the in-place + mirror
827
+ * enumerations agree, and a foreign frontmatter `slug:` cannot break the
828
+ * enumerate→resolve round-trip.
829
+ */
830
+ async function readObservationsFromTree(
831
+ ref: string,
832
+ cwd: string,
833
+ env: NodeJS.ProcessEnv | undefined,
834
+ ): Promise<LedgerObservationItem[]> {
835
+ const base = `${ref}:${workFolderRel('observations')}`;
836
+ const items: LedgerObservationItem[] = [];
837
+ for (const file of await listMarkdownInTree(base, cwd, env)) {
838
+ const content = await showInTree(base, file, cwd, env);
839
+ if (content === undefined) {
840
+ continue;
841
+ }
842
+ const fm = parseFrontmatter(content);
843
+ items.push({
844
+ file,
845
+ slug: basename(file, '.md'),
846
+ triaged: fm.triaged,
847
+ });
848
+ }
849
+ return items.sort((a, b) => a.slug.localeCompare(b.slug));
850
+ }
851
+
852
+ /**
853
+ * The ONLY ledger-read strategy: current behaviour. The local method reads the
854
+ * working tree (offline); the arbiter method reads `<arbiter>/main`. A future
855
+ * strategy would be a different object implementing the same interface — chosen
856
+ * NOWHERE today (no mode/config selects it).
857
+ */
858
+ export const currentLedgerRead: LedgerReadStrategy = {
859
+ resolveLocalState({repoPath}) {
860
+ return {
861
+ ready: readLocalReady(repoPath),
862
+ doneSlugs: readLocalDoneSlugs(repoPath),
863
+ observations: readLocalObservations(repoPath),
864
+ };
865
+ },
866
+ async resolveArbiterState({slug, cwd, arbiter, env}) {
867
+ const task = await readTaskOnArbiter(slug, arbiter, cwd, env);
868
+ const doneSlugs = await readDoneSlugsOnArbiter(arbiter, cwd, env);
869
+ return {task, doneSlugs};
870
+ },
871
+ resolveSpecExistence({repoPath, slug}) {
872
+ const specFile = findSpecFileBySlug(repoPath, 'specs-ready', slug);
873
+ const specTaskedFile = findSpecFileBySlug(repoPath, 'specs-tasked', slug);
874
+ return {
875
+ exists: specFile !== undefined || specTaskedFile !== undefined,
876
+ specFile,
877
+ specTaskedFile,
878
+ };
879
+ },
880
+ resolveSpecPool({repoPath}) {
881
+ return readLocalSpecPool(repoPath);
882
+ },
883
+ resolveLocalTaskStaging({repoPath}) {
884
+ return readLocalTaskStaging(repoPath);
885
+ },
886
+ resolveLocalSpecStaging({repoPath}) {
887
+ return readLocalSpecStaging(repoPath);
888
+ },
889
+ resolveLocalSpecTasked({repoPath}) {
890
+ return readLocalSpecTasked(repoPath);
891
+ },
892
+ async resolveMirrorTaskStaging({mirrorPath, ref = 'main', env}) {
893
+ return readTaskStagingFromTree(ref, mirrorPath, env);
894
+ },
895
+ async resolveMirrorSpecStaging({mirrorPath, ref = 'main', env}) {
896
+ return readSpecStagingFromTree(ref, mirrorPath, env);
897
+ },
898
+ async resolveMirrorSpecTasked({mirrorPath, ref = 'main', env}) {
899
+ return readSpecTaskedFromTree(ref, mirrorPath, env);
900
+ },
901
+ async resolveMirrorState({mirrorPath, ref = 'main', env}) {
902
+ // A hub mirror is BARE — read the full `work/` lifecycle from its committed
903
+ // `<ref>:work/...` tree, running git INSIDE the mirror (`git -C <mirror>`).
904
+ // The ref is mirror-LOCAL (`main`), never `origin/main`.
905
+ const [ready, doneSlugs, observations] = await Promise.all([
906
+ readReadyFromTree(ref, mirrorPath, env),
907
+ readDoneSlugsFromTree(ref, mirrorPath, env),
908
+ readObservationsFromTree(ref, mirrorPath, env),
909
+ ]);
910
+ return {ready, doneSlugs, observations};
911
+ },
912
+ async resolveMirrorSpecPool({mirrorPath, ref = 'main', env}) {
913
+ // The prd pool from the bare mirror's committed `<ref>:work/prds*` tree — the
914
+ // mirror-ref counterpart of `resolveSpecPool` (a working-tree read). Same shape,
915
+ // so `taskableSpecs` applies identically to either source.
916
+ return readSpecPoolFromTree(ref, mirrorPath, env);
917
+ },
918
+ };
919
+
920
+ /**
921
+ * The active ledger-read strategy. There is exactly one (current behaviour);
922
+ * this indirection is the seam's single insertion point — NOT a selectable mode.
923
+ */
924
+ export const ledgerRead: LedgerReadStrategy = currentLedgerRead;