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,337 @@
1
+ import {NullHarness, type Harness} from './harness.js';
2
+ import {launchWithOptionalWatch} from './agent-launch.js';
3
+ import {boundaryLine} from './watch-session.js';
4
+ import {extractJsonObjectSpan} from './verdict-json.js';
5
+ import {parseableJsonContractPrompt} from './review-verdict.js';
6
+ import type {NewQuestion} from './sidecar.js';
7
+
8
+ /**
9
+ * The **SURFACE gate** (prd `advance-loop`, task `advance-rung-surface`,
10
+ * US #32/33) — the surface-question rung's fresh-context spawn, the DIRECT mirror
11
+ * of the PR/code review gate ({@link import('./review-gate.js')}). On
12
+ * `classify=surface`, the advance engine spawns a FRESH-CONTEXT agent with the
13
+ * `surface-questions` SKILL loaded (`skills/surface-questions/SKILL.md`); the
14
+ * skill GATHERS the item's open-judgement residue and EMITS questions and writes
15
+ * NOTHING (doc-shaped, like `review`). The ENGINE then ITSELF persists them to
16
+ * the sidecar CAS-atomically + sets `needsAnswers:true` (task
17
+ * `advance-rung-surface`'s persist half) — **the skill JUDGES, the engine
18
+ * PERSISTS.**
19
+ *
20
+ * This module is the SEAM (the {@link SurfaceGate} function type) + its
21
+ * production harness-backed implementation ({@link harnessSurfaceGate}), exactly
22
+ * as `review-gate.ts` is the seam + `harnessReviewGate`. The seam is injectable:
23
+ * tests stub a canned emitted-questions list (no real model); production launches
24
+ * the `surface-questions` agent through the EXISTING harness seam
25
+ * ({@link Harness}/`LaunchInput`), routing an optional `surfaceModel` override
26
+ * through `LaunchInput.model` — NOT a new model/launch mechanism (the §13
27
+ * model-routing intent). It mirrors `harnessReviewGate` byte-for-byte in shape;
28
+ * only the PROMPT ({@link buildSurfacePrompt}) and the parsed payload
29
+ * ({@link parseSurfaceEmit}, a `{questions}` list rather than a `{verdict}`)
30
+ * differ.
31
+ *
32
+ * ALWAYS-allowed: there is NO gate check before surfacing — surfacing a question
33
+ * is never gated, even with every autonomy flag off (the "question loop with zero
34
+ * autonomy" case, US #23). The expensive (agent/model) work is POST-lock,
35
+ * winner-only — but that sequencing is the ENGINE's job (`advance.ts`); this
36
+ * module is only the spawn→emit→parse.
37
+ */
38
+
39
+ /**
40
+ * One question the `surface-questions` skill EMITS — the THREE authoring fields of
41
+ * the sidecar entry shape (`skills/surface-questions/SKILL.md` → "The emitted
42
+ * question shape"). It maps 1:1 onto {@link NewQuestion} (what the engine appends
43
+ * to the sidecar), so the engine persists with ZERO translation. The skill does
44
+ * NOT assign `id`/`answered`/`answer`/`allAnswered` — those are the sidecar's
45
+ * machine-owned fields the engine owns. A surfaced question is a PLAIN question:
46
+ * there is NO `disposition` token any more (task
47
+ * `agentic-apply-retire-disposition-vocabulary`) — what to DO with the answered
48
+ * signal is decided by the AGENTIC apply decision, not stamped on the question.
49
+ */
50
+ export interface SurfaceQuestion {
51
+ /** The question, verbatim. */
52
+ question: string;
53
+ /** Inline context so the human need not open the item. */
54
+ context?: string;
55
+ /** Optional suggested default (the humility aid; NEVER a decision). */
56
+ default?: string;
57
+ }
58
+
59
+ /**
60
+ * What the `surface-questions` SKILL emits (and this gate parses): the item's
61
+ * identity (orientation only) + an ORDERED list of questions. An EMPTY list is a
62
+ * valid, honest result ("no open judgement") — the engine writes no sidecar.
63
+ */
64
+ export interface SurfaceEmit {
65
+ /** The namespaced identity the skill surfaced for (orientation; advisory). */
66
+ item?: string;
67
+ /** The ordered emitted questions (possibly empty). */
68
+ questions: SurfaceQuestion[];
69
+ }
70
+
71
+ /** What the surface gate needs to launch a fresh-context surface of one item. */
72
+ export interface SurfaceGateInput {
73
+ /** The namespaced identity the surface is for (`task:foo` / `prd:bar` / `observation:baz`). */
74
+ item: string;
75
+ /** The working clone/checkout the gate runs in. */
76
+ cwd: string;
77
+ /**
78
+ * The model the SURFACE agent runs on. `undefined` ⇒ no forced model (the
79
+ * harness's own default). Flows to the launch through `LaunchInput.model`.
80
+ */
81
+ surfaceModel?: string;
82
+ /** Environment for the surface-agent launch. */
83
+ env?: NodeJS.ProcessEnv;
84
+ /** `--watch`: tail the surface agent's pi session live (pure observer). */
85
+ watch?: boolean;
86
+ /** Where the tailed surface lines are written (defaults to stderr). */
87
+ watchSink?: (line: string) => void;
88
+ /** Emit ANSI colour in the tailed surface lines (the caller's TTY decision). */
89
+ color?: boolean;
90
+ /** The HOST-ONLY sessions root the surface session FILE is generated under. */
91
+ sessionsDir?: string;
92
+ }
93
+
94
+ /**
95
+ * The surface-gate SEAM: run a fresh-context surface of the item and return the
96
+ * parsed emitted questions. Injected by tests (a canned list, no real model);
97
+ * production uses {@link harnessSurfaceGate}. Mirrors `review-gate.ts`'s
98
+ * `ReviewGate` seam shape so the engine wiring is testable as pure logic.
99
+ */
100
+ export type SurfaceGate = (input: SurfaceGateInput) => Promise<SurfaceEmit>;
101
+
102
+ /** Raised when the surface agent ran but produced no parseable emit. */
103
+ export class SurfaceParseError extends Error {}
104
+
105
+ /**
106
+ * Parse the `surface-questions` SKILL's emitted questions out of the surface
107
+ * agent's textual output. The skill emits a `{item, questions:[…]}` JSON object
108
+ * (the agent may wrap it in prose / a fenced block), so we extract the first JSON
109
+ * object carrying a `questions` field and validate its shape. An EMPTY
110
+ * `questions` list is VALID (the honest "no open judgement" result). Throws
111
+ * {@link SurfaceParseError} when no valid emit is present (the caller treats an
112
+ * unparseable emit as an error — never a silent "surfaced nothing").
113
+ *
114
+ * The emit MAY also carry a free-prose `note` field (the surface counterpart of
115
+ * the verdict's `review`): a HOME inside the object for the agent's reasoning /
116
+ * findings so it never needs to write prose AROUND the JSON (the cause of the
117
+ * "no parseable {questions}" trailing-chatter failure — observation
118
+ * `surface-rung-agent-emits-no-parseable-questions`). The engine does not
119
+ * persist `note`, so it is simply IGNORED here (like every unrecognised field);
120
+ * the prompt's job is to give the prose a place to go, not the parser's to keep
121
+ * it.
122
+ */
123
+ export function parseSurfaceEmit(output: string): SurfaceEmit {
124
+ const span = extractJsonObjectSpan(output, 'questions');
125
+ if (span === undefined) {
126
+ throw new SurfaceParseError(
127
+ 'surface agent produced no parseable {questions} result',
128
+ );
129
+ }
130
+ let parsed: unknown;
131
+ try {
132
+ parsed = JSON.parse(output.slice(span.start, span.end));
133
+ } catch (err) {
134
+ throw new SurfaceParseError(
135
+ `surface emit was not valid JSON: ${(err as Error).message}`,
136
+ );
137
+ }
138
+ return validateEmit(parsed);
139
+ }
140
+
141
+ /** Validate a parsed object is a `{item?, questions:[…]}` shape; normalise it. */
142
+ function validateEmit(parsed: unknown): SurfaceEmit {
143
+ if (typeof parsed !== 'object' || parsed === null) {
144
+ throw new SurfaceParseError('surface emit was not an object');
145
+ }
146
+ const obj = parsed as Record<string, unknown>;
147
+ if (!Array.isArray(obj.questions)) {
148
+ throw new SurfaceParseError(
149
+ 'surface emit had no `questions` array (an empty array is valid; absence is not)',
150
+ );
151
+ }
152
+ const questions: SurfaceQuestion[] = obj.questions.map((q) => {
153
+ const item = (typeof q === 'object' && q !== null ? q : {}) as Record<
154
+ string,
155
+ unknown
156
+ >;
157
+ const question: SurfaceQuestion = {
158
+ question: typeof item.question === 'string' ? item.question : '',
159
+ };
160
+ if (typeof item.context === 'string' && item.context !== '') {
161
+ question.context = item.context;
162
+ }
163
+ if (typeof item.default === 'string' && item.default !== '') {
164
+ question.default = item.default;
165
+ }
166
+ return question;
167
+ });
168
+ return {
169
+ ...(typeof obj.item === 'string' ? {item: obj.item} : {}),
170
+ // A question with an EMPTY `question` string carries no judgement — drop it
171
+ // (the agent may have emitted a placeholder), so an all-empty list is the
172
+ // same honest "no open judgement" as an empty array.
173
+ questions: questions.filter((q) => q.question.trim() !== ''),
174
+ };
175
+ }
176
+
177
+ /**
178
+ * Convert the emitted questions to the {@link NewQuestion} shape the engine
179
+ * appends to the sidecar — a 1:1 field map (the emit shape IS the sidecar
180
+ * authoring shape, by design), so the engine persists with ZERO translation.
181
+ */
182
+ export function toNewQuestions(emit: SurfaceEmit): NewQuestion[] {
183
+ return emit.questions.map((q) => {
184
+ const nq: NewQuestion = {question: q.question};
185
+ if (q.context !== undefined) {
186
+ nq.context = q.context;
187
+ }
188
+ if (q.default !== undefined) {
189
+ nq.default = q.default;
190
+ }
191
+ return nq;
192
+ });
193
+ }
194
+
195
+ /**
196
+ * Render the surface-agent PROMPT: instruct a fresh-context agent to apply the
197
+ * **surface-questions discipline** (`work/protocol/SURFACE-PROTOCOL.md`) to ONE
198
+ * `work/` item and to EMIT a single `{item, questions}` JSON object (so
199
+ * {@link parseSurfaceEmit} can read it). The discipline body (the two laws —
200
+ * GATHER-only / PERSIST-NEVER — the humility rule, the composed sources, the
201
+ * emitted-question shape) lives in `SURFACE-PROTOCOL.md` — NOT inlined here
202
+ * (task `surface-protocol-doc-and-prompt`). The shape's source of truth is
203
+ * {@link parseSurfaceEmit}; the doc DESCRIBES it (D2).
204
+ *
205
+ * This builder owns ONLY the PER-BUILDER framing: who you are (a fresh-context
206
+ * question-surfacer, the engine's surface-question rung), what you are
207
+ * surfacing (ONE namespaced item), and the required JSON output shape. It
208
+ * MIRRORS {@link buildReviewPrompt}: a fresh-context agent that EDITS nothing
209
+ * and EMITS a single structured object the ENGINE routes/persists.
210
+ */
211
+ export function buildSurfacePrompt(item: string): string {
212
+ return [
213
+ `You are a FRESH-CONTEXT question-surfacer for the work/ item "${item}".`,
214
+ `Apply the surface-questions discipline defined in`,
215
+ `\`work/protocol/SURFACE-PROTOCOL.md\` (the in-band, protocol-native`,
216
+ `surface-questions protocol every set-up repo carries; the human-facing`,
217
+ `pointer is \`skills/surface-questions/SKILL.md\`) to this ONE item:`,
218
+ `formulate its open questions and EMIT them. Its two laws, its humility`,
219
+ `aid, the composed sources you draw from, and the emitted-question shape`,
220
+ `ALL live in that doc — read them there.`,
221
+ `The skill JUDGES; the engine PERSISTS.`,
222
+ ``,
223
+ `Do NOT edit any files, run no git — you EMIT questions only.`,
224
+ ``,
225
+ `Your investigation may be substantial (you compose review's verdict, you`,
226
+ `probe an observation against current reality). Put ANY explanation,`,
227
+ `reasoning, or "here is what I found" prose IN the \`note\` field of the JSON`,
228
+ `below — that is its home. This MIRRORS Gate-2's verdict, which carries its`,
229
+ `human-readable prose in a \`review\` field for exactly this reason: with a`,
230
+ `channel for prose INSIDE the object, you never need to write anything`,
231
+ `around it.`,
232
+ ``,
233
+ `The single JSON object below MUST be your FINAL and ONLY output. Do NOT`,
234
+ `narrate your process ("Let me check…"), do NOT add any remark, summary, or`,
235
+ `sign-off BEFORE or AFTER it, and do NOT take any further turn once you have`,
236
+ `emitted it — emitting the object is how you finish. A trailing chatty turn`,
237
+ `after the object strands the run (the reader sees only your last turn).`,
238
+ ``,
239
+ `Output ONLY a single JSON object of this exact shape (no prose OUTSIDE it;`,
240
+ `see \`SURFACE-PROTOCOL.md\` → "The emitted question shape" for the`,
241
+ `prose-described contract this mirrors). The example below is EXPANDED over`,
242
+ `several lines for READABILITY, but you MUST emit it MINIFIED — ONE single`,
243
+ `line, no newlines between the keys:`,
244
+ ``,
245
+ '```json',
246
+ `{"item": "${item}",`,
247
+ ` "questions": [`,
248
+ ` {"question": "…",`,
249
+ ` "context": "…",`,
250
+ ` "default": "… (optional; omit if none)"}`,
251
+ ` ],`,
252
+ ` "note": "… (optional; your reasoning / findings prose lives HERE, not outside the object)"}`,
253
+ '```',
254
+ ``,
255
+ `An EMPTY \`questions\` array is a VALID, honest result (no open judgement) —`,
256
+ `emit the object with \`"questions": []\` (put WHY in \`note\`); do NOT replace`,
257
+ `it with a prose explanation. Absence of the field is NOT valid.`,
258
+ ``,
259
+ // The SHARED defensive-JSON contract (the same hardening Gate-2's verdict
260
+ // prompt carries) — the surface rung hit the IDENTICAL unparseable-emit
261
+ // failure the verdict gate did, so it reuses the one contract rather than
262
+ // staying the lone un-hardened seam. The longest field is `note` (the free
263
+ // prose channel, the surface counterpart of the verdict's `review`).
264
+ parseableJsonContractPrompt('result', 'note'),
265
+ ].join('\n');
266
+ }
267
+
268
+ /** What a harness-backed surface gate needs to launch the surface agent. */
269
+ export interface HarnessSurfaceGateOptions {
270
+ /** The harness seam used to launch the fresh-context surface agent. */
271
+ harness?: Harness;
272
+ /** The agent command the null/shell adapter shells out to (`{model}`-aware). */
273
+ agentCmd?: string;
274
+ /**
275
+ * Read the surface agent's textual output for parsing. Production reads
276
+ * `launched.output` (the ANSWER channel, distinct from `detail`); tests inject
277
+ * `readOutput` to stub a canned emit string.
278
+ */
279
+ readOutput?: (output: string | undefined) => string;
280
+ }
281
+
282
+ /**
283
+ * The PRODUCTION surface gate: launch the `surface-questions` SKILL as a
284
+ * fresh-context agent through the EXISTING harness seam, routing the
285
+ * `surfaceModel` override via `LaunchInput.model` (the §13 model-routing intent —
286
+ * NOT a new mechanism), then parse the emitted `{item, questions}`. It is the
287
+ * DIRECT mirror of `harnessReviewGate`: a SEPARATE harness launch (fresh context
288
+ * = not the engine's session) in the same checkout `cwd`, fed
289
+ * {@link buildSurfacePrompt}; the model flows through `LaunchInput.model`, which
290
+ * each adapter injects natively. The surface uses a DISTINCT session id
291
+ * (`<item>-surface`) so its session never collides with a build/review session.
292
+ */
293
+ export function harnessSurfaceGate(
294
+ options: HarnessSurfaceGateOptions = {},
295
+ ): SurfaceGate {
296
+ const harness = options.harness ?? new NullHarness();
297
+ const readOutput = options.readOutput ?? ((output) => output ?? '');
298
+ return async (input: SurfaceGateInput): Promise<SurfaceEmit> => {
299
+ if (input.watch === true) {
300
+ const sink =
301
+ input.watchSink ??
302
+ ((line: string) => process.stderr.write(`${line}\n`));
303
+ sink(
304
+ boundaryLine(
305
+ `surface — gathering questions for ${input.item}…`,
306
+ input.color ?? false,
307
+ ),
308
+ );
309
+ }
310
+ // A safe session-id stem (the namespaced identity has a `:` that is not a
311
+ // valid path stem). The same `:`→`-` convention the sidecar/lock identity uses.
312
+ const sessionId = `${input.item.replace(/:/g, '-')}-surface`;
313
+ const launched = await launchWithOptionalWatch({
314
+ harness,
315
+ dir: input.cwd,
316
+ slug: input.item,
317
+ command: options.agentCmd ?? '',
318
+ prompt: buildSurfacePrompt(input.item),
319
+ model: input.surfaceModel,
320
+ sessionId,
321
+ sessionsDir: input.sessionsDir,
322
+ watch: input.watch,
323
+ watchSink: input.watchSink,
324
+ color: input.color,
325
+ env: input.env,
326
+ });
327
+ if (!launched.ok) {
328
+ throw new SurfaceParseError(
329
+ `surface agent launch failed${launched.detail ? `: ${launched.detail}` : ''}`,
330
+ );
331
+ }
332
+ // Read the emit from the agent's ANSWER channel (`output`), NOT `detail`
333
+ // (empty on success). An empty/absent output → parseSurfaceEmit throws → the
334
+ // engine surfaces nothing and reports it (never a silent success).
335
+ return parseSurfaceEmit(readOutput(launched.output));
336
+ };
337
+ }
@@ -0,0 +1,241 @@
1
+ import {existsSync, mkdirSync, readFileSync, writeFileSync} from 'node:fs';
2
+ import {dirname, join} from 'node:path';
3
+ import {run, type RunResult} from './git.js';
4
+ import {parseFrontmatter, setNeedsAnswersMarker} from './frontmatter.js';
5
+ import {
6
+ appendQuestions,
7
+ newSidecar,
8
+ parseSidecar,
9
+ serialiseSidecar,
10
+ sidecarPathFor,
11
+ type NewQuestion,
12
+ type SidecarModel,
13
+ } from './sidecar.js';
14
+
15
+ /**
16
+ * The engine-owned SURFACE PERSIST (prd `advance-loop`, task
17
+ * `advance-rung-surface`, US #15/33) — the half of the surface rung the ENGINE
18
+ * owns (the skill JUDGES, the engine PERSISTS). Given the questions the
19
+ * `surface-questions` skill EMITTED (gathered by `surface-gate.ts`'s spawn), the
20
+ * engine writes them to the sidecar `work/questions/<type>-<slug>.md` and sets
21
+ * `needsAnswers:true` on the item body — in ONE commit, exactly as the review
22
+ * gate persists a verdict and `applyAtomic` resolves an answer batch in one
23
+ * commit.
24
+ *
25
+ * It is the SIBLING of {@link import('./sidecar-apply.js').applyAtomic}: that is
26
+ * the APPLY rung's one-commit primitive (resolve/re-pause); this is the SURFACE
27
+ * rung's one-commit primitive (append-or-create + set `needsAnswers`). Kept in a
28
+ * SEPARATE module so the surface rung's persist and the apply rung's persist stay
29
+ * file-orthogonal (the rung bodies land in different tasks).
30
+ *
31
+ * The load-bearing rules (the task's acceptance criteria):
32
+ *
33
+ * - **Append-never-overwrite (US #15).** When a sidecar ALREADY exists, the new
34
+ * questions are APPENDED ({@link appendQuestions} mints `qN+1…`), NEVER
35
+ * overwriting an existing (answered or unanswered) entry. A re-surface that
36
+ * adds questions to a previously-all-answered sidecar FLIPS it back to
37
+ * not-all-answered (the appended entries are pending).
38
+ * - **Set `needsAnswers:true` atomically (invariant 1).** The item body's
39
+ * `needsAnswers` flag is set to `true` in the SAME commit the sidecar is
40
+ * written, so the `needsAnswers:true ⟺ active sidecar` invariant holds the
41
+ * instant the commit lands.
42
+ * - **Identity-keyed sidecar path.** The sidecar path derives PURELY from the
43
+ * item's namespaced identity ({@link sidecarPathFor}) — it survives the item's
44
+ * `git mv`s with no lock-step move.
45
+ *
46
+ * This is the LOCAL one-commit primitive over a working tree (the
47
+ * throwaway-git-repo test pattern the apply/lock tests use). The `advancing` CAS
48
+ * lock that makes this WINNER-ONLY is held by `performAdvance` BEFORE this is
49
+ * called — so the expensive spawn + this persist are both POST-lock. This module
50
+ * does NOT race the arbiter; that is the lock's job.
51
+ */
52
+
53
+ export interface SurfacePersistOptions {
54
+ /** Working clone/worktree the persist commits in. */
55
+ cwd: string;
56
+ /** The namespaced item identity (`task:foo` / `prd:bar` / `observation:baz`). */
57
+ item: string;
58
+ /**
59
+ * The item file path RELATIVE to `cwd` (e.g. `work/backlog/foo.md`). The
60
+ * `needsAnswers:true` flag is set on THIS file; the sidecar path is derived
61
+ * from the identity, NOT from this path.
62
+ */
63
+ itemPath: string;
64
+ /** The questions the `surface-questions` skill emitted (engine appends them). */
65
+ questions: NewQuestion[];
66
+ /** Advisory committer id for the commit subject. Defaults to git user.name. */
67
+ by?: string;
68
+ /** Environment for child git processes. */
69
+ env?: NodeJS.ProcessEnv;
70
+ /** Sink for human-readable progress notes. */
71
+ note?: (message: string) => void;
72
+ }
73
+
74
+ export interface SurfacePersistResult {
75
+ /** `surfaced` (questions written + needsAnswers set) or `nothing` (empty emit). */
76
+ outcome: 'surfaced' | 'nothing';
77
+ /** The commit sha the persist produced (`undefined` on a `nothing` no-op). */
78
+ commit?: string;
79
+ /** The sidecar path (relative to `cwd`) the persist touched. */
80
+ sidecarPath: string;
81
+ /** How many entries the sidecar carries after this persist. */
82
+ entryCount: number;
83
+ }
84
+
85
+ /** Raised for usage errors (a missing repo, an unreadable item). */
86
+ export class SurfacePersistError extends Error {
87
+ constructor(message: string) {
88
+ super(message);
89
+ this.name = 'SurfacePersistError';
90
+ }
91
+ }
92
+
93
+ function gitSoft(
94
+ args: string[],
95
+ cwd: string,
96
+ env: NodeJS.ProcessEnv | undefined,
97
+ ): RunResult {
98
+ return run('git', args, cwd, {env});
99
+ }
100
+
101
+ function gitHard(
102
+ args: string[],
103
+ cwd: string,
104
+ env: NodeJS.ProcessEnv | undefined,
105
+ ): RunResult {
106
+ const result = run('git', args, cwd, {env});
107
+ if (result.status !== 0) {
108
+ throw new SurfacePersistError(
109
+ `git ${args.join(' ')} failed (exit ${result.status}): ${result.stderr.trim()}`,
110
+ );
111
+ }
112
+ return result;
113
+ }
114
+
115
+ function resolveBy(cwd: string, env: NodeJS.ProcessEnv | undefined): string {
116
+ const name = gitSoft(['config', 'user.name'], cwd, env);
117
+ if (name.status === 0 && name.stdout.trim() !== '') {
118
+ return name.stdout.trim();
119
+ }
120
+ const e = env ?? process.env;
121
+ return e.USER ?? e.USERNAME ?? '';
122
+ }
123
+
124
+ /**
125
+ * Persist the SURFACED questions ATOMICALLY: APPEND them to the existing sidecar
126
+ * (or CREATE it first-pass), and set `needsAnswers:true` on the item body — ONE
127
+ * commit. An EMPTY question set is a clean NO-OP (no sidecar written, the item
128
+ * untouched): the honest "no open judgement" result the skill is allowed to
129
+ * emit; nothing to commit, so `needsAnswers` is NOT set.
130
+ *
131
+ * Append-never-overwrite: when a sidecar exists, the new questions are APPENDED
132
+ * (never mutating an answered entry); a re-surface flips a previously-all-answered
133
+ * sidecar back to not-all-answered. Returns the produced commit + the resulting
134
+ * entry count.
135
+ */
136
+ export function persistSurfacedQuestions(
137
+ options: SurfacePersistOptions,
138
+ ): SurfacePersistResult {
139
+ const {cwd, item, itemPath, questions, env} = options;
140
+ const note = options.note ?? (() => {});
141
+
142
+ if (gitSoft(['rev-parse', '--git-dir'], cwd, env).status !== 0) {
143
+ throw new SurfacePersistError('not inside a git repository');
144
+ }
145
+
146
+ const sidecarPath = sidecarPathFor(item);
147
+ const sidecarAbs = join(cwd, sidecarPath);
148
+
149
+ // Build the post-persist sidecar model: APPEND to an existing one (never
150
+ // overwrite), else CREATE first-pass. Read the current sidecar from the tree
151
+ // so the append is over the COMMITTED history (identity-keyed, folder-agnostic).
152
+ let model: SidecarModel;
153
+ const existing = readExistingSidecar(sidecarAbs);
154
+ if (existing !== undefined) {
155
+ model = appendQuestions(existing, questions);
156
+ } else {
157
+ model = newSidecar(item, questions);
158
+ }
159
+
160
+ // An empty emit ⇒ the sidecar would carry no entries: surface NOTHING (the
161
+ // honest result). Do NOT write a sidecar or set `needsAnswers` — a sidecar with
162
+ // no open questions should not exist (it keeps invariant 1 + the "pending ⇒
163
+ // NO-OP" classifier honest).
164
+ if (model.entries.length === 0) {
165
+ const message = `surface ${item}: no open judgement — nothing surfaced (no sidecar written).`;
166
+ note(message);
167
+ return {outcome: 'nothing', sidecarPath, entryCount: 0};
168
+ }
169
+
170
+ // Set `needsAnswers:true` on the item body (the only in-body signal — the
171
+ // sidecar path is identity-derived, no back-pointer). The item file may not
172
+ // have a `needsAnswers` line yet (and may be fence-less — observations are born
173
+ // that way); `setNeedsAnswersMarker` prepends a fence when needed and is
174
+ // idempotent otherwise.
175
+ const itemAbs = join(cwd, itemPath);
176
+ const itemBody = readItem(itemAbs, cwd, itemPath, env);
177
+ const flagged = setNeedsAnswersMarker(itemBody, true);
178
+
179
+ // DEFENSE IN DEPTH (the `sidecar-without-needsAnswers` guard): the surface
180
+ // commit is only atomic if the flag ACTUALLY landed. If — for any reason — the
181
+ // flag did not parse back as `true` (e.g. a degenerate body the marker writer
182
+ // cannot annotate), ABORT BEFORE writing the sidecar, so we never produce the
183
+ // torn invariant (sidecar present, flag absent) a later tick refuses to advance.
184
+ if (parseFrontmatter(flagged).needsAnswers !== true) {
185
+ throw new SurfacePersistError(
186
+ `surface ${item}: could not set needsAnswers:true on '${itemPath}' ` +
187
+ `(the item body could not be annotated) — refusing to write the sidecar ` +
188
+ `without the flag (that would tear the needsAnswers ⟺ sidecar invariant).`,
189
+ );
190
+ }
191
+ writeFileSync(itemAbs, flagged);
192
+
193
+ // Write the appended/created sidecar.
194
+ mkdirSync(dirname(sidecarAbs), {recursive: true});
195
+ writeFileSync(sidecarAbs, serialiseSidecar(model));
196
+
197
+ // Stage exactly the two paths and commit them TOGETHER (one atomic commit) —
198
+ // the sidecar write + the `needsAnswers:true` flip land in the SAME commit, so
199
+ // `needsAnswers:true ⟺ active sidecar` holds the instant it lands.
200
+ const by = options.by || resolveBy(cwd, env);
201
+ gitHard(['add', '--', itemPath, sidecarPath], cwd, env);
202
+ const subject = `advance: surface ${item} (${model.entries.length} question(s), by ${by})`;
203
+ gitHard(['commit', '--quiet', '-m', subject], cwd, env);
204
+ const commit = gitHard(['rev-parse', 'HEAD'], cwd, env).stdout.trim();
205
+ note(subject);
206
+
207
+ return {
208
+ outcome: 'surfaced',
209
+ commit,
210
+ sidecarPath,
211
+ entryCount: model.entries.length,
212
+ };
213
+ }
214
+
215
+ /** Read + parse the existing sidecar (from the tree, then the working file). */
216
+ function readExistingSidecar(sidecarAbs: string): SidecarModel | undefined {
217
+ if (!existsSync(sidecarAbs)) {
218
+ return undefined;
219
+ }
220
+ return parseSidecar(readFileSync(sidecarAbs, 'utf8'));
221
+ }
222
+
223
+ /** Read the item body from the tree (committed) then the working-tree file. */
224
+ function readItem(
225
+ itemAbs: string,
226
+ cwd: string,
227
+ itemPath: string,
228
+ env: NodeJS.ProcessEnv | undefined,
229
+ ): string {
230
+ const show = gitSoft(['show', `:${itemPath}`], cwd, env);
231
+ if (show.status === 0) {
232
+ return show.stdout;
233
+ }
234
+ try {
235
+ return readFileSync(itemAbs, 'utf8');
236
+ } catch {
237
+ throw new SurfacePersistError(
238
+ `cannot read item body for '${itemPath}' (the surface rung needs the item file)`,
239
+ );
240
+ }
241
+ }