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,159 @@
1
+ /**
2
+ * The `install-ci` VERIFY-WORKFLOW capability (prd
3
+ * `land-time-reverify-and-parallel-merge-ceiling`, task
4
+ * `install-ci-tier1-branch-protection`; Story 11 — the Tier-1 GitHub ceiling).
5
+ * Emits a small `verify.yml` workflow whose ONLY job is `verify` and runs on
6
+ * `pull_request` (and `merge_group`, the Tier-2 forward seam). It produces the
7
+ * GitHub check named exactly {@link VERIFY_CHECK_CONTEXT}, which the
8
+ * branch-protection step ({@link installCIBranchProtectionStep}) names as the
9
+ * required-status check `context`. Co-locating the two strings — the EMITTED
10
+ * job/check name AND the REQUIRED context — in one constant pins the
11
+ * acceptance-criterion "context matches the workflow's job name" by construction
12
+ * (a single test diffs the two).
13
+ *
14
+ * The workflow is deliberately thin: it wires the same composite setup action
15
+ * the other capabilities use, then runs `dorfl verify` — the deterministic shell
16
+ * gate the repo declares in `.dorfl.json`. No agent, no provider secrets, no
17
+ * `gh` mutation; it is read-only with respect to `work/`.
18
+ *
19
+ * `merge_group` is present (with no extra wiring) so a follow-on Tier-2 task
20
+ * (GitHub Merge Queue) can flip the ruleset on without changing this workflow's
21
+ * trigger surface — the forward seam the spec's Applied Answers q3 names.
22
+ */
23
+
24
+ import type {ResolvedCIConfig} from './install-ci-core.js';
25
+
26
+ /**
27
+ * The required-status-check CONTEXT install-ci sets via branch protection AND the
28
+ * job/check name the emitted verify workflow produces. ONE source of truth so
29
+ * the two strings can never drift (the "context matches the workflow's job name"
30
+ * acceptance criterion is enforced by both reading this constant).
31
+ */
32
+ export const VERIFY_CHECK_CONTEXT = 'verify';
33
+
34
+ /** The capability id (the registry key + the emitted workflow file stem). */
35
+ export const VERIFY_CAPABILITY_ID = 'verify';
36
+
37
+ /** The wizard-facing label for the verify capability. */
38
+ export const VERIFY_CAPABILITY_LABEL =
39
+ 'Run the repo `verify` gate on every PR (the Tier-1 GitHub ceiling: produces the required-status check `verify` that branch protection requires)';
40
+
41
+ /** The repo-relative path (under the output base) of the emitted workflow. */
42
+ export const VERIFY_WORKFLOW_PATH = 'workflows/verify.yml';
43
+
44
+ /**
45
+ * Generate the verify workflow YAML. Deterministic: the same config produces
46
+ * byte-identical output. The job is named exactly {@link VERIFY_CHECK_CONTEXT}
47
+ * so the GitHub check it produces matches the required-status `context` install-ci
48
+ * configures on `main` — by construction, not by hand-typed agreement.
49
+ */
50
+ export function generateVerifyWorkflow(_config: ResolvedCIConfig): string {
51
+ return `\
52
+ # dorfl — the VERIFY workflow (Tier-1 GitHub ceiling; prd
53
+ # land-time-reverify-and-parallel-merge-ceiling, task
54
+ # install-ci-tier1-branch-protection). EMITTED by \`dorfl install-ci\`; the
55
+ # human commits it. DO NOT hand-edit a copy — re-run install-ci to upgrade.
56
+ #
57
+ # This workflow exists SOLELY to produce a GitHub check named \`${VERIFY_CHECK_CONTEXT}\`
58
+ # on every pull request, which install-ci's branch-protection step requires
59
+ # (\`required_status_checks.strict: true\` + a required \`${VERIFY_CHECK_CONTEXT}\` context)
60
+ # so a PR cannot be merged stale. The merge button is disabled until \`${VERIFY_CHECK_CONTEXT}\`
61
+ # reports success on the rebased PR head — closing the PR-merge-time drift window
62
+ # story 7 names.
63
+ #
64
+ # \`merge_group\` is listed so a follow-on Tier-2 task (GitHub Merge Queue) can
65
+ # enable speculative-rebase merging by flipping the ruleset, WITHOUT changing
66
+ # this workflow's trigger surface (the Applied Answer q3 forward seam).
67
+ #
68
+ # CONTEXT NAMING — the job is named EXACTLY \`${VERIFY_CHECK_CONTEXT}\`. install-ci
69
+ # names the same string as the required-context, so they cannot drift. If you
70
+ # rename the job here you MUST re-run install-ci (or the protection's required
71
+ # context will not match this workflow and every PR will block forever).
72
+ #
73
+ # SAFETY (US #9): the running job requests NO \`workflows\` permission and runs
74
+ # only \`dorfl verify\` (a deterministic shell gate; \`pnpm format:check && pnpm
75
+ # build && pnpm test\` for the dorfl repo). It cannot edit \`.github/workflows/**\`
76
+ # or mutate \`work/\`.
77
+
78
+ name: ${VERIFY_CHECK_CONTEXT}
79
+
80
+ on:
81
+ pull_request:
82
+ # Tier-2 forward seam: a follow-on task enables GitHub Merge Queue and the
83
+ # same job re-runs on the speculative-rebase merge-group head, no template edit.
84
+ merge_group:
85
+
86
+ # Serialise overlapping verify runs on the same ref (the latest commit wins —
87
+ # stale runs are cancelled, since \`verify\` is a pure pass/fail gate).
88
+ concurrency:
89
+ group: ${VERIFY_CHECK_CONTEXT}-\${{ github.ref }}
90
+ cancel-in-progress: true
91
+
92
+ # NO \`workflows\` permission (US #9). \`contents: read\` is all the gate needs.
93
+ permissions:
94
+ contents: read
95
+
96
+ jobs:
97
+ # The job name IS the GitHub check context — it must equal VERIFY_CHECK_CONTEXT
98
+ # (\`${VERIFY_CHECK_CONTEXT}\`) or install-ci's branch protection will require a
99
+ # context this workflow does not produce.
100
+ ${VERIFY_CHECK_CONTEXT}:
101
+ runs-on: ubuntu-latest
102
+ steps:
103
+ - uses: actions/checkout@v4
104
+ with:
105
+ fetch-depth: 0
106
+ - uses: ./.github/actions/dorfl-setup
107
+ - name: run the repo verify gate
108
+ run: dorfl verify
109
+ `;
110
+ }
111
+
112
+ /** A single structural problem found in the generated verify workflow. */
113
+ export interface VerifyWorkflowProblem {
114
+ id: string;
115
+ message: string;
116
+ }
117
+
118
+ /** Result of {@link validateVerifyWorkflow}. */
119
+ export interface VerifyWorkflowValidation {
120
+ ok: boolean;
121
+ problems: VerifyWorkflowProblem[];
122
+ }
123
+
124
+ /**
125
+ * Structurally validate the verify workflow against the task's acceptance
126
+ * criteria (job name = required context, runs on `pull_request`, ships the
127
+ * `merge_group` seam, no `workflows:` permission).
128
+ */
129
+ export function validateVerifyWorkflow(text: string): VerifyWorkflowValidation {
130
+ const problems: VerifyWorkflowProblem[] = [];
131
+ const require = (id: string, present: boolean, message: string): void => {
132
+ if (!present) problems.push({id, message});
133
+ };
134
+ const operative = text
135
+ .split('\n')
136
+ .filter((line) => !/^\s*#/.test(line))
137
+ .join('\n');
138
+
139
+ require('job-named-verify-context', new RegExp(
140
+ `^\\s{2}${VERIFY_CHECK_CONTEXT}:\\s*$`,
141
+ 'm',
142
+ ).test(
143
+ operative,
144
+ ), `the workflow must declare a job named exactly \`${VERIFY_CHECK_CONTEXT}\` ` +
145
+ '(its name IS the GitHub check context install-ci requires).');
146
+ require('trigger-pull-request', /\bon:\s*[\s\S]*?\bpull_request\s*:/.test(
147
+ operative,
148
+ ), 'must trigger on `pull_request` (the check must run on every PR).');
149
+ require('trigger-merge-group-seam', /\bmerge_group\s*:/.test(
150
+ operative,
151
+ ), 'must list `merge_group` as a trigger (the Tier-2 GitHub Merge Queue forward seam).');
152
+ require('no-workflows-permission', !/\bworkflows\s*:\s*write\b/.test(
153
+ operative,
154
+ ), 'must request NO `workflows` permission (US #9).');
155
+ require('runs-dorfl-verify', /dorfl verify\b/.test(
156
+ operative,
157
+ ), 'the job must run `dorfl verify` (the deterministic shell gate the repo declares).');
158
+ return {ok: problems.length === 0, problems};
159
+ }
package/src/verify.ts ADDED
@@ -0,0 +1,123 @@
1
+ import {spawn} from 'node:child_process';
2
+
3
+ /**
4
+ * The per-repo acceptance gate, run as `dorfl verify`. It is a
5
+ * deterministic shell gate — a declared, per-repo command (or ordered list of
6
+ * commands) — NOT prose interpreted by a model. There is no LLM in this loop:
7
+ * the gate is known by reading config, and it either passes (exit 0) or it does
8
+ * not. This same mechanism is consumed by the human `complete` command (where it
9
+ * is a default-on, `--skip-verify`-able safety-net) and by the autonomous
10
+ * `run-once`/`watch` (where it is the authoritative, non-skippable trust
11
+ * boundary). `verify` itself just runs the gate; callers decide authority.
12
+ *
13
+ * It is read-only with respect to `work/`: it runs the declared check and never
14
+ * moves or commits anything.
15
+ */
16
+
17
+ /**
18
+ * The per-repo gate, as declared in config. A single shell command, or an
19
+ * ordered list of commands run in sequence (each must pass for the gate to
20
+ * pass). `undefined` (unset) ⇒ {@link DEFAULT_VERIFY_COMMAND} is used.
21
+ */
22
+ export type VerifyConfig = string | string[];
23
+
24
+ /**
25
+ * The sensible default when no `verify` is configured: build, then test, then
26
+ * check formatting across the workspace. Deterministic, auditable, no model.
27
+ */
28
+ export const DEFAULT_VERIFY_COMMAND =
29
+ 'pnpm -r build && pnpm -r test && pnpm -r format:check';
30
+
31
+ /**
32
+ * Resolve the declared gate into an ordered, non-empty list of shell commands.
33
+ * Unset ⇒ the default. A string ⇒ a single command. A list ⇒ the list, with
34
+ * blank/whitespace-only entries dropped (and the default substituted if that
35
+ * leaves nothing). Each command is run in sequence; all must pass.
36
+ */
37
+ export function resolveVerifyCommands(
38
+ verify: VerifyConfig | undefined,
39
+ ): string[] {
40
+ if (verify === undefined) {
41
+ return [DEFAULT_VERIFY_COMMAND];
42
+ }
43
+ const list = Array.isArray(verify) ? verify : [verify];
44
+ const commands = list.filter((command) => command.trim() !== '');
45
+ return commands.length > 0 ? commands : [DEFAULT_VERIFY_COMMAND];
46
+ }
47
+
48
+ export interface RunVerifyOptions {
49
+ /** The repo to run the gate in (its working directory). */
50
+ cwd: string;
51
+ /** The declared gate (string | list). Unset ⇒ the default command. */
52
+ verify?: VerifyConfig;
53
+ /** Environment for the gate's child processes. */
54
+ env?: NodeJS.ProcessEnv;
55
+ /** Sink for streamed stdout chunks. Defaults to `process.stdout.write`. */
56
+ onStdout?: (chunk: string) => void;
57
+ /** Sink for streamed stderr chunks. Defaults to `process.stderr.write`. */
58
+ onStderr?: (chunk: string) => void;
59
+ }
60
+
61
+ export interface RunVerifyResult {
62
+ /** The exit code of the gate: 0 iff every command passed. */
63
+ exitCode: number;
64
+ /** The ordered commands that were run (resolved from config). */
65
+ commands: string[];
66
+ /** Whether the gate passed (exitCode === 0). */
67
+ passed: boolean;
68
+ }
69
+
70
+ /**
71
+ * Run the resolved gate command(s) in `cwd`, streaming output, and resolve with
72
+ * the gate's status: exit 0 iff every command passed. Commands run in sequence;
73
+ * the first non-zero exit short-circuits the rest and becomes the result
74
+ * (mirroring `&&` semantics). Each command is run through `bash -c` so that
75
+ * shell operators in the declared gate (`&&`, pipes, etc.) behave as written.
76
+ */
77
+ export async function runVerify(
78
+ options: RunVerifyOptions,
79
+ ): Promise<RunVerifyResult> {
80
+ const commands = resolveVerifyCommands(options.verify);
81
+ const onStdout =
82
+ options.onStdout ?? ((chunk: string) => process.stdout.write(chunk));
83
+ const onStderr =
84
+ options.onStderr ?? ((chunk: string) => process.stderr.write(chunk));
85
+
86
+ for (const command of commands) {
87
+ const exitCode = await runOne(command, options.cwd, options.env, {
88
+ onStdout,
89
+ onStderr,
90
+ });
91
+ if (exitCode !== 0) {
92
+ return {exitCode, commands, passed: false};
93
+ }
94
+ }
95
+ return {exitCode: 0, commands, passed: true};
96
+ }
97
+
98
+ /** Spawn one command via `bash -c`, streaming its output, resolving its code. */
99
+ function runOne(
100
+ command: string,
101
+ cwd: string,
102
+ env: NodeJS.ProcessEnv | undefined,
103
+ sinks: {onStdout: (chunk: string) => void; onStderr: (chunk: string) => void},
104
+ ): Promise<number> {
105
+ return new Promise((resolvePromise, reject) => {
106
+ const child = spawn('bash', ['-c', command], {
107
+ cwd,
108
+ env: env ?? process.env,
109
+ });
110
+ child.stdout.on('data', (chunk: Buffer) => {
111
+ sinks.onStdout(chunk.toString('utf8'));
112
+ });
113
+ child.stderr.on('data', (chunk: Buffer) => {
114
+ sinks.onStderr(chunk.toString('utf8'));
115
+ });
116
+ child.on('error', (err) =>
117
+ reject(new Error(`failed to spawn gate command: ${err.message}`)),
118
+ );
119
+ child.on('close', (code) => {
120
+ resolvePromise(code ?? -1);
121
+ });
122
+ });
123
+ }
@@ -0,0 +1,397 @@
1
+ import {open, type FileHandle} from 'node:fs/promises';
2
+
3
+ /**
4
+ * The **`do --watch` observer** (tasks `do-watch` + `do-watch-session-log-format`)
5
+ * — a READ-ONLY concurrent tail of the pi session `.jsonl` event log, restoring
6
+ * for `do` the live agent-conversation view `ar-run.sh --watch` gave.
7
+ *
8
+ * `ar-run.sh --watch` piped `pi -p --mode json | jq` to surface the high-signal
9
+ * events; `do` runs the agent CAPTURED through the harness seam, so that live
10
+ * view was lost. The pi adapter writes a session `.jsonl` at the KNOWN file path
11
+ * the caller generated (`--session <path>`, task `session-path-pi-default`) —
12
+ * but that is pi's SESSION-PERSISTENCE log, a DIFFERENT format from the
13
+ * `--mode json` STREAM `ar-run.sh` piped. The tailer is pointed at that EXACT
14
+ * path (no newest-by-mtime dir guessing), so the stale-sibling race is gone.
15
+ *
16
+ * A session-log record is `{"type":"message", "message":{role, content[]}}` (or a
17
+ * `session`/`model_change`/`thinking_level_change` preamble record). The earlier
18
+ * classifier matched the STREAM vocabulary (`tool_start`/`message_end`/`agent_end`),
19
+ * none of which occur in the session log — so every line fell through to skip and
20
+ * `do --watch` was silently a no-op. This module tails the growing session log and
21
+ * surfaces the same high-signal level `ar-run.sh --watch` gave, read off the
22
+ * SESSION-LOG shape:
23
+ *
24
+ * - an `assistant` `message` → its `content[]` `text` parts, then `▶ <name>`
25
+ * (cyan) per `content[]` `toolCall` part;
26
+ * - `✓ agent finished` (green) on PROCESS EXIT — the session log has no
27
+ * `agent_end` event, so the tailer emits it once on `stop()`;
28
+ * - everything else (`session`/`model_change`/user messages/tool results/…) →
29
+ * skipped.
30
+ *
31
+ * The classifier mirrors pi-remote's `session-pool.ts` reference parser (`type` →
32
+ * `role` → `content[]` block walk over `thinking`/`text`/`toolCall`, incl.
33
+ * `tc.name||tc.toolName` and content-as-string). The JSONL is parsed in TS (NO
34
+ * `jq` — that bash dependency is part of what `do` replaces). It is a PURE
35
+ * OBSERVER: it only READS the log; it never changes the run's outcome, gate,
36
+ * integration, git, or exit code. Colour is honoured ONLY on a TTY / when
37
+ * `NO_COLOR` is unset (the same rule as `output.ts`), threaded in by the caller
38
+ * as a boolean.
39
+ */
40
+
41
+ // The same conventional ANSI codes `ar-run.sh`'s jq filter emitted (cyan tool
42
+ // marker, green finished marker, reset). Colour is applied ONLY when the caller
43
+ // passes `color: true` (its TTY/NO_COLOR decision); plain otherwise.
44
+ const CYAN = '\u001b[36m';
45
+ const GREEN = '\u001b[32m';
46
+ const RESET = '\u001b[0m';
47
+
48
+ /** Wrap `text` in `code` + reset when `color`, else return it unchanged. */
49
+ function paint(text: string, color: boolean, code: string): string {
50
+ return color ? `${code}${text}${RESET}` : text;
51
+ }
52
+
53
+ /**
54
+ * A structural view of the pi SESSION-LOG records we classify. It mirrors the
55
+ * `@earendil-works/pi-coding-agent` `SessionEntry` / `SessionMessageEntry`
56
+ * shapes (`type:"message"` with a nested `message.role` + `message.content`) but
57
+ * is declared locally so the observer needs no runtime dependency on that
58
+ * package's (heavy) type tree — dorfl does not otherwise depend on it.
59
+ * The content blocks are read defensively (like pi-remote's reference parser,
60
+ * which casts them via `as any`): a content part may be a `text`, a `thinking`,
61
+ * or a `toolCall` (whose name is `name` OR `toolName`), or the whole content may
62
+ * be a plain string.
63
+ */
64
+ interface SessionLogRecord {
65
+ type?: unknown;
66
+ message?: {
67
+ role?: unknown;
68
+ content?: unknown;
69
+ };
70
+ }
71
+
72
+ /** The green `✓ agent finished` line, emitted on PROCESS EXIT (not a log event). */
73
+ export function finishedLine(color: boolean): string {
74
+ return paint('✓ agent finished', color, GREEN);
75
+ }
76
+
77
+ /**
78
+ * A one-line VISUAL BOUNDARY banner the caller prints between two tailed agent
79
+ * streams (e.g. the build stream and the Gate-2 review stream — task
80
+ * `watch-review-session`), so a watching human knows the first stream ended and
81
+ * the next began. Reuses this module's colour rule (cyan, the same marker hue as
82
+ * the `▶ <tool>` lines) so it reads as part of the same live view. Pure: returns
83
+ * the string; the caller routes it to the watch sink.
84
+ */
85
+ export function boundaryLine(label: string, color: boolean): string {
86
+ return paint(`▶ ${label}`, color, CYAN);
87
+ }
88
+
89
+ /**
90
+ * Parse ONE pi SESSION-LOG `.jsonl` line and return the high-signal lines to
91
+ * surface — or `[]` to SKIP it. This is the pure, unit-testable classifier,
92
+ * mirroring pi-remote's `session-pool.ts` block walk:
93
+ *
94
+ * - a `{type:"message", message:{role:"assistant", content}}` record → for each
95
+ * `content[]` part: a `text` part yields its text (parts concatenated into
96
+ * ONE line, like the old `jq` `.content[]` select); a `toolCall` part yields
97
+ * `▶ <name>` (cyan; `name` OR `toolName`, defaulting to `tool`); a `thinking`
98
+ * part (and anything else) is skipped. A plain-string `content` yields one
99
+ * text line.
100
+ * - everything else (`session`/`model_change`/`thinking_level_change`, user
101
+ * messages, tool results, blank/malformed lines) → `[]` (skipped).
102
+ *
103
+ * "Finished" is NOT a record here — the session log has no `agent_end`; the
104
+ * tailer emits {@link finishedLine} on process exit instead.
105
+ *
106
+ * Malformed JSON is skipped (not thrown): a partially-written trailing line in a
107
+ * growing log must not crash the observer.
108
+ */
109
+ export function formatWatchEvent(line: string, color: boolean): string[] {
110
+ const trimmed = line.trim();
111
+ if (trimmed === '') {
112
+ return [];
113
+ }
114
+ let event: unknown;
115
+ try {
116
+ event = JSON.parse(trimmed);
117
+ } catch {
118
+ // A half-written trailing line in a growing log — skip, never throw.
119
+ return [];
120
+ }
121
+ if (typeof event !== 'object' || event === null) {
122
+ return [];
123
+ }
124
+ const record = event as SessionLogRecord;
125
+ if (record.type !== 'message') {
126
+ return [];
127
+ }
128
+ const message = record.message;
129
+ if (!message || message.role !== 'assistant') {
130
+ // Skip user turns, tool results, and any non-assistant message.
131
+ return [];
132
+ }
133
+ return assistantLines(message.content, color);
134
+ }
135
+
136
+ /**
137
+ * Walk an assistant `message.content` into the lines to surface, mirroring
138
+ * pi-remote's `session-pool.ts` reference parser. The `text` parts are
139
+ * concatenated into a SINGLE leading line (so a multi-part assistant turn reads
140
+ * as one sentence, as `ar-run.sh --watch` showed it); each `toolCall` part adds a
141
+ * `▶ <name>` line after it. A plain-string content yields the single text line.
142
+ * `thinking` parts and any other block type are skipped.
143
+ */
144
+ function assistantLines(content: unknown, color: boolean): string[] {
145
+ if (typeof content === 'string') {
146
+ return content === '' ? [] : [content];
147
+ }
148
+ if (!Array.isArray(content)) {
149
+ return [];
150
+ }
151
+ const lines: string[] = [];
152
+ const text = assistantContentText(content);
153
+ for (const part of content) {
154
+ if (typeof part !== 'object' || part === null) {
155
+ continue;
156
+ }
157
+ const p = part as Record<string, unknown>;
158
+ if (p.type === 'toolCall') {
159
+ const name =
160
+ (typeof p.name === 'string' && p.name !== '' && p.name) ||
161
+ (typeof p.toolName === 'string' && p.toolName !== '' && p.toolName) ||
162
+ 'tool';
163
+ lines.push(paint(`▶ ${name}`, color, CYAN));
164
+ }
165
+ // `text` is collected by assistantContentText; `thinking` and any other
166
+ // block type are skipped.
167
+ }
168
+ return text === '' ? lines : [text, ...lines];
169
+ }
170
+
171
+ /**
172
+ * Concatenate the `text` parts of ONE assistant `message.content` (the answer
173
+ * text, with tool/thinking blocks dropped) — the single source of truth for
174
+ * "what did the assistant SAY" shared by the {@link assistantLines} watch view
175
+ * and the {@link lastAssistantText} output reader (task `harness-agent-output`).
176
+ * A plain-string content is itself the text. Returns `''` when there is no text.
177
+ */
178
+ function assistantContentText(content: unknown): string {
179
+ if (typeof content === 'string') {
180
+ return content;
181
+ }
182
+ if (!Array.isArray(content)) {
183
+ return '';
184
+ }
185
+ const textParts: string[] = [];
186
+ for (const part of content) {
187
+ if (typeof part !== 'object' || part === null) {
188
+ continue;
189
+ }
190
+ const p = part as Record<string, unknown>;
191
+ if (p.type === 'text' && typeof p.text === 'string') {
192
+ textParts.push(p.text);
193
+ }
194
+ }
195
+ return textParts.join('');
196
+ }
197
+
198
+ /**
199
+ * Extract the **last assistant message's text** from a pi session `.jsonl`
200
+ * (task `harness-agent-output`) — the agent's final ANSWER, surfaced through
201
+ * the harness seam as `LaunchResult.output`. It REUSES this module's session-log
202
+ * shape walk (one parser, not two): it scans the `{type:"message",
203
+ * message:{role:"assistant", content[]}}` records, takes the LAST one carrying
204
+ * non-empty `text`, and returns its concatenated text.
205
+ *
206
+ * Returns `undefined` when the log has no assistant text at all — an absent log,
207
+ * a malformed/short log, or a run whose only assistant turn was tool-calls (no
208
+ * `text` part). A tool-only assistant turn is NOT a final answer, so a LATER
209
+ * text turn (if any) wins; with no text turn anywhere the result is `undefined`.
210
+ *
211
+ * Malformed/blank lines are skipped (never thrown): a partially-written trailing
212
+ * line in a just-closed log must not crash the reader.
213
+ */
214
+ export function lastAssistantText(jsonl: string): string | undefined {
215
+ let last: string | undefined;
216
+ for (const line of jsonl.split('\n')) {
217
+ const trimmed = line.trim();
218
+ if (trimmed === '') {
219
+ continue;
220
+ }
221
+ let event: unknown;
222
+ try {
223
+ event = JSON.parse(trimmed);
224
+ } catch {
225
+ continue; // a half-written / malformed line — skip, never throw.
226
+ }
227
+ if (typeof event !== 'object' || event === null) {
228
+ continue;
229
+ }
230
+ const record = event as SessionLogRecord;
231
+ if (record.type !== 'message') {
232
+ continue;
233
+ }
234
+ const message = record.message;
235
+ if (!message || message.role !== 'assistant') {
236
+ continue;
237
+ }
238
+ const text = assistantContentText(message.content);
239
+ if (text !== '') {
240
+ last = text; // a later text turn supersedes an earlier one.
241
+ }
242
+ }
243
+ return last;
244
+ }
245
+
246
+ export interface SessionTailerOptions {
247
+ /**
248
+ * The EXACT pi session `.jsonl` file path to tail. The caller generated this
249
+ * BEFORE pi launched (`--session <path>`, task `session-path-pi-default`) and
250
+ * passed the SAME path to the adapter, so the tailer reads the run's own log
251
+ * — no newest-by-mtime dir guessing, no stale-sibling race. The file does NOT
252
+ * yet exist when the tailer starts (pi creates it asynchronously after spawn);
253
+ * the tailer polls until it appears (ENOENT is tolerated as "not yet").
254
+ */
255
+ sessionFile: string;
256
+ /** Emit ANSI colour (the caller's TTY/`NO_COLOR` decision). */
257
+ color: boolean;
258
+ /** Where formatted high-signal lines are written (defaults to stderr). */
259
+ sink?: (line: string) => void;
260
+ /** How often (ms) to poll for new bytes / the log's appearance. */
261
+ pollIntervalMs?: number;
262
+ }
263
+
264
+ const DEFAULT_POLL_INTERVAL_MS = 100;
265
+
266
+ /**
267
+ * A concurrent, READ-ONLY tail of the pi session `.jsonl`. It polls the KNOWN
268
+ * session-file path (which the pi adapter creates only once pi starts) until it
269
+ * appears, then reads newly-appended bytes, splits them into complete lines, and
270
+ * surfaces each via {@link formatWatchEvent}. A partial trailing line is
271
+ * buffered until its newline arrives, so an event split across two reads is
272
+ * never mis-parsed.
273
+ *
274
+ * It is a pure observer: nothing it does feeds back into the run. `start()`
275
+ * begins polling; `stop()` performs one final drain (to catch events written
276
+ * just before the agent exited), emits the `✓ agent finished` line ONCE (the
277
+ * session log has no `agent_end` — process exit IS the finish signal), and
278
+ * releases the file handle. Created and driven by `do --watch` ALONGSIDE the
279
+ * (async) agent launch; `stop()` runs when that launch returns (i.e. the agent
280
+ * process exited).
281
+ */
282
+ export class SessionTailer {
283
+ private readonly sessionFile: string;
284
+ private readonly color: boolean;
285
+ private readonly sink: (line: string) => void;
286
+ private readonly pollIntervalMs: number;
287
+
288
+ private handle: FileHandle | undefined;
289
+ private offset = 0;
290
+ private pending = '';
291
+ private timer: NodeJS.Timeout | undefined;
292
+ private polling = false;
293
+ private stopped = false;
294
+ private finishedEmitted = false;
295
+
296
+ constructor(options: SessionTailerOptions) {
297
+ this.sessionFile = options.sessionFile;
298
+ this.color = options.color;
299
+ this.sink = options.sink ?? ((line) => process.stderr.write(`${line}\n`));
300
+ this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
301
+ }
302
+
303
+ /** Begin polling for the known session file and tailing its new bytes. */
304
+ start(): void {
305
+ if (this.timer !== undefined || this.stopped) {
306
+ return;
307
+ }
308
+ this.timer = setInterval(() => {
309
+ void this.poll();
310
+ }, this.pollIntervalMs);
311
+ // `unref` so an orphaned timer never keeps the process alive past the run.
312
+ this.timer.unref?.();
313
+ }
314
+
315
+ /**
316
+ * Stop tailing: one final drain (events written right before the agent exited
317
+ * must still be surfaced), emit the `✓ agent finished` line ONCE (process exit
318
+ * is the finish signal — the session log carries no `agent_end`), then release
319
+ * the handle. Idempotent: a second `stop()` re-emits nothing.
320
+ */
321
+ async stop(): Promise<void> {
322
+ const wasStopped = this.stopped;
323
+ this.stopped = true;
324
+ if (this.timer !== undefined) {
325
+ clearInterval(this.timer);
326
+ this.timer = undefined;
327
+ }
328
+ if (!wasStopped) {
329
+ await this.drain();
330
+ }
331
+ if (this.handle !== undefined) {
332
+ await this.handle.close();
333
+ this.handle = undefined;
334
+ }
335
+ if (!this.finishedEmitted) {
336
+ this.finishedEmitted = true;
337
+ this.sink(finishedLine(this.color));
338
+ }
339
+ }
340
+
341
+ /** One poll tick: ensure the handle is open, then drain new bytes. */
342
+ private async poll(): Promise<void> {
343
+ if (this.polling) {
344
+ return; // a slow read must not overlap the next tick.
345
+ }
346
+ this.polling = true;
347
+ try {
348
+ await this.drain();
349
+ } catch {
350
+ // A transient read error (the log being rotated/created) — try next tick.
351
+ } finally {
352
+ this.polling = false;
353
+ }
354
+ }
355
+
356
+ /** Open the log if not yet open, read appended bytes, surface whole lines. */
357
+ private async drain(): Promise<void> {
358
+ if (this.handle === undefined) {
359
+ // Open the KNOWN path. pi creates it ASYNCHRONOUSLY after spawn, so until
360
+ // it exists `open` throws ENOENT — treat that as "not yet" and retry next
361
+ // tick (NEVER open once at start(), which would race the file into being).
362
+ try {
363
+ this.handle = await open(this.sessionFile, 'r');
364
+ } catch (err) {
365
+ if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
366
+ return; // file not written yet — wait for it.
367
+ }
368
+ throw err; // a real error — bubble to poll's try/catch (next-tick retry).
369
+ }
370
+ }
371
+ const stats = await this.handle.stat();
372
+ if (stats.size <= this.offset) {
373
+ return; // no new bytes.
374
+ }
375
+ const length = stats.size - this.offset;
376
+ const buffer = Buffer.alloc(length);
377
+ const {bytesRead} = await this.handle.read(buffer, 0, length, this.offset);
378
+ this.offset += bytesRead;
379
+ this.pending += buffer.toString('utf8', 0, bytesRead);
380
+ this.flushLines();
381
+ }
382
+
383
+ /** Split the buffer on newlines, surfacing each COMPLETE line; keep the rest. */
384
+ private flushLines(): void {
385
+ let newlineIndex = this.pending.indexOf('\n');
386
+ while (newlineIndex !== -1) {
387
+ const line = this.pending.slice(0, newlineIndex);
388
+ this.pending = this.pending.slice(newlineIndex + 1);
389
+ // A single record may surface MULTIPLE lines (assistant text + each of
390
+ // its tool starts), or none (skipped record types).
391
+ for (const formatted of formatWatchEvent(line, this.color)) {
392
+ this.sink(formatted);
393
+ }
394
+ newlineIndex = this.pending.indexOf('\n');
395
+ }
396
+ }
397
+ }