dorfl 0.1.1 → 0.2.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 (492) hide show
  1. package/dist/advance-ci-template.d.ts +3 -3
  2. package/dist/advance-ci-template.js +1 -1
  3. package/dist/advance-ci-template.js.map +1 -1
  4. package/dist/advance-classify.d.ts +5 -5
  5. package/dist/advance-classify.d.ts.map +1 -1
  6. package/dist/advance-classify.js +4 -4
  7. package/dist/advance-drivers.d.ts +8 -8
  8. package/dist/advance-drivers.d.ts.map +1 -1
  9. package/dist/advance-drivers.js +20 -8
  10. package/dist/advance-drivers.js.map +1 -1
  11. package/dist/advance-isolated.d.ts +3 -3
  12. package/dist/advance-isolated.d.ts.map +1 -1
  13. package/dist/advance-isolated.js +1 -1
  14. package/dist/advance-lifecycle-template.d.ts +2 -2
  15. package/dist/advance-lifecycle-template.d.ts.map +1 -1
  16. package/dist/advance-lifecycle-template.js +85 -13
  17. package/dist/advance-lifecycle-template.js.map +1 -1
  18. package/dist/advance-loop-driver.d.ts +3 -3
  19. package/dist/advance-loop-driver.d.ts.map +1 -1
  20. package/dist/advance-loop-driver.js +1 -1
  21. package/dist/advance-treeless-publish.d.ts +24 -1
  22. package/dist/advance-treeless-publish.d.ts.map +1 -1
  23. package/dist/advance-treeless-publish.js +41 -0
  24. package/dist/advance-treeless-publish.js.map +1 -1
  25. package/dist/advance.d.ts +69 -17
  26. package/dist/advance.d.ts.map +1 -1
  27. package/dist/advance.js +409 -102
  28. package/dist/advance.js.map +1 -1
  29. package/dist/advancing-lock.d.ts +31 -3
  30. package/dist/advancing-lock.d.ts.map +1 -1
  31. package/dist/advancing-lock.js +55 -5
  32. package/dist/advancing-lock.js.map +1 -1
  33. package/dist/agent-launch.d.ts +12 -0
  34. package/dist/agent-launch.d.ts.map +1 -1
  35. package/dist/agent-launch.js +22 -12
  36. package/dist/agent-launch.js.map +1 -1
  37. package/dist/agent-stop.d.ts +40 -2
  38. package/dist/agent-stop.d.ts.map +1 -1
  39. package/dist/agent-stop.js +30 -2
  40. package/dist/agent-stop.js.map +1 -1
  41. package/dist/apply-decide.d.ts +19 -5
  42. package/dist/apply-decide.d.ts.map +1 -1
  43. package/dist/apply-decide.js +38 -9
  44. package/dist/apply-decide.js.map +1 -1
  45. package/dist/apply-merge-action.d.ts +20 -8
  46. package/dist/apply-merge-action.d.ts.map +1 -1
  47. package/dist/apply-merge-action.js +44 -9
  48. package/dist/apply-merge-action.js.map +1 -1
  49. package/dist/apply-persist.d.ts +62 -31
  50. package/dist/apply-persist.d.ts.map +1 -1
  51. package/dist/apply-persist.js +173 -44
  52. package/dist/apply-persist.js.map +1 -1
  53. package/dist/apply-stuck-action.d.ts +151 -0
  54. package/dist/apply-stuck-action.d.ts.map +1 -0
  55. package/dist/apply-stuck-action.js +125 -0
  56. package/dist/apply-stuck-action.js.map +1 -0
  57. package/dist/brand.d.ts +12 -1
  58. package/dist/brand.d.ts.map +1 -1
  59. package/dist/brand.js +2 -1
  60. package/dist/brand.js.map +1 -1
  61. package/dist/buildable-body.d.ts +14 -14
  62. package/dist/buildable-body.js +9 -9
  63. package/dist/claim-cas.d.ts +3 -3
  64. package/dist/claim-cas.js +1 -1
  65. package/dist/claim-cas.js.map +1 -1
  66. package/dist/cli-spinner.d.ts +1 -1
  67. package/dist/cli-spinner.js +1 -1
  68. package/dist/cli.d.ts +10 -0
  69. package/dist/cli.d.ts.map +1 -1
  70. package/dist/cli.js +385 -128
  71. package/dist/cli.js.map +1 -1
  72. package/dist/close-job-template.d.ts +3 -3
  73. package/dist/close-job-template.js +9 -9
  74. package/dist/close-job.d.ts +8 -8
  75. package/dist/close-job.js +25 -25
  76. package/dist/close-job.js.map +1 -1
  77. package/dist/complete.d.ts +9 -6
  78. package/dist/complete.d.ts.map +1 -1
  79. package/dist/complete.js +99 -45
  80. package/dist/complete.js.map +1 -1
  81. package/dist/concurrency.d.ts +1 -1
  82. package/dist/concurrency.js +1 -1
  83. package/dist/config.d.ts +86 -40
  84. package/dist/config.d.ts.map +1 -1
  85. package/dist/config.js +61 -9
  86. package/dist/config.js.map +1 -1
  87. package/dist/continue-branch.d.ts +1 -1
  88. package/dist/continue-branch.d.ts.map +1 -1
  89. package/dist/continue-branch.js +23 -1
  90. package/dist/continue-branch.js.map +1 -1
  91. package/dist/cwd-section.js +1 -1
  92. package/dist/cwd-section.js.map +1 -1
  93. package/dist/decision-engine.d.ts +39 -11
  94. package/dist/decision-engine.d.ts.map +1 -1
  95. package/dist/decision-engine.js +10 -6
  96. package/dist/decision-engine.js.map +1 -1
  97. package/dist/do-autopick.d.ts +6 -6
  98. package/dist/do-autopick.d.ts.map +1 -1
  99. package/dist/do-autopick.js +16 -6
  100. package/dist/do-autopick.js.map +1 -1
  101. package/dist/do-config.d.ts +4 -4
  102. package/dist/do-config.js +3 -3
  103. package/dist/do-config.js.map +1 -1
  104. package/dist/do-remote-auto.d.ts +2 -2
  105. package/dist/do-remote-auto.js +1 -1
  106. package/dist/do.d.ts +74 -81
  107. package/dist/do.d.ts.map +1 -1
  108. package/dist/do.js +439 -50
  109. package/dist/do.js.map +1 -1
  110. package/dist/drop-source.d.ts +2 -2
  111. package/dist/env-config.d.ts.map +1 -1
  112. package/dist/env-config.js +19 -11
  113. package/dist/env-config.js.map +1 -1
  114. package/dist/failure-cause.d.ts +3 -2
  115. package/dist/failure-cause.d.ts.map +1 -1
  116. package/dist/failure-cause.js +28 -1
  117. package/dist/failure-cause.js.map +1 -1
  118. package/dist/format.d.ts +6 -6
  119. package/dist/format.d.ts.map +1 -1
  120. package/dist/format.js +13 -30
  121. package/dist/format.js.map +1 -1
  122. package/dist/frontmatter.d.ts +28 -15
  123. package/dist/frontmatter.d.ts.map +1 -1
  124. package/dist/frontmatter.js +38 -24
  125. package/dist/frontmatter.js.map +1 -1
  126. package/dist/gc.d.ts +65 -6
  127. package/dist/gc.d.ts.map +1 -1
  128. package/dist/gc.js +126 -9
  129. package/dist/gc.js.map +1 -1
  130. package/dist/github.d.ts +14 -0
  131. package/dist/github.d.ts.map +1 -1
  132. package/dist/github.js +73 -0
  133. package/dist/github.js.map +1 -1
  134. package/dist/harness.d.ts +25 -0
  135. package/dist/harness.d.ts.map +1 -1
  136. package/dist/harness.js.map +1 -1
  137. package/dist/index.d.ts +4 -1
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/index.js +2 -1
  140. package/dist/index.js.map +1 -1
  141. package/dist/install-ci-branch-protection.d.ts +133 -39
  142. package/dist/install-ci-branch-protection.d.ts.map +1 -1
  143. package/dist/install-ci-branch-protection.js +191 -49
  144. package/dist/install-ci-branch-protection.js.map +1 -1
  145. package/dist/install-ci-capabilities/advance-lifecycle.d.ts +1 -1
  146. package/dist/install-ci-capabilities/advance-lifecycle.js +1 -1
  147. package/dist/install-ci-capabilities/close-job.d.ts +1 -1
  148. package/dist/install-ci-capabilities/close-job.js +1 -1
  149. package/dist/install-ci-capabilities/example-noop.d.ts +1 -1
  150. package/dist/install-ci-capabilities/example-noop.js +1 -1
  151. package/dist/install-ci-capabilities/intake.d.ts +2 -2
  152. package/dist/install-ci-capabilities/intake.js +2 -2
  153. package/dist/install-ci-capabilities/verify.d.ts +1 -1
  154. package/dist/install-ci-capabilities/verify.js +1 -1
  155. package/dist/install-ci-core.d.ts +24 -4
  156. package/dist/install-ci-core.d.ts.map +1 -1
  157. package/dist/install-ci-core.js +12 -5
  158. package/dist/install-ci-core.js.map +1 -1
  159. package/dist/install-ci-github.d.ts +33 -1
  160. package/dist/install-ci-github.d.ts.map +1 -1
  161. package/dist/install-ci-github.js +74 -1
  162. package/dist/install-ci-github.js.map +1 -1
  163. package/dist/install-ci.d.ts +1 -1
  164. package/dist/install-ci.js +4 -4
  165. package/dist/install-ci.js.map +1 -1
  166. package/dist/install-skills.d.ts +123 -0
  167. package/dist/install-skills.d.ts.map +1 -0
  168. package/dist/install-skills.js +100 -0
  169. package/dist/install-skills.js.map +1 -0
  170. package/dist/intake-event.d.ts +6 -6
  171. package/dist/intake-event.js +6 -6
  172. package/dist/intake-marker.d.ts +3 -3
  173. package/dist/intake-marker.d.ts.map +1 -1
  174. package/dist/intake-triage.d.ts +1 -1
  175. package/dist/intake-triage.js +2 -2
  176. package/dist/intake-trigger-template.d.ts +8 -8
  177. package/dist/intake-trigger-template.d.ts.map +1 -1
  178. package/dist/intake-trigger-template.js +17 -17
  179. package/dist/intake-trigger-template.js.map +1 -1
  180. package/dist/intake.d.ts +65 -52
  181. package/dist/intake.d.ts.map +1 -1
  182. package/dist/intake.js +92 -76
  183. package/dist/intake.js.map +1 -1
  184. package/dist/integration-core.d.ts +27 -24
  185. package/dist/integration-core.d.ts.map +1 -1
  186. package/dist/integration-core.js +191 -77
  187. package/dist/integration-core.js.map +1 -1
  188. package/dist/integrator.d.ts +1 -1
  189. package/dist/integrator.d.ts.map +1 -1
  190. package/dist/integrator.js +19 -3
  191. package/dist/integrator.js.map +1 -1
  192. package/dist/isolation.d.ts +4 -4
  193. package/dist/isolation.d.ts.map +1 -1
  194. package/dist/isolation.js +9 -0
  195. package/dist/isolation.js.map +1 -1
  196. package/dist/issue-provider.d.ts +4 -4
  197. package/dist/issue-provider.js +1 -1
  198. package/dist/item-lock.d.ts +216 -149
  199. package/dist/item-lock.d.ts.map +1 -1
  200. package/dist/item-lock.js +345 -270
  201. package/dist/item-lock.js.map +1 -1
  202. package/dist/item-path.d.ts +2 -2
  203. package/dist/item-path.js +2 -2
  204. package/dist/ledger-lint.d.ts +9 -9
  205. package/dist/ledger-lint.js +9 -9
  206. package/dist/ledger-read.d.ts +57 -57
  207. package/dist/ledger-read.d.ts.map +1 -1
  208. package/dist/ledger-read.js +24 -24
  209. package/dist/ledger-read.js.map +1 -1
  210. package/dist/ledger-write.d.ts +33 -28
  211. package/dist/ledger-write.d.ts.map +1 -1
  212. package/dist/ledger-write.js +100 -122
  213. package/dist/ledger-write.js.map +1 -1
  214. package/dist/lifecycle-gather.d.ts +18 -1
  215. package/dist/lifecycle-gather.d.ts.map +1 -1
  216. package/dist/lifecycle-gather.js +23 -17
  217. package/dist/lifecycle-gather.js.map +1 -1
  218. package/dist/lifecycle-pools.d.ts +44 -7
  219. package/dist/lifecycle-pools.d.ts.map +1 -1
  220. package/dist/lifecycle-pools.js +27 -7
  221. package/dist/lifecycle-pools.js.map +1 -1
  222. package/dist/merge-question-surfacer.d.ts +18 -4
  223. package/dist/merge-question-surfacer.d.ts.map +1 -1
  224. package/dist/merge-question-surfacer.js +20 -5
  225. package/dist/merge-question-surfacer.js.map +1 -1
  226. package/dist/migrate-stuck-locks.d.ts +129 -0
  227. package/dist/migrate-stuck-locks.d.ts.map +1 -0
  228. package/dist/migrate-stuck-locks.js +355 -0
  229. package/dist/migrate-stuck-locks.js.map +1 -0
  230. package/dist/mint-adr.js +4 -4
  231. package/dist/mirror-pool-scan.d.ts +2 -2
  232. package/dist/mirror-pool-scan.js +3 -3
  233. package/dist/mirror-pool-scan.js.map +1 -1
  234. package/dist/needs-attention.d.ts +304 -27
  235. package/dist/needs-attention.d.ts.map +1 -1
  236. package/dist/needs-attention.js +542 -67
  237. package/dist/needs-attention.js.map +1 -1
  238. package/dist/orphan-sidecar.d.ts +10 -6
  239. package/dist/orphan-sidecar.d.ts.map +1 -1
  240. package/dist/orphan-sidecar.js +35 -2
  241. package/dist/orphan-sidecar.js.map +1 -1
  242. package/dist/pi-harness.d.ts +16 -0
  243. package/dist/pi-harness.d.ts.map +1 -1
  244. package/dist/pi-harness.js +82 -2
  245. package/dist/pi-harness.js.map +1 -1
  246. package/dist/placement.d.ts +8 -8
  247. package/dist/placement.js +3 -3
  248. package/dist/prd-to-spec.d.ts.map +1 -1
  249. package/dist/prd-to-spec.js +9 -5
  250. package/dist/prd-to-spec.js.map +1 -1
  251. package/dist/prompt.d.ts +16 -19
  252. package/dist/prompt.d.ts.map +1 -1
  253. package/dist/prompt.js +17 -19
  254. package/dist/prompt.js.map +1 -1
  255. package/dist/protocol/CLAIM-PROTOCOL.md +17 -10
  256. package/dist/protocol/REVIEW-PROTOCOL.md +4 -1
  257. package/dist/protocol/SURFACE-PROTOCOL.md +16 -2
  258. package/dist/protocol/TASKING-PROTOCOL.md +3 -1
  259. package/dist/protocol/WORK-CONTRACT.md +22 -18
  260. package/dist/protocol/task-template.md +1 -1
  261. package/dist/readiness.d.ts +1 -1
  262. package/dist/reap-branches.d.ts +12 -9
  263. package/dist/reap-branches.d.ts.map +1 -1
  264. package/dist/reap-branches.js +25 -7
  265. package/dist/reap-branches.js.map +1 -1
  266. package/dist/recover-isolated.d.ts +12 -0
  267. package/dist/recover-isolated.d.ts.map +1 -1
  268. package/dist/recover-isolated.js +6 -1
  269. package/dist/recover-isolated.js.map +1 -1
  270. package/dist/repo-config.d.ts +23 -2
  271. package/dist/repo-config.d.ts.map +1 -1
  272. package/dist/repo-config.js +64 -18
  273. package/dist/repo-config.js.map +1 -1
  274. package/dist/repo-mirror.d.ts.map +1 -1
  275. package/dist/repo-mirror.js +18 -2
  276. package/dist/repo-mirror.js.map +1 -1
  277. package/dist/review-gate.d.ts +3 -3
  278. package/dist/review-gate.d.ts.map +1 -1
  279. package/dist/review-gate.js +11 -10
  280. package/dist/review-gate.js.map +1 -1
  281. package/dist/review-verdict.d.ts +2 -2
  282. package/dist/review-verdict.d.ts.map +1 -1
  283. package/dist/review-verdict.js +2 -2
  284. package/dist/review-verdict.js.map +1 -1
  285. package/dist/run.d.ts +2 -2
  286. package/dist/run.d.ts.map +1 -1
  287. package/dist/run.js +58 -23
  288. package/dist/run.js.map +1 -1
  289. package/dist/scan.d.ts +26 -17
  290. package/dist/scan.d.ts.map +1 -1
  291. package/dist/scan.js +29 -15
  292. package/dist/scan.js.map +1 -1
  293. package/dist/select-order.d.ts +1 -1
  294. package/dist/select-priority.d.ts +14 -14
  295. package/dist/select-priority.d.ts.map +1 -1
  296. package/dist/select-priority.js +5 -5
  297. package/dist/select-priority.js.map +1 -1
  298. package/dist/sidecar-apply.js +1 -1
  299. package/dist/sidecar-apply.js.map +1 -1
  300. package/dist/sidecar.d.ts +47 -12
  301. package/dist/sidecar.d.ts.map +1 -1
  302. package/dist/sidecar.js +84 -4
  303. package/dist/sidecar.js.map +1 -1
  304. package/dist/skills/answer-questions/SKILL.md +89 -0
  305. package/dist/skills/capture-signal/SKILL.md +52 -0
  306. package/dist/skills/convert-from-prd-to-spec/SKILL.md +90 -0
  307. package/dist/skills/drive-tasks/SKILL.md +218 -0
  308. package/dist/skills/from-idea/SKILL.md +83 -0
  309. package/dist/skills/merge-prs/SKILL.md +70 -0
  310. package/dist/skills/orchestrate/SKILL.md +101 -0
  311. package/dist/skills/promote/SKILL.md +35 -0
  312. package/dist/skills/review/SKILL.md +16 -0
  313. package/dist/skills/setup/SKILL.md +258 -0
  314. package/dist/skills/setup/protocol/ADR-FORMAT.md +47 -0
  315. package/dist/skills/setup/protocol/CLAIM-PROTOCOL.md +224 -0
  316. package/dist/skills/setup/protocol/REVIEW-PROTOCOL.md +122 -0
  317. package/dist/skills/setup/protocol/SURFACE-PROTOCOL.md +135 -0
  318. package/dist/skills/setup/protocol/TASKING-PROTOCOL.md +124 -0
  319. package/dist/skills/setup/protocol/WORK-CONTRACT.md +280 -0
  320. package/dist/skills/setup/protocol/spec-template.md +71 -0
  321. package/dist/skills/setup/protocol/task-template.md +65 -0
  322. package/dist/skills/surface-questions/SKILL.md +16 -0
  323. package/dist/skills/to-spec/SKILL.md +34 -0
  324. package/dist/skills/to-task/SKILL.md +19 -0
  325. package/dist/skills/triage-observations/SKILL.md +78 -0
  326. package/dist/skills/work/SKILL.md +51 -0
  327. package/dist/slug-namespace.d.ts +6 -6
  328. package/dist/slug-namespace.js +8 -8
  329. package/dist/slug-namespace.js.map +1 -1
  330. package/dist/spec-complete.d.ts.map +1 -1
  331. package/dist/spec-complete.js +4 -5
  332. package/dist/spec-complete.js.map +1 -1
  333. package/dist/start.d.ts +1 -1
  334. package/dist/start.d.ts.map +1 -1
  335. package/dist/start.js +54 -60
  336. package/dist/start.js.map +1 -1
  337. package/dist/status.d.ts +3 -3
  338. package/dist/status.js +4 -4
  339. package/dist/status.js.map +1 -1
  340. package/dist/surface-gate.d.ts +2 -2
  341. package/dist/surface-gate.d.ts.map +1 -1
  342. package/dist/surface-gate.js +10 -3
  343. package/dist/surface-gate.js.map +1 -1
  344. package/dist/surface-persist.d.ts +2 -2
  345. package/dist/surface-persist.d.ts.map +1 -1
  346. package/dist/surface-persist.js +1 -1
  347. package/dist/surface-persist.js.map +1 -1
  348. package/dist/tasker-review-loop.d.ts +11 -10
  349. package/dist/tasker-review-loop.d.ts.map +1 -1
  350. package/dist/tasker-review-loop.js +8 -8
  351. package/dist/tasker-review-loop.js.map +1 -1
  352. package/dist/tasking-eligibility.d.ts +21 -21
  353. package/dist/tasking-eligibility.d.ts.map +1 -1
  354. package/dist/tasking-eligibility.js +10 -10
  355. package/dist/tasking-lock.d.ts +10 -10
  356. package/dist/tasking-lock.d.ts.map +1 -1
  357. package/dist/tasking-lock.js +69 -49
  358. package/dist/tasking-lock.js.map +1 -1
  359. package/dist/tasking.d.ts +73 -39
  360. package/dist/tasking.d.ts.map +1 -1
  361. package/dist/tasking.js +309 -95
  362. package/dist/tasking.js.map +1 -1
  363. package/dist/triage-gate.d.ts +1 -1
  364. package/dist/triage-persist.d.ts +15 -11
  365. package/dist/triage-persist.d.ts.map +1 -1
  366. package/dist/triage-persist.js +48 -18
  367. package/dist/triage-persist.js.map +1 -1
  368. package/dist/vendor/incur/agents.d.ts +58 -0
  369. package/dist/vendor/incur/agents.d.ts.map +1 -0
  370. package/dist/vendor/incur/agents.js +343 -0
  371. package/dist/vendor/incur/agents.js.map +1 -0
  372. package/dist/verify-workflow-template.d.ts +1 -1
  373. package/dist/verify-workflow-template.js +3 -3
  374. package/dist/watch-session.d.ts +11 -3
  375. package/dist/watch-session.d.ts.map +1 -1
  376. package/dist/watch-session.js +94 -7
  377. package/dist/watch-session.js.map +1 -1
  378. package/dist/work-layout.d.ts +15 -9
  379. package/dist/work-layout.d.ts.map +1 -1
  380. package/dist/work-layout.js +14 -9
  381. package/dist/work-layout.js.map +1 -1
  382. package/dist/workspace.d.ts +2 -2
  383. package/package.json +2 -2
  384. package/src/advance-ci-template.ts +4 -4
  385. package/src/advance-classify.ts +5 -5
  386. package/src/advance-drivers.ts +26 -13
  387. package/src/advance-isolated.ts +3 -3
  388. package/src/advance-lifecycle-template.ts +98 -13
  389. package/src/advance-loop-driver.ts +3 -3
  390. package/src/advance-treeless-publish.ts +46 -1
  391. package/src/advance.ts +495 -115
  392. package/src/advancing-lock.ts +102 -7
  393. package/src/agent-launch.ts +37 -12
  394. package/src/agent-stop.ts +60 -2
  395. package/src/apply-decide.ts +38 -9
  396. package/src/apply-merge-action.ts +49 -11
  397. package/src/apply-persist.ts +236 -62
  398. package/src/apply-stuck-action.ts +260 -0
  399. package/src/brand.ts +14 -2
  400. package/src/buildable-body.ts +14 -14
  401. package/src/claim-cas.ts +4 -4
  402. package/src/cli-spinner.ts +1 -1
  403. package/src/cli.ts +472 -141
  404. package/src/close-job-template.ts +9 -9
  405. package/src/close-job.ts +26 -26
  406. package/src/complete.ts +121 -63
  407. package/src/concurrency.ts +1 -1
  408. package/src/config.ts +143 -49
  409. package/src/continue-branch.ts +23 -1
  410. package/src/cwd-section.ts +1 -1
  411. package/src/decision-engine.ts +57 -19
  412. package/src/do-autopick.ts +21 -10
  413. package/src/do-config.ts +7 -7
  414. package/src/do-remote-auto.ts +2 -2
  415. package/src/do.ts +558 -85
  416. package/src/drop-source.ts +2 -2
  417. package/src/env-config.ts +19 -11
  418. package/src/failure-cause.ts +30 -1
  419. package/src/format.ts +13 -33
  420. package/src/frontmatter.ts +55 -35
  421. package/src/gc.ts +172 -9
  422. package/src/github.ts +78 -0
  423. package/src/harness.ts +25 -0
  424. package/src/index.ts +10 -0
  425. package/src/install-ci-branch-protection.ts +283 -58
  426. package/src/install-ci-capabilities/advance-lifecycle.ts +1 -1
  427. package/src/install-ci-capabilities/close-job.ts +1 -1
  428. package/src/install-ci-capabilities/example-noop.ts +1 -1
  429. package/src/install-ci-capabilities/intake.ts +2 -2
  430. package/src/install-ci-capabilities/verify.ts +1 -1
  431. package/src/install-ci-core.ts +34 -7
  432. package/src/install-ci-github.ts +87 -1
  433. package/src/install-ci.ts +4 -4
  434. package/src/install-skills.ts +166 -0
  435. package/src/intake-event.ts +6 -6
  436. package/src/intake-marker.ts +3 -3
  437. package/src/intake-triage.ts +2 -2
  438. package/src/intake-trigger-template.ts +18 -18
  439. package/src/intake.ts +138 -103
  440. package/src/integration-core.ts +234 -100
  441. package/src/integrator.ts +22 -9
  442. package/src/isolation.ts +13 -4
  443. package/src/issue-provider.ts +4 -4
  444. package/src/item-lock.ts +505 -361
  445. package/src/item-path.ts +2 -2
  446. package/src/ledger-lint.ts +9 -9
  447. package/src/ledger-read.ts +81 -81
  448. package/src/ledger-write.ts +137 -152
  449. package/src/lifecycle-gather.ts +45 -22
  450. package/src/lifecycle-pools.ts +71 -13
  451. package/src/merge-question-surfacer.ts +32 -8
  452. package/src/migrate-stuck-locks.ts +451 -0
  453. package/src/mint-adr.ts +4 -4
  454. package/src/mirror-pool-scan.ts +5 -5
  455. package/src/needs-attention.ts +877 -104
  456. package/src/orphan-sidecar.ts +49 -8
  457. package/src/pi-harness.ts +82 -2
  458. package/src/placement.ts +8 -8
  459. package/src/prd-to-spec.ts +13 -5
  460. package/src/prompt.ts +20 -25
  461. package/src/readiness.ts +1 -1
  462. package/src/reap-branches.ts +38 -14
  463. package/src/recover-isolated.ts +18 -1
  464. package/src/repo-config.ts +66 -17
  465. package/src/repo-mirror.ts +23 -1
  466. package/src/review-gate.ts +12 -11
  467. package/src/review-verdict.ts +3 -3
  468. package/src/run.ts +69 -23
  469. package/src/scan.ts +36 -22
  470. package/src/select-order.ts +1 -1
  471. package/src/select-priority.ts +15 -15
  472. package/src/sidecar-apply.ts +1 -1
  473. package/src/sidecar.ts +141 -14
  474. package/src/slug-namespace.ts +10 -10
  475. package/src/spec-complete.ts +4 -5
  476. package/src/start.ts +57 -63
  477. package/src/status.ts +7 -7
  478. package/src/surface-gate.ts +12 -5
  479. package/src/surface-persist.ts +3 -3
  480. package/src/tasker-review-loop.ts +18 -17
  481. package/src/tasking-eligibility.ts +21 -21
  482. package/src/tasking-lock.ts +75 -60
  483. package/src/tasking.ts +381 -135
  484. package/src/triage-gate.ts +1 -1
  485. package/src/triage-persist.ts +71 -27
  486. package/src/vendor/incur/LICENSE +21 -0
  487. package/src/vendor/incur/README.md +19 -0
  488. package/src/vendor/incur/agents.ts +392 -0
  489. package/src/verify-workflow-template.ts +3 -3
  490. package/src/watch-session.ts +102 -7
  491. package/src/work-layout.ts +14 -9
  492. package/src/workspace.ts +2 -2
@@ -3,7 +3,7 @@ import {launchWithOptionalWatch} from './agent-launch.js';
3
3
  import {extractJsonObjectSpan} from './verdict-json.js';
4
4
 
5
5
  /**
6
- * The **TRIAGE auto-disposition GATE** (prd `advance-loop`, task
6
+ * The **TRIAGE auto-disposition GATE** (spec `advance-loop`, task
7
7
  * `advance-rung-triage`, US #17) — the CONSERVATIVE, `observationTriage: 'auto'`-
8
8
  * gated exception to the question-gated default. On `classify=triage-observation`
9
9
  * AND `observationTriage` resolved to `'auto'`, the engine asks this gate whether
@@ -10,9 +10,10 @@ import {
10
10
  import {resolveSidecarIdentity, sidecarPathFor} from './sidecar.js';
11
11
  import type {TriageAutoKind} from './triage-gate.js';
12
12
  import {renderTaskBody, renderSpecBody} from './buildable-body.js';
13
+ import {setFrontmatterMarker} from './frontmatter.js';
13
14
 
14
15
  /**
15
- * The engine-owned TRIAGE PERSIST (prd `advance-loop`, task `advance-rung-triage`,
16
+ * The engine-owned TRIAGE PERSIST (spec `advance-loop`, task `advance-rung-triage`,
16
17
  * US #16/17/24/30) — the half of the observation-triage rung the ENGINE owns (the
17
18
  * triage gate JUDGES, the engine ACTS). It is the SIBLING of `surface-persist.ts`
18
19
  * (the surface rung's persist) and `apply-persist.ts` (the apply rung's persist),
@@ -232,8 +233,8 @@ export interface PromoteObservationOptions {
232
233
  * triage-local {@link createItemThroughCas} writer (one local commit through the
233
234
  * CAS) — NOT intake's branch+integrate band — so the CAS-loser-backs-off
234
235
  * guarantee and the same-commit note deletion are uniform across the two routes.
235
- * MIGRATE step (prd `prd-to-spec-vocabulary-cutover-and-migration-command`): the
236
- * produced VALUE is `'spec'` (the verdict outcome renamed from `'prd'`).
236
+ * MIGRATE step (spec `prd-to-spec-vocabulary-cutover-and-migration-command`): the
237
+ * produced VALUE is `'spec'` (the verdict outcome renamed from ''prd'').
237
238
  */
238
239
  artifact?: 'task' | 'spec';
239
240
  /**
@@ -273,11 +274,20 @@ export interface PromoteObservationOptions {
273
274
  export interface PromoteObservationResult {
274
275
  /**
275
276
  * `promoted` (the new item landed via the CAS + the observation+sidecar were
276
- * deleted in the SAME commit), `lost` (the same-slug new-item race was lost —
277
- * the loser backs off, observation left INTACT), or `contended` (the CAS push
278
- * kept failing). Maps onto the claim-CAS exit codes.
277
+ * deleted in the SAME commit), `already-triaged` (the target task ALREADY exists
278
+ * on the arbiter AND was PROVABLY minted from THIS observation in a prior run a
279
+ * TERMINAL, benign idempotency fact, exit 0; the observation is left intact but a
280
+ * retry can never succeed, so it is NOT loud), `lost` (a genuine concurrent-create
281
+ * race for a same-path NEW item was lost — the loser backs off, observation left
282
+ * INTACT, retry helps), or `contended` (the CAS push kept failing). Maps onto the
283
+ * claim-CAS exit codes.
279
284
  */
280
- outcome: 'promoted' | 'lost' | 'contended' | 'usage-error';
285
+ outcome:
286
+ | 'promoted'
287
+ | 'already-triaged'
288
+ | 'lost'
289
+ | 'contended'
290
+ | 'usage-error';
281
291
  exitCode: 0 | 1 | 2 | 3;
282
292
  /** The new task's path (relative to repo root) on a WIN. */
283
293
  newItemPath?: string;
@@ -287,22 +297,22 @@ export interface PromoteObservationResult {
287
297
 
288
298
  /**
289
299
  * Promote an ANSWERED observation to a NEW, SELF-CONTAINED artifact (US #1/#3/#8
290
- * for the task route; US #4/#9 for the PRD route): CAS-create the new item keyed
300
+ * for the task route; US #4/#9 for the SPEC route): CAS-create the new item keyed
291
301
  * on the NEW item's identity (its target path), with the observation note + its
292
302
  * answered sidecar `git rm`-ed IN THE SAME atomic commit. Promote is ONE commit
293
303
  * (create + delete).
294
304
  *
295
305
  * The artifact TYPE (`options.artifact`) selects the target + body shape: `'task'`
296
- * (default) mints `work/tasks/ready/<slug>.md`; `'prd'` mints
297
- * `work/prds/proposed/<slug>.md` (PRD staging — a human later promotes it to
306
+ * (default) mints `work/tasks/ready/<slug>.md`; `'spec'` mints
307
+ * `work/specs/proposed/<slug>.md` (SPEC staging — a human later promotes it to
298
308
  * `ready/`). BOTH routes use the SAME triage-local {@link createItemThroughCas}
299
309
  * writer (NOT intake's `switchToWorkBranch`/`performIntegration` branch+integrate
300
310
  * band, which is intake's standalone front door): one create/integrate surface for
301
- * triage, the CAS-loser-backs-off guarantee uniform across task and PRD promotion.
311
+ * triage, the CAS-loser-backs-off guarantee uniform across task and SPEC promotion.
302
312
  *
303
313
  * The minted body is built FROM the observation (see {@link buildPromotedBody}):
304
314
  * its mechanism + fix prose is carried into the artifact's lead section (`## What
305
- * to build` for a task, `## Problem Statement` for a PRD), and its
315
+ * to build` for a task, `## Problem Statement` for a SPEC), and its
306
316
  * `## Open questions` scoping is transcribed into the new item's own
307
317
  * `## Open questions` block with `needsAnswers` set when questions remain (cleared
308
318
  * when none do) — so an agent can build from the artifact ALONE and no decision
@@ -340,11 +350,24 @@ export async function promoteObservation(
340
350
  `${newSlug}.md`,
341
351
  );
342
352
  const by = options.by || resolveBy(cwd, env);
343
- const content = ensureTaskDispatchable(
344
- artifact,
345
- newSlug,
346
- options.stubContent ??
347
- buildPromotedBody(artifact, newSlug, readItem(cwd, itemPath, env)),
353
+ // Stamp the observation→task PROVENANCE back-reference `promotedFrom: <item>` into
354
+ // the minted body (task `observation-triage-already-triaged-benign-skip`). It is
355
+ // the PROVABLE LINK the create-CAS lost-race disambiguator reads to tell case A
356
+ // (this observation ALREADY minted this task — already triaged, benign skip) from
357
+ // case B (a genuine concurrent-create race with an UNRELATED same-path item — loud
358
+ // exit 2). Distinct from `origin:` (how BORN: human/issue) and `reviewOf:` (the
359
+ // review-nits back-pointer); this is the triage-promote lineage. Matching on this
360
+ // explicit field — not the slug — is what keeps an unrelated same-slug task from
361
+ // false-positiving into a benign skip.
362
+ const content = setFrontmatterMarker(
363
+ ensureTaskDispatchable(
364
+ artifact,
365
+ newSlug,
366
+ options.stubContent ??
367
+ buildPromotedBody(artifact, newSlug, readItem(cwd, itemPath, env)),
368
+ ),
369
+ 'promotedFrom',
370
+ item,
348
371
  );
349
372
 
350
373
  // The note + its answered sidecar `git rm` IN THE SAME create commit (promote =
@@ -359,6 +382,10 @@ export async function promoteObservation(
359
382
  path: newItemPath,
360
383
  content,
361
384
  deletePaths: [itemPath, sidecarPath],
385
+ // The provenance disambiguator: on a LOST create-race, the CAS reads the
386
+ // existing file's `promotedFrom:` and, iff it equals THIS observation, reports
387
+ // the benign `already-exists-from-source` instead of the loud `lost`.
388
+ sourceItem: item,
362
389
  cwd,
363
390
  arbiter: options.arbiter,
364
391
  by,
@@ -369,6 +396,23 @@ export async function promoteObservation(
369
396
  ? {contention: options.contention}
370
397
  : {}),
371
398
  });
399
+ // TERMINAL 'already triaged' (case A): the task this observation would mint
400
+ // ALREADY exists on the arbiter AND was provably minted from THIS observation in
401
+ // a prior run. A benign idempotency fact (exit 0) — the human already decided when
402
+ // they minted it — NOT a retry. The observation is left intact (a later
403
+ // discharge-by-deletion or a human deletes it); this leg does not red CI.
404
+ if (created.outcome === 'already-exists-from-source') {
405
+ const message =
406
+ `promote ${item}: ${newItemPath} was already minted FROM this observation ` +
407
+ `in a prior run (${created.message}) — already triaged. Benign skip, no retry.`;
408
+ note(message);
409
+ return {
410
+ outcome: 'already-triaged',
411
+ exitCode: 0,
412
+ newItemPath,
413
+ message,
414
+ };
415
+ }
372
416
  if (created.exitCode !== 0) {
373
417
  const message =
374
418
  `promote ${item}: the new item ${newItemPath} ${created.outcome} the ` +
@@ -398,10 +442,10 @@ export async function promoteObservation(
398
442
  *
399
443
  * The artifact TYPE selects the frontmatter + lead heading: a `task` gets
400
444
  * `## What to build` + `blockedBy: []` + a `## Prompt` (the buildable-task shape);
401
- * a `prd` gets `## Problem Statement` (the PRD document shape, with no `blockedBy` —
402
- * a PRD is not a blockable task — and no `## Prompt`, since a PRD is not
445
+ * a `spec` gets `## Problem Statement` (the SPEC document shape, with no `blockedBy` —
446
+ * a SPEC is not a blockable task — and no `## Prompt`, since a SPEC is not
403
447
  * dispatched by `do`/`run`). BOTH carry the SAME transcribed mechanism prose +
404
- * open-question block, so a PRD minted into `proposed/` is just as self-contained
448
+ * open-question block, so a SPEC minted into `proposed/` is just as self-contained
405
449
  * as a task.
406
450
  *
407
451
  * The `## Prompt` (task only) is the STRUCTURAL dispatchability the validator
@@ -409,9 +453,9 @@ export async function promoteObservation(
409
453
  * dispatched build throws "has no '## Prompt' section". The body BELOW the
410
454
  * frontmatter (lead section + mechanism prose + optional `## Open questions` +
411
455
  * the task-only `## Prompt`) is rendered by the SHARED owner of the
412
- * buildable-task/PRD schema, {@link renderTaskBody} / {@link renderSpecBody}
456
+ * buildable-task/SPEC schema, {@link renderTaskBody} / {@link renderSpecBody}
413
457
  * (`buildable-body.ts`), so the producer and the consumer cannot drift apart
414
- * (prd `centralize-buildable-task-renderer-shared-by-intake-and-promotion`,
458
+ * (spec `centralize-buildable-task-renderer-shared-by-intake-and-promotion`,
415
459
  * US #3/#5/#6). This function owns only the FRONTMATTER writer; the section
416
460
  * skeleton lives in the one renderer. The empty-mechanism `## Prompt` seed is
417
461
  * passed EXPLICITLY (`Build the task '<slug>', described above.`) so promotion's
@@ -434,8 +478,8 @@ export async function promoteObservation(
434
478
  * fails with `has no '## Prompt' section` (the `extractPromptSection`/`resolveTask`
435
479
  * guard in `prompt.ts`). This is the robust backstop that closes that hole
436
480
  * regardless of agent compliance: for a TASK, if the body has no `## Prompt`
437
- * heading, append a seeded one (blockquoted, matching the renderer's shape). A PRD
438
- * is left UNTOUCHED — a PRD is a north-star doc, not dispatched by `do`/`run`, and carries no
481
+ * heading, append a seeded one (blockquoted, matching the renderer's shape). A SPEC
482
+ * is left UNTOUCHED — a SPEC is a north-star doc, not dispatched by `do`/`run`, and carries no
439
483
  * `## Prompt` by design.
440
484
  */
441
485
  function ensureTaskDispatchable(
@@ -472,7 +516,7 @@ function buildPromotedBody(
472
516
  `title: ${slug}`,
473
517
  `slug: ${slug}`,
474
518
  `needsAnswers: ${hasQuestions ? 'true' : 'false'}`,
475
- // A PRD is a north-star doc, not a blockable task — only the task shape carries
519
+ // A SPEC is a north-star doc, not a blockable task — only the task shape carries
476
520
  // `blockedBy`.
477
521
  ...(artifact === 'spec' ? [] : ['blockedBy: []']),
478
522
  '---',
@@ -488,8 +532,8 @@ function buildPromotedBody(
488
532
  // no leading blank. Do NOT move the separator into the renderer.
489
533
  const fenceToBody = frontmatter.join('\n') + '\n\n';
490
534
  // The body BELOW the frontmatter is rendered by the SHARED schema owner so the
491
- // section skeleton has one home, not two (prd
492
- // `centralize-buildable-task-renderer-shared-by-intake-and-promotion`). A PRD
535
+ // section skeleton has one home, not two (spec
536
+ // `centralize-buildable-task-renderer-shared-by-intake-and-promotion`). A SPEC
493
537
  // goes through `renderSpecBody` (no `## Prompt`); a task through
494
538
  // `renderTaskBody` (always a `## Prompt`).
495
539
  if (artifact === 'spec') {
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present weth, LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,19 @@
1
+ # Vendored: `incur/src/internal/agents.ts` (MIT)
2
+
3
+ `agents.ts` here is a **verbatim** copy of `src/internal/agents.ts` from
4
+ [wevm/incur](https://github.com/wevm/incur) (MIT). See `LICENSE` beside it for the
5
+ required copyright + permission notice, which is also duplicated as a header
6
+ comment at the top of `agents.ts` itself so the file stays attribution-complete
7
+ in isolation.
8
+
9
+ We VENDOR rather than depend (see
10
+ `docs/adr/skill-install-vendors-incur-agents-map.md`): the harness-destination
11
+ map + copy/symlink logic are the one hard, drift-prone piece we need, and the
12
+ file is dependency-free (only `node:fs`/`os`/`path`). Keep it BYTE-CLOSE to
13
+ upstream so a future incur update is a mechanical re-copy — put all wrapper
14
+ code outside this directory (`../../install-skills.ts`).
15
+
16
+ To refresh: re-fetch `src/internal/agents.ts` from the upstream tag you want,
17
+ overwrite `agents.ts`, keep the small ATTRIBUTION HEADER block at the top
18
+ (above the original `import` lines) intact, and re-copy `LICENSE` if it
19
+ changed upstream.
@@ -0,0 +1,392 @@
1
+ // ---------------------------------------------------------------------------
2
+ // VENDORED FROM: https://github.com/wevm/incur
3
+ // Source: src/internal/agents.ts
4
+ // License: MIT (see ./LICENSE beside this file)
5
+ // Copyright: (c) 2025-present weth, LLC
6
+ //
7
+ // This file is a VERBATIM copy of the upstream `src/internal/agents.ts` from
8
+ // wevm/incur, preserved byte-close so future upstream updates are a mechanical
9
+ // re-copy. Do NOT edit it in place — put all dorfl wrapper code OUTSIDE this
10
+ // directory (see `../../install-skills.ts`). Only the block ABOVE this line is
11
+ // dorfl-authored (attribution header). See `./README.md` for provenance and
12
+ // the `docs/adr/skill-install-vendors-incur-agents-map.md` ADR for why we
13
+ // vendor rather than depend.
14
+ //
15
+ // MIT permission notice (required by upstream license, kept in-file so the
16
+ // attribution survives isolation from the sibling LICENSE):
17
+ //
18
+ // Permission is hereby granted, free of charge, to any person obtaining a
19
+ // copy of this software and associated documentation files (the "Software"),
20
+ // to deal in the Software without restriction, including without limitation
21
+ // the rights to use, copy, modify, merge, publish, distribute, sublicense,
22
+ // and/or sell copies of the Software, and to permit persons to whom the
23
+ // Software is furnished to do so, subject to the following conditions:
24
+ //
25
+ // The above copyright notice and this permission notice shall be included
26
+ // in all copies or substantial portions of the Software.
27
+ //
28
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
29
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
31
+ // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
32
+ // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
33
+ // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
34
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
+ // ---------------------------------------------------------------------------
36
+
37
+ import * as fs from 'node:fs'
38
+ import * as os from 'node:os'
39
+ import * as path from 'node:path'
40
+
41
+ /** Agent configuration for skill installation. */
42
+ export type Agent = {
43
+ /** Display name. */
44
+ name: string
45
+ /** Absolute path to the global skills directory. */
46
+ globalSkillsDir: string
47
+ /** Project-relative skills directory path. */
48
+ projectSkillsDir: string
49
+ /** Whether this agent uses the canonical `.agents/skills` path. */
50
+ universal: boolean
51
+ /** Checks if the agent is installed on the system. */
52
+ detect(): boolean
53
+ }
54
+
55
+ const home = os.homedir()
56
+ const configHome = process.env.XDG_CONFIG_HOME || path.join(home, '.config')
57
+ const claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || path.join(home, '.claude')
58
+ const codexHome = process.env.CODEX_HOME?.trim() || path.join(home, '.codex')
59
+
60
+ /** All known agent definitions. */
61
+ export const all: Agent[] = [
62
+ // Universal agents (project skillsDir = .agents/skills)
63
+ {
64
+ name: 'Amp',
65
+ globalSkillsDir: path.join(configHome, 'agents', 'skills'),
66
+ projectSkillsDir: '.agents/skills',
67
+ universal: true,
68
+ detect: () => fs.existsSync(path.join(configHome, 'amp')),
69
+ },
70
+ {
71
+ name: 'Cline',
72
+ globalSkillsDir: path.join(home, '.agents', 'skills'),
73
+ projectSkillsDir: '.agents/skills',
74
+ universal: true,
75
+ detect: () => fs.existsSync(path.join(home, '.cline')),
76
+ },
77
+ {
78
+ name: 'Codex',
79
+ globalSkillsDir: path.join(codexHome, 'skills'),
80
+ projectSkillsDir: '.agents/skills',
81
+ universal: true,
82
+ detect: () => fs.existsSync(codexHome),
83
+ },
84
+ {
85
+ name: 'Cursor',
86
+ globalSkillsDir: path.join(home, '.cursor', 'skills'),
87
+ projectSkillsDir: '.agents/skills',
88
+ universal: true,
89
+ detect: () => fs.existsSync(path.join(home, '.cursor')),
90
+ },
91
+ {
92
+ name: 'Gemini CLI',
93
+ globalSkillsDir: path.join(home, '.gemini', 'skills'),
94
+ projectSkillsDir: '.agents/skills',
95
+ universal: true,
96
+ detect: () => fs.existsSync(path.join(home, '.gemini')),
97
+ },
98
+ {
99
+ name: 'GitHub Copilot',
100
+ globalSkillsDir: path.join(home, '.copilot', 'skills'),
101
+ projectSkillsDir: '.agents/skills',
102
+ universal: true,
103
+ detect: () => fs.existsSync(path.join(home, '.copilot')),
104
+ },
105
+ {
106
+ name: 'Kimi CLI',
107
+ globalSkillsDir: path.join(configHome, 'agents', 'skills'),
108
+ projectSkillsDir: '.agents/skills',
109
+ universal: true,
110
+ detect: () => fs.existsSync(path.join(home, '.kimi')),
111
+ },
112
+ {
113
+ name: 'OpenCode',
114
+ globalSkillsDir: path.join(configHome, 'opencode', 'skills'),
115
+ projectSkillsDir: '.agents/skills',
116
+ universal: true,
117
+ detect: () => fs.existsSync(path.join(configHome, 'opencode')),
118
+ },
119
+
120
+ // Non-universal agents (need symlink from their skills dir to canonical)
121
+ {
122
+ name: 'Claude Code',
123
+ globalSkillsDir: path.join(claudeHome, 'skills'),
124
+ projectSkillsDir: '.claude/skills',
125
+ universal: false,
126
+ detect: () => fs.existsSync(claudeHome),
127
+ },
128
+ {
129
+ name: 'Windsurf',
130
+ globalSkillsDir: path.join(home, '.codeium', 'windsurf', 'skills'),
131
+ projectSkillsDir: '.windsurf/skills',
132
+ universal: false,
133
+ detect: () => fs.existsSync(path.join(home, '.codeium', 'windsurf')),
134
+ },
135
+ {
136
+ name: 'Continue',
137
+ globalSkillsDir: path.join(home, '.continue', 'skills'),
138
+ projectSkillsDir: '.continue/skills',
139
+ universal: false,
140
+ detect: () => fs.existsSync(path.join(home, '.continue')),
141
+ },
142
+ {
143
+ name: 'Roo',
144
+ globalSkillsDir: path.join(home, '.roo', 'skills'),
145
+ projectSkillsDir: '.roo/skills',
146
+ universal: false,
147
+ detect: () => fs.existsSync(path.join(home, '.roo')),
148
+ },
149
+ {
150
+ name: 'Kilo',
151
+ globalSkillsDir: path.join(home, '.kilocode', 'skills'),
152
+ projectSkillsDir: '.kilocode/skills',
153
+ universal: false,
154
+ detect: () => fs.existsSync(path.join(home, '.kilocode')),
155
+ },
156
+ {
157
+ name: 'Goose',
158
+ globalSkillsDir: path.join(configHome, 'goose', 'skills'),
159
+ projectSkillsDir: '.goose/skills',
160
+ universal: false,
161
+ detect: () => fs.existsSync(path.join(configHome, 'goose')),
162
+ },
163
+ {
164
+ name: 'Augment',
165
+ globalSkillsDir: path.join(home, '.augment', 'skills'),
166
+ projectSkillsDir: '.augment/skills',
167
+ universal: false,
168
+ detect: () => fs.existsSync(path.join(home, '.augment')),
169
+ },
170
+ {
171
+ name: 'Trae',
172
+ globalSkillsDir: path.join(home, '.trae', 'skills'),
173
+ projectSkillsDir: '.trae/skills',
174
+ universal: false,
175
+ detect: () => fs.existsSync(path.join(home, '.trae')),
176
+ },
177
+ {
178
+ name: 'Junie',
179
+ globalSkillsDir: path.join(home, '.junie', 'skills'),
180
+ projectSkillsDir: '.junie/skills',
181
+ universal: false,
182
+ detect: () => fs.existsSync(path.join(home, '.junie')),
183
+ },
184
+ {
185
+ name: 'Crush',
186
+ globalSkillsDir: path.join(configHome, 'crush', 'skills'),
187
+ projectSkillsDir: '.crush/skills',
188
+ universal: false,
189
+ detect: () => fs.existsSync(path.join(configHome, 'crush')),
190
+ },
191
+ {
192
+ name: 'Kiro CLI',
193
+ globalSkillsDir: path.join(home, '.kiro', 'skills'),
194
+ projectSkillsDir: '.kiro/skills',
195
+ universal: false,
196
+ detect: () => fs.existsSync(path.join(home, '.kiro')),
197
+ },
198
+ {
199
+ name: 'Qwen Code',
200
+ globalSkillsDir: path.join(home, '.qwen', 'skills'),
201
+ projectSkillsDir: '.qwen/skills',
202
+ universal: false,
203
+ detect: () => fs.existsSync(path.join(home, '.qwen')),
204
+ },
205
+ {
206
+ name: 'OpenHands',
207
+ globalSkillsDir: path.join(home, '.openhands', 'skills'),
208
+ projectSkillsDir: '.openhands/skills',
209
+ universal: false,
210
+ detect: () => fs.existsSync(path.join(home, '.openhands')),
211
+ },
212
+ ]
213
+
214
+ /** Detects which agents are installed on the system. */
215
+ export function detect(): Agent[] {
216
+ return all.filter((a) => a.detect())
217
+ }
218
+
219
+ /**
220
+ * Installs skill directories to the canonical location and creates symlinks for
221
+ * detected non-universal agents.
222
+ *
223
+ * @param sourceDir - Directory containing skill subdirectories (each with a `SKILL.md`).
224
+ * @param options - Installation options.
225
+ * @returns Installed canonical paths.
226
+ */
227
+ export function install(sourceDir: string, options: install.Options = {}): install.Result {
228
+ const isGlobal = options.global !== false
229
+ const cwd = options.cwd || process.cwd()
230
+ const base = isGlobal ? home : cwd
231
+ const canonicalBase = path.join(base, '.agents', 'skills')
232
+ const detected = options.agents ?? detect()
233
+
234
+ const paths: string[] = []
235
+ const agents: install.AgentInstall[] = []
236
+
237
+ for (const skill of discoverSkills(sourceDir)) {
238
+ const canonicalDir = path.join(canonicalBase, skill.name)
239
+
240
+ // Copy to canonical location
241
+ rmForce(canonicalDir)
242
+ fs.mkdirSync(canonicalDir, { recursive: true })
243
+ if (skill.root)
244
+ fs.copyFileSync(path.join(skill.dir, 'SKILL.md'), path.join(canonicalDir, 'SKILL.md'))
245
+ else fs.cpSync(skill.dir, canonicalDir, { recursive: true })
246
+ paths.push(canonicalDir)
247
+
248
+ // Create symlinks for non-universal agents
249
+ for (const agent of detected) {
250
+ if (agent.universal) continue
251
+ const agentSkillsDir = isGlobal
252
+ ? agent.globalSkillsDir
253
+ : path.join(cwd, agent.projectSkillsDir)
254
+ const agentDir = path.join(agentSkillsDir, skill.name)
255
+
256
+ // Skip if agent dir resolves to canonical (no symlink needed)
257
+ if (agentDir === canonicalDir) continue
258
+
259
+ try {
260
+ rmForce(agentDir)
261
+ fs.mkdirSync(path.dirname(agentDir), { recursive: true })
262
+ // Resolve through any existing symlinks in parent directories
263
+ const realLinkDir = resolveParent(path.dirname(agentDir))
264
+ const realTarget = resolveParent(canonicalDir)
265
+ const rel = path.relative(realLinkDir, realTarget)
266
+ fs.symlinkSync(rel, agentDir)
267
+ agents.push({ agent: agent.name, path: agentDir, mode: 'symlink' })
268
+ } catch {
269
+ // Fallback to copy if symlink fails (e.g. Windows without permissions)
270
+ try {
271
+ fs.cpSync(canonicalDir, agentDir, { recursive: true })
272
+ agents.push({ agent: agent.name, path: agentDir, mode: 'copy' })
273
+ } catch {}
274
+ }
275
+ }
276
+ }
277
+
278
+ return { paths, agents }
279
+ }
280
+
281
+ export declare namespace install {
282
+ type Options = {
283
+ /** Override detected agents. */
284
+ agents?: Agent[] | undefined
285
+ /** Working directory for project-local installs. */
286
+ cwd?: string | undefined
287
+ /** Install globally. Defaults to `true`. */
288
+ global?: boolean | undefined
289
+ }
290
+ type Result = {
291
+ /** Canonical install paths. */
292
+ paths: string[]
293
+ /** Per-agent install details (non-universal agents only). */
294
+ agents: AgentInstall[]
295
+ }
296
+ type AgentInstall = {
297
+ /** Agent display name. */
298
+ agent: string
299
+ /** Installed path. */
300
+ path: string
301
+ /** Whether it was symlinked or copied. */
302
+ mode: 'symlink' | 'copy'
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Removes a skill by name from the canonical location and all detected agent directories.
308
+ */
309
+ export function remove(
310
+ skillName: string,
311
+ options: { global?: boolean | undefined; cwd?: string | undefined } = {},
312
+ ) {
313
+ const isGlobal = options.global !== false
314
+ const cwd = options.cwd || process.cwd()
315
+ const base = isGlobal ? home : cwd
316
+ const canonicalDir = path.join(base, '.agents', 'skills', skillName)
317
+ rmForce(canonicalDir)
318
+
319
+ for (const agent of detect()) {
320
+ if (agent.universal) continue
321
+ const agentSkillsDir = isGlobal ? agent.globalSkillsDir : path.join(cwd, agent.projectSkillsDir)
322
+ const agentDir = path.join(agentSkillsDir, skillName)
323
+ rmForce(agentDir)
324
+ }
325
+ }
326
+
327
+ /** Recursively discovers skill directories (those containing a `SKILL.md`). */
328
+ function discoverSkills(rootDir: string): { name: string; dir: string; root?: boolean }[] {
329
+ const results: { name: string; dir: string; root?: boolean }[] = []
330
+
331
+ function visit(dir: string) {
332
+ let entries: fs.Dirent[]
333
+ try {
334
+ entries = fs.readdirSync(dir, { withFileTypes: true })
335
+ } catch {
336
+ return
337
+ }
338
+ for (const entry of entries) {
339
+ if (!entry.isDirectory()) continue
340
+ const subDir = path.join(dir, entry.name)
341
+ const skillPath = path.join(subDir, 'SKILL.md')
342
+ if (fs.existsSync(skillPath)) {
343
+ const content = fs.readFileSync(skillPath, 'utf8')
344
+ const nameMatch = content.match(/^name:\s*(.+)$/m)
345
+ results.push({ name: sanitizeName(nameMatch?.[1] ?? entry.name), dir: subDir })
346
+ }
347
+ visit(subDir)
348
+ }
349
+ }
350
+
351
+ visit(rootDir)
352
+
353
+ // Root-level SKILL.md (e.g. depth=0)
354
+ const rootSkill = path.join(rootDir, 'SKILL.md')
355
+ if (fs.existsSync(rootSkill)) {
356
+ const content = fs.readFileSync(rootSkill, 'utf8')
357
+ const nameMatch = content.match(/^name:\s*(.+)$/m)
358
+ const name = sanitizeName(nameMatch?.[1] ?? 'skill')
359
+ if (!results.some((r) => r.name === name)) results.push({ name, dir: rootDir, root: true })
360
+ }
361
+
362
+ return results
363
+ }
364
+
365
+ /** Sanitizes a skill name for use as a directory name. */
366
+ function sanitizeName(name: string): string {
367
+ return name.trim().replace(/[/\\]/g, '-').replace(/\.\./g, '').slice(0, 255)
368
+ }
369
+
370
+ /** Removes a file, directory, or symlink (including broken symlinks). */
371
+ function rmForce(target: string) {
372
+ try {
373
+ const stat = fs.lstatSync(target)
374
+ if (stat.isSymbolicLink()) fs.unlinkSync(target)
375
+ else fs.rmSync(target, { recursive: true, force: true })
376
+ } catch {}
377
+ }
378
+
379
+ /** Resolves parent directories through symlinks. */
380
+ function resolveParent(dir: string): string {
381
+ try {
382
+ return fs.realpathSync(dir)
383
+ } catch {
384
+ const parent = path.dirname(dir)
385
+ if (parent === dir) return dir
386
+ try {
387
+ return path.join(fs.realpathSync(parent), path.relative(parent, dir))
388
+ } catch {
389
+ return dir
390
+ }
391
+ }
392
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The `install-ci` VERIFY-WORKFLOW capability (prd
2
+ * The `install-ci` VERIFY-WORKFLOW capability (spec
3
3
  * `land-time-reverify-and-parallel-merge-ceiling`, task
4
4
  * `install-ci-tier1-branch-protection`; Story 11 — the Tier-1 GitHub ceiling).
5
5
  * Emits a small `verify.yml` workflow whose ONLY job is `verify` and runs on
@@ -49,7 +49,7 @@ export const VERIFY_WORKFLOW_PATH = 'workflows/verify.yml';
49
49
  */
50
50
  export function generateVerifyWorkflow(_config: ResolvedCIConfig): string {
51
51
  return `\
52
- # dorfl — the VERIFY workflow (Tier-1 GitHub ceiling; prd
52
+ # dorfl — the VERIFY workflow (Tier-1 GitHub ceiling; spec
53
53
  # land-time-reverify-and-parallel-merge-ceiling, task
54
54
  # install-ci-tier1-branch-protection). EMITTED by \`dorfl install-ci\`; the
55
55
  # human commits it. DO NOT hand-edit a copy — re-run install-ci to upgrade.
@@ -100,7 +100,7 @@ jobs:
100
100
  ${VERIFY_CHECK_CONTEXT}:
101
101
  runs-on: ubuntu-latest
102
102
  steps:
103
- - uses: actions/checkout@v4
103
+ - uses: actions/checkout@v5
104
104
  with:
105
105
  fetch-depth: 0
106
106
  - uses: ./.github/actions/dorfl-setup