panopticon-cli 0.6.5 → 0.6.6
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.
- package/README.md +2 -2
- package/dist/{agents-DfYify9s.js → agents-CfFDs52G.js} +14 -14
- package/dist/{agents-DfYify9s.js.map → agents-CfFDs52G.js.map} +1 -1
- package/dist/{agents-BKsVoIc9.js → agents-D_2oRFVf.js} +1 -1
- package/dist/{archive-planning-BJrZ3tmN.js → archive-planning-D97ziGec.js} +3 -3
- package/dist/{archive-planning-BJrZ3tmN.js.map → archive-planning-D97ziGec.js.map} +1 -1
- package/dist/{archive-planning-C3m3hfa5.js → archive-planning-DK90wn9Q.js} +1 -1
- package/dist/{browser-Cvdznzc0.js → browser-CX7jXfXX.js} +1 -1
- package/dist/{browser-Cvdznzc0.js.map → browser-CX7jXfXX.js.map} +1 -1
- package/dist/{clean-planning-DvhZAUv4.js → clean-planning-D_lz4aQq.js} +2 -2
- package/dist/{clean-planning-DvhZAUv4.js.map → clean-planning-D_lz4aQq.js.map} +1 -1
- package/dist/clean-planning-x1S-JdmO.js +2 -0
- package/dist/cli/index.js +291 -760
- package/dist/cli/index.js.map +1 -1
- package/dist/{close-issue-Dr7yZmrr.js → close-issue-CaFE0stN.js} +11 -7
- package/dist/close-issue-CaFE0stN.js.map +1 -0
- package/dist/close-issue-CjcfZI9s.js +2 -0
- package/dist/compact-beads-B0_qE1w3.js +2 -0
- package/dist/{compact-beads-BCOtIIRl.js → compact-beads-CjFkteSU.js} +2 -2
- package/dist/{compact-beads-BCOtIIRl.js.map → compact-beads-CjFkteSU.js.map} +1 -1
- package/dist/{config-CRzMQRgA.js → config-BQNKsi9G.js} +2 -2
- package/dist/{config-CRzMQRgA.js.map → config-BQNKsi9G.js.map} +1 -1
- package/dist/{config-BYgUzQ21.js → config-agyKgF5C.js} +1 -1
- package/dist/{config-yaml-BgOACZAB.js → config-yaml-DGbLSMCa.js} +1 -1
- package/dist/{config-yaml-BgOACZAB.js.map → config-yaml-DGbLSMCa.js.map} +1 -1
- package/dist/{config-yaml-fdyvyL0S.js → config-yaml-Dqt4FWQH.js} +1 -1
- package/dist/dashboard/{acceptance-criteria-e5iiHlRx.js → acceptance-criteria-Dk9hhiYj.js} +1 -1
- package/dist/dashboard/{acceptance-criteria-e5iiHlRx.js.map → acceptance-criteria-Dk9hhiYj.js.map} +1 -1
- package/dist/dashboard/{agent-enrichment-C67LJBgD.js → agent-enrichment-DdO7ZqjI.js} +11 -7
- package/dist/dashboard/agent-enrichment-DdO7ZqjI.js.map +1 -0
- package/dist/dashboard/{agent-enrichment-Cq0P1cNZ.js → agent-enrichment-dLeGE1fX.js} +1 -1
- package/dist/dashboard/{agents-YyO6t5Xa.js → agents-DCpQQ_W5.js} +14 -14
- package/dist/dashboard/{agents-YyO6t5Xa.js.map → agents-DCpQQ_W5.js.map} +1 -1
- package/dist/dashboard/{agents-BVBVCyat.js → agents-Dgh2TjSp.js} +1 -1
- package/dist/dashboard/{archive-planning-h-hAjk0P.js → archive-planning-BmW9UDTr.js} +3 -3
- package/dist/dashboard/{archive-planning-h-hAjk0P.js.map → archive-planning-BmW9UDTr.js.map} +1 -1
- package/dist/dashboard/{archive-planning-CScs1MOC.js → archive-planning-C3Ebf9yC.js} +1 -1
- package/dist/dashboard/{beads-qNB0yAHV.js → beads-Bv-AdX7G.js} +3 -3
- package/dist/dashboard/{beads-qNB0yAHV.js.map → beads-Bv-AdX7G.js.map} +1 -1
- package/dist/dashboard/{beads-D_FRedEJ.js → beads-By6-X07V.js} +1 -1
- package/dist/dashboard/clean-planning-D60L8rPY.js +2 -0
- package/dist/dashboard/{clean-planning-qafw99vY.js → clean-planning-VEJu5suh.js} +2 -2
- package/dist/dashboard/{clean-planning-qafw99vY.js.map → clean-planning-VEJu5suh.js.map} +1 -1
- package/dist/dashboard/close-issue-C2KeSKKJ.js +2 -0
- package/dist/dashboard/{close-issue-DfIggeZD.js → close-issue-DtKdsSTm.js} +11 -7
- package/dist/dashboard/close-issue-DtKdsSTm.js.map +1 -0
- package/dist/dashboard/compact-beads-C7BN5N11.js +2 -0
- package/dist/dashboard/{compact-beads-Dt0qTqsC.js → compact-beads-D8Vt3qyv.js} +2 -2
- package/dist/dashboard/{compact-beads-Dt0qTqsC.js.map → compact-beads-D8Vt3qyv.js.map} +1 -1
- package/dist/dashboard/{config-CUREjHP7.js → config-CDkGjnwy.js} +2 -2
- package/dist/dashboard/{config-CUREjHP7.js.map → config-CDkGjnwy.js.map} +1 -1
- package/dist/dashboard/{config-BeI3uy-8.js → config-CTXkBATQ.js} +1 -1
- package/dist/dashboard/{database-CozA13Wy.js → database-DhqASALP.js} +1 -1
- package/dist/dashboard/{database-C0y0hXBx.js → database-cxmQryoh.js} +2 -2
- package/dist/dashboard/{database-C0y0hXBx.js.map → database-cxmQryoh.js.map} +1 -1
- package/dist/dashboard/{dist-src-oG2iHzgI.js → dist-src-DTm11oQr.js} +1 -1
- package/dist/dashboard/{dist-src-oG2iHzgI.js.map → dist-src-DTm11oQr.js.map} +1 -1
- package/dist/dashboard/{event-store-D7kLBd07.js → event-store-VWWUmOfn.js} +1 -1
- package/dist/dashboard/{event-store-O9q0Gweh.js → event-store-vSmAA3Zp.js} +9 -4
- package/dist/dashboard/event-store-vSmAA3Zp.js.map +1 -0
- package/dist/dashboard/{factory-BnLdiQW-.js → factory-C8nhLGHB.js} +3 -3
- package/dist/dashboard/{factory-BnLdiQW-.js.map → factory-C8nhLGHB.js.map} +1 -1
- package/dist/dashboard/{feedback-writer-DyovUANg.js → feedback-writer-CudSe1WK.js} +2 -2
- package/dist/dashboard/{feedback-writer-DyovUANg.js.map → feedback-writer-CudSe1WK.js.map} +1 -1
- package/dist/dashboard/{feedback-writer-gSUv_W0h.js → feedback-writer-Wgv1cd1r.js} +1 -1
- package/dist/dashboard/{git-utils-BJRioREj.js → git-utils-C1m4SwAe.js} +1 -1
- package/dist/dashboard/{git-utils-BJRioREj.js.map → git-utils-C1m4SwAe.js.map} +1 -1
- package/dist/dashboard/{git-utils-BtCRddq3.js → git-utils-DQI8EYoj.js} +1 -1
- package/dist/dashboard/{github-app-XO-LBUGk.js → github-app-DClWjjHr.js} +1 -1
- package/dist/dashboard/{github-app-XO-LBUGk.js.map → github-app-DClWjjHr.js.map} +1 -1
- package/dist/dashboard/{health-events-db-584nYgJB.js → health-events-db-BMXQfInV.js} +1 -1
- package/dist/dashboard/{health-events-db-B3ChzN65.js → health-events-db-Do4NrOhC.js} +2 -2
- package/dist/dashboard/{health-events-db-B3ChzN65.js.map → health-events-db-Do4NrOhC.js.map} +1 -1
- package/dist/dashboard/{hooks-CKhs3N68.js → hooks-CB4T47NC.js} +1 -1
- package/dist/dashboard/{hooks-CErbP8Oq.js → hooks-CjqXOlNb.js} +2 -2
- package/dist/dashboard/{hooks-CErbP8Oq.js.map → hooks-CjqXOlNb.js.map} +1 -1
- package/dist/dashboard/hume-CA2pftu_.js +3 -0
- package/dist/dashboard/{hume-CX_U3Qha.js → hume-JsAlMOJC.js} +2 -2
- package/dist/dashboard/{hume-CX_U3Qha.js.map → hume-JsAlMOJC.js.map} +1 -1
- package/dist/dashboard/{inspect-agent-B57kGDUV.js → inspect-agent-7eour7EA.js} +3 -3
- package/dist/dashboard/{inspect-agent-B57kGDUV.js.map → inspect-agent-7eour7EA.js.map} +1 -1
- package/dist/dashboard/{io-yGovuG4U.js → io-CWlFW78i.js} +1 -1
- package/dist/dashboard/{io-AJg-mzFi.js → io-DKS6359z.js} +1 -1
- package/dist/dashboard/{io-AJg-mzFi.js.map → io-DKS6359z.js.map} +1 -1
- package/dist/dashboard/issue-id-vwYJdsf8.js +62 -0
- package/dist/dashboard/issue-id-vwYJdsf8.js.map +1 -0
- package/dist/dashboard/{issue-service-singleton-DQK42EqH.js → issue-service-singleton-Co__-6kL.js} +1 -1
- package/dist/dashboard/{issue-service-singleton-sb2HkB9f.js → issue-service-singleton-Wv4xBm3y.js} +7 -7
- package/dist/dashboard/{issue-service-singleton-sb2HkB9f.js.map → issue-service-singleton-Wv4xBm3y.js.map} +1 -1
- package/dist/dashboard/{label-cleanup-CZEsbtq9.js → label-cleanup-nVKTmIIW.js} +7 -4
- package/dist/dashboard/label-cleanup-nVKTmIIW.js.map +1 -0
- package/dist/dashboard/lifecycle-BcUmtkR4.js +7 -0
- package/dist/dashboard/{merge-agent-GLtMEsTu.js → merge-agent-CGN3TT0a.js} +1 -1
- package/dist/dashboard/{merge-agent-twroFuAh.js → merge-agent-yudQOPZc.js} +148 -46
- package/dist/dashboard/merge-agent-yudQOPZc.js.map +1 -0
- package/dist/dashboard/{paths-COdEvoXR.js → paths-BDyJ7BiV.js} +19 -2
- package/dist/dashboard/{paths-COdEvoXR.js.map → paths-BDyJ7BiV.js.map} +1 -1
- package/dist/dashboard/{pipeline-notifier-DM5AHG5Q.js → pipeline-notifier-CCSN-jar.js} +1 -1
- package/dist/dashboard/{pipeline-notifier-DM5AHG5Q.js.map → pipeline-notifier-CCSN-jar.js.map} +1 -1
- package/dist/dashboard/{plan-utils-BkCIhn3B.js → plan-utils-Bkcsqr_s.js} +3 -3
- package/dist/dashboard/{plan-utils-BkCIhn3B.js.map → plan-utils-Bkcsqr_s.js.map} +1 -1
- package/dist/dashboard/{prd-draft-D09Afalc.js → prd-draft-BD8oMkZ1.js} +2 -2
- package/dist/dashboard/{prd-draft-D09Afalc.js.map → prd-draft-BD8oMkZ1.js.map} +1 -1
- package/dist/dashboard/{projection-cache-DQ9zegkK.js → projection-cache-C0EL8s8h.js} +1 -1
- package/dist/dashboard/{projection-cache-DQ9zegkK.js.map → projection-cache-C0EL8s8h.js.map} +1 -1
- package/dist/dashboard/{projects-DyT3vSy-.js → projects-C5ozxjwP.js} +1 -1
- package/dist/dashboard/{projects-Cq3TWdPS.js → projects-CFVl4oHn.js} +25 -13
- package/dist/dashboard/projects-CFVl4oHn.js.map +1 -0
- package/dist/dashboard/{providers-Ck2sQd_F.js → providers-B5Y4H2Mg.js} +4 -4
- package/dist/dashboard/providers-B5Y4H2Mg.js.map +1 -0
- package/dist/dashboard/{providers-DVQnDekG.js → providers-csVZVPkE.js} +1 -1
- package/dist/dashboard/public/assets/{dist-CCJbQrSB.js → dist-BaQPC-c6.js} +1 -1
- package/dist/dashboard/public/assets/index-ByLmYGhW.js +212 -0
- package/dist/dashboard/public/assets/index-OEEbThNN.css +1 -0
- package/dist/dashboard/public/index.html +2 -2
- package/dist/dashboard/rally-6McpKKRa.js +3 -0
- package/dist/dashboard/{rally-Cwuae-4C.js → rally-YjFRxIiC.js} +2 -2
- package/dist/dashboard/{rally-Cwuae-4C.js.map → rally-YjFRxIiC.js.map} +1 -1
- package/dist/dashboard/{rally-api-DSUxm7EO.js → rally-api-C0WqCSkT.js} +1 -1
- package/dist/dashboard/{rally-api-DSUxm7EO.js.map → rally-api-C0WqCSkT.js.map} +1 -1
- package/dist/dashboard/{rally-api-CEH5KZi4.js → rally-api-DNttdCW4.js} +1 -1
- package/dist/dashboard/{remote-BHTTMpJJ.js → remote-Cigqjj3f.js} +2 -2
- package/dist/dashboard/{remote-BXo_iIku.js → remote-ObpNZ7hF.js} +2 -2
- package/dist/dashboard/{remote-BXo_iIku.js.map → remote-ObpNZ7hF.js.map} +1 -1
- package/dist/dashboard/{remote-agents-CTKVhFFY.js → remote-agents-Bf3GuM7t.js} +1 -1
- package/dist/dashboard/{remote-agents-C0_0LLNd.js → remote-agents-DFyjT1Le.js} +1 -1
- package/dist/dashboard/{remote-agents-C0_0LLNd.js.map → remote-agents-DFyjT1Le.js.map} +1 -1
- package/dist/dashboard/{review-status-CK3eBGyb.js → review-status-BtXqWBhS.js} +1 -1
- package/dist/dashboard/{review-status-CV55Tl-n.js → review-status-Bymwzh2i.js} +44 -4
- package/dist/dashboard/{review-status-CV55Tl-n.js.map → review-status-Bymwzh2i.js.map} +1 -1
- package/dist/dashboard/server.js +559 -253
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/{settings-CuHV-wcv.js → settings-BHlDG7TK.js} +2 -2
- package/dist/dashboard/settings-BHlDG7TK.js.map +1 -0
- package/dist/dashboard/settings-XWvDcj-D.js +2 -0
- package/dist/dashboard/{shadow-engineering-BUeZunaE.js → shadow-engineering-lIn1W_95.js} +1 -1
- package/dist/dashboard/{shadow-engineering-BUeZunaE.js.map → shadow-engineering-lIn1W_95.js.map} +1 -1
- package/dist/dashboard/{shadow-state-DHQ-kASN.js → shadow-state-BIexcxkv.js} +1 -1
- package/dist/dashboard/{shadow-state-DHQ-kASN.js.map → shadow-state-BIexcxkv.js.map} +1 -1
- package/dist/dashboard/{spawn-planning-session-8FFAqLdK.js → spawn-planning-session-33Jf-d5T.js} +6 -6
- package/dist/dashboard/{spawn-planning-session-8FFAqLdK.js.map → spawn-planning-session-33Jf-d5T.js.map} +1 -1
- package/dist/dashboard/{spawn-planning-session-U0Lqpjen.js → spawn-planning-session-D5hrVdWM.js} +1 -1
- package/dist/dashboard/{specialist-context-ColzlmGE.js → specialist-context-DGukHSn8.js} +6 -6
- package/dist/dashboard/{specialist-context-ColzlmGE.js.map → specialist-context-DGukHSn8.js.map} +1 -1
- package/dist/dashboard/{specialist-logs-BhmDpFIq.js → specialist-logs-CIw4qfTy.js} +1 -1
- package/dist/dashboard/{specialists-C6s3U6tX.js → specialists-B_zrayaP.js} +37 -36
- package/dist/dashboard/specialists-B_zrayaP.js.map +1 -0
- package/dist/dashboard/{specialists-Cny632-T.js → specialists-Cp-PgspS.js} +1 -1
- package/dist/dashboard/{test-agent-queue-tqI4VDsu.js → test-agent-queue-ypF_ecHo.js} +4 -4
- package/dist/dashboard/{test-agent-queue-tqI4VDsu.js.map → test-agent-queue-ypF_ecHo.js.map} +1 -1
- package/dist/dashboard/{tldr-daemon-BNFyS7W_.js → tldr-daemon-B_oLRD8z.js} +2 -2
- package/dist/dashboard/{tldr-daemon-BNFyS7W_.js.map → tldr-daemon-B_oLRD8z.js.map} +1 -1
- package/dist/dashboard/{tldr-daemon-A6JqC59u.js → tldr-daemon-Cfs0bXTi.js} +1 -1
- package/dist/dashboard/{tmux-DYGAVJfb.js → tmux-BzxdKItf.js} +1 -1
- package/dist/dashboard/{tmux-IlN1Slv-.js → tmux-LwG0tHhU.js} +2 -2
- package/dist/dashboard/{tmux-IlN1Slv-.js.map → tmux-LwG0tHhU.js.map} +1 -1
- package/dist/dashboard/{tracker-config-BzNLnmcE.js → tracker-config-BP59uH4V.js} +1 -1
- package/dist/dashboard/{tracker-config-CNM_5rEf.js → tracker-config-e7ph1QqT.js} +2 -2
- package/dist/dashboard/{tracker-config-CNM_5rEf.js.map → tracker-config-e7ph1QqT.js.map} +1 -1
- package/dist/dashboard/{tunnel-D2BkwU7k.js → tunnel-0RzzuXPf.js} +1 -1
- package/dist/dashboard/{tunnel-Dub2hiAA.js → tunnel-DldbBPWL.js} +2 -2
- package/dist/dashboard/{tunnel-Dub2hiAA.js.map → tunnel-DldbBPWL.js.map} +1 -1
- package/dist/dashboard/{types-CWA-o4UN.js → types-RKZjGE5N.js} +1 -1
- package/dist/dashboard/{types-CWA-o4UN.js.map → types-RKZjGE5N.js.map} +1 -1
- package/dist/dashboard/{vtt-parser-BAXygRf0.js → vtt-parser-99vFekRQ.js} +1 -1
- package/dist/dashboard/{vtt-parser-BAXygRf0.js.map → vtt-parser-99vFekRQ.js.map} +1 -1
- package/dist/dashboard/{work-agent-prompt-JYq_OugP.js → work-agent-prompt-fCg67nyo.js} +65 -10
- package/dist/dashboard/{work-agent-prompt-JYq_OugP.js.map → work-agent-prompt-fCg67nyo.js.map} +1 -1
- package/dist/dashboard/{work-type-router-Cxp8_ur2.js → work-type-router-CWVW2Wk_.js} +1 -1
- package/dist/dashboard/{work-type-router-Cxp8_ur2.js.map → work-type-router-CWVW2Wk_.js.map} +1 -1
- package/dist/dashboard/{work-type-router-Com2amST.js → work-type-router-Di5gCQwh.js} +1 -1
- package/dist/dashboard/{workflows-N1UTipYl.js → workflows-BSMipN07.js} +35 -17
- package/dist/dashboard/workflows-BSMipN07.js.map +1 -0
- package/dist/dashboard/workflows-DaYWQIS2.js +2 -0
- package/dist/dashboard/{workspace-config-cmp5_ipD.js → workspace-config-DVDR-Ukh.js} +1 -1
- package/dist/dashboard/workspace-config-DVDR-Ukh.js.map +1 -0
- package/dist/dashboard/{workspace-manager-CjpWPgzL.js → workspace-manager-BYfzs_t2.js} +1 -1
- package/dist/dashboard/{workspace-manager-D_y9ZmW_.js → workspace-manager-C7OfT62A.js} +44 -24
- package/dist/dashboard/workspace-manager-C7OfT62A.js.map +1 -0
- package/dist/{dns-BKzHm-2q.js → dns-D_aKQJjb.js} +1 -1
- package/dist/{dns-DZwOWvVO.js → dns-Yxq4NNS7.js} +1 -1
- package/dist/{dns-DZwOWvVO.js.map → dns-Yxq4NNS7.js.map} +1 -1
- package/dist/{factory-DFu3IT4r.js → factory-BRBGw6OB.js} +1 -1
- package/dist/{factory-DfzczxN1.js → factory-DzsOiZVc.js} +3 -3
- package/dist/{factory-DfzczxN1.js.map → factory-DzsOiZVc.js.map} +1 -1
- package/dist/{feedback-writer-CwdnOkPO.js → feedback-writer-ygXN5F9N.js} +2 -2
- package/dist/{feedback-writer-CwdnOkPO.js.map → feedback-writer-ygXN5F9N.js.map} +1 -1
- package/dist/{github-app-CHKwxOeQ.js → github-app-DykduJ0X.js} +1 -1
- package/dist/{github-app-CHKwxOeQ.js.map → github-app-DykduJ0X.js.map} +1 -1
- package/dist/hume-9nv1VmMV.js +3 -0
- package/dist/{hume-DnV-tDsh.js → hume-DoCbph2h.js} +2 -2
- package/dist/{hume-DnV-tDsh.js.map → hume-DoCbph2h.js.map} +1 -1
- package/dist/index.d.ts +17 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -7
- package/dist/issue-id-CAcekoIw.js +62 -0
- package/dist/issue-id-CAcekoIw.js.map +1 -0
- package/dist/{label-cleanup-31ElPqqv.js → label-cleanup-C8R9Rspn.js} +7 -4
- package/dist/label-cleanup-C8R9Rspn.js.map +1 -0
- package/dist/{manifest-DL0oDbpv.js → manifest-B4ghOD-V.js} +1 -1
- package/dist/{manifest-DL0oDbpv.js.map → manifest-B4ghOD-V.js.map} +1 -1
- package/dist/{merge-agent-VQH9z9t8.js → merge-agent-DlUiUanN.js} +86 -33
- package/dist/merge-agent-DlUiUanN.js.map +1 -0
- package/dist/{paths-lMaxrYtT.js → paths-CDJ_HsbN.js} +19 -2
- package/dist/{paths-lMaxrYtT.js.map → paths-CDJ_HsbN.js.map} +1 -1
- package/dist/{pipeline-notifier-OJ-d3Y60.js → pipeline-notifier-XgDdCdvT.js} +1 -1
- package/dist/{pipeline-notifier-OJ-d3Y60.js.map → pipeline-notifier-XgDdCdvT.js.map} +1 -1
- package/dist/{projects-CvLepaxC.js → projects-Bk-5QhFQ.js} +25 -13
- package/dist/projects-Bk-5QhFQ.js.map +1 -0
- package/dist/{projects-DMWmPeIU.js → projects-DhU7rAVN.js} +1 -1
- package/dist/{providers-DcCPZ5K4.js → providers-DSU1vfQF.js} +4 -4
- package/dist/providers-DSU1vfQF.js.map +1 -0
- package/dist/rally-DdPvGa-w.js +3 -0
- package/dist/{rally-uUUZXp1h.js → rally-Dy00NElU.js} +1 -1
- package/dist/{rally-uUUZXp1h.js.map → rally-Dy00NElU.js.map} +1 -1
- package/dist/{remote-CkLBqLJc.js → remote-CYiOJg0q.js} +2 -2
- package/dist/{remote-CkLBqLJc.js.map → remote-CYiOJg0q.js.map} +1 -1
- package/dist/{remote-agents-C5Bd2fgt.js → remote-agents-CZXrUF4f.js} +1 -1
- package/dist/{remote-agents-C5Bd2fgt.js.map → remote-agents-CZXrUF4f.js.map} +1 -1
- package/dist/{remote-agents-BTzD-wMQ.js → remote-agents-ycHHVsgf.js} +1 -1
- package/dist/{remote-workspace-Dxghqiti.js → remote-workspace-CA33UuVI.js} +4 -4
- package/dist/{remote-workspace-Dxghqiti.js.map → remote-workspace-CA33UuVI.js.map} +1 -1
- package/dist/{review-status-2TdtHNcs.js → review-status-D6H2WOw8.js} +1 -1
- package/dist/{review-status-Bm1bWNEa.js → review-status-DEDvCKMP.js} +44 -4
- package/dist/{review-status-Bm1bWNEa.js.map → review-status-DEDvCKMP.js.map} +1 -1
- package/dist/{tracker-C_62ukEq.js → settings-BcWPTrua.js} +7 -199
- package/dist/settings-BcWPTrua.js.map +1 -0
- package/dist/shadow-state-BZzxfEGw.js +2 -0
- package/dist/{shadow-state-CFFHf05M.js → shadow-state-CE3dQfll.js} +1 -1
- package/dist/{shadow-state-CFFHf05M.js.map → shadow-state-CE3dQfll.js.map} +1 -1
- package/dist/{specialist-context-BdNFsfMG.js → specialist-context-BAUWL1Fl.js} +6 -6
- package/dist/{specialist-context-BdNFsfMG.js.map → specialist-context-BAUWL1Fl.js.map} +1 -1
- package/dist/{specialist-logs-CLztE_bE.js → specialist-logs-DQKKQV9B.js} +1 -1
- package/dist/{specialists-aUoUVWsN.js → specialists-Bfb9ATzw.js} +1 -1
- package/dist/{specialists-DEKqgkxp.js → specialists-D7Kj5o6s.js} +35 -34
- package/dist/specialists-D7Kj5o6s.js.map +1 -0
- package/dist/sync-DMfgd389.js +693 -0
- package/dist/sync-DMfgd389.js.map +1 -0
- package/dist/sync-TL6y-8K6.js +2 -0
- package/dist/{tldr-daemon-BCEFPItr.js → tldr-daemon-CFx4LXAl.js} +2 -2
- package/dist/{tldr-daemon-BCEFPItr.js.map → tldr-daemon-CFx4LXAl.js.map} +1 -1
- package/dist/{tldr-daemon-xBAx4cBE.js → tldr-daemon-D_EooADG.js} +1 -1
- package/dist/{tmux-DN6H886Y.js → tmux-CBtui_Cl.js} +1 -1
- package/dist/{tmux-CKdNxxJx.js → tmux-D6Ah4I8z.js} +2 -2
- package/dist/{tmux-CKdNxxJx.js.map → tmux-D6Ah4I8z.js.map} +1 -1
- package/dist/tracker-BhYYvU3p.js +198 -0
- package/dist/tracker-BhYYvU3p.js.map +1 -0
- package/dist/{tracker-utils-CVU2W1sX.js → tracker-utils-ChQyut8w.js} +34 -12
- package/dist/tracker-utils-ChQyut8w.js.map +1 -0
- package/dist/{traefik-DHgBoWXX.js → traefik-C80EbDu_.js} +4 -4
- package/dist/{traefik-DHgBoWXX.js.map → traefik-C80EbDu_.js.map} +1 -1
- package/dist/{traefik-BR-edbZv.js → traefik-CgHl7Bge.js} +1 -1
- package/dist/{tunnel-BZO9Q5oe.js → tunnel-DXOJ1wMM.js} +1 -1
- package/dist/{tunnel-Bl1qNSyQ.js → tunnel-DzXEPwIc.js} +2 -2
- package/dist/{tunnel-Bl1qNSyQ.js.map → tunnel-DzXEPwIc.js.map} +1 -1
- package/dist/{types-DewGdaIP.js → types-BhJj1SP1.js} +1 -1
- package/dist/{types-DewGdaIP.js.map → types-BhJj1SP1.js.map} +1 -1
- package/dist/{work-type-router-CS2BB1vS.js → work-type-router-CHjciPyS.js} +3 -3
- package/dist/{work-type-router-CS2BB1vS.js.map → work-type-router-CHjciPyS.js.map} +1 -1
- package/dist/{workspace-config-CNXOpKuj.js → workspace-config-fUafvYMp.js} +1 -1
- package/dist/workspace-config-fUafvYMp.js.map +1 -0
- package/dist/workspace-manager-B9jS4Dsq.js +3 -0
- package/dist/{workspace-manager-CncdZkIy.js → workspace-manager-DuLhnzJV.js} +112 -27
- package/dist/workspace-manager-DuLhnzJV.js.map +1 -0
- package/package.json +2 -1
- package/scripts/post-merge-deploy.sh +25 -5
- package/scripts/record-cost-event.js +57 -7
- package/scripts/record-cost-event.js.map +1 -1
- package/skills/pan-help/SKILL.md +1 -1
- package/skills/pan-sync/SKILL.md +6 -6
- package/skills/workspace-add-repo/skill.md +46 -0
- package/templates/claude-md/sections/warnings.md +15 -2
- package/dist/clean-planning-sZXvy3Y5.js +0 -2
- package/dist/close-issue-Dml437qV.js +0 -2
- package/dist/close-issue-Dr7yZmrr.js.map +0 -1
- package/dist/compact-beads-iu218JcO.js +0 -2
- package/dist/dashboard/agent-enrichment-C67LJBgD.js.map +0 -1
- package/dist/dashboard/clean-planning-DCu3cOTu.js +0 -2
- package/dist/dashboard/close-issue-DfIggeZD.js.map +0 -1
- package/dist/dashboard/close-issue-DwdwYtar.js +0 -2
- package/dist/dashboard/compact-beads-DXY2fK2s.js +0 -2
- package/dist/dashboard/event-store-O9q0Gweh.js.map +0 -1
- package/dist/dashboard/hume-MZndNDVU.js +0 -3
- package/dist/dashboard/label-cleanup-CZEsbtq9.js.map +0 -1
- package/dist/dashboard/lifecycle-ZTYdrr2O.js +0 -7
- package/dist/dashboard/merge-agent-twroFuAh.js.map +0 -1
- package/dist/dashboard/projects-Cq3TWdPS.js.map +0 -1
- package/dist/dashboard/providers-Ck2sQd_F.js.map +0 -1
- package/dist/dashboard/public/assets/index-CpSmB2ts.css +0 -1
- package/dist/dashboard/public/assets/index-yarWhi0M.js +0 -214
- package/dist/dashboard/rally-CQ1OBJrJ.js +0 -3
- package/dist/dashboard/settings-CuHV-wcv.js.map +0 -1
- package/dist/dashboard/settings-DMeGBRsk.js +0 -2
- package/dist/dashboard/specialists-C6s3U6tX.js.map +0 -1
- package/dist/dashboard/workflows-B2ARUpOa.js +0 -2
- package/dist/dashboard/workflows-N1UTipYl.js.map +0 -1
- package/dist/dashboard/workspace-config-cmp5_ipD.js.map +0 -1
- package/dist/dashboard/workspace-manager-D_y9ZmW_.js.map +0 -1
- package/dist/hume-BjmwmJ9E.js +0 -3
- package/dist/label-cleanup-31ElPqqv.js.map +0 -1
- package/dist/merge-agent-VQH9z9t8.js.map +0 -1
- package/dist/projects-CvLepaxC.js.map +0 -1
- package/dist/providers-DcCPZ5K4.js.map +0 -1
- package/dist/rally-DR9x8--6.js +0 -3
- package/dist/shadow-state-p3jpGRPJ.js +0 -2
- package/dist/specialists-DEKqgkxp.js.map +0 -1
- package/dist/tracker-C_62ukEq.js.map +0 -1
- package/dist/tracker-utils-CVU2W1sX.js.map +0 -1
- package/dist/workspace-config-CNXOpKuj.js.map +0 -1
- package/dist/workspace-manager-CncdZkIy.js.map +0 -1
- package/dist/workspace-manager-Cx0r2Jnv.js +0 -3
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as movePrd, r as findWorkspacePath } from "./archive-planning-
|
|
1
|
+
import { i as movePrd, r as findWorkspacePath } from "./archive-planning-BmW9UDTr.js";
|
|
2
2
|
export { findWorkspacePath, movePrd };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as updateItemStatus, i as readWorkspacePlan, n as init_io, o as updateSubItemStatus } from "./io-
|
|
2
|
-
import { t as extractACFromDocument } from "./acceptance-criteria-
|
|
1
|
+
import { a as updateItemStatus, i as readWorkspacePlan, n as init_io, o as updateSubItemStatus } from "./io-DKS6359z.js";
|
|
2
|
+
import { t as extractACFromDocument } from "./acceptance-criteria-Dk9hhiYj.js";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
4
4
|
import { join, resolve } from "path";
|
|
5
5
|
import { exec } from "child_process";
|
|
@@ -295,4 +295,4 @@ function getVBriefACStatus(workspacePath) {
|
|
|
295
295
|
//#endregion
|
|
296
296
|
export { getVBriefACStatus as n, syncBeadStatusToVBrief as r, createBeadsFromVBrief as t };
|
|
297
297
|
|
|
298
|
-
//# sourceMappingURL=beads-
|
|
298
|
+
//# sourceMappingURL=beads-Bv-AdX7G.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"beads-qNB0yAHV.js","names":[],"sources":["../../src/lib/vbrief/beads.ts"],"sourcesContent":["/**\n * createBeadsFromVBrief\n *\n * Converts a vBRIEF plan document into beads tasks, preserving dependency\n * relationships from blocking edges. This replaces LLM-generated `bd create`\n * shell commands with a deterministic, programmatic conversion.\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join, resolve } from 'path';\nimport { readWorkspacePlan, updateItemStatus, updateSubItemStatus } from './io.js';\nimport { extractACFromDocument } from './acceptance-criteria.js';\nimport type { AcceptanceCriterion } from './acceptance-criteria.js';\nimport type { VBriefDocument, VBriefItem, VBriefItemStatus } from './types.js';\n\nconst execAsync = promisify(exec);\n\nexport interface CreateBeadsResult {\n success: boolean;\n created: string[];\n errors: string[];\n /** Map from vBRIEF item ID → created bead ID */\n beadIds: Map<string, string>;\n}\n\n/**\n * Converts a vBRIEF plan.vbrief.json into beads tasks with dependencies.\n *\n * @param workspacePath - Path to the workspace root (contains .planning/plan.vbrief.json)\n * @returns Result with created bead IDs and any errors\n */\nexport async function createBeadsFromVBrief(workspacePath: string): Promise<CreateBeadsResult> {\n const created: string[] = [];\n const errors: string[] = [];\n const beadIds = new Map<string, string>();\n\n // Verify bd CLI is available\n try {\n await execAsync('which bd', { encoding: 'utf-8' });\n } catch {\n return { success: false, created: [], errors: ['bd (beads) CLI not found in PATH'], beadIds };\n }\n\n // Ensure beads is reachable from this workspace.\n // Workspaces are git worktrees: only committed .beads files (issues.jsonl) are present.\n // The .beads/redirect file — which points bd at the main repo's shared Dolt database —\n // is gitignored and must be created explicitly if missing.\n const beadsDir = join(workspacePath, '.beads');\n const redirectPath = join(beadsDir, 'redirect');\n if (!existsSync(redirectPath)) {\n // Worktrees live at <projectRoot>/workspaces/feature-<id>/ — two levels up\n const projectRoot = resolve(workspacePath, '..', '..');\n const mainBeadsDir = join(projectRoot, '.beads');\n if (existsSync(mainBeadsDir)) {\n mkdirSync(beadsDir, { recursive: true });\n writeFileSync(redirectPath, '../../.beads', 'utf-8');\n console.log(`[beads] Created redirect to main repo .beads/ in ${workspacePath}`);\n } else if (!existsSync(beadsDir)) {\n // No main .beads/ and no local .beads/ — fall back to bd init\n try {\n await execAsync('bd init', { encoding: 'utf-8', cwd: workspacePath, timeout: 15000 });\n await execAsync('git config beads.role contributor', { cwd: workspacePath }).catch(() => {});\n console.log(`[beads] Initialized beads database in ${workspacePath}`);\n } catch (initErr: any) {\n return { success: false, created: [], errors: [`Failed to initialize beads: ${initErr.message}`], beadIds };\n }\n }\n }\n\n // Read the vBRIEF plan — must be spec-compliant format\n const doc = readWorkspacePlan(workspacePath);\n if (!doc) {\n return { success: false, created: [], errors: ['No plan.vbrief.json found in workspace'], beadIds };\n }\n\n const { plan } = doc;\n\n // Verify db connectivity — the Dolt database for this project may not exist yet\n // on fresh installs (bd was installed but bd init was never run at the project root).\n // If connectivity fails for any reason and a redirect exists, auto-initialize with\n // the right prefix so beads creation can proceed without manual intervention.\n const issueLabel = plan.id.toLowerCase();\n const redirectExists = existsSync(redirectPath);\n try {\n await execAsync('bd list --json --limit 0', {\n encoding: 'utf-8', cwd: workspacePath, timeout: 8000,\n });\n } catch (connectErr: any) {\n // When redirect exists but DB is unreachable (not found, connection refused, timeout,\n // or any other error), always attempt bd init --prefix to initialize the database.\n // This covers fresh installs, corrupted DBs, and cases where the redirect was created\n // but bd init was never run for this prefix.\n if (redirectExists) {\n const prefix = issueLabel;\n const connectErrMsg = String(connectErr?.message ?? connectErr?.stderr ?? '');\n\n // Categorize the connectivity error for diagnostic clarity\n let connectCategory: string;\n if (connectErrMsg.toLowerCase().includes('connect') || connectErrMsg.toLowerCase().includes('refused') || connectErrMsg.toLowerCase().includes('econnrefused')) {\n connectCategory = 'Dolt server not running';\n } else if (connectErrMsg.toLowerCase().includes('not found') || connectErrMsg.toLowerCase().includes('not exist') || connectErrMsg.toLowerCase().includes('no such')) {\n connectCategory = 'database not found';\n } else {\n connectCategory = connectErrMsg.split('\\n')[0] || 'unknown connectivity error';\n }\n\n console.log(`[beads] Database unreachable (${connectCategory}) — auto-running bd init --prefix ${prefix}`);\n try {\n await execAsync(`bd init --prefix ${prefix}`, {\n encoding: 'utf-8', cwd: workspacePath, timeout: 20000,\n });\n await execAsync('git config beads.role contributor', { cwd: workspacePath }).catch(() => {});\n console.log(`[beads] bd init succeeded for prefix ${prefix}`);\n } catch (initErr: any) {\n // Init failed — return early with a specific error so callers know exactly what happened\n // rather than proceeding with bead creation against a broken database.\n const initErrMsg = String(initErr?.message ?? initErr?.stderr ?? '');\n const detail = `database init failed: ${initErrMsg.split('\\n')[0]} (connectivity: ${connectCategory})`;\n console.warn(`[beads] ${detail}`);\n return { success: false, created: [], errors: [detail], beadIds };\n }\n }\n }\n\n // Idempotency: clear any existing beads for this issue before creating new ones.\n // Re-planning means \"the old plan was invalid\" — start fresh.\n try {\n const { stdout: existingJson } = await execAsync(\n `bd list --json -l \"${issueLabel}\" --status all --limit 0`,\n { encoding: 'utf-8', cwd: workspacePath, timeout: 15000 }\n );\n const existingBeads = JSON.parse(existingJson || '[]');\n if (Array.isArray(existingBeads) && existingBeads.length > 0) {\n const ids = existingBeads.map((b: any) => b.id).filter(Boolean);\n for (const id of ids) {\n try {\n await execAsync(`bd delete ${id} --force`, { encoding: 'utf-8', cwd: workspacePath, timeout: 10000 });\n } catch {\n // Individual delete failure is non-fatal\n }\n }\n console.log(`[beads] Cleared ${ids.length} existing beads for ${issueLabel} before re-creating`);\n }\n } catch {\n // If listing fails (no beads exist, bd not initialized), proceed with creation\n }\n\n // Build blocking-edge map: item.id → set of item IDs that block it\n // (i.e., blockers[B] = { A } means A blocks B, so B depends on A)\n const blockers = new Map<string, Set<string>>();\n for (const item of plan.items) {\n blockers.set(item.id, new Set());\n }\n for (const edge of plan.edges) {\n if (edge.type === 'blocks') {\n const blockersOfTo = blockers.get(edge.to);\n if (blockersOfTo) {\n blockersOfTo.add(edge.from);\n }\n }\n }\n\n // Topological sort (Kahn's algorithm) so we create items after their blockers\n const inDegree = new Map<string, number>();\n const adjacency = new Map<string, string[]>(); // from → list of items it blocks\n for (const item of plan.items) {\n inDegree.set(item.id, 0);\n adjacency.set(item.id, []);\n }\n for (const edge of plan.edges) {\n if (edge.type === 'blocks') {\n inDegree.set(edge.to, (inDegree.get(edge.to) ?? 0) + 1);\n adjacency.get(edge.from)?.push(edge.to);\n }\n }\n\n const queue: string[] = [];\n for (const item of plan.items) {\n if ((inDegree.get(item.id) ?? 0) === 0) {\n queue.push(item.id);\n }\n }\n\n const itemById = new Map<string, VBriefItem>(plan.items.map(i => [i.id, i]));\n const sortedIds: string[] = [];\n while (queue.length > 0) {\n const id = queue.shift()!;\n sortedIds.push(id);\n for (const dependent of adjacency.get(id) ?? []) {\n const newDegree = (inDegree.get(dependent) ?? 1) - 1;\n inDegree.set(dependent, newDegree);\n if (newDegree === 0) {\n queue.push(dependent);\n }\n }\n }\n\n // If we have a cycle, fall back to original order\n const orderedIds = sortedIds.length === plan.items.length\n ? sortedIds\n : plan.items.map(i => i.id);\n\n // Create beads in dependency order\n for (const itemId of orderedIds) {\n const item = itemById.get(itemId);\n if (!item) continue;\n\n const fullTitle = `${plan.id}: ${item.title}`;\n const difficulty = item.metadata?.difficulty ?? 'medium';\n const issueLabel = item.metadata?.issueLabel ?? plan.id.toLowerCase();\n const phase = item.metadata?.phase;\n\n try {\n // Build labels\n const labels = [issueLabel, `difficulty:${difficulty}`];\n if (phase !== undefined) labels.push(`phase-${phase}`);\n const labelStr = labels.join(',');\n\n // Build description from narrative Action + acceptance criteria\n const actionText = item.narrative?.Action ?? '';\n const acLines = (item.subItems ?? [])\n .filter(s => s.metadata?.kind === 'acceptance_criterion')\n .map(s => `- AC: ${s.title}`)\n .join('\\n');\n const description = [actionText, acLines].filter(Boolean).join('\\n');\n\n // Build deps from blocking edges (blockers that have been created)\n const blockingDeps = [...(blockers.get(itemId) ?? [])].map(blockerId => {\n const beadId = beadIds.get(blockerId);\n return beadId ? `blocks:${beadId}` : null;\n }).filter((d): d is string => d !== null);\n\n // Assemble bd create command\n const escapedTitle = fullTitle.replace(/\"/g, '\\\\\"');\n let cmd = `bd create \"${escapedTitle}\" --type task --silent -l \"${labelStr}\"`;\n\n if (description) {\n const escapedDesc = description.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n');\n cmd += ` -d \"${escapedDesc}\"`;\n }\n\n if (blockingDeps.length > 0) {\n cmd += ` --deps \"${blockingDeps.join(',')}\"`;\n }\n\n const { stdout } = await execAsync(cmd, { encoding: 'utf-8', cwd: workspacePath });\n const beadId = stdout.trim();\n\n if (beadId) {\n beadIds.set(itemId, beadId);\n created.push(fullTitle);\n } else {\n errors.push(`Created \"${item.title}\" but could not capture bead ID`);\n created.push(fullTitle);\n }\n } catch (error: any) {\n const errMsg = error.stderr?.toString() || error.message || String(error);\n errors.push(`Failed to create \"${item.title}\": ${errMsg.split('\\n')[0]}`);\n }\n }\n\n return { success: errors.length === 0, created, errors, beadIds };\n}\n\n/**\n * Syncs a closed bead's status to the corresponding vBRIEF item.\n *\n * Reads the bead title from .beads/issues.jsonl, strips the issue prefix\n * (e.g. \"PAN-388: Wire createBeadsFromVBrief()\" → \"Wire createBeadsFromVBrief()\"),\n * finds the matching item in plan.vbrief.json, and calls updateItemStatus().\n *\n * No-ops gracefully when:\n * - No plan.vbrief.json exists (legacy workspace)\n * - Bead ID not found in issues.jsonl\n * - No matching vBRIEF item found\n */\n/**\n * Returns the vBRIEF item ID that was updated, or null if no match was found.\n */\nexport function syncBeadStatusToVBrief(\n beadId: string,\n workspacePath: string,\n status: VBriefItemStatus = 'completed',\n /** Optional: bead title from caller (e.g. bd list --json output). Falls back to .beads/issues.jsonl lookup. */\n knownTitle?: string\n): string | null {\n try {\n const doc = readWorkspacePlan(workspacePath);\n if (!doc) return null;\n\n let beadTitle: string | null = knownTitle ?? null;\n\n // Fallback: read bead title from .beads/issues.jsonl (legacy flat-file beads)\n if (!beadTitle) {\n const beadsFile = join(workspacePath, '.beads', 'issues.jsonl');\n if (existsSync(beadsFile)) {\n const lines = readFileSync(beadsFile, 'utf-8').split('\\n').filter(Boolean);\n for (const line of lines) {\n try {\n const bead = JSON.parse(line);\n if (bead.id === beadId && bead.title) {\n beadTitle = bead.title as string;\n break;\n }\n } catch {\n // skip malformed lines\n }\n }\n }\n }\n\n if (!beadTitle) return null;\n\n // Strip issue prefix: \"{PLAN_ID}: {item.title}\" → \"{item.title}\"\n const planId = doc.plan.id;\n const prefix = `${planId}: `;\n const itemTitle = beadTitle.startsWith(prefix)\n ? beadTitle.slice(prefix.length)\n : beadTitle;\n\n // Find matching item (case-insensitive)\n const itemTitleLower = itemTitle.toLowerCase();\n const matchingItem = doc.plan.items.find(\n i => i.title.toLowerCase() === itemTitleLower\n );\n\n if (!matchingItem) return null;\n\n // io.ts handles vBRIEFInfo.updated, plan.updated, plan.sequence, and item.completed\n // timestamps automatically. Each call below constitutes one write → one sequence increment.\n updateItemStatus(workspacePath, matchingItem.id, status);\n\n // Also mark all AC subItems as completed when the parent item is completed.\n // Each updateSubItemStatus call increments sequence separately (one write per subItem).\n if (status === 'completed' && matchingItem.subItems) {\n for (const sub of matchingItem.subItems) {\n if (sub.metadata?.kind === 'acceptance_criterion' && sub.status !== 'completed') {\n updateSubItemStatus(workspacePath, matchingItem.id, sub.id, 'completed');\n }\n }\n }\n\n console.log(`[vbrief-sync] Updated item \"${matchingItem.id}\" to \"${status}\" from bead ${beadId}`);\n return matchingItem.id;\n } catch (err: any) {\n // Non-fatal: log and continue\n console.warn(`[vbrief-sync] Failed to sync bead ${beadId}: ${err.message}`);\n return null;\n }\n}\n\n/** Per-item AC status summary. */\nexport interface ItemACStatus {\n itemId: string;\n itemTitle: string;\n completed: number;\n pending: number;\n total: number;\n criteria: AcceptanceCriterion[];\n}\n\n/** Result of getVBriefACStatus(). null means no plan or no AC found. */\nexport interface VBriefACStatus {\n allCompleted: boolean;\n items: ItemACStatus[];\n totalCompleted: number;\n totalPending: number;\n totalCount: number;\n}\n\n/**\n * Get structured AC status from a workspace's vBRIEF plan.\n *\n * Returns per-item AC counts (completed/pending/total) plus an overall\n * allCompleted flag. Returns null if no plan exists or no AC are found\n * (legacy workspace compatibility).\n *\n * Used by: verification gate, pan work done, merge agent, prompt injection.\n */\nexport function getVBriefACStatus(workspacePath: string): VBriefACStatus | null {\n const doc = readWorkspacePlan(workspacePath);\n if (!doc) return null;\n\n const allCriteria = extractACFromDocument(doc);\n if (allCriteria.length === 0) return null;\n\n // Group by item\n const itemMap = new Map<string, ItemACStatus>();\n for (const ac of allCriteria) {\n let item = itemMap.get(ac.itemId);\n if (!item) {\n item = { itemId: ac.itemId, itemTitle: ac.itemTitle, completed: 0, pending: 0, total: 0, criteria: [] };\n itemMap.set(ac.itemId, item);\n }\n item.total++;\n item.criteria.push(ac);\n if (ac.status === 'completed' || ac.status === 'cancelled') {\n item.completed++;\n } else {\n item.pending++;\n }\n }\n\n const items = Array.from(itemMap.values());\n const totalCompleted = items.reduce((sum, i) => sum + i.completed, 0);\n const totalPending = items.reduce((sum, i) => sum + i.pending, 0);\n const totalCount = totalCompleted + totalPending;\n\n return {\n allCompleted: totalPending === 0,\n items,\n totalCompleted,\n totalPending,\n totalCount,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;SAYmF;AAKnF,MAAM,YAAY,UAAU,KAAK;;;;;;;AAgBjC,eAAsB,sBAAsB,eAAmD;CAC7F,MAAM,UAAoB,EAAE;CAC5B,MAAM,SAAmB,EAAE;CAC3B,MAAM,0BAAU,IAAI,KAAqB;AAGzC,KAAI;AACF,QAAM,UAAU,YAAY,EAAE,UAAU,SAAS,CAAC;SAC5C;AACN,SAAO;GAAE,SAAS;GAAO,SAAS,EAAE;GAAE,QAAQ,CAAC,mCAAmC;GAAE;GAAS;;CAO/F,MAAM,WAAW,KAAK,eAAe,SAAS;CAC9C,MAAM,eAAe,KAAK,UAAU,WAAW;AAC/C,KAAI,CAAC,WAAW,aAAa;MAIvB,WADiB,KADD,QAAQ,eAAe,MAAM,KAAK,EACf,SAAS,CACpB,EAAE;AAC5B,aAAU,UAAU,EAAE,WAAW,MAAM,CAAC;AACxC,iBAAc,cAAc,gBAAgB,QAAQ;AACpD,WAAQ,IAAI,oDAAoD,gBAAgB;aACvE,CAAC,WAAW,SAAS,CAE9B,KAAI;AACF,SAAM,UAAU,WAAW;IAAE,UAAU;IAAS,KAAK;IAAe,SAAS;IAAO,CAAC;AACrF,SAAM,UAAU,qCAAqC,EAAE,KAAK,eAAe,CAAC,CAAC,YAAY,GAAG;AAC5F,WAAQ,IAAI,yCAAyC,gBAAgB;WAC9D,SAAc;AACrB,UAAO;IAAE,SAAS;IAAO,SAAS,EAAE;IAAE,QAAQ,CAAC,+BAA+B,QAAQ,UAAU;IAAE;IAAS;;;CAMjH,MAAM,MAAM,kBAAkB,cAAc;AAC5C,KAAI,CAAC,IACH,QAAO;EAAE,SAAS;EAAO,SAAS,EAAE;EAAE,QAAQ,CAAC,yCAAyC;EAAE;EAAS;CAGrG,MAAM,EAAE,SAAS;CAMjB,MAAM,aAAa,KAAK,GAAG,aAAa;CACxC,MAAM,iBAAiB,WAAW,aAAa;AAC/C,KAAI;AACF,QAAM,UAAU,4BAA4B;GAC1C,UAAU;GAAS,KAAK;GAAe,SAAS;GACjD,CAAC;UACK,YAAiB;AAKxB,MAAI,gBAAgB;GAClB,MAAM,SAAS;GACf,MAAM,gBAAgB,OAAO,YAAY,WAAW,YAAY,UAAU,GAAG;GAG7E,IAAI;AACJ,OAAI,cAAc,aAAa,CAAC,SAAS,UAAU,IAAI,cAAc,aAAa,CAAC,SAAS,UAAU,IAAI,cAAc,aAAa,CAAC,SAAS,eAAe,CAC5J,mBAAkB;YACT,cAAc,aAAa,CAAC,SAAS,YAAY,IAAI,cAAc,aAAa,CAAC,SAAS,YAAY,IAAI,cAAc,aAAa,CAAC,SAAS,UAAU,CAClK,mBAAkB;OAElB,mBAAkB,cAAc,MAAM,KAAK,CAAC,MAAM;AAGpD,WAAQ,IAAI,iCAAiC,gBAAgB,oCAAoC,SAAS;AAC1G,OAAI;AACF,UAAM,UAAU,oBAAoB,UAAU;KAC5C,UAAU;KAAS,KAAK;KAAe,SAAS;KACjD,CAAC;AACF,UAAM,UAAU,qCAAqC,EAAE,KAAK,eAAe,CAAC,CAAC,YAAY,GAAG;AAC5F,YAAQ,IAAI,wCAAwC,SAAS;YACtD,SAAc;IAIrB,MAAM,SAAS,yBADI,OAAO,SAAS,WAAW,SAAS,UAAU,GAAG,CACjB,MAAM,KAAK,CAAC,GAAG,kBAAkB,gBAAgB;AACpG,YAAQ,KAAK,WAAW,SAAS;AACjC,WAAO;KAAE,SAAS;KAAO,SAAS,EAAE;KAAE,QAAQ,CAAC,OAAO;KAAE;KAAS;;;;AAOvE,KAAI;EACF,MAAM,EAAE,QAAQ,iBAAiB,MAAM,UACrC,sBAAsB,WAAW,2BACjC;GAAE,UAAU;GAAS,KAAK;GAAe,SAAS;GAAO,CAC1D;EACD,MAAM,gBAAgB,KAAK,MAAM,gBAAgB,KAAK;AACtD,MAAI,MAAM,QAAQ,cAAc,IAAI,cAAc,SAAS,GAAG;GAC5D,MAAM,MAAM,cAAc,KAAK,MAAW,EAAE,GAAG,CAAC,OAAO,QAAQ;AAC/D,QAAK,MAAM,MAAM,IACf,KAAI;AACF,UAAM,UAAU,aAAa,GAAG,WAAW;KAAE,UAAU;KAAS,KAAK;KAAe,SAAS;KAAO,CAAC;WAC/F;AAIV,WAAQ,IAAI,mBAAmB,IAAI,OAAO,sBAAsB,WAAW,qBAAqB;;SAE5F;CAMR,MAAM,2BAAW,IAAI,KAA0B;AAC/C,MAAK,MAAM,QAAQ,KAAK,MACtB,UAAS,IAAI,KAAK,oBAAI,IAAI,KAAK,CAAC;AAElC,MAAK,MAAM,QAAQ,KAAK,MACtB,KAAI,KAAK,SAAS,UAAU;EAC1B,MAAM,eAAe,SAAS,IAAI,KAAK,GAAG;AAC1C,MAAI,aACF,cAAa,IAAI,KAAK,KAAK;;CAMjC,MAAM,2BAAW,IAAI,KAAqB;CAC1C,MAAM,4BAAY,IAAI,KAAuB;AAC7C,MAAK,MAAM,QAAQ,KAAK,OAAO;AAC7B,WAAS,IAAI,KAAK,IAAI,EAAE;AACxB,YAAU,IAAI,KAAK,IAAI,EAAE,CAAC;;AAE5B,MAAK,MAAM,QAAQ,KAAK,MACtB,KAAI,KAAK,SAAS,UAAU;AAC1B,WAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,GAAG,IAAI,KAAK,EAAE;AACvD,YAAU,IAAI,KAAK,KAAK,EAAE,KAAK,KAAK,GAAG;;CAI3C,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,QAAQ,KAAK,MACtB,MAAK,SAAS,IAAI,KAAK,GAAG,IAAI,OAAO,EACnC,OAAM,KAAK,KAAK,GAAG;CAIvB,MAAM,WAAW,IAAI,IAAwB,KAAK,MAAM,KAAI,MAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;CAC5E,MAAM,YAAsB,EAAE;AAC9B,QAAO,MAAM,SAAS,GAAG;EACvB,MAAM,KAAK,MAAM,OAAO;AACxB,YAAU,KAAK,GAAG;AAClB,OAAK,MAAM,aAAa,UAAU,IAAI,GAAG,IAAI,EAAE,EAAE;GAC/C,MAAM,aAAa,SAAS,IAAI,UAAU,IAAI,KAAK;AACnD,YAAS,IAAI,WAAW,UAAU;AAClC,OAAI,cAAc,EAChB,OAAM,KAAK,UAAU;;;CAM3B,MAAM,aAAa,UAAU,WAAW,KAAK,MAAM,SAC/C,YACA,KAAK,MAAM,KAAI,MAAK,EAAE,GAAG;AAG7B,MAAK,MAAM,UAAU,YAAY;EAC/B,MAAM,OAAO,SAAS,IAAI,OAAO;AACjC,MAAI,CAAC,KAAM;EAEX,MAAM,YAAY,GAAG,KAAK,GAAG,IAAI,KAAK;EACtC,MAAM,aAAa,KAAK,UAAU,cAAc;EAChD,MAAM,aAAa,KAAK,UAAU,cAAc,KAAK,GAAG,aAAa;EACrE,MAAM,QAAQ,KAAK,UAAU;AAE7B,MAAI;GAEF,MAAM,SAAS,CAAC,YAAY,cAAc,aAAa;AACvD,OAAI,UAAU,KAAA,EAAW,QAAO,KAAK,SAAS,QAAQ;GACtD,MAAM,WAAW,OAAO,KAAK,IAAI;GAQjC,MAAM,cAAc,CALD,KAAK,WAAW,UAAU,KAC5B,KAAK,YAAY,EAAE,EACjC,QAAO,MAAK,EAAE,UAAU,SAAS,uBAAuB,CACxD,KAAI,MAAK,SAAS,EAAE,QAAQ,CAC5B,KAAK,KAAK,CAC4B,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAK;GAGpE,MAAM,eAAe,CAAC,GAAI,SAAS,IAAI,OAAO,IAAI,EAAE,CAAE,CAAC,KAAI,cAAa;IACtE,MAAM,SAAS,QAAQ,IAAI,UAAU;AACrC,WAAO,SAAS,UAAU,WAAW;KACrC,CAAC,QAAQ,MAAmB,MAAM,KAAK;GAIzC,IAAI,MAAM,cADW,UAAU,QAAQ,MAAM,OAAM,CACd,6BAA6B,SAAS;AAE3E,OAAI,aAAa;IACf,MAAM,cAAc,YAAY,QAAQ,MAAM,OAAM,CAAC,QAAQ,OAAO,MAAM;AAC1E,WAAO,QAAQ,YAAY;;AAG7B,OAAI,aAAa,SAAS,EACxB,QAAO,YAAY,aAAa,KAAK,IAAI,CAAC;GAG5C,MAAM,EAAE,WAAW,MAAM,UAAU,KAAK;IAAE,UAAU;IAAS,KAAK;IAAe,CAAC;GAClF,MAAM,SAAS,OAAO,MAAM;AAE5B,OAAI,QAAQ;AACV,YAAQ,IAAI,QAAQ,OAAO;AAC3B,YAAQ,KAAK,UAAU;UAClB;AACL,WAAO,KAAK,YAAY,KAAK,MAAM,iCAAiC;AACpE,YAAQ,KAAK,UAAU;;WAElB,OAAY;GACnB,MAAM,SAAS,MAAM,QAAQ,UAAU,IAAI,MAAM,WAAW,OAAO,MAAM;AACzE,UAAO,KAAK,qBAAqB,KAAK,MAAM,KAAK,OAAO,MAAM,KAAK,CAAC,KAAK;;;AAI7E,QAAO;EAAE,SAAS,OAAO,WAAW;EAAG;EAAS;EAAQ;EAAS;;;;;;;;;;;;;;;;;AAkBnE,SAAgB,uBACd,QACA,eACA,SAA2B,aAE3B,YACe;AACf,KAAI;EACF,MAAM,MAAM,kBAAkB,cAAc;AAC5C,MAAI,CAAC,IAAK,QAAO;EAEjB,IAAI,YAA2B,cAAc;AAG7C,MAAI,CAAC,WAAW;GACd,MAAM,YAAY,KAAK,eAAe,UAAU,eAAe;AAC/D,OAAI,WAAW,UAAU,EAAE;IACzB,MAAM,QAAQ,aAAa,WAAW,QAAQ,CAAC,MAAM,KAAK,CAAC,OAAO,QAAQ;AAC1E,SAAK,MAAM,QAAQ,MACjB,KAAI;KACF,MAAM,OAAO,KAAK,MAAM,KAAK;AAC7B,SAAI,KAAK,OAAO,UAAU,KAAK,OAAO;AACpC,kBAAY,KAAK;AACjB;;YAEI;;;AAOd,MAAI,CAAC,UAAW,QAAO;EAIvB,MAAM,SAAS,GADA,IAAI,KAAK,GACC;EAMzB,MAAM,kBALY,UAAU,WAAW,OAAO,GAC1C,UAAU,MAAM,OAAO,OAAO,GAC9B,WAG6B,aAAa;EAC9C,MAAM,eAAe,IAAI,KAAK,MAAM,MAClC,MAAK,EAAE,MAAM,aAAa,KAAK,eAChC;AAED,MAAI,CAAC,aAAc,QAAO;AAI1B,mBAAiB,eAAe,aAAa,IAAI,OAAO;AAIxD,MAAI,WAAW,eAAe,aAAa;QACpC,MAAM,OAAO,aAAa,SAC7B,KAAI,IAAI,UAAU,SAAS,0BAA0B,IAAI,WAAW,YAClE,qBAAoB,eAAe,aAAa,IAAI,IAAI,IAAI,YAAY;;AAK9E,UAAQ,IAAI,+BAA+B,aAAa,GAAG,QAAQ,OAAO,cAAc,SAAS;AACjG,SAAO,aAAa;UACb,KAAU;AAEjB,UAAQ,KAAK,qCAAqC,OAAO,IAAI,IAAI,UAAU;AAC3E,SAAO;;;;;;;;;;;;AAgCX,SAAgB,kBAAkB,eAA8C;CAC9E,MAAM,MAAM,kBAAkB,cAAc;AAC5C,KAAI,CAAC,IAAK,QAAO;CAEjB,MAAM,cAAc,sBAAsB,IAAI;AAC9C,KAAI,YAAY,WAAW,EAAG,QAAO;CAGrC,MAAM,0BAAU,IAAI,KAA2B;AAC/C,MAAK,MAAM,MAAM,aAAa;EAC5B,IAAI,OAAO,QAAQ,IAAI,GAAG,OAAO;AACjC,MAAI,CAAC,MAAM;AACT,UAAO;IAAE,QAAQ,GAAG;IAAQ,WAAW,GAAG;IAAW,WAAW;IAAG,SAAS;IAAG,OAAO;IAAG,UAAU,EAAE;IAAE;AACvG,WAAQ,IAAI,GAAG,QAAQ,KAAK;;AAE9B,OAAK;AACL,OAAK,SAAS,KAAK,GAAG;AACtB,MAAI,GAAG,WAAW,eAAe,GAAG,WAAW,YAC7C,MAAK;MAEL,MAAK;;CAIT,MAAM,QAAQ,MAAM,KAAK,QAAQ,QAAQ,CAAC;CAC1C,MAAM,iBAAiB,MAAM,QAAQ,KAAK,MAAM,MAAM,EAAE,WAAW,EAAE;CACrE,MAAM,eAAe,MAAM,QAAQ,KAAK,MAAM,MAAM,EAAE,SAAS,EAAE;CACjE,MAAM,aAAa,iBAAiB;AAEpC,QAAO;EACL,cAAc,iBAAiB;EAC/B;EACA;EACA;EACA;EACD"}
|
|
1
|
+
{"version":3,"file":"beads-Bv-AdX7G.js","names":[],"sources":["../../src/lib/vbrief/beads.ts"],"sourcesContent":["/**\n * createBeadsFromVBrief\n *\n * Converts a vBRIEF plan document into beads tasks, preserving dependency\n * relationships from blocking edges. This replaces LLM-generated `bd create`\n * shell commands with a deterministic, programmatic conversion.\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join, resolve } from 'path';\nimport { readWorkspacePlan, updateItemStatus, updateSubItemStatus } from './io.js';\nimport { extractACFromDocument } from './acceptance-criteria.js';\nimport type { AcceptanceCriterion } from './acceptance-criteria.js';\nimport type { VBriefDocument, VBriefItem, VBriefItemStatus } from './types.js';\n\nconst execAsync = promisify(exec);\n\nexport interface CreateBeadsResult {\n success: boolean;\n created: string[];\n errors: string[];\n /** Map from vBRIEF item ID → created bead ID */\n beadIds: Map<string, string>;\n}\n\n/**\n * Converts a vBRIEF plan.vbrief.json into beads tasks with dependencies.\n *\n * @param workspacePath - Path to the workspace root (contains .planning/plan.vbrief.json)\n * @returns Result with created bead IDs and any errors\n */\nexport async function createBeadsFromVBrief(workspacePath: string): Promise<CreateBeadsResult> {\n const created: string[] = [];\n const errors: string[] = [];\n const beadIds = new Map<string, string>();\n\n // Verify bd CLI is available\n try {\n await execAsync('which bd', { encoding: 'utf-8' });\n } catch {\n return { success: false, created: [], errors: ['bd (beads) CLI not found in PATH'], beadIds };\n }\n\n // Ensure beads is reachable from this workspace.\n // Workspaces are git worktrees: only committed .beads files (issues.jsonl) are present.\n // The .beads/redirect file — which points bd at the main repo's shared Dolt database —\n // is gitignored and must be created explicitly if missing.\n const beadsDir = join(workspacePath, '.beads');\n const redirectPath = join(beadsDir, 'redirect');\n if (!existsSync(redirectPath)) {\n // Worktrees live at <projectRoot>/workspaces/feature-<id>/ — two levels up\n const projectRoot = resolve(workspacePath, '..', '..');\n const mainBeadsDir = join(projectRoot, '.beads');\n if (existsSync(mainBeadsDir)) {\n mkdirSync(beadsDir, { recursive: true });\n writeFileSync(redirectPath, '../../.beads', 'utf-8');\n console.log(`[beads] Created redirect to main repo .beads/ in ${workspacePath}`);\n } else if (!existsSync(beadsDir)) {\n // No main .beads/ and no local .beads/ — fall back to bd init\n try {\n await execAsync('bd init', { encoding: 'utf-8', cwd: workspacePath, timeout: 15000 });\n await execAsync('git config beads.role contributor', { cwd: workspacePath }).catch(() => {});\n console.log(`[beads] Initialized beads database in ${workspacePath}`);\n } catch (initErr: any) {\n return { success: false, created: [], errors: [`Failed to initialize beads: ${initErr.message}`], beadIds };\n }\n }\n }\n\n // Read the vBRIEF plan — must be spec-compliant format\n const doc = readWorkspacePlan(workspacePath);\n if (!doc) {\n return { success: false, created: [], errors: ['No plan.vbrief.json found in workspace'], beadIds };\n }\n\n const { plan } = doc;\n\n // Verify db connectivity — the Dolt database for this project may not exist yet\n // on fresh installs (bd was installed but bd init was never run at the project root).\n // If connectivity fails for any reason and a redirect exists, auto-initialize with\n // the right prefix so beads creation can proceed without manual intervention.\n const issueLabel = plan.id.toLowerCase();\n const redirectExists = existsSync(redirectPath);\n try {\n await execAsync('bd list --json --limit 0', {\n encoding: 'utf-8', cwd: workspacePath, timeout: 8000,\n });\n } catch (connectErr: any) {\n // When redirect exists but DB is unreachable (not found, connection refused, timeout,\n // or any other error), always attempt bd init --prefix to initialize the database.\n // This covers fresh installs, corrupted DBs, and cases where the redirect was created\n // but bd init was never run for this prefix.\n if (redirectExists) {\n const prefix = issueLabel;\n const connectErrMsg = String(connectErr?.message ?? connectErr?.stderr ?? '');\n\n // Categorize the connectivity error for diagnostic clarity\n let connectCategory: string;\n if (connectErrMsg.toLowerCase().includes('connect') || connectErrMsg.toLowerCase().includes('refused') || connectErrMsg.toLowerCase().includes('econnrefused')) {\n connectCategory = 'Dolt server not running';\n } else if (connectErrMsg.toLowerCase().includes('not found') || connectErrMsg.toLowerCase().includes('not exist') || connectErrMsg.toLowerCase().includes('no such')) {\n connectCategory = 'database not found';\n } else {\n connectCategory = connectErrMsg.split('\\n')[0] || 'unknown connectivity error';\n }\n\n console.log(`[beads] Database unreachable (${connectCategory}) — auto-running bd init --prefix ${prefix}`);\n try {\n await execAsync(`bd init --prefix ${prefix}`, {\n encoding: 'utf-8', cwd: workspacePath, timeout: 20000,\n });\n await execAsync('git config beads.role contributor', { cwd: workspacePath }).catch(() => {});\n console.log(`[beads] bd init succeeded for prefix ${prefix}`);\n } catch (initErr: any) {\n // Init failed — return early with a specific error so callers know exactly what happened\n // rather than proceeding with bead creation against a broken database.\n const initErrMsg = String(initErr?.message ?? initErr?.stderr ?? '');\n const detail = `database init failed: ${initErrMsg.split('\\n')[0]} (connectivity: ${connectCategory})`;\n console.warn(`[beads] ${detail}`);\n return { success: false, created: [], errors: [detail], beadIds };\n }\n }\n }\n\n // Idempotency: clear any existing beads for this issue before creating new ones.\n // Re-planning means \"the old plan was invalid\" — start fresh.\n try {\n const { stdout: existingJson } = await execAsync(\n `bd list --json -l \"${issueLabel}\" --status all --limit 0`,\n { encoding: 'utf-8', cwd: workspacePath, timeout: 15000 }\n );\n const existingBeads = JSON.parse(existingJson || '[]');\n if (Array.isArray(existingBeads) && existingBeads.length > 0) {\n const ids = existingBeads.map((b: any) => b.id).filter(Boolean);\n for (const id of ids) {\n try {\n await execAsync(`bd delete ${id} --force`, { encoding: 'utf-8', cwd: workspacePath, timeout: 10000 });\n } catch {\n // Individual delete failure is non-fatal\n }\n }\n console.log(`[beads] Cleared ${ids.length} existing beads for ${issueLabel} before re-creating`);\n }\n } catch {\n // If listing fails (no beads exist, bd not initialized), proceed with creation\n }\n\n // Build blocking-edge map: item.id → set of item IDs that block it\n // (i.e., blockers[B] = { A } means A blocks B, so B depends on A)\n const blockers = new Map<string, Set<string>>();\n for (const item of plan.items) {\n blockers.set(item.id, new Set());\n }\n for (const edge of plan.edges) {\n if (edge.type === 'blocks') {\n const blockersOfTo = blockers.get(edge.to);\n if (blockersOfTo) {\n blockersOfTo.add(edge.from);\n }\n }\n }\n\n // Topological sort (Kahn's algorithm) so we create items after their blockers\n const inDegree = new Map<string, number>();\n const adjacency = new Map<string, string[]>(); // from → list of items it blocks\n for (const item of plan.items) {\n inDegree.set(item.id, 0);\n adjacency.set(item.id, []);\n }\n for (const edge of plan.edges) {\n if (edge.type === 'blocks') {\n inDegree.set(edge.to, (inDegree.get(edge.to) ?? 0) + 1);\n adjacency.get(edge.from)?.push(edge.to);\n }\n }\n\n const queue: string[] = [];\n for (const item of plan.items) {\n if ((inDegree.get(item.id) ?? 0) === 0) {\n queue.push(item.id);\n }\n }\n\n const itemById = new Map<string, VBriefItem>(plan.items.map(i => [i.id, i]));\n const sortedIds: string[] = [];\n while (queue.length > 0) {\n const id = queue.shift()!;\n sortedIds.push(id);\n for (const dependent of adjacency.get(id) ?? []) {\n const newDegree = (inDegree.get(dependent) ?? 1) - 1;\n inDegree.set(dependent, newDegree);\n if (newDegree === 0) {\n queue.push(dependent);\n }\n }\n }\n\n // If we have a cycle, fall back to original order\n const orderedIds = sortedIds.length === plan.items.length\n ? sortedIds\n : plan.items.map(i => i.id);\n\n // Create beads in dependency order\n for (const itemId of orderedIds) {\n const item = itemById.get(itemId);\n if (!item) continue;\n\n const fullTitle = `${plan.id}: ${item.title}`;\n const difficulty = item.metadata?.difficulty ?? 'medium';\n const issueLabel = item.metadata?.issueLabel ?? plan.id.toLowerCase();\n const phase = item.metadata?.phase;\n\n try {\n // Build labels\n const labels = [issueLabel, `difficulty:${difficulty}`];\n if (phase !== undefined) labels.push(`phase-${phase}`);\n const labelStr = labels.join(',');\n\n // Build description from narrative Action + acceptance criteria\n const actionText = item.narrative?.Action ?? '';\n const acLines = (item.subItems ?? [])\n .filter(s => s.metadata?.kind === 'acceptance_criterion')\n .map(s => `- AC: ${s.title}`)\n .join('\\n');\n const description = [actionText, acLines].filter(Boolean).join('\\n');\n\n // Build deps from blocking edges (blockers that have been created)\n const blockingDeps = [...(blockers.get(itemId) ?? [])].map(blockerId => {\n const beadId = beadIds.get(blockerId);\n return beadId ? `blocks:${beadId}` : null;\n }).filter((d): d is string => d !== null);\n\n // Assemble bd create command\n const escapedTitle = fullTitle.replace(/\"/g, '\\\\\"');\n let cmd = `bd create \"${escapedTitle}\" --type task --silent -l \"${labelStr}\"`;\n\n if (description) {\n const escapedDesc = description.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n');\n cmd += ` -d \"${escapedDesc}\"`;\n }\n\n if (blockingDeps.length > 0) {\n cmd += ` --deps \"${blockingDeps.join(',')}\"`;\n }\n\n const { stdout } = await execAsync(cmd, { encoding: 'utf-8', cwd: workspacePath });\n const beadId = stdout.trim();\n\n if (beadId) {\n beadIds.set(itemId, beadId);\n created.push(fullTitle);\n } else {\n errors.push(`Created \"${item.title}\" but could not capture bead ID`);\n created.push(fullTitle);\n }\n } catch (error: any) {\n const errMsg = error.stderr?.toString() || error.message || String(error);\n errors.push(`Failed to create \"${item.title}\": ${errMsg.split('\\n')[0]}`);\n }\n }\n\n return { success: errors.length === 0, created, errors, beadIds };\n}\n\n/**\n * Syncs a closed bead's status to the corresponding vBRIEF item.\n *\n * Reads the bead title from .beads/issues.jsonl, strips the issue prefix\n * (e.g. \"PAN-388: Wire createBeadsFromVBrief()\" → \"Wire createBeadsFromVBrief()\"),\n * finds the matching item in plan.vbrief.json, and calls updateItemStatus().\n *\n * No-ops gracefully when:\n * - No plan.vbrief.json exists (legacy workspace)\n * - Bead ID not found in issues.jsonl\n * - No matching vBRIEF item found\n */\n/**\n * Returns the vBRIEF item ID that was updated, or null if no match was found.\n */\nexport function syncBeadStatusToVBrief(\n beadId: string,\n workspacePath: string,\n status: VBriefItemStatus = 'completed',\n /** Optional: bead title from caller (e.g. bd list --json output). Falls back to .beads/issues.jsonl lookup. */\n knownTitle?: string\n): string | null {\n try {\n const doc = readWorkspacePlan(workspacePath);\n if (!doc) return null;\n\n let beadTitle: string | null = knownTitle ?? null;\n\n // Fallback: read bead title from .beads/issues.jsonl (legacy flat-file beads)\n if (!beadTitle) {\n const beadsFile = join(workspacePath, '.beads', 'issues.jsonl');\n if (existsSync(beadsFile)) {\n const lines = readFileSync(beadsFile, 'utf-8').split('\\n').filter(Boolean);\n for (const line of lines) {\n try {\n const bead = JSON.parse(line);\n if (bead.id === beadId && bead.title) {\n beadTitle = bead.title as string;\n break;\n }\n } catch {\n // skip malformed lines\n }\n }\n }\n }\n\n if (!beadTitle) return null;\n\n // Strip issue prefix: \"{PLAN_ID}: {item.title}\" → \"{item.title}\"\n const planId = doc.plan.id;\n const prefix = `${planId}: `;\n const itemTitle = beadTitle.startsWith(prefix)\n ? beadTitle.slice(prefix.length)\n : beadTitle;\n\n // Find matching item (case-insensitive)\n const itemTitleLower = itemTitle.toLowerCase();\n const matchingItem = doc.plan.items.find(\n i => i.title.toLowerCase() === itemTitleLower\n );\n\n if (!matchingItem) return null;\n\n // io.ts handles vBRIEFInfo.updated, plan.updated, plan.sequence, and item.completed\n // timestamps automatically. Each call below constitutes one write → one sequence increment.\n updateItemStatus(workspacePath, matchingItem.id, status);\n\n // Also mark all AC subItems as completed when the parent item is completed.\n // Each updateSubItemStatus call increments sequence separately (one write per subItem).\n if (status === 'completed' && matchingItem.subItems) {\n for (const sub of matchingItem.subItems) {\n if (sub.metadata?.kind === 'acceptance_criterion' && sub.status !== 'completed') {\n updateSubItemStatus(workspacePath, matchingItem.id, sub.id, 'completed');\n }\n }\n }\n\n console.log(`[vbrief-sync] Updated item \"${matchingItem.id}\" to \"${status}\" from bead ${beadId}`);\n return matchingItem.id;\n } catch (err: any) {\n // Non-fatal: log and continue\n console.warn(`[vbrief-sync] Failed to sync bead ${beadId}: ${err.message}`);\n return null;\n }\n}\n\n/** Per-item AC status summary. */\nexport interface ItemACStatus {\n itemId: string;\n itemTitle: string;\n completed: number;\n pending: number;\n total: number;\n criteria: AcceptanceCriterion[];\n}\n\n/** Result of getVBriefACStatus(). null means no plan or no AC found. */\nexport interface VBriefACStatus {\n allCompleted: boolean;\n items: ItemACStatus[];\n totalCompleted: number;\n totalPending: number;\n totalCount: number;\n}\n\n/**\n * Get structured AC status from a workspace's vBRIEF plan.\n *\n * Returns per-item AC counts (completed/pending/total) plus an overall\n * allCompleted flag. Returns null if no plan exists or no AC are found\n * (legacy workspace compatibility).\n *\n * Used by: verification gate, pan work done, merge agent, prompt injection.\n */\nexport function getVBriefACStatus(workspacePath: string): VBriefACStatus | null {\n const doc = readWorkspacePlan(workspacePath);\n if (!doc) return null;\n\n const allCriteria = extractACFromDocument(doc);\n if (allCriteria.length === 0) return null;\n\n // Group by item\n const itemMap = new Map<string, ItemACStatus>();\n for (const ac of allCriteria) {\n let item = itemMap.get(ac.itemId);\n if (!item) {\n item = { itemId: ac.itemId, itemTitle: ac.itemTitle, completed: 0, pending: 0, total: 0, criteria: [] };\n itemMap.set(ac.itemId, item);\n }\n item.total++;\n item.criteria.push(ac);\n if (ac.status === 'completed' || ac.status === 'cancelled') {\n item.completed++;\n } else {\n item.pending++;\n }\n }\n\n const items = Array.from(itemMap.values());\n const totalCompleted = items.reduce((sum, i) => sum + i.completed, 0);\n const totalPending = items.reduce((sum, i) => sum + i.pending, 0);\n const totalCount = totalCompleted + totalPending;\n\n return {\n allCompleted: totalPending === 0,\n items,\n totalCompleted,\n totalPending,\n totalCount,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as getVBriefACStatus, r as syncBeadStatusToVBrief, t as createBeadsFromVBrief } from "./beads-
|
|
1
|
+
import { n as getVBriefACStatus, r as syncBeadStatusToVBrief, t as createBeadsFromVBrief } from "./beads-Bv-AdX7G.js";
|
|
2
2
|
export { createBeadsFromVBrief, getVBriefACStatus, syncBeadStatusToVBrief };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as stepSkipped, n as stepFailed, r as stepOk } from "./types-
|
|
1
|
+
import { i as stepSkipped, n as stepFailed, r as stepOk } from "./types-RKZjGE5N.js";
|
|
2
2
|
import { exec } from "child_process";
|
|
3
3
|
import { promisify } from "util";
|
|
4
4
|
//#region ../../lib/lifecycle/clean-planning.ts
|
|
@@ -74,4 +74,4 @@ async function cleanPlanningArtifacts(ctx) {
|
|
|
74
74
|
//#endregion
|
|
75
75
|
export { cleanPlanningArtifacts as t };
|
|
76
76
|
|
|
77
|
-
//# sourceMappingURL=clean-planning-
|
|
77
|
+
//# sourceMappingURL=clean-planning-VEJu5suh.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clean-planning-
|
|
1
|
+
{"version":3,"file":"clean-planning-VEJu5suh.js","names":[],"sources":["../../src/lib/lifecycle/clean-planning.ts"],"sourcesContent":["/**\n * clean-planning — Remove ephemeral .planning/ artifacts from main after merge.\n *\n * After a feature branch merges to main, ephemeral planning files\n * (STATE.md, PRD.md, PLANNING_PROMPT.md, .planning-complete, feedback/)\n * land on main and pollute new workspaces that inherit them.\n *\n * This module removes those files from the git index and working tree\n * with a dedicated commit, so new workspaces start clean.\n *\n * Idempotent — if none of the target files are tracked, returns skipped.\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport type { LifecycleContext, StepResult } from './types.js';\nimport { stepOk, stepSkipped, stepFailed } from './types.js';\n\nconst execAsync = promisify(exec);\n\n/** Ephemeral planning files to remove from main after merge */\nconst EPHEMERAL_PLANNING_FILES = [\n '.planning/STATE.md',\n '.planning/PRD.md',\n '.planning/WORKSPACE.md',\n '.planning/PLANNING_PROMPT.md',\n '.planning/PLANNING_PROMPT.md.archived',\n '.planning/.planning-complete',\n];\n\n/**\n * Remove ephemeral planning artifacts from main after a feature branch merge.\n *\n * Uses `git rm` to remove tracked files from both the index and working tree,\n * then commits the deletion. Untracked files are silently skipped.\n */\nexport async function cleanPlanningArtifacts(\n ctx: LifecycleContext,\n): Promise<StepResult> {\n const step = 'clean-planning';\n const { issueId, projectPath } = ctx;\n\n try {\n // Build the list of files git is currently tracking in .planning/\n // that match our ephemeral set. We include feedback/ glob separately.\n let trackedFiles: string[] = [];\n\n // Check individual ephemeral files\n for (const file of EPHEMERAL_PLANNING_FILES) {\n try {\n const { stdout } = await execAsync(\n `git ls-files -- ${file}`,\n { cwd: projectPath, encoding: 'utf-8' },\n );\n if (stdout.trim()) {\n trackedFiles.push(file);\n }\n } catch {\n // git ls-files failure is non-fatal\n }\n }\n\n // Check feedback/ directory\n try {\n const { stdout } = await execAsync(\n `git ls-files -- .planning/feedback/`,\n { cwd: projectPath, encoding: 'utf-8' },\n );\n if (stdout.trim()) {\n trackedFiles.push('.planning/feedback/');\n }\n } catch {\n // Non-fatal\n }\n\n if (trackedFiles.length === 0) {\n return stepSkipped(step, ['No tracked ephemeral planning files found on main']);\n }\n\n // Remove tracked files from index and working tree\n const fileArgs = trackedFiles.map(f => `\"${f}\"`).join(' ');\n await execAsync(\n `git rm -rf --ignore-unmatch ${fileArgs}`,\n { cwd: projectPath, encoding: 'utf-8' },\n );\n\n // Check if anything was actually staged for deletion\n try {\n await execAsync('git diff --cached --quiet', { cwd: projectPath, encoding: 'utf-8' });\n // Nothing staged — files may have already been removed\n return stepSkipped(step, ['No staged deletions after git rm (already clean)']);\n } catch {\n // There are staged changes — commit them\n await execAsync(\n `git commit -m \"chore: remove ephemeral planning state after ${issueId} merge\"`,\n { cwd: projectPath, encoding: 'utf-8' },\n );\n }\n\n return stepOk(step, [\n `Removed ${trackedFiles.length} ephemeral planning file(s) from main`,\n `Files: ${trackedFiles.join(', ')}`,\n ]);\n } catch (err) {\n return stepFailed(step, `Failed to clean planning artifacts: ${(err as Error).message}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkBA,MAAM,YAAY,UAAU,KAAK;;AAGjC,MAAM,2BAA2B;CAC/B;CACA;CACA;CACA;CACA;CACA;CACD;;;;;;;AAQD,eAAsB,uBACpB,KACqB;CACrB,MAAM,OAAO;CACb,MAAM,EAAE,SAAS,gBAAgB;AAEjC,KAAI;EAGF,IAAI,eAAyB,EAAE;AAG/B,OAAK,MAAM,QAAQ,yBACjB,KAAI;GACF,MAAM,EAAE,WAAW,MAAM,UACvB,mBAAmB,QACnB;IAAE,KAAK;IAAa,UAAU;IAAS,CACxC;AACD,OAAI,OAAO,MAAM,CACf,cAAa,KAAK,KAAK;UAEnB;AAMV,MAAI;GACF,MAAM,EAAE,WAAW,MAAM,UACvB,uCACA;IAAE,KAAK;IAAa,UAAU;IAAS,CACxC;AACD,OAAI,OAAO,MAAM,CACf,cAAa,KAAK,sBAAsB;UAEpC;AAIR,MAAI,aAAa,WAAW,EAC1B,QAAO,YAAY,MAAM,CAAC,oDAAoD,CAAC;AAKjF,QAAM,UACJ,+BAFe,aAAa,KAAI,MAAK,IAAI,EAAE,GAAG,CAAC,KAAK,IAAI,IAGxD;GAAE,KAAK;GAAa,UAAU;GAAS,CACxC;AAGD,MAAI;AACF,SAAM,UAAU,6BAA6B;IAAE,KAAK;IAAa,UAAU;IAAS,CAAC;AAErF,UAAO,YAAY,MAAM,CAAC,mDAAmD,CAAC;UACxE;AAEN,SAAM,UACJ,+DAA+D,QAAQ,UACvE;IAAE,KAAK;IAAa,UAAU;IAAS,CACxC;;AAGH,SAAO,OAAO,MAAM,CAClB,WAAW,aAAa,OAAO,wCAC/B,UAAU,aAAa,KAAK,KAAK,GAClC,CAAC;UACK,KAAK;AACZ,SAAO,WAAW,MAAM,uCAAwC,IAAc,UAAU"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as extractPrefix, r as init_issue_id, t as extractNumber } from "./issue-id-vwYJdsf8.js";
|
|
2
|
+
import { i as stepSkipped, n as stepFailed, r as stepOk, t as getLinearApiKey } from "./types-RKZjGE5N.js";
|
|
2
3
|
import { exec } from "child_process";
|
|
3
4
|
import { promisify } from "util";
|
|
4
5
|
//#region ../../lib/lifecycle/close-issue.ts
|
|
@@ -15,6 +16,7 @@ import { promisify } from "util";
|
|
|
15
16
|
* 3. Remove workflow labels (in-progress, in-review, needs-close-out)
|
|
16
17
|
* 4. Add completion comment
|
|
17
18
|
*/
|
|
19
|
+
init_issue_id();
|
|
18
20
|
const execAsync = promisify(exec);
|
|
19
21
|
const CLOSED_OUT_LABEL = "closed-out";
|
|
20
22
|
const CLOSED_OUT_COLOR = "1d4ed8";
|
|
@@ -122,8 +124,9 @@ async function closeLinearDirect(ctx, apiKey) {
|
|
|
122
124
|
try {
|
|
123
125
|
const { LinearClient } = await import("@linear/sdk");
|
|
124
126
|
const client = new LinearClient({ apiKey });
|
|
125
|
-
const issueNumber =
|
|
126
|
-
const issuePrefix = ctx.issueId
|
|
127
|
+
const issueNumber = extractNumber(ctx.issueId);
|
|
128
|
+
const issuePrefix = extractPrefix(ctx.issueId);
|
|
129
|
+
if (issueNumber === null || issuePrefix === null) return stepFailed(step, `Could not parse issue ID: ${ctx.issueId}`);
|
|
127
130
|
const results = await client.issues({
|
|
128
131
|
filter: {
|
|
129
132
|
number: { eq: issueNumber },
|
|
@@ -157,7 +160,7 @@ async function closeRallyDirect(ctx) {
|
|
|
157
160
|
const step = "close-issue:transition";
|
|
158
161
|
if (!ctx.rally) return stepFailed(step, "Rally config not provided");
|
|
159
162
|
try {
|
|
160
|
-
const { RallyTracker } = await import("./rally-
|
|
163
|
+
const { RallyTracker } = await import("./rally-6McpKKRa.js");
|
|
161
164
|
await new RallyTracker({
|
|
162
165
|
apiKey: ctx.rally.apiKey,
|
|
163
166
|
server: ctx.rally.server,
|
|
@@ -210,8 +213,9 @@ async function applyLabelLinear(ctx, apiKey) {
|
|
|
210
213
|
try {
|
|
211
214
|
const { LinearClient } = await import("@linear/sdk");
|
|
212
215
|
const client = new LinearClient({ apiKey });
|
|
213
|
-
const issueNum =
|
|
214
|
-
const teamKey = ctx.issueId
|
|
216
|
+
const issueNum = extractNumber(ctx.issueId);
|
|
217
|
+
const teamKey = extractPrefix(ctx.issueId);
|
|
218
|
+
if (issueNum === null || teamKey === null) return stepFailed(step, `Could not parse issue ID: ${ctx.issueId}`);
|
|
215
219
|
const results = await client.issues({
|
|
216
220
|
filter: {
|
|
217
221
|
number: { eq: issueNum },
|
|
@@ -246,4 +250,4 @@ async function applyLabelLinear(ctx, apiKey) {
|
|
|
246
250
|
//#endregion
|
|
247
251
|
export { closeIssue as t };
|
|
248
252
|
|
|
249
|
-
//# sourceMappingURL=close-issue-
|
|
253
|
+
//# sourceMappingURL=close-issue-DtKdsSTm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"close-issue-DtKdsSTm.js","names":[],"sources":["../../src/lib/lifecycle/close-issue.ts"],"sourcesContent":["/**\n * close-issue — Transition issue to closed/done state + label management.\n *\n * Uses the IssueTracker abstraction when available, with fallback to\n * direct API calls for contexts where the tracker isn't set up (e.g.,\n * standalone CLI).\n *\n * Operations:\n * 1. Transition issue to closed state\n * 2. Add 'closed-out' label\n * 3. Remove workflow labels (in-progress, in-review, needs-close-out)\n * 4. Add completion comment\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport type { IssueTracker } from '../tracker/interface.js';\nimport type { LifecycleContext, StepResult } from './types.js';\nimport { stepOk, stepSkipped, stepFailed, getLinearApiKey } from './types.js';\nimport { extractNumber, extractPrefix } from '../issue-id.js';\n\nconst execAsync = promisify(exec);\n\nconst CLOSED_OUT_LABEL = 'closed-out';\nconst CLOSED_OUT_COLOR = '1d4ed8';\nconst WORKFLOW_LABELS = ['in-progress', 'in-review', 'needs-close-out'];\n\n/** Options for close-issue */\nexport interface CloseIssueOptions {\n /** IssueTracker instance (preferred — uses abstraction layer) */\n tracker?: IssueTracker;\n /** Reason for closing */\n reason?: string;\n /** Comment to add when closing */\n comment?: string;\n /** Apply the closed-out label. Default: true */\n applyLabel?: boolean;\n /** Only apply label (skip state transition). Default: false */\n labelOnly?: boolean;\n}\n\n/**\n * Close an issue and manage labels.\n *\n * If a tracker is provided, uses the abstraction layer.\n * Otherwise, falls back to direct gh CLI (GitHub) or Linear SDK calls.\n */\nexport async function closeIssue(\n ctx: LifecycleContext,\n opts: CloseIssueOptions = {},\n): Promise<StepResult[]> {\n const results: StepResult[] = [];\n const { applyLabel = true, labelOnly = false, comment } = opts;\n\n // Step 1: Transition to closed (unless labelOnly)\n if (!labelOnly) {\n const closeResult = opts.tracker\n ? await closeViaTracker(ctx, opts.tracker, comment)\n : await closeViaDirect(ctx, comment);\n results.push(closeResult);\n\n // If close failed, don't bother with labels\n if (!closeResult.success && !closeResult.skipped) {\n return results;\n }\n }\n\n // Step 2: Close any open PR for the feature branch (GitHub only)\n if (ctx.github) {\n const prResult = await closeGitHubPr(ctx);\n results.push(prResult);\n }\n\n // Step 3: Apply closed-out label + remove workflow labels\n if (applyLabel) {\n const labelResult = await applyClosedOutLabel(ctx, opts.tracker);\n results.push(labelResult);\n }\n\n return results;\n}\n\n/**\n * Close via IssueTracker abstraction.\n */\nasync function closeViaTracker(\n ctx: LifecycleContext,\n tracker: IssueTracker,\n comment?: string,\n): Promise<StepResult> {\n const step = 'close-issue:transition';\n try {\n await tracker.transitionIssue(ctx.issueId, 'closed');\n if (comment) {\n try {\n await tracker.addComment(ctx.issueId, comment);\n } catch {\n // Non-fatal — comment is best-effort\n }\n }\n return stepOk(step, [`Closed ${ctx.issueId} via ${tracker.name} tracker`]);\n } catch (err) {\n return stepFailed(step, `Failed to close via tracker: ${(err as Error).message}`);\n }\n}\n\n/**\n * Close via direct API calls (fallback when no tracker configured).\n * Determines issue type from context and uses appropriate method.\n */\nasync function closeViaDirect(\n ctx: LifecycleContext,\n comment?: string,\n): Promise<StepResult> {\n const step = 'close-issue:transition';\n\n if (ctx.github) {\n return closeGitHubDirect(ctx, comment);\n }\n\n // Rally issue\n if (ctx.rally) {\n return closeRallyDirect(ctx);\n }\n\n // Try Linear\n const linearApiKey = getLinearApiKey();\n if (linearApiKey) {\n return closeLinearDirect(ctx, linearApiKey);\n }\n\n return stepFailed(step, 'No tracker available and cannot determine issue type');\n}\n\n/**\n * Close a GitHub issue via gh CLI.\n */\nasync function closeGitHubDirect(ctx: LifecycleContext, comment?: string): Promise<StepResult> {\n const step = 'close-issue:transition';\n if (!ctx.github) {\n return stepFailed(step, 'GitHub config not provided');\n }\n const { owner, repo, number } = ctx.github;\n try {\n const commentArg = comment ? ` --comment \"${comment.replace(/\"/g, '\\\\\"')}\"` : '';\n await execAsync(\n `gh issue close ${number} --repo ${owner}/${repo}${commentArg}`,\n { encoding: 'utf-8' },\n );\n return stepOk(step, [`Closed GitHub issue #${number} on ${owner}/${repo}`]);\n } catch (err) {\n return stepFailed(step, `gh issue close failed: ${(err as Error).message}`);\n }\n}\n\n/**\n * Close any open GitHub PR for the feature branch.\n */\nasync function closeGitHubPr(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'close-issue:close-pr';\n if (!ctx.github) {\n return stepSkipped(step, ['Not a GitHub issue']);\n }\n const { owner, repo } = ctx.github;\n const issueLower = ctx.issueId.toLowerCase();\n const branchName = `feature/${issueLower}`;\n\n try {\n const { stdout: prListRaw } = await execAsync(\n `gh pr list --repo ${owner}/${repo} --head \"${branchName}\" --state open --json number --jq '.[0].number'`,\n { encoding: 'utf-8' },\n );\n const prNumber = prListRaw.trim();\n if (!prNumber) {\n return stepSkipped(step, ['No open PR found for branch']);\n }\n await execAsync(\n `gh pr close ${prNumber} --repo ${owner}/${repo} --comment \"Merged via Panopticon lifecycle\"`,\n { encoding: 'utf-8' },\n );\n return stepOk(step, [`Closed PR #${prNumber} on ${owner}/${repo}`]);\n } catch (err) {\n return stepSkipped(step, [`PR close failed (non-fatal): ${(err as Error).message}`]);\n }\n}\n\n/**\n * Rate limit circuit breaker for Linear API.\n * After hitting a rate limit, stop all Linear API calls for COOLDOWN_MS.\n * This prevents the 24,626-call storm that exhausted Linear's 5000 req/hr limit (PAN-328).\n */\nlet _linearRateLimitUntil = 0;\nconst LINEAR_RATE_LIMIT_COOLDOWN_MS = 60 * 60 * 1000; // 1 hour (matches Linear's 5000/hr window)\n\n/**\n * Close a Linear issue via SDK (find by identifier, transition to Done).\n */\nasync function closeLinearDirect(ctx: LifecycleContext, apiKey: string): Promise<StepResult> {\n const step = 'close-issue:transition';\n\n // Circuit breaker: if we recently hit a rate limit, fail fast without making API calls\n if (Date.now() < _linearRateLimitUntil) {\n const remainingMin = Math.ceil((_linearRateLimitUntil - Date.now()) / 60000);\n return stepFailed(step, `Linear rate limit cooldown active (${remainingMin}min remaining). Issue will be closed during close-out ceremony.`);\n }\n\n try {\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey });\n\n const issueNumber = extractNumber(ctx.issueId);\n const issuePrefix = extractPrefix(ctx.issueId);\n if (issueNumber === null || issuePrefix === null) {\n return stepFailed(step, `Could not parse issue ID: ${ctx.issueId}`);\n }\n const results = await client.issues({\n filter: {\n number: { eq: issueNumber },\n team: { key: { eq: issuePrefix } },\n },\n first: 1,\n });\n\n if (results.nodes.length === 0) {\n return stepFailed(step, `Issue ${ctx.issueId} not found in Linear`);\n }\n\n const issue = results.nodes[0];\n const team = await issue.team;\n if (team) {\n const states = await team.states();\n const doneState = states.nodes.find(s => s.name === 'Done') ||\n states.nodes.find(s => s.type === 'completed');\n if (doneState) {\n await issue.update({ stateId: doneState.id });\n }\n }\n\n return stepOk(step, [`Moved Linear issue ${ctx.issueId} to Done`]);\n } catch (err) {\n const message = (err as Error).message;\n\n // Detect rate limit errors and activate circuit breaker\n if (message.includes('Rate limit') || message.includes('rate limit') || message.includes('429')) {\n _linearRateLimitUntil = Date.now() + LINEAR_RATE_LIMIT_COOLDOWN_MS;\n console.warn(`[close-issue] Linear rate limit hit — circuit breaker activated for 1 hour`);\n return stepFailed(step, `Linear rate limit exceeded. Circuit breaker activated — no Linear API calls for 1 hour. Issue will be closed during close-out ceremony.`);\n }\n\n return stepFailed(step, `Linear close failed: ${message}`);\n }\n}\n\n/**\n * Close a Rally issue via RallyTracker.\n */\nasync function closeRallyDirect(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'close-issue:transition';\n if (!ctx.rally) {\n return stepFailed(step, 'Rally config not provided');\n }\n try {\n const { RallyTracker } = await import('../tracker/rally.js');\n const tracker = new RallyTracker({\n apiKey: ctx.rally.apiKey,\n server: ctx.rally.server,\n workspace: ctx.rally.workspace,\n project: ctx.rally.project,\n });\n await tracker.transitionIssue(ctx.issueId, 'closed');\n return stepOk(step, [`Closed Rally issue ${ctx.issueId}`]);\n } catch (err) {\n return stepFailed(step, `Rally close failed: ${(err as Error).message}`);\n }\n}\n\n/**\n * Apply 'closed-out' label and remove workflow labels.\n * Uses tracker if available, falls back to direct calls.\n */\nasync function applyClosedOutLabel(\n ctx: LifecycleContext,\n tracker?: IssueTracker,\n): Promise<StepResult> {\n const step = 'close-issue:label';\n\n if (tracker) {\n return applyLabelViaTracker(ctx, tracker);\n }\n\n if (ctx.github) {\n return applyLabelGitHub(ctx);\n }\n\n const linearApiKey = getLinearApiKey();\n if (linearApiKey) {\n return applyLabelLinear(ctx, linearApiKey);\n }\n\n return stepSkipped(step, ['No tracker available for label management']);\n}\n\nasync function applyLabelViaTracker(\n ctx: LifecycleContext,\n tracker: IssueTracker,\n): Promise<StepResult> {\n const step = 'close-issue:label';\n try {\n const issue = await tracker.getIssue(ctx.issueId);\n const newLabels = issue.labels.filter(l => !WORKFLOW_LABELS.includes(l));\n if (!newLabels.includes(CLOSED_OUT_LABEL)) {\n newLabels.push(CLOSED_OUT_LABEL);\n }\n await tracker.updateIssue(ctx.issueId, { labels: newLabels });\n return stepOk(step, [`Applied '${CLOSED_OUT_LABEL}' label via ${tracker.name} tracker`]);\n } catch (err) {\n // Label management is non-fatal\n return stepSkipped(step, [`Label management failed (non-fatal): ${(err as Error).message}`]);\n }\n}\n\nasync function applyLabelGitHub(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'close-issue:label';\n if (!ctx.github) return stepSkipped(step);\n const { owner, repo, number } = ctx.github;\n\n try {\n // Ensure label exists\n await execAsync(\n `gh label create \"${CLOSED_OUT_LABEL}\" --repo ${owner}/${repo} --color \"${CLOSED_OUT_COLOR}\" --description \"Verified and closed out\" --force 2>/dev/null || true`,\n { encoding: 'utf-8' },\n );\n // Add label\n await execAsync(\n `gh issue edit ${number} --repo ${owner}/${repo} --add-label \"${CLOSED_OUT_LABEL}\"`,\n { encoding: 'utf-8' },\n );\n // Remove workflow labels\n for (const label of WORKFLOW_LABELS) {\n await execAsync(\n `gh issue edit ${number} --repo ${owner}/${repo} --remove-label \"${label}\" 2>/dev/null || true`,\n { encoding: 'utf-8' },\n );\n }\n return stepOk(step, [`Applied '${CLOSED_OUT_LABEL}' label on GitHub`]);\n } catch (err) {\n return stepSkipped(step, [`Label management failed (non-fatal): ${(err as Error).message}`]);\n }\n}\n\nasync function applyLabelLinear(ctx: LifecycleContext, apiKey: string): Promise<StepResult> {\n const step = 'close-issue:label';\n try {\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey });\n\n const issueNum = extractNumber(ctx.issueId);\n const teamKey = extractPrefix(ctx.issueId);\n if (issueNum === null || teamKey === null) {\n return stepFailed(step, `Could not parse issue ID: ${ctx.issueId}`);\n }\n const results = await client.issues({\n filter: {\n number: { eq: issueNum },\n team: { key: { eq: teamKey } },\n },\n first: 1,\n });\n if (results.nodes.length === 0) {\n return stepSkipped(step, ['Issue not found for label management']);\n }\n\n const issue = results.nodes[0];\n\n // Find or create closed-out label\n const labels = await client.issueLabels({ filter: { name: { eq: CLOSED_OUT_LABEL } } });\n let labelId: string;\n if (labels.nodes.length > 0) {\n labelId = labels.nodes[0].id;\n } else {\n const created = await client.createIssueLabel({ name: CLOSED_OUT_LABEL, color: `#${CLOSED_OUT_COLOR}` });\n const createdLabel = await created.issueLabel;\n labelId = createdLabel ? createdLabel.id : '';\n }\n\n if (labelId) {\n const existingLabels = await issue.labels();\n const labelIds = existingLabels.nodes.map(l => l.id);\n if (!labelIds.includes(labelId)) {\n labelIds.push(labelId);\n await issue.update({ labelIds });\n }\n }\n\n return stepOk(step, [`Applied '${CLOSED_OUT_LABEL}' label on Linear`]);\n } catch (err) {\n return stepSkipped(step, [`Linear label management failed (non-fatal): ${(err as Error).message}`]);\n }\n}\n\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as stepSkipped, n as stepFailed, r as stepOk } from "./types-
|
|
1
|
+
import { i as stepSkipped, n as stepFailed, r as stepOk } from "./types-RKZjGE5N.js";
|
|
2
2
|
import { existsSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
import { exec } from "child_process";
|
|
@@ -43,4 +43,4 @@ async function compactBeads(ctx, opts = {}) {
|
|
|
43
43
|
//#endregion
|
|
44
44
|
export { compactBeads as t };
|
|
45
45
|
|
|
46
|
-
//# sourceMappingURL=compact-beads-
|
|
46
|
+
//# sourceMappingURL=compact-beads-D8Vt3qyv.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compact-beads-
|
|
1
|
+
{"version":3,"file":"compact-beads-D8Vt3qyv.js","names":[],"sources":["../../src/lib/lifecycle/compact-beads.ts"],"sourcesContent":["/**\n * compact-beads — Beads compaction + git commit/push.\n *\n * Extracted from merge-agent.ts conditionalBeadsCompaction().\n * Compacts closed beads older than 30 days and commits the result.\n */\n\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport type { LifecycleContext, StepResult } from './types.js';\nimport { stepOk, stepSkipped, stepFailed } from './types.js';\n\nconst execAsync = promisify(exec);\n\n/** Options for beads compaction */\nexport interface CompactBeadsOptions {\n /** Number of days to keep closed beads. Default: 30 */\n days?: number;\n}\n\n/**\n * Compact closed beads older than N days.\n * Idempotent — returns skip if no beads to compact.\n */\nexport async function compactBeads(\n ctx: LifecycleContext,\n opts: CompactBeadsOptions = {},\n): Promise<StepResult> {\n const { days = 30 } = opts;\n const step = 'compact-beads';\n\n // Check if bd CLI is available\n try {\n await execAsync('which bd', { encoding: 'utf-8' });\n } catch {\n return stepSkipped(step, ['bd CLI not available']);\n }\n\n // Check if .beads directory exists\n const beadsDir = join(ctx.projectPath, '.beads');\n if (!existsSync(beadsDir)) {\n return stepSkipped(step, ['No .beads directory in project']);\n }\n\n // Count old closed beads\n try {\n const { stdout: countOutput } = await execAsync(\n `bd list --status closed --json 2>/dev/null | jq '[.[] | select(.closed_at != null) | select((now - (.closed_at | fromdateiso8601)) > (${days} * 24 * 60 * 60))] | length' 2>/dev/null || echo \"0\"`,\n { cwd: ctx.projectPath, encoding: 'utf-8' },\n );\n\n const count = parseInt(countOutput.trim(), 10) || 0;\n if (count === 0) {\n return stepSkipped(step, ['No closed beads older than ' + days + ' days']);\n }\n\n // Run compaction\n await execAsync(`bd admin compact --days ${days}`, {\n cwd: ctx.projectPath,\n encoding: 'utf-8',\n });\n\n // Beads are ephemeral (derived from vBRIEF) — no git commit needed\n return stepOk(step, [`Compacted ${count} closed beads`]);\n } catch (err) {\n return stepFailed(step, `Beads compaction failed: ${(err as Error).message}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;AAcA,MAAM,YAAY,UAAU,KAAK;;;;;AAYjC,eAAsB,aACpB,KACA,OAA4B,EAAE,EACT;CACrB,MAAM,EAAE,OAAO,OAAO;CACtB,MAAM,OAAO;AAGb,KAAI;AACF,QAAM,UAAU,YAAY,EAAE,UAAU,SAAS,CAAC;SAC5C;AACN,SAAO,YAAY,MAAM,CAAC,uBAAuB,CAAC;;AAKpD,KAAI,CAAC,WADY,KAAK,IAAI,aAAa,SAAS,CACvB,CACvB,QAAO,YAAY,MAAM,CAAC,iCAAiC,CAAC;AAI9D,KAAI;EACF,MAAM,EAAE,QAAQ,gBAAgB,MAAM,UACpC,yIAAyI,KAAK,uDAC9I;GAAE,KAAK,IAAI;GAAa,UAAU;GAAS,CAC5C;EAED,MAAM,QAAQ,SAAS,YAAY,MAAM,EAAE,GAAG,IAAI;AAClD,MAAI,UAAU,EACZ,QAAO,YAAY,MAAM,CAAC,gCAAgC,OAAO,QAAQ,CAAC;AAI5E,QAAM,UAAU,2BAA2B,QAAQ;GACjD,KAAK,IAAI;GACT,UAAU;GACX,CAAC;AAGF,SAAO,OAAO,MAAM,CAAC,aAAa,MAAM,eAAe,CAAC;UACjD,KAAK;AACZ,SAAO,WAAW,MAAM,4BAA6B,IAAc,UAAU"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as __require, n as __esmMin, t as __commonJSMin } from "./chunk-DORXReHP.js";
|
|
2
|
-
import {
|
|
2
|
+
import { _ as init_paths, a as CONFIG_FILE } from "./paths-BDyJ7BiV.js";
|
|
3
3
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
4
4
|
import { dirname, join, parse } from "path";
|
|
5
5
|
import { homedir } from "os";
|
|
@@ -1638,4 +1638,4 @@ var init_config = __esmMin((() => {
|
|
|
1638
1638
|
//#endregion
|
|
1639
1639
|
export { init_config as a, require_toml as c, getDevrootPath as i, getDashboardApiUrl as n, loadConfig as o, getDefaultConfig as r, saveConfig as s, findDevrootForProject as t };
|
|
1640
1640
|
|
|
1641
|
-
//# sourceMappingURL=config-
|
|
1641
|
+
//# sourceMappingURL=config-CDkGjnwy.js.map
|