dorfl 0.0.0 → 0.1.1

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 +3100 -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 +208 -0
  162. package/dist/frontmatter.d.ts.map +1 -0
  163. package/dist/frontmatter.js +344 -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 +329 -0
  330. package/dist/prd-to-spec.d.ts.map +1 -0
  331. package/dist/prd-to-spec.js +706 -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 +363 -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 +951 -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 +4379 -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 +477 -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 +1059 -0
  581. package/src/prepare.ts +230 -0
  582. package/src/prompt.ts +763 -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 +1437 -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
package/src/sidecar.ts ADDED
@@ -0,0 +1,700 @@
1
+ import {parseSlugArg, type SlugNamespace} from './slug-namespace.js';
2
+ import {workItemRel} from './work-layout.js';
3
+
4
+ /**
5
+ * The **question/answer SIDECAR contract** (prd `advance-loop`, task
6
+ * `advance-sidecar-contract`) — the one genuinely-new piece of the `advance`
7
+ * family. A strict, tooling-OWNED per-item file `work/questions/<type>-<slug>.md`
8
+ * carrying per-entry answered-state, so the tooling fully owns the Q&A artifact
9
+ * (no fragile round-trip parse of human-authored prose in the item body).
10
+ *
11
+ * This module is the FORMAT + the in-memory model + the pure read/write/append/
12
+ * derived-`allAnswered` operations. The ATOMIC apply (mutate the item body AND
13
+ * the sidecar in ONE commit) lives in {@link applyAtomic} (`sidecar-apply.ts`).
14
+ * It builds NOTHING above the contract — no tick, no verb, no lock, no rungs;
15
+ * later tasks of the family consume these.
16
+ *
17
+ * # On-disk text format (REFORMATTED — ADR `question-sidecar-human-readable-format`)
18
+ *
19
+ * The sidecar is the HUMAN-FACING surface of the answer loop: humans read the
20
+ * question and write the answer in this file, very often through the GitHub web
21
+ * UI. The original `key: |` YAML-block-scalar format rendered as run-together
22
+ * noise on GitHub (literal `|` pipes, collapsed indentation). The on-disk format
23
+ * is now **real Markdown with machine state in HTML comments**:
24
+ *
25
+ * - An IDENTITY HTML comment at the top carries `item`/`type`/`slug`/
26
+ * `allAnswered` (`<!-- dorfl-sidecar: item=... type=... slug=... allAnswered=... -->`).
27
+ * - Per entry: a `## Qn` heading (entry separator + answer boundary), a BOLD
28
+ * question line, a BLOCKQUOTE context, an ITALIC suggested-default
29
+ * (`_Suggested default: …_`), a per-entry HTML COMMENT carrying
30
+ * `id=…` (and an explicit `answered=…` OVERRIDE when it disagrees with the
31
+ * answer-derived predicate), a fixed answer marker
32
+ * `**Your answer** (write below this line):`, then the human's answer prose.
33
+ * (The `disposition=…` field is RETIRED — task
34
+ * `agentic-apply-retire-disposition-vocabulary`; an entry is binary, and a
35
+ * stale `disposition=` token in an old sidecar is parsed away.)
36
+ * - The answer is HEADING-DELIMITED: it spans from the answer marker up to
37
+ * the next entry `## ` heading (NOT a `---` rule), so a literal `---`
38
+ * inside an answer cannot break parsing.
39
+ *
40
+ * GitHub renders HTML comments as nothing, so the machine state is invisible to
41
+ * the human and unbreakable by their edit. The human just types prose under the
42
+ * answer marker with no format knowledge.
43
+ *
44
+ * Round-trip is **SEMANTIC** (model-equal, not byte-equal): a parse → serialise
45
+ * canonicalises whitespace; the MODEL (entries, ids, answers, answered-state) is
46
+ * preserved. The load-bearing rules are kept:
47
+ *
48
+ * - **Identity-keyed, NOT folder-keyed.** The path is derived PURELY from the
49
+ * item's NAMESPACED identity (`<type>-<slug>`, `:`→`-` for the filename),
50
+ * using {@link parseSlugArg} (the `slug-namespace.ts` resolver) as the single
51
+ * source of truth for the identity. There is NO back-pointer field in the
52
+ * item body — the only in-body signal is the existing `needsAnswers` flag —
53
+ * so the sidecar survives the item's `git mv`s between lifecycle folders
54
+ * with no lock-step move.
55
+ * - **The answered predicate (MAINTAINER-RESOLVED §1):** a non-empty
56
+ * `answer` ⇒ ANSWERED, with an explicit `answered=…` HTML-comment field as
57
+ * an OVERRIDE. The override is encoded in the per-entry HTML comment ONLY
58
+ * when it DISAGREES with the derived predicate (an empty answer with
59
+ * `answered=true`, or a non-empty answer with `answered=false`); otherwise
60
+ * the field is omitted so a tolerant "human only types under the answer
61
+ * marker" edit cannot be re-interpreted as a sticky override on the next
62
+ * parse.
63
+ * - **`allAnswered` is DERIVED** — recomputed from the entries on every
64
+ * serialise; the classifier MAY read it for a cheap scan but MUST NOT trust
65
+ * it over the entries.
66
+ * - **Entry ids are stable + monotonic** (`q1`, `q2`, …), NEVER reused.
67
+ * APPEND adds `qN+1` and never mutates an existing answered entry (the
68
+ * sidecar is the item's full Q&A history).
69
+ */
70
+
71
+ /**
72
+ * The item-types a sidecar can key onto (the slug-namespace + obs).
73
+ *
74
+ * HARD CUTOVER (spec `prd-to-spec-vocabulary-cutover-and-migration-command`,
75
+ * contract step): the legacy `'prd'` type member is GONE — the parent-spec type
76
+ * is `'spec'` only. A `spec:<slug>` identity keys onto the `spec-<slug>`
77
+ * lock/sidecar entry. The on-disk `prd-<slug>.md` sidecar FILE (dorfl's
78
+ * not-yet-converted data) is still probed by {@link sidecarPathCandidates} as a
79
+ * legacy file-path fallback — that is a DATA alias the migration command removes,
80
+ * NOT this type member.
81
+ */
82
+ export type SidecarType = 'spec' | 'task' | 'observation';
83
+
84
+ /**
85
+ * The optional, machine-only `kind` AXIS on a question entry — the dispatch
86
+ * signal the answered-question apply rung reads to choose deterministic-action
87
+ * (`merge`, `stuck`) vs agentic-content (`triage`, `spec`) routing WITHOUT
88
+ * sniffing the shape of another field. Absent ⇒ the existing binary content
89
+ * entry (every pre-`kind` sidecar parses + renders byte-identically).
90
+ *
91
+ * INTERIM PRIMITIVE — REMOVE when question sidecars move to KIND-BASED
92
+ * SUBFOLDERS (`work/questions/merge/`, …), where the folder ENCODES the kind
93
+ * and this per-entry field is redundant. See the observation
94
+ * `questions-folder-rename-and-kind-axis-prefix-vs-subfolder-2026-06-21` + idea
95
+ * `folder-taxonomy-and-prd-edit-handshake`. Built deliberately as a single
96
+ * typed field read in exactly ONE place (the apply dispatch, a later task) so
97
+ * the folder-cutover can DELETE it in one move.
98
+ *
99
+ * A mistyped/unknown `kind=` token parses to `undefined` (silent-on-malformed,
100
+ * mirroring the retired `disposition` precedent), never a throw, never a
101
+ * coerce.
102
+ */
103
+ export type SidecarKind = 'merge' | 'stuck' | 'triage' | 'spec';
104
+
105
+ const SIDECAR_KINDS: ReadonlySet<SidecarKind> = new Set<SidecarKind>([
106
+ 'merge',
107
+ 'stuck',
108
+ 'triage',
109
+ 'spec',
110
+ ]);
111
+
112
+ /** One question entry in the sidecar (the per-entry source of truth). */
113
+ export interface SidecarEntry {
114
+ /** Stable, monotonic id (`q1`, `q2`, …); never reused once minted. */
115
+ id: string;
116
+ /** The question, verbatim. */
117
+ question: string;
118
+ /** Inline context so the human need not open the item. Empty when absent. */
119
+ context: string;
120
+ /** Optional suggested default (the surface-questions humility aid). */
121
+ default?: string;
122
+ /**
123
+ * The human's answer; empty/absent while unanswered. A NON-EMPTY answer ⇒
124
+ * answered (see {@link isEntryAnswered}).
125
+ */
126
+ answer: string;
127
+ /**
128
+ * The explicit `answered` OVERRIDE, when the human/tooling wrote one. `true`
129
+ * forces answered; `false` overrides a non-empty answer back to unanswered.
130
+ * `undefined` ⇒ no override (the answered-ness derives from `answer`).
131
+ */
132
+ answeredOverride?: boolean;
133
+ /**
134
+ * Optional dispatch axis (see {@link SidecarKind}). Absent ⇒ the existing
135
+ * binary content entry. INTERIM — removable once question sidecars move to
136
+ * kind-based SUBFOLDERS.
137
+ */
138
+ kind?: SidecarKind;
139
+ }
140
+
141
+ /** The parsed sidecar: identity frontmatter + ordered entries. */
142
+ export interface SidecarModel {
143
+ /** The NAMESPACED identity (`spec:autotask`, `task:foo`, `observation:bar`). */
144
+ item: string;
145
+ /** The item type (redundant with the filename; explicit for the parser). */
146
+ type: SidecarType;
147
+ /** The bare slug. */
148
+ slug: string;
149
+ /** The ordered question entries (the source of truth for answered-state). */
150
+ entries: SidecarEntry[];
151
+ }
152
+
153
+ /** Raised for a structurally-invalid sidecar the parser cannot trust. */
154
+ export class SidecarParseError extends Error {
155
+ constructor(message: string) {
156
+ super(message);
157
+ this.name = 'SidecarParseError';
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Is this entry ANSWERED? The MAINTAINER-RESOLVED §1 predicate: a non-empty
163
+ * `answer` ⇒ answered, with the explicit `answered=…` override (carried in the
164
+ * per-entry HTML comment) winning when present. An explicit `answered=false`
165
+ * overrides a non-empty answer back to unanswered; an explicit `answered=true`
166
+ * forces answered even with an empty answer.
167
+ */
168
+ export function isEntryAnswered(entry: SidecarEntry): boolean {
169
+ if (entry.answeredOverride !== undefined) {
170
+ return entry.answeredOverride;
171
+ }
172
+ return entry.answer.trim() !== '';
173
+ }
174
+
175
+ /** Every entry that is NOT yet answered (derived from the entries). */
176
+ export function pendingEntries(model: SidecarModel): SidecarEntry[] {
177
+ return model.entries.filter((entry) => !isEntryAnswered(entry));
178
+ }
179
+
180
+ /**
181
+ * Is the WHOLE sidecar answered? DERIVED from the entries (never read off the
182
+ * identity comment mirror). An EMPTY sidecar (no entries) is NOT all-answered —
183
+ * a sidecar with no open questions should not exist (it would be deleted on
184
+ * full resolution), so `allAnswered` over zero entries is `false`, keeping the
185
+ * "pending ⇒ NO-OP" classifier honest.
186
+ */
187
+ export function allAnswered(model: SidecarModel): boolean {
188
+ return model.entries.length > 0 && pendingEntries(model).length === 0;
189
+ }
190
+
191
+ const TYPE_TO_NAMESPACE: Record<SidecarType, string> = {
192
+ spec: 'spec',
193
+ task: 'task',
194
+ observation: 'observation',
195
+ };
196
+
197
+ /** Map a namespaced-identity prefix onto the sidecar type. */
198
+ function typeForNamespace(
199
+ explicit: SlugNamespace | undefined,
200
+ rawPrefix: string,
201
+ ): SidecarType {
202
+ // A `spec:` prefix / `explicit === 'spec'` maps to the `'spec'` type — NOT the
203
+ // `task` fall-through below — so `spec:<slug>` gets its own `spec-<slug>`
204
+ // lock/sidecar entry.
205
+ if (explicit === 'spec') {
206
+ return 'spec';
207
+ }
208
+ if (explicit === 'task') {
209
+ return 'task';
210
+ }
211
+ // `parseSlugArg` only knows `task:`/`prd:`; the sidecar adds the
212
+ // `observation:` namespace (`obs:` is the CLI alias the verb resolves; the
213
+ // sidecar stores the canonical `observation`). A bare slug (no prefix)
214
+ // defaults to the task namespace, matching the resolver's "bare = task".
215
+ if (rawPrefix === 'observation' || rawPrefix === 'obs') {
216
+ return 'observation';
217
+ }
218
+ return 'task';
219
+ }
220
+
221
+ /** The resolved identity of a sidecar: `{type, slug, item}`. */
222
+ export interface SidecarIdentity {
223
+ type: SidecarType;
224
+ slug: string;
225
+ /** The canonical namespaced identity (`<namespace>:<slug>`). */
226
+ item: string;
227
+ }
228
+
229
+ /**
230
+ * Resolve a namespaced-identity argument (`spec:autotask`, `task:foo`,
231
+ * `observation:bar`, `obs:bar`, or a bare `<slug>` = task) into its
232
+ * `{type, slug, item}`. PURE string work over {@link parseSlugArg} — the
233
+ * resolver is the single source of truth for the task/spec split; the sidecar
234
+ * extends it with the `observation` namespace.
235
+ */
236
+ export function resolveSidecarIdentity(identity: string): SidecarIdentity {
237
+ // `observation:`/`obs:` are not slug-namespace prefixes — peel them first.
238
+ const colon = identity.indexOf(':');
239
+ if (colon !== -1) {
240
+ const prefix = identity.slice(0, colon);
241
+ if (prefix === 'observation' || prefix === 'obs') {
242
+ const slug = identity.slice(colon + 1);
243
+ return {type: 'observation', slug, item: `observation:${slug}`};
244
+ }
245
+ }
246
+ const parsed = parseSlugArg(identity);
247
+ const type = typeForNamespace(parsed.explicit, identity.slice(0, colon));
248
+ return {
249
+ type,
250
+ slug: parsed.slug,
251
+ item: `${TYPE_TO_NAMESPACE[type]}:${parsed.slug}`,
252
+ };
253
+ }
254
+
255
+ /**
256
+ * Derive the sidecar PATH `work/questions/<type>-<slug>.md` from the item's
257
+ * namespaced identity. The identity is the single source of truth; `:`→`-` for
258
+ * the filename. Accepts the same forms as {@link resolveSidecarIdentity}.
259
+ */
260
+ export function sidecarPathFor(identity: string): string {
261
+ const {type, slug} = resolveSidecarIdentity(identity);
262
+ return workItemRel('questions', `${type}-${slug}.md`);
263
+ }
264
+
265
+ /**
266
+ * The ordered candidate sidecar PATHS a READER should probe for `identity`: the
267
+ * canonical {@link sidecarPathFor} path FIRST, then any legacy-data fallback that
268
+ * may still be on disk before the migration command converts it.
269
+ *
270
+ * MIGRATE step (prd `prd-to-spec-vocabulary-cutover-and-migration-command`): the
271
+ * producer side now emits `spec:<slug>`, so {@link sidecarPathFor} resolves
272
+ * `work/questions/spec-<slug>.md`. But the ON-DISK sidecar is still the legacy
273
+ * `work/questions/prd-<slug>.md` until `dorfl prd-to-spec` renames the DATA. So a
274
+ * `spec`-typed identity ALSO probes the legacy `prd-<slug>.md` as a fallback, and
275
+ * a reader takes the FIRST candidate that exists. This is a FILE-PATH DATA alias
276
+ * the migration command removes (it converts `prd-<slug>.md → spec-<slug>.md` on
277
+ * disk); it is NOT the `SlugNamespace`/`SidecarType` `'prd'` type member. Every
278
+ * non-`spec` type has a single candidate (its canonical path), unchanged.
279
+ */
280
+ export function sidecarPathCandidates(identity: string): string[] {
281
+ const {type, slug} = resolveSidecarIdentity(identity);
282
+ const canonical = workItemRel('questions', `${type}-${slug}.md`);
283
+ if (type === 'spec') {
284
+ return [canonical, workItemRel('questions', `prd-${slug}.md`)];
285
+ }
286
+ return [canonical];
287
+ }
288
+
289
+ // --- Format constants -----------------------------------------------------
290
+
291
+ /** The fixed answer marker the human types prose under. */
292
+ const ANSWER_MARKER = '**Your answer** (write below this line):';
293
+
294
+ // --- Parse ----------------------------------------------------------------
295
+
296
+ /** Pull the next monotonic id given the highest existing id number. */
297
+ function nextId(entries: SidecarEntry[]): string {
298
+ let max = 0;
299
+ for (const entry of entries) {
300
+ const m = /^q(\d+)$/.exec(entry.id);
301
+ if (m) {
302
+ const n = Number(m[1]);
303
+ if (n > max) {
304
+ max = n;
305
+ }
306
+ }
307
+ }
308
+ return `q${max + 1}`;
309
+ }
310
+
311
+ /** Normalise CRLF → LF and strip a leading BOM. */
312
+ function normaliseText(text: string): string {
313
+ return text.replace(/\r\n/g, '\n').replace(/^\uFEFF/, '');
314
+ }
315
+
316
+ /** Strip leading + trailing blank lines, leaving inner blanks intact. */
317
+ function trimBlankLines(value: string): string {
318
+ return value.replace(/^\n+/, '').replace(/\n+$/, '');
319
+ }
320
+
321
+ interface IdentityFields {
322
+ item: string;
323
+ allAnswered?: boolean;
324
+ }
325
+
326
+ /** Parse the top identity HTML comment. */
327
+ function parseIdentityComment(line: string): IdentityFields | undefined {
328
+ const match = /^<!--\s*dorfl-sidecar:\s*(.*?)\s*-->\s*$/.exec(line);
329
+ if (!match) {
330
+ return undefined;
331
+ }
332
+ const fields: Record<string, string> = {};
333
+ for (const token of match[1].split(/\s+/)) {
334
+ if (token === '') {
335
+ continue;
336
+ }
337
+ const eq = token.indexOf('=');
338
+ if (eq === -1) {
339
+ continue;
340
+ }
341
+ fields[token.slice(0, eq)] = token.slice(eq + 1);
342
+ }
343
+ const item = fields['item'];
344
+ if (item === undefined || item === '') {
345
+ return undefined;
346
+ }
347
+ const out: IdentityFields = {item};
348
+ if (fields['allAnswered'] !== undefined) {
349
+ out.allAnswered = fields['allAnswered'] === 'true';
350
+ }
351
+ return out;
352
+ }
353
+
354
+ interface EntryFields {
355
+ id?: string;
356
+ answered?: boolean;
357
+ kind?: SidecarKind;
358
+ }
359
+
360
+ /** Parse a per-entry `<!-- qN fields: key=val … -->` HTML comment. */
361
+ function parseEntryComment(line: string): EntryFields | undefined {
362
+ const match = /^<!--\s*q\d+\s+fields:\s*(.*?)\s*-->\s*$/.exec(line);
363
+ if (!match) {
364
+ return undefined;
365
+ }
366
+ const out: EntryFields = {};
367
+ for (const token of match[1].split(/\s+/)) {
368
+ if (token === '') {
369
+ continue;
370
+ }
371
+ const eq = token.indexOf('=');
372
+ if (eq === -1) {
373
+ continue;
374
+ }
375
+ const key = token.slice(0, eq);
376
+ const value = token.slice(eq + 1);
377
+ if (key === 'id') {
378
+ out.id = value;
379
+ } else if (key === 'answered') {
380
+ if (value === 'true') {
381
+ out.answered = true;
382
+ } else if (value === 'false') {
383
+ out.answered = false;
384
+ }
385
+ } else if (key === 'kind') {
386
+ // Silent-on-malformed (retired `disposition` precedent): a mistyped or
387
+ // unknown kind reads as `undefined`, never a throw, never a coerce.
388
+ if (SIDECAR_KINDS.has(value as SidecarKind)) {
389
+ out.kind = value as SidecarKind;
390
+ }
391
+ }
392
+ }
393
+ return out;
394
+ }
395
+
396
+ /** Parse one entry's content lines (between two `## ` headings) into an entry. */
397
+ function parseEntrySection(lines: string[]): SidecarEntry {
398
+ let id = '';
399
+ let question = '';
400
+ const contextLines: string[] = [];
401
+ let inBlockquote = false;
402
+ let defaultVal: string | undefined;
403
+ let answeredOverride: boolean | undefined;
404
+ let kind: SidecarKind | undefined;
405
+ let answerStart = -1;
406
+
407
+ for (let i = 0; i < lines.length; i++) {
408
+ const line = lines[i];
409
+ if (line === ANSWER_MARKER) {
410
+ answerStart = i + 1;
411
+ break;
412
+ }
413
+ const entryFields = parseEntryComment(line);
414
+ if (entryFields) {
415
+ if (entryFields.id !== undefined) {
416
+ id = entryFields.id;
417
+ }
418
+ if (entryFields.answered !== undefined) {
419
+ answeredOverride = entryFields.answered;
420
+ }
421
+ if (entryFields.kind !== undefined) {
422
+ kind = entryFields.kind;
423
+ }
424
+ inBlockquote = false;
425
+ continue;
426
+ }
427
+ // Blockquote context: collect the FIRST contiguous run of `> …` lines.
428
+ // Once a non-quote line breaks the run, later `>` lines (e.g. the human
429
+ // quoting something in their answer's preamble) are ignored as context.
430
+ const blockquoteMatch = /^>\s?(.*)$/.exec(line);
431
+ if (blockquoteMatch && (contextLines.length === 0 || inBlockquote)) {
432
+ contextLines.push(blockquoteMatch[1]);
433
+ inBlockquote = true;
434
+ continue;
435
+ }
436
+ if (inBlockquote && !blockquoteMatch && line.trim() !== '') {
437
+ inBlockquote = false;
438
+ }
439
+ // Italic "_Suggested default: …_" line.
440
+ const defaultMatch = /^_Suggested default:\s*(.+?)_\s*$/.exec(line);
441
+ if (defaultMatch && defaultVal === undefined) {
442
+ defaultVal = defaultMatch[1];
443
+ continue;
444
+ }
445
+ // Bold question line (first one wins; skip the answer marker line which
446
+ // has trailing `(write below this line):` and so does not match this regex).
447
+ const questionMatch = /^\*\*(.+?)\*\*\s*$/.exec(line);
448
+ if (questionMatch && question === '') {
449
+ question = questionMatch[1];
450
+ continue;
451
+ }
452
+ }
453
+
454
+ if (id === '') {
455
+ throw new SidecarParseError(
456
+ 'sidecar entry is missing its id (HTML comment)',
457
+ );
458
+ }
459
+
460
+ const context = trimBlankLines(contextLines.join('\n'));
461
+ let answer = '';
462
+ if (answerStart >= 0) {
463
+ answer = trimBlankLines(lines.slice(answerStart).join('\n'));
464
+ }
465
+
466
+ // Re-interpret the override: store it ONLY when it DISAGREES with the
467
+ // answer-derived predicate (so a redundant `answered=false` over an empty
468
+ // answer cannot become a sticky override that freezes a later tolerant edit).
469
+ const derivedAnswered = answer.trim() !== '';
470
+ let finalOverride: boolean | undefined;
471
+ if (answeredOverride === true && !derivedAnswered) {
472
+ finalOverride = true;
473
+ } else if (answeredOverride === false && derivedAnswered) {
474
+ finalOverride = false;
475
+ }
476
+
477
+ const entry: SidecarEntry = {
478
+ id,
479
+ question,
480
+ context,
481
+ answer,
482
+ };
483
+ if (defaultVal !== undefined) {
484
+ entry.default = defaultVal;
485
+ }
486
+ if (finalOverride !== undefined) {
487
+ entry.answeredOverride = finalOverride;
488
+ }
489
+ if (kind !== undefined) {
490
+ entry.kind = kind;
491
+ }
492
+ return entry;
493
+ }
494
+
495
+ /**
496
+ * Parse a sidecar document into its typed model. The on-disk format is the
497
+ * human-readable Markdown + HTML-comments form (see the module doc); the
498
+ * identity comment lives at the top, each entry opens with a `## ` heading, and
499
+ * the answer is heading-delimited (everything between the answer marker and the
500
+ * next `## ` heading is the answer). TOLERANT of the human typing only under
501
+ * the answer marker: a non-empty answer ⇒ answered (no comment edit needed).
502
+ */
503
+ export function parseSidecar(text: string): SidecarModel {
504
+ const lines = normaliseText(text).split('\n');
505
+
506
+ // Find the identity HTML comment (scan from the top, skipping blank lines).
507
+ let identity: IdentityFields | undefined;
508
+ let cursor = 0;
509
+ while (cursor < lines.length) {
510
+ const line = lines[cursor];
511
+ cursor++;
512
+ if (line.trim() === '') {
513
+ continue;
514
+ }
515
+ identity = parseIdentityComment(line);
516
+ if (identity) {
517
+ break;
518
+ }
519
+ throw new SidecarParseError(
520
+ 'sidecar must open with an `<!-- dorfl-sidecar: … -->` identity comment',
521
+ );
522
+ }
523
+ if (!identity) {
524
+ throw new SidecarParseError('sidecar is missing its identity HTML comment');
525
+ }
526
+ const resolved = resolveSidecarIdentity(identity.item);
527
+
528
+ // Split the rest into per-entry sections on `## ` headings. Anything before
529
+ // the first heading is preamble we ignore (a stray human note, or the blank
530
+ // line after the identity comment).
531
+ const entries: SidecarEntry[] = [];
532
+ let sectionLines: string[] | undefined;
533
+ for (let i = cursor; i < lines.length; i++) {
534
+ const line = lines[i];
535
+ if (/^##\s+/.test(line)) {
536
+ if (sectionLines !== undefined) {
537
+ entries.push(parseEntrySection(sectionLines));
538
+ }
539
+ sectionLines = [];
540
+ continue;
541
+ }
542
+ if (sectionLines !== undefined) {
543
+ sectionLines.push(line);
544
+ }
545
+ }
546
+ if (sectionLines !== undefined) {
547
+ entries.push(parseEntrySection(sectionLines));
548
+ }
549
+
550
+ return {
551
+ item: resolved.item,
552
+ type: resolved.type,
553
+ slug: resolved.slug,
554
+ entries,
555
+ };
556
+ }
557
+
558
+ // --- Serialise ------------------------------------------------------------
559
+
560
+ /** Collapse internal newlines so a value renders as a single Markdown line. */
561
+ function singleLine(value: string): string {
562
+ return value.replace(/\s*\n\s*/g, ' ').trim();
563
+ }
564
+
565
+ /** Render a multi-line value as a Markdown blockquote (each line `> …`). */
566
+ function blockquote(value: string): string[] {
567
+ const trimmed = trimBlankLines(value);
568
+ if (trimmed === '') {
569
+ return [];
570
+ }
571
+ return trimmed.split('\n').map((line) => (line === '' ? '>' : `> ${line}`));
572
+ }
573
+
574
+ /**
575
+ * Serialise a model to its CANONICAL human-readable Markdown text. The identity
576
+ * HTML comment at the top carries `item`/`type`/`slug` + the derived
577
+ * `allAnswered` mirror; each entry is a `## Qn` heading, a bold question line,
578
+ * a blockquote context (when non-empty), an italic suggested-default (when
579
+ * present), a per-entry HTML comment carrying `id` (and an explicit `answered`
580
+ * override when it disagrees with the derived predicate), the fixed answer
581
+ * marker, then the answer prose. Round-trip is SEMANTIC:
582
+ * `parseSidecar(serialiseSidecar(m))` recovers an equal MODEL; re-serialising
583
+ * canonicalises the text.
584
+ */
585
+ export function serialiseSidecar(model: SidecarModel): string {
586
+ const out: string[] = [];
587
+ const identityParts = [
588
+ `item=${model.item}`,
589
+ `type=${model.type}`,
590
+ `slug=${model.slug}`,
591
+ `allAnswered=${allAnswered(model)}`,
592
+ ];
593
+ out.push(`<!-- dorfl-sidecar: ${identityParts.join(' ')} -->`);
594
+
595
+ model.entries.forEach((entry) => {
596
+ out.push('');
597
+ const heading = entry.id.replace(/^q/, 'Q');
598
+ out.push(`## ${heading}`);
599
+ out.push('');
600
+ out.push(`**${singleLine(entry.question)}**`);
601
+ const ctx = blockquote(entry.context);
602
+ if (ctx.length > 0) {
603
+ out.push('');
604
+ out.push(...ctx);
605
+ }
606
+ if (entry.default !== undefined && entry.default.trim() !== '') {
607
+ out.push('');
608
+ out.push(`_Suggested default: ${singleLine(entry.default)}_`);
609
+ }
610
+ out.push('');
611
+ // Per-entry machine comment. The override is emitted ONLY when it
612
+ // DISAGREES with the answer-derived predicate (otherwise the
613
+ // just-serialised line would re-parse as a sticky override).
614
+ const fields: string[] = [`id=${entry.id}`];
615
+ const derivedAnswered = entry.answer.trim() !== '';
616
+ if (entry.answeredOverride === true && !derivedAnswered) {
617
+ fields.push('answered=true');
618
+ } else if (entry.answeredOverride === false && derivedAnswered) {
619
+ fields.push('answered=false');
620
+ }
621
+ if (entry.kind !== undefined) {
622
+ fields.push(`kind=${entry.kind}`);
623
+ }
624
+ out.push(`<!-- ${entry.id} fields: ${fields.join(' ')} -->`);
625
+ out.push('');
626
+ out.push(ANSWER_MARKER);
627
+ const answerText = trimBlankLines(entry.answer);
628
+ if (answerText !== '') {
629
+ out.push('');
630
+ out.push(answerText);
631
+ }
632
+ });
633
+ out.push('');
634
+ return out.join('\n');
635
+ }
636
+
637
+ // --- Append ---------------------------------------------------------------
638
+
639
+ /** A new question to append (no id — the appender mints the next monotonic id). */
640
+ export interface NewQuestion {
641
+ question: string;
642
+ context?: string;
643
+ default?: string;
644
+ /**
645
+ * Optional dispatch {@link SidecarKind} the surfacer stamps so the apply
646
+ * rung can route a runner-ACTION question (`merge`, `stuck`) to the
647
+ * deterministic dispatch vs a CONTENT question (`triage`, `spec`) to the
648
+ * agentic `decide()` path. INTERIM — removable once kind-subfolders land.
649
+ */
650
+ kind?: SidecarKind;
651
+ }
652
+
653
+ /**
654
+ * Append `newQuestions` to the model, minting `qN+1…` ids off the highest
655
+ * existing id. NEVER overwrites or mutates an existing entry (answered or not) —
656
+ * the sidecar is the item's full Q&A history. Appending flips a previously-
657
+ * `allAnswered` sidecar back to not-all-answered (the new entries are pending).
658
+ * Returns a NEW model (the input is not mutated).
659
+ */
660
+ export function appendQuestions(
661
+ model: SidecarModel,
662
+ newQuestions: NewQuestion[],
663
+ ): SidecarModel {
664
+ const entries = model.entries.slice();
665
+ for (const q of newQuestions) {
666
+ const entry: SidecarEntry = {
667
+ id: nextId(entries),
668
+ question: q.question,
669
+ context: q.context ?? '',
670
+ answer: '',
671
+ };
672
+ if (q.default !== undefined) {
673
+ entry.default = q.default;
674
+ }
675
+ if (q.kind !== undefined) {
676
+ entry.kind = q.kind;
677
+ }
678
+ entries.push(entry);
679
+ }
680
+ return {...model, entries};
681
+ }
682
+
683
+ /**
684
+ * Build a fresh sidecar model for `identity` carrying `newQuestions` (ids minted
685
+ * `q1…`). The first-pass constructor the surface-question rung uses before there
686
+ * is any sidecar to append to.
687
+ */
688
+ export function newSidecar(
689
+ identity: string,
690
+ newQuestions: NewQuestion[],
691
+ ): SidecarModel {
692
+ const resolved = resolveSidecarIdentity(identity);
693
+ const base: SidecarModel = {
694
+ item: resolved.item,
695
+ type: resolved.type,
696
+ slug: resolved.slug,
697
+ entries: [],
698
+ };
699
+ return appendQuestions(base, newQuestions);
700
+ }