panopticon-cli 0.6.5 → 0.6.7
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-CXaO6nOE.js} +1 -1
- package/dist/dashboard/public/assets/index-CzFZIb87.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
package/dist/cli/index.js
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { r as __require } from "../chunk-ruWRV7i3.js";
|
|
3
|
-
import { A as SKILLS_DIR, B as TRAEFIK_CERTS_DIR, G as
|
|
4
|
-
import { a as init_config,
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { n as
|
|
8
|
-
import { a as
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { a as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { i as
|
|
15
|
-
import { n as
|
|
16
|
-
import { n as
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { i as
|
|
22
|
-
import { a as
|
|
23
|
-
import { i as
|
|
24
|
-
import {
|
|
25
|
-
import "../
|
|
26
|
-
import {
|
|
27
|
-
import "../
|
|
28
|
-
import
|
|
29
|
-
import {
|
|
3
|
+
import { A as SKILLS_DIR, B as TRAEFIK_CERTS_DIR, G as init_paths, L as SOURCE_TRAEFIK_TEMPLATES, O as PROJECT_PRDS_SUBDIR, R as SYNC_TARGET, S as PRD_DRAFTS_DIR, T as PROJECT_PRDS_ACTIVE_SUBDIR, V as TRAEFIK_DIR, b as PANOPTICON_HOME$1, d as CLAUDE_MD_TEMPLATES, f as COMMANDS_DIR, l as CERTS_DIR, m as CONFIG_FILE$1, t as AGENTS_DIR, u as CLAUDE_DIR, v as INIT_DIRS, w as PROJECT_DOCS_SUBDIR } from "../paths-CDJ_HsbN.js";
|
|
4
|
+
import { a as init_config, n as getDashboardApiUrl, o as loadConfig$1, r as getDefaultConfig, s as saveConfig } from "../config-BQNKsi9G.js";
|
|
5
|
+
import { a as addAlias, c as getShellRcFile, o as detectShell, s as getAliasInstructions } from "../tracker-BhYYvU3p.js";
|
|
6
|
+
import { _ as cleanOldBackups, b as listBackups, m as refreshCache, x as restoreBackup } from "../settings-BcWPTrua.js";
|
|
7
|
+
import { n as extractPrefix, r as init_issue_id, t as extractNumber } from "../issue-id-CAcekoIw.js";
|
|
8
|
+
import { S as unregisterProject, a as findProjectByTeam, c as getProject, f as hasProjects, g as loadProjectsConfig, h as listProjects, m as initializeProjectsConfig, p as init_projects, r as extractTeamPrefix, s as getIssuePrefix, t as PROJECTS_CONFIG_FILE, v as registerProject, y as resolveProjectFromIssue } from "../projects-Bk-5QhFQ.js";
|
|
9
|
+
import { i as needsMigration, n as hasLegacySettings, r as migrateConfig, t as syncCommand$1 } from "../sync-DMfgd389.js";
|
|
10
|
+
import { n as init_workspace_config, r as replacePlaceholders } from "../workspace-config-fUafvYMp.js";
|
|
11
|
+
import { a as detectDnsSyncMethod, f as syncDnsToWindows, m as init_platform, o as ensureBaseDomain, p as detectPlatform$1, s as init_dns } from "../dns-Yxq4NNS7.js";
|
|
12
|
+
import { d as mergeSkillsIntoWorkspace, i as init_workspace_manager, l as applyProjectTemplateOverlay, n as createWorkspace, s as removeWorkspace, t as addReposToWorkspace, u as init_skills_merge } from "../workspace-manager-DuLhnzJV.js";
|
|
13
|
+
import { d as sessionExists, i as createSession, l as sendKeys, o as init_tmux, s as killSession, u as sendKeysAsync } from "../tmux-D6Ah4I8z.js";
|
|
14
|
+
import { a as generateFixedPointPrompt, c as popFromHook, i as clearHook, l as pushToHook, n as init_work_type_router, r as checkHook, s as init_hooks, t as getModelId, u as sendMail } from "../work-type-router-CHjciPyS.js";
|
|
15
|
+
import { C as init_config$1, D as getAgentRankings, E as getAgentCV, O as init_cv, S as getHealthThresholdsMs, T as formatCV, _ as saveAgentState, a as getAgentRuntimeState, b as stopAgent, c as getProviderEnvForModel, d as init_agents, f as listRunningAgents, g as saveAgentRuntimeState, m as recoverAgent, n as detectCrashedAgents, o as getAgentState, p as messageAgent, r as getAgentDir, t as autoRecoverAgents, v as saveSessionId, w as loadCloisterConfig, y as spawnAgent } from "../agents-CfFDs52G.js";
|
|
16
|
+
import { n as init_config_yaml, r as loadConfig$2 } from "../config-yaml-DGbLSMCa.js";
|
|
17
|
+
import { i as NotImplementedError, o as init_interface } from "../rally-Dy00NElU.js";
|
|
18
|
+
import { n as createTrackerFromConfig, o as init_factory, t as createTracker } from "../factory-DzsOiZVc.js";
|
|
19
|
+
import { n as resolveGitHubIssue, r as resolveTrackerType, t as isGitHubIssue } from "../tracker-utils-ChQyut8w.js";
|
|
20
|
+
import { a as isShadowed, c as needsSync, d as updateTrackerStatusCache, i as getUnsyncedHistory, n as getPendingSyncCount, o as listShadowedIssues, r as getShadowState, s as markAsSynced, t as createShadowState, u as updateShadowState } from "../shadow-state-CE3dQfll.js";
|
|
21
|
+
import { a as findRemoteWorkspaceMetadata, i as deleteWorkspaceMetadata, n as isRemoteAvailable, o as loadWorkspaceMetadata, r as WORKSPACES_DIR, s as saveWorkspaceMetadata, t as createFlyProviderFromConfig } from "../remote-CYiOJg0q.js";
|
|
22
|
+
import { a as spawnRemoteAgent, n as isRemoteAgentRunning, o as createFlyProvider } from "../remote-agents-CZXrUF4f.js";
|
|
23
|
+
import { At as formatCost, Bt as init_io, Ct as getProjectDirs, D as getSpecialistStatus, Dt as checkBudget, Et as parseClaudeSession, Ft as getWeeklySummary, H as recordWake, Ht as updateItemStatus, It as init_cost, Lt as readIssueCosts, Mt as getAllBudgets, Nt as getDailySummary, O as getTmuxSessionName, Ot as createBudget, Pt as getMonthlySummary, Rt as readTodayCosts, T as getSpecialistMetadata, Tt as init_jsonl_parser, Ut as updateSubItemStatus, Vt as readWorkspacePlan, Y as spawnEphemeralSpecialist, a as completeSpecialistTask, f as getAllProjectSpecialistStatuses, i as clearSessionId, it as wakeSpecialistOrQueue, j as init_specialists, jt as generateReport$1, kt as deleteBudget, p as getAllSpecialistStatus, q as setSessionId, r as checkSpecialistQueue, w as getSessionId, wt as getSessionFiles, zt as summarizeCosts } from "../specialists-D7Kj5o6s.js";
|
|
24
|
+
import { i as init_tldr_daemon, n as getTldrDaemonService, r as getTldrMetrics } from "../tldr-daemon-CFx4LXAl.js";
|
|
25
|
+
import { a as saveReviewStatuses, c as getDatabase, i as loadReviewStatuses, l as init_database, o as setReviewStatus, r as init_review_status, s as closeDatabase } from "../review-status-DEDvCKMP.js";
|
|
26
|
+
import { i as stepSkipped, n as stepFailed, r as stepOk } from "../types-BhJj1SP1.js";
|
|
27
|
+
import { r as findWorkspacePath, t as archivePlanning } from "../archive-planning-D97ziGec.js";
|
|
28
|
+
import "../clean-planning-D_lz4aQq.js";
|
|
29
|
+
import { t as closeIssue } from "../close-issue-CaFE0stN.js";
|
|
30
|
+
import "../compact-beads-CjFkteSU.js";
|
|
31
|
+
import { a as generateTlsConfig, i as generatePanopticonTraefikConfig, n as cleanupTemplateFiles, r as ensureProjectCerts } from "../traefik-C80EbDu_.js";
|
|
32
|
+
import { appendFileSync, chmodSync, copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "fs";
|
|
30
33
|
import { basename, dirname, join, resolve } from "path";
|
|
31
34
|
import { homedir, platform } from "os";
|
|
32
35
|
import { Command } from "commander";
|
|
@@ -35,7 +38,6 @@ import { fileURLToPath } from "url";
|
|
|
35
38
|
import ora from "ora";
|
|
36
39
|
import { exec, execFile, execSync, spawn } from "child_process";
|
|
37
40
|
import { parse as parse$1 } from "yaml";
|
|
38
|
-
import yaml from "js-yaml";
|
|
39
41
|
import { promisify } from "util";
|
|
40
42
|
import inquirer from "inquirer";
|
|
41
43
|
import { LinearClient } from "@linear/sdk";
|
|
@@ -119,8 +121,7 @@ async function initCommand$1() {
|
|
|
119
121
|
}
|
|
120
122
|
console.log("");
|
|
121
123
|
console.log("Next steps:");
|
|
122
|
-
console.log(chalk.dim(" 1.
|
|
123
|
-
console.log(chalk.dim(" 2. Start dashboard: pan up"));
|
|
124
|
+
console.log(chalk.dim(" 1. Start dashboard: pan up (auto-syncs skills)"));
|
|
124
125
|
} catch (error) {
|
|
125
126
|
spinner.fail("Failed to initialize");
|
|
126
127
|
console.error(chalk.red(error.message));
|
|
@@ -128,675 +129,6 @@ async function initCommand$1() {
|
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
131
|
//#endregion
|
|
131
|
-
//#region src/lib/config-migration.ts
|
|
132
|
-
init_projects();
|
|
133
|
-
/**
|
|
134
|
-
* Configuration Migration
|
|
135
|
-
*
|
|
136
|
-
* Migrates from legacy settings.json format to new config.yaml format.
|
|
137
|
-
* Legacy presets are no longer supported - all selection is now smart/capability-based.
|
|
138
|
-
*/
|
|
139
|
-
/** Path to legacy settings file */
|
|
140
|
-
const LEGACY_SETTINGS_PATH = join(homedir(), ".panopticon", "settings.json");
|
|
141
|
-
/** Path to new config file */
|
|
142
|
-
const NEW_CONFIG_PATH = join(homedir(), ".panopticon", "config.yaml");
|
|
143
|
-
/** Path to backup of legacy settings */
|
|
144
|
-
const BACKUP_SETTINGS_PATH = join(homedir(), ".panopticon", "settings.json.backup");
|
|
145
|
-
/**
|
|
146
|
-
* Check if migration is needed
|
|
147
|
-
* Returns true if settings.json exists and config.yaml doesn't
|
|
148
|
-
*/
|
|
149
|
-
function needsMigration() {
|
|
150
|
-
return existsSync(LEGACY_SETTINGS_PATH) && !existsSync(NEW_CONFIG_PATH);
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Check if legacy settings exist (even if already migrated)
|
|
154
|
-
*/
|
|
155
|
-
function hasLegacySettings() {
|
|
156
|
-
return existsSync(LEGACY_SETTINGS_PATH);
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Determine which providers are enabled based on API keys
|
|
160
|
-
*/
|
|
161
|
-
function detectEnabledProviders(settings) {
|
|
162
|
-
return {
|
|
163
|
-
anthropic: true,
|
|
164
|
-
openai: !!settings.api_keys.openai,
|
|
165
|
-
google: !!settings.api_keys.google,
|
|
166
|
-
zai: !!settings.api_keys.zai,
|
|
167
|
-
kimi: false
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Convert legacy settings.json to new config.yaml format
|
|
172
|
-
*/
|
|
173
|
-
function convertToYamlConfig(settings) {
|
|
174
|
-
return {
|
|
175
|
-
models: {
|
|
176
|
-
providers: detectEnabledProviders(settings),
|
|
177
|
-
overrides: {},
|
|
178
|
-
gemini_thinking_level: 3
|
|
179
|
-
},
|
|
180
|
-
api_keys: settings.api_keys
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
function migrateConfig(options = {}) {
|
|
184
|
-
const { backup = true, deleteLegacy = false, dryRun = false } = options;
|
|
185
|
-
try {
|
|
186
|
-
if (!needsMigration()) {
|
|
187
|
-
if (existsSync(NEW_CONFIG_PATH)) return {
|
|
188
|
-
success: true,
|
|
189
|
-
overridesCount: 0,
|
|
190
|
-
providersEnabled: ["anthropic"],
|
|
191
|
-
message: "Config already migrated (config.yaml exists)"
|
|
192
|
-
};
|
|
193
|
-
return {
|
|
194
|
-
success: false,
|
|
195
|
-
overridesCount: 0,
|
|
196
|
-
providersEnabled: [],
|
|
197
|
-
message: "No legacy settings.json found to migrate"
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
const yamlConfig = convertToYamlConfig(loadSettings());
|
|
201
|
-
const yamlContent = yaml.dump(yamlConfig, {
|
|
202
|
-
indent: 2,
|
|
203
|
-
lineWidth: 120,
|
|
204
|
-
noRefs: true
|
|
205
|
-
});
|
|
206
|
-
if (dryRun) {
|
|
207
|
-
const providersEnabled = Object.entries(yamlConfig.models?.providers || {}).filter(([_, enabled]) => enabled).map(([name]) => name);
|
|
208
|
-
return {
|
|
209
|
-
success: true,
|
|
210
|
-
overridesCount: Object.keys(yamlConfig.models?.overrides || {}).length,
|
|
211
|
-
providersEnabled,
|
|
212
|
-
message: `Would migrate to smart selection with ${providersEnabled.length} providers enabled`
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
writeFileSync(NEW_CONFIG_PATH, yamlContent, "utf-8");
|
|
216
|
-
if (backup) writeFileSync(BACKUP_SETTINGS_PATH, readFileSync(LEGACY_SETTINGS_PATH, "utf-8"), "utf-8");
|
|
217
|
-
if (deleteLegacy) renameSync(LEGACY_SETTINGS_PATH, `${LEGACY_SETTINGS_PATH}.migrated`);
|
|
218
|
-
const providersEnabled = Object.entries(yamlConfig.models?.providers || {}).filter(([_, enabled]) => enabled).map(([name]) => name);
|
|
219
|
-
return {
|
|
220
|
-
success: true,
|
|
221
|
-
overridesCount: Object.keys(yamlConfig.models?.overrides || {}).length,
|
|
222
|
-
providersEnabled,
|
|
223
|
-
message: `Successfully migrated to smart selection with ${providersEnabled.length} providers`
|
|
224
|
-
};
|
|
225
|
-
} catch (error) {
|
|
226
|
-
return {
|
|
227
|
-
success: false,
|
|
228
|
-
overridesCount: 0,
|
|
229
|
-
providersEnabled: [],
|
|
230
|
-
message: "Migration failed",
|
|
231
|
-
error: error.message
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
function cleanupLegacyRuntimeSymlinks() {
|
|
236
|
-
const legacyDirs = [
|
|
237
|
-
{
|
|
238
|
-
name: "codex",
|
|
239
|
-
base: join(homedir(), ".codex")
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
name: "cursor",
|
|
243
|
-
base: join(homedir(), ".cursor")
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
name: "gemini",
|
|
247
|
-
base: join(homedir(), ".gemini")
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
name: "opencode",
|
|
251
|
-
base: join(homedir(), ".opencode")
|
|
252
|
-
}
|
|
253
|
-
];
|
|
254
|
-
const cleaned = [];
|
|
255
|
-
const errors = [];
|
|
256
|
-
for (const { name, base } of legacyDirs) for (const subdir of [
|
|
257
|
-
"skills",
|
|
258
|
-
"commands",
|
|
259
|
-
"agents"
|
|
260
|
-
]) {
|
|
261
|
-
const dir = join(base, subdir);
|
|
262
|
-
if (!existsSync(dir)) continue;
|
|
263
|
-
try {
|
|
264
|
-
const entries = readdirSync(dir);
|
|
265
|
-
for (const entry of entries) {
|
|
266
|
-
const entryPath = join(dir, entry);
|
|
267
|
-
try {
|
|
268
|
-
if (!lstatSync(entryPath).isSymbolicLink()) continue;
|
|
269
|
-
if (readlinkSync(entryPath).includes(".panopticon")) {
|
|
270
|
-
unlinkSync(entryPath);
|
|
271
|
-
cleaned.push(`${name}/${subdir}/${entry}`);
|
|
272
|
-
}
|
|
273
|
-
} catch (err) {
|
|
274
|
-
errors.push(`${name}/${subdir}/${entry}: ${err.message}`);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
} catch (err) {
|
|
278
|
-
errors.push(`${name}/${subdir}: ${err.message}`);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return {
|
|
282
|
-
cleaned,
|
|
283
|
-
total: cleaned.length,
|
|
284
|
-
errors
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Migrate legacy sync config by stripping the 'targets' field from config.toml.
|
|
289
|
-
* This handles users who had `targets = ["claude", "codex"]` in their config.
|
|
290
|
-
*/
|
|
291
|
-
function migrateSyncTargets() {
|
|
292
|
-
const configPath = join(homedir(), ".panopticon", "config.toml");
|
|
293
|
-
if (!existsSync(configPath)) return {
|
|
294
|
-
migrated: false,
|
|
295
|
-
hadNonClaudeTargets: false
|
|
296
|
-
};
|
|
297
|
-
try {
|
|
298
|
-
const content = readFileSync(configPath, "utf-8");
|
|
299
|
-
const targetsMatch = content.match(/^targets\s*=\s*\[([^\]]*)\]/m);
|
|
300
|
-
if (!targetsMatch) return {
|
|
301
|
-
migrated: false,
|
|
302
|
-
hadNonClaudeTargets: false
|
|
303
|
-
};
|
|
304
|
-
const targetsStr = targetsMatch[1];
|
|
305
|
-
const hadNonClaudeTargets = /codex|cursor|gemini|opencode/i.test(targetsStr);
|
|
306
|
-
writeFileSync(configPath, content.replace(/^targets\s*=\s*\[[^\]]*\]\s*\n?/m, ""), "utf-8");
|
|
307
|
-
return {
|
|
308
|
-
migrated: true,
|
|
309
|
-
hadNonClaudeTargets
|
|
310
|
-
};
|
|
311
|
-
} catch {
|
|
312
|
-
return {
|
|
313
|
-
migrated: false,
|
|
314
|
-
hadNonClaudeTargets: false
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
//#endregion
|
|
319
|
-
//#region src/lib/multi-tool-sync.ts
|
|
320
|
-
init_workspace_config();
|
|
321
|
-
init_platform();
|
|
322
|
-
init_dns();
|
|
323
|
-
init_skills_merge();
|
|
324
|
-
init_workspace_manager();
|
|
325
|
-
/**
|
|
326
|
-
* Multi-Tool Skill Sync
|
|
327
|
-
*
|
|
328
|
-
* Writes Panopticon skills to other AI tool formats so skills authored once
|
|
329
|
-
* in .pan/skills/ are available across all configured tools.
|
|
330
|
-
*
|
|
331
|
-
* Configured via `tools.also_sync` in ~/.panopticon/config.yaml and .pan.yaml.
|
|
332
|
-
* Per-project .pan.yaml values are merged additively with global config.
|
|
333
|
-
*
|
|
334
|
-
* Supported targets:
|
|
335
|
-
* cursor → .cursor/rules/<skill-name>.mdc
|
|
336
|
-
* codex → AGENTS.md (named blocks)
|
|
337
|
-
* windsurf → .windsurf/rules/<skill-name>.md
|
|
338
|
-
* cline → .clinerules/<skill-name>.md
|
|
339
|
-
* copilot → .github/instructions/<skill-name>.instructions.md
|
|
340
|
-
* aider → CONVENTIONS.md (named blocks)
|
|
341
|
-
*/
|
|
342
|
-
init_paths();
|
|
343
|
-
/** Strip YAML frontmatter from a skill markdown file */
|
|
344
|
-
function stripFrontmatter(content) {
|
|
345
|
-
if (!content.startsWith("---")) return content;
|
|
346
|
-
const end = content.indexOf("\n---", 4);
|
|
347
|
-
if (end === -1) return content;
|
|
348
|
-
return content.slice(end + 4).trimStart();
|
|
349
|
-
}
|
|
350
|
-
/** Extract the skill name from frontmatter, or fall back to dir name */
|
|
351
|
-
function extractSkillName(content, fallback) {
|
|
352
|
-
if (!content.startsWith("---")) return fallback;
|
|
353
|
-
const end = content.indexOf("\n---", 4);
|
|
354
|
-
if (end === -1) return fallback;
|
|
355
|
-
const match = content.slice(4, end).match(/^name:\s*(.+)$/m);
|
|
356
|
-
return match ? match[1].trim() : fallback;
|
|
357
|
-
}
|
|
358
|
-
/** Read main SKILL.md content for a skill directory */
|
|
359
|
-
function readSkillContent(skillDir) {
|
|
360
|
-
const skillMd = join(skillDir, "SKILL.md");
|
|
361
|
-
if (!existsSync(skillMd)) {
|
|
362
|
-
const files = existsSync(skillDir) ? readdirSync(skillDir).filter((f) => f.endsWith(".md")) : [];
|
|
363
|
-
if (files.length === 0) return null;
|
|
364
|
-
return readFileSync(join(skillDir, files[0]), "utf-8");
|
|
365
|
-
}
|
|
366
|
-
return readFileSync(skillMd, "utf-8");
|
|
367
|
-
}
|
|
368
|
-
/** Collect all skill directories from the given skills root */
|
|
369
|
-
function collectSkillDirs(skillsDir) {
|
|
370
|
-
if (!existsSync(skillsDir)) return [];
|
|
371
|
-
return readdirSync(skillsDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => ({
|
|
372
|
-
name: e.name,
|
|
373
|
-
dir: join(skillsDir, e.name)
|
|
374
|
-
}));
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Update or insert a named block in a file.
|
|
378
|
-
* Blocks are delimited by: <!-- panopticon:<skill-name> start --> ... <!-- panopticon:<skill-name> end -->
|
|
379
|
-
*/
|
|
380
|
-
function upsertNamedBlock(filePath, blockName, content) {
|
|
381
|
-
const startTag = `<!-- panopticon:${blockName} start -->`;
|
|
382
|
-
const endTag = `<!-- panopticon:${blockName} end -->`;
|
|
383
|
-
const block = `${startTag}\n${content}\n${endTag}`;
|
|
384
|
-
let existing = existsSync(filePath) ? readFileSync(filePath, "utf-8") : "";
|
|
385
|
-
const startIdx = existing.indexOf(startTag);
|
|
386
|
-
const endIdx = existing.indexOf(endTag);
|
|
387
|
-
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) existing = existing.slice(0, startIdx) + block + existing.slice(endIdx + endTag.length);
|
|
388
|
-
else {
|
|
389
|
-
if (existing.length > 0 && !existing.endsWith("\n")) existing += "\n";
|
|
390
|
-
existing += "\n" + block + "\n";
|
|
391
|
-
}
|
|
392
|
-
writeFileSync(filePath, existing, "utf-8");
|
|
393
|
-
}
|
|
394
|
-
/** Sync a single skill to the cursor target */
|
|
395
|
-
function syncToCursor(projectPath, skillName, rawContent) {
|
|
396
|
-
const rulesDir = join(projectPath, ".cursor", "rules");
|
|
397
|
-
mkdirSync(rulesDir, { recursive: true });
|
|
398
|
-
const body = stripFrontmatter(rawContent);
|
|
399
|
-
writeFileSync(join(rulesDir, `${skillName}.mdc`), body, "utf-8");
|
|
400
|
-
}
|
|
401
|
-
/** Sync a single skill to the windsurf target */
|
|
402
|
-
function syncToWindsurf(projectPath, skillName, rawContent) {
|
|
403
|
-
const rulesDir = join(projectPath, ".windsurf", "rules");
|
|
404
|
-
mkdirSync(rulesDir, { recursive: true });
|
|
405
|
-
writeFileSync(join(rulesDir, `${skillName}.md`), stripFrontmatter(rawContent), "utf-8");
|
|
406
|
-
}
|
|
407
|
-
/** Sync a single skill to the cline target */
|
|
408
|
-
function syncToCline(projectPath, skillName, rawContent) {
|
|
409
|
-
const rulesDir = join(projectPath, ".clinerules");
|
|
410
|
-
mkdirSync(rulesDir, { recursive: true });
|
|
411
|
-
writeFileSync(join(rulesDir, `${skillName}.md`), stripFrontmatter(rawContent), "utf-8");
|
|
412
|
-
}
|
|
413
|
-
/** Sync a single skill to the copilot target */
|
|
414
|
-
function syncToCopilot(projectPath, skillName, rawContent) {
|
|
415
|
-
const instructionsDir = join(projectPath, ".github", "instructions");
|
|
416
|
-
mkdirSync(instructionsDir, { recursive: true });
|
|
417
|
-
writeFileSync(join(instructionsDir, `${skillName}.instructions.md`), stripFrontmatter(rawContent), "utf-8");
|
|
418
|
-
}
|
|
419
|
-
/** Sync a single skill to AGENTS.md (codex) as a named block */
|
|
420
|
-
function syncToCodex(projectPath, skillName, rawContent) {
|
|
421
|
-
upsertNamedBlock(join(projectPath, "AGENTS.md"), skillName, `## ${skillName}\n\n${stripFrontmatter(rawContent)}`);
|
|
422
|
-
}
|
|
423
|
-
/** Sync a single skill to CONVENTIONS.md (aider) as a named block */
|
|
424
|
-
function syncToAider(projectPath, skillName, rawContent) {
|
|
425
|
-
upsertNamedBlock(join(projectPath, "CONVENTIONS.md"), skillName, `## ${skillName}\n\n${stripFrontmatter(rawContent)}`);
|
|
426
|
-
}
|
|
427
|
-
const TOOL_WRITERS = {
|
|
428
|
-
cursor: syncToCursor,
|
|
429
|
-
windsurf: syncToWindsurf,
|
|
430
|
-
cline: syncToCline,
|
|
431
|
-
copilot: syncToCopilot,
|
|
432
|
-
codex: syncToCodex,
|
|
433
|
-
aider: syncToAider
|
|
434
|
-
};
|
|
435
|
-
/**
|
|
436
|
-
* Resolve the merged list of tools to sync.
|
|
437
|
-
* Global config is the base; per-project .pan.yaml adds more (never removes).
|
|
438
|
-
*/
|
|
439
|
-
function resolveAlsoSyncTools(projectPath) {
|
|
440
|
-
const tools = /* @__PURE__ */ new Set();
|
|
441
|
-
const globalConfig = join(PANOPTICON_HOME$1, "config.yaml");
|
|
442
|
-
if (existsSync(globalConfig)) try {
|
|
443
|
-
const globalTools = yaml.load(readFileSync(globalConfig, "utf-8"))?.tools?.also_sync || [];
|
|
444
|
-
for (const t of globalTools) if (t in TOOL_WRITERS) tools.add(t);
|
|
445
|
-
} catch {}
|
|
446
|
-
if (projectPath) {
|
|
447
|
-
const panYaml = join(projectPath, ".pan.yaml");
|
|
448
|
-
const legacyYaml = join(projectPath, ".panopticon.yaml");
|
|
449
|
-
const configPath = existsSync(panYaml) ? panYaml : existsSync(legacyYaml) ? legacyYaml : null;
|
|
450
|
-
if (configPath) try {
|
|
451
|
-
const projectTools = yaml.load(readFileSync(configPath, "utf-8"))?.tools?.also_sync || [];
|
|
452
|
-
for (const t of projectTools) if (t in TOOL_WRITERS) tools.add(t);
|
|
453
|
-
} catch {}
|
|
454
|
-
}
|
|
455
|
-
return Array.from(tools);
|
|
456
|
-
}
|
|
457
|
-
/**
|
|
458
|
-
* Sync skills from a skills directory to all configured tools.
|
|
459
|
-
*
|
|
460
|
-
* @param skillsDir Directory containing skill subdirectories
|
|
461
|
-
* @param projectPath Project root where tool targets live
|
|
462
|
-
* @param tools Tools to sync to (from resolveAlsoSyncTools)
|
|
463
|
-
*/
|
|
464
|
-
function syncSkillsToTools(skillsDir, projectPath, tools) {
|
|
465
|
-
if (tools.length === 0 || !existsSync(skillsDir)) return [];
|
|
466
|
-
const skills = collectSkillDirs(skillsDir);
|
|
467
|
-
const results = [];
|
|
468
|
-
for (const tool of tools) {
|
|
469
|
-
const writer = TOOL_WRITERS[tool];
|
|
470
|
-
const result = {
|
|
471
|
-
tool,
|
|
472
|
-
written: [],
|
|
473
|
-
skipped: [],
|
|
474
|
-
errors: []
|
|
475
|
-
};
|
|
476
|
-
for (const { name, dir } of skills) try {
|
|
477
|
-
const rawContent = readSkillContent(dir);
|
|
478
|
-
if (!rawContent) {
|
|
479
|
-
result.skipped.push(name);
|
|
480
|
-
continue;
|
|
481
|
-
}
|
|
482
|
-
writer(projectPath, extractSkillName(rawContent, name), rawContent);
|
|
483
|
-
result.written.push(name);
|
|
484
|
-
} catch (err) {
|
|
485
|
-
result.errors.push(`${name}: ${err.message}`);
|
|
486
|
-
}
|
|
487
|
-
results.push(result);
|
|
488
|
-
}
|
|
489
|
-
return results;
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* Run the full multi-tool sync for a project.
|
|
493
|
-
* Sources: .pan/skills/ (project-local) and/or ~/.panopticon/skills/ (global).
|
|
494
|
-
*/
|
|
495
|
-
function runMultiToolSync(projectPath) {
|
|
496
|
-
const tools = resolveAlsoSyncTools(projectPath);
|
|
497
|
-
if (tools.length === 0) return [];
|
|
498
|
-
const allResults = [];
|
|
499
|
-
const globalResults = syncSkillsToTools(join(PANOPTICON_HOME$1, "skills"), projectPath, tools);
|
|
500
|
-
allResults.push(...globalResults);
|
|
501
|
-
const projectSkillsDir = join(projectPath, ".pan", "skills");
|
|
502
|
-
if (existsSync(projectSkillsDir)) {
|
|
503
|
-
const projectResults = syncSkillsToTools(projectSkillsDir, projectPath, tools);
|
|
504
|
-
for (const pr of projectResults) {
|
|
505
|
-
const existing = allResults.find((r) => r.tool === pr.tool);
|
|
506
|
-
if (existing) {
|
|
507
|
-
existing.written.push(...pr.written);
|
|
508
|
-
existing.errors.push(...pr.errors);
|
|
509
|
-
} else allResults.push(pr);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
return allResults;
|
|
513
|
-
}
|
|
514
|
-
//#endregion
|
|
515
|
-
//#region src/cli/commands/sync.ts
|
|
516
|
-
init_config();
|
|
517
|
-
init_paths();
|
|
518
|
-
const BUNDLED_GIT_HOOKS_DIR = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "scripts", "git-hooks");
|
|
519
|
-
function checkCommand$2(cmd) {
|
|
520
|
-
try {
|
|
521
|
-
execSync(`which ${cmd}`, { stdio: "pipe" });
|
|
522
|
-
return true;
|
|
523
|
-
} catch {
|
|
524
|
-
return false;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
async function syncCommand$1(options) {
|
|
528
|
-
if (options.dryRun) {
|
|
529
|
-
console.log(chalk.bold("Sync Plan (dry run):\n"));
|
|
530
|
-
if (isDevMode()) console.log(chalk.magenta("Developer mode detected - dev-skills will be synced\n"));
|
|
531
|
-
const hooksPlan = planHooksSync();
|
|
532
|
-
if (hooksPlan.length > 0) {
|
|
533
|
-
console.log(chalk.cyan("hooks (bin scripts):"));
|
|
534
|
-
for (const hook of hooksPlan) {
|
|
535
|
-
const icon = hook.status === "new" ? chalk.green("+") : chalk.blue("↻");
|
|
536
|
-
const status = hook.status === "new" ? "" : chalk.dim("[update]");
|
|
537
|
-
console.log(` ${icon} ${hook.name} ${status}`);
|
|
538
|
-
}
|
|
539
|
-
console.log("");
|
|
540
|
-
}
|
|
541
|
-
const devrootPath = getDevrootPath();
|
|
542
|
-
console.log(chalk.cyan(`devroot (${devrootPath || "disabled"}):`));
|
|
543
|
-
if (!devrootPath) console.log(chalk.dim(" (devroot disabled — set sync.devroot in config)"));
|
|
544
|
-
else {
|
|
545
|
-
const plan = planSync();
|
|
546
|
-
const allItems = [
|
|
547
|
-
...plan.skills,
|
|
548
|
-
...plan.agents,
|
|
549
|
-
...plan.rules,
|
|
550
|
-
...plan.commands
|
|
551
|
-
];
|
|
552
|
-
if (allItems.length === 0) console.log(chalk.dim(" (nothing to sync)"));
|
|
553
|
-
else for (const item of allItems) {
|
|
554
|
-
const icon = item.status === "conflict" ? chalk.yellow("!") : item.status === "symlink" ? chalk.blue("↻") : chalk.green("+");
|
|
555
|
-
const label = item.status === "conflict" ? chalk.yellow("[modified]") : item.status === "symlink" ? chalk.dim("[update]") : chalk.green("[new]");
|
|
556
|
-
console.log(` ${icon} ${item.name} ${label}`);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
const dryRunProjects = listProjects();
|
|
560
|
-
for (const { config } of dryRunProjects) {
|
|
561
|
-
if (!existsSync(config.path)) continue;
|
|
562
|
-
const panSkillsDir = join(config.path, ".pan", "skills");
|
|
563
|
-
if (existsSync(panSkillsDir)) {
|
|
564
|
-
const skills = readdirSync(panSkillsDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
565
|
-
if (skills.length > 0) {
|
|
566
|
-
console.log(chalk.cyan(`\n.pan/skills/ (${config.name}):`));
|
|
567
|
-
for (const skillName of skills) console.log(` ${chalk.green("+")} ${skillName} ${chalk.green("[project-local]")}`);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
const tools = resolveAlsoSyncTools(config.path);
|
|
571
|
-
if (tools.length > 0) {
|
|
572
|
-
console.log(chalk.cyan(`\nmulti-tool sync (${config.name}): ${tools.join(", ")}`));
|
|
573
|
-
if (existsSync(join(config.path, ".pan", "skills"))) {
|
|
574
|
-
const skills = readdirSync(join(config.path, ".pan", "skills"), { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
575
|
-
for (const tool of tools) for (const skillName of skills) console.log(` ${chalk.green("+")} ${skillName} → ${tool}`);
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
console.log("");
|
|
580
|
-
console.log(chalk.dim("Run without --dry-run to apply changes."));
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
const syncMigration = migrateSyncTargets();
|
|
584
|
-
if (syncMigration.migrated) {
|
|
585
|
-
if (syncMigration.hadNonClaudeTargets) console.log(chalk.yellow("Config updated: removed non-Claude sync targets (Panopticon now syncs to Claude Code only)."));
|
|
586
|
-
}
|
|
587
|
-
const cleanupResult = cleanupLegacyRuntimeSymlinks();
|
|
588
|
-
if (cleanupResult.cleaned.length > 0) console.log(chalk.dim(`Removed ${cleanupResult.total} legacy runtime symlink(s): ${cleanupResult.cleaned.join(", ")}`));
|
|
589
|
-
const migration = migrateStalePersonalContent();
|
|
590
|
-
if (migration.removedSymlinks.length > 0) {
|
|
591
|
-
console.log(chalk.cyan(`Migrated: removed ${migration.removedSymlinks.length} Panopticon symlink(s) from ~/.claude/`));
|
|
592
|
-
if (migration.preservedUserContent.length > 0) console.log(chalk.dim(` Preserved ${migration.preservedUserContent.length} user-created item(s)`));
|
|
593
|
-
}
|
|
594
|
-
if (loadConfig$1().sync.backup_before_sync) {
|
|
595
|
-
const spinner = ora("Creating backup...").start();
|
|
596
|
-
const backup = createBackup([
|
|
597
|
-
SYNC_TARGET.skills,
|
|
598
|
-
SYNC_TARGET.commands,
|
|
599
|
-
SYNC_TARGET.agents
|
|
600
|
-
]);
|
|
601
|
-
if (backup.targets.length > 0) spinner.succeed(`Backup created: ${backup.timestamp}`);
|
|
602
|
-
else spinner.info("No existing content to backup");
|
|
603
|
-
if (options.backupOnly) return;
|
|
604
|
-
}
|
|
605
|
-
const cacheSpinner = ora("Refreshing cache from repo...").start();
|
|
606
|
-
const cacheResult = refreshCache();
|
|
607
|
-
const cacheParts = [];
|
|
608
|
-
if (cacheResult.skills.copied > 0) cacheParts.push(`${cacheResult.skills.copied} skills`);
|
|
609
|
-
if (cacheResult.agents.copied > 0) cacheParts.push(`${cacheResult.agents.copied} agents`);
|
|
610
|
-
if (cacheResult.rules.copied > 0) cacheParts.push(`${cacheResult.rules.copied} rules`);
|
|
611
|
-
cacheSpinner.succeed(`Cache refreshed: ${cacheParts.length > 0 ? cacheParts.join(", ") : "up to date"}`);
|
|
612
|
-
const devrootPath = getDevrootPath();
|
|
613
|
-
const spinner = ora(`Syncing to devroot (${devrootPath || "disabled"})...`).start();
|
|
614
|
-
if (!devrootPath) spinner.info("Devroot disabled (set sync.devroot in config to enable)");
|
|
615
|
-
else {
|
|
616
|
-
const result = executeSync({
|
|
617
|
-
force: options.force,
|
|
618
|
-
diff: options.diff
|
|
619
|
-
});
|
|
620
|
-
const totalSynced = result.created.length + result.updated.length;
|
|
621
|
-
if (result.diffs.length > 0) {
|
|
622
|
-
spinner.info(`Showing diffs for ${result.diffs.length} modified file(s):\n`);
|
|
623
|
-
for (const d of result.diffs) {
|
|
624
|
-
console.log(chalk.cyan(`--- ${d.path} (installed)`));
|
|
625
|
-
console.log(chalk.cyan(`+++ ${d.path} (current on disk)`));
|
|
626
|
-
const sourceLines = d.sourceContent.split("\n");
|
|
627
|
-
const targetLines = d.targetContent.split("\n");
|
|
628
|
-
const maxLines = Math.max(sourceLines.length, targetLines.length);
|
|
629
|
-
for (let i = 0; i < maxLines; i++) if (sourceLines[i] !== targetLines[i]) {
|
|
630
|
-
if (targetLines[i] !== void 0) console.log(chalk.red(`- ${targetLines[i]}`));
|
|
631
|
-
if (sourceLines[i] !== void 0) console.log(chalk.green(`+ ${sourceLines[i]}`));
|
|
632
|
-
}
|
|
633
|
-
console.log("");
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
if (result.conflicts.length > 0 && !options.force) {
|
|
637
|
-
spinner.warn(`Synced ${totalSynced} items, ${result.conflicts.length} conflicts`);
|
|
638
|
-
console.log("");
|
|
639
|
-
console.log(chalk.yellow("Modified since Panopticon installed:"));
|
|
640
|
-
for (const name of result.conflicts) console.log(chalk.dim(` - ${name}`));
|
|
641
|
-
console.log("");
|
|
642
|
-
console.log(chalk.dim("Use --force to overwrite, --diff to see changes."));
|
|
643
|
-
} else if (result.skipped.length > 0) spinner.succeed(`Synced ${totalSynced} items to devroot (${result.skipped.length} user-owned skipped)`);
|
|
644
|
-
else spinner.succeed(`Synced ${totalSynced} items to devroot`);
|
|
645
|
-
}
|
|
646
|
-
const hooksSpinner = ora("Syncing hooks...").start();
|
|
647
|
-
const hooksResult = syncHooks();
|
|
648
|
-
if (hooksResult.errors.length > 0) {
|
|
649
|
-
hooksSpinner.warn(`Synced ${hooksResult.synced.length} hooks, ${hooksResult.errors.length} errors`);
|
|
650
|
-
for (const error of hooksResult.errors) console.log(chalk.red(` ✗ ${error}`));
|
|
651
|
-
} else if (hooksResult.synced.length > 0) hooksSpinner.succeed(`Synced ${hooksResult.synced.length} hooks to ~/.panopticon/bin/`);
|
|
652
|
-
else hooksSpinner.info("No hooks to sync");
|
|
653
|
-
const projects = listProjects();
|
|
654
|
-
if (projects.length > 0 && checkCommand$2("bd")) for (const { key, config } of projects) {
|
|
655
|
-
if (!existsSync(config.path)) continue;
|
|
656
|
-
if (!existsSync(join(config.path, ".beads"))) continue;
|
|
657
|
-
try {
|
|
658
|
-
execSync("bd list --json --limit 0 2>&1", {
|
|
659
|
-
cwd: config.path,
|
|
660
|
-
stdio: "pipe",
|
|
661
|
-
timeout: 8e3
|
|
662
|
-
});
|
|
663
|
-
} catch (e) {
|
|
664
|
-
const msg = String(e?.stdout ?? e?.stderr ?? e?.message ?? "");
|
|
665
|
-
if (msg.includes("database") && (msg.includes("not found") || msg.includes("not exist") || msg.includes("defaulting"))) {
|
|
666
|
-
const beadsSpinner = ora(`Initializing beads database for ${config.name}...`).start();
|
|
667
|
-
try {
|
|
668
|
-
const prefix = (key || config.name).toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
669
|
-
execSync(`bd init --prefix ${prefix}`, {
|
|
670
|
-
cwd: config.path,
|
|
671
|
-
stdio: "pipe",
|
|
672
|
-
timeout: 2e4
|
|
673
|
-
});
|
|
674
|
-
try {
|
|
675
|
-
execSync("git config beads.role contributor", {
|
|
676
|
-
cwd: config.path,
|
|
677
|
-
stdio: "pipe"
|
|
678
|
-
});
|
|
679
|
-
} catch {}
|
|
680
|
-
beadsSpinner.succeed(`Beads database initialized for ${config.name} (prefix: ${prefix})`);
|
|
681
|
-
} catch {
|
|
682
|
-
beadsSpinner.warn(`Could not auto-initialize beads for ${config.name} — run: cd ${config.path} && bd init`);
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
if (!checkCommand$2("jq")) {
|
|
688
|
-
console.log(chalk.yellow("\n ⚠ jq not found — statusline and other features need it"));
|
|
689
|
-
console.log(chalk.dim(" Install: apt install jq / brew install jq\n"));
|
|
690
|
-
}
|
|
691
|
-
const statuslineSpinner = ora("Syncing statusline...").start();
|
|
692
|
-
const statuslineResult = syncStatusline();
|
|
693
|
-
if (statuslineResult.errors.length > 0) {
|
|
694
|
-
statuslineSpinner.warn(`Synced statusline to ${statuslineResult.synced.length} runtime(s), ${statuslineResult.errors.length} error(s)`);
|
|
695
|
-
for (const error of statuslineResult.errors) console.log(chalk.red(` ✗ ${error}`));
|
|
696
|
-
} else if (statuslineResult.synced.length > 0) statuslineSpinner.succeed(`Synced statusline to ${statuslineResult.synced.join(", ")}`);
|
|
697
|
-
else statuslineSpinner.info("No statusline script found (scripts/statusline.sh)");
|
|
698
|
-
if (!checkCommand$2("claude-code-router")) {
|
|
699
|
-
const routerSpinner = ora("Installing claude-code-router...").start();
|
|
700
|
-
try {
|
|
701
|
-
execSync("npm install -g @musistudio/claude-code-router", {
|
|
702
|
-
stdio: "pipe",
|
|
703
|
-
timeout: 12e4
|
|
704
|
-
});
|
|
705
|
-
routerSpinner.succeed("claude-code-router installed");
|
|
706
|
-
} catch (error) {
|
|
707
|
-
routerSpinner.warn("Failed to install claude-code-router - run: npm install -g @musistudio/claude-code-router");
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
if (!checkCommand$2("mkcert")) {
|
|
711
|
-
const mkcertSpinner = ora("Installing mkcert...").start();
|
|
712
|
-
try {
|
|
713
|
-
const binDir = join(homedir(), ".local", "bin");
|
|
714
|
-
mkdirSync(binDir, { recursive: true });
|
|
715
|
-
const mkcertPath = join(binDir, "mkcert");
|
|
716
|
-
execSync(`curl -sL "https://github.com/FiloSottile/mkcert/releases/latest/download/mkcert-v1.4.4-linux-${process.arch === "x64" ? "amd64" : process.arch}" -o "${mkcertPath}" && chmod +x "${mkcertPath}"`, {
|
|
717
|
-
stdio: "pipe",
|
|
718
|
-
timeout: 6e4
|
|
719
|
-
});
|
|
720
|
-
mkcertSpinner.succeed("mkcert installed");
|
|
721
|
-
} catch {
|
|
722
|
-
mkcertSpinner.warn("Failed to install mkcert - run: https://github.com/FiloSottile/mkcert/releases");
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
if (!checkCommand$2("ox")) {
|
|
726
|
-
const oxSpinner = ora("Installing SageOx CLI (ox)...").start();
|
|
727
|
-
try {
|
|
728
|
-
const binDir = join(homedir(), ".local", "bin");
|
|
729
|
-
mkdirSync(binDir, { recursive: true });
|
|
730
|
-
const oxPath = join(binDir, "ox");
|
|
731
|
-
const arch = process.arch === "x64" ? "amd64" : process.arch;
|
|
732
|
-
execSync(`curl -sL "https://github.com/eltmon/ox/releases/download/latest/ox-${process.platform === "darwin" ? "darwin" : "linux"}-${arch}" -o "${oxPath}" && chmod +x "${oxPath}"`, {
|
|
733
|
-
stdio: "pipe",
|
|
734
|
-
timeout: 6e4
|
|
735
|
-
});
|
|
736
|
-
oxSpinner.succeed("SageOx CLI installed");
|
|
737
|
-
} catch {
|
|
738
|
-
oxSpinner.warn("Failed to install SageOx CLI - see: https://github.com/eltmon/ox/releases");
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
for (const { config } of projects) {
|
|
742
|
-
if (!existsSync(config.path)) continue;
|
|
743
|
-
const migResult = migratePanopticonToPan(config.path);
|
|
744
|
-
if (migResult.migrated.length > 0) console.log(chalk.cyan(`Migrated .panopticon/ → .pan/ in ${config.name}: ${migResult.migrated.join(", ")}`));
|
|
745
|
-
if (migResult.skipped.length > 0) console.log(chalk.yellow(`Migration skipped (both exist) in ${config.name}: ${migResult.skipped.join(", ")}`));
|
|
746
|
-
for (const err of migResult.errors) console.log(chalk.red(`Migration error in ${config.name}: ${err}`));
|
|
747
|
-
const toolSyncResults = runMultiToolSync(config.path);
|
|
748
|
-
for (const r of toolSyncResults) {
|
|
749
|
-
if (r.written.length > 0) console.log(chalk.cyan(`Synced ${r.written.length} skill(s) to ${r.tool} in ${config.name}`));
|
|
750
|
-
for (const err of r.errors) console.log(chalk.red(`Multi-tool sync error (${r.tool}) in ${config.name}: ${err}`));
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
if (projects.length > 0 && existsSync(BUNDLED_GIT_HOOKS_DIR)) {
|
|
754
|
-
const gitHooksSpinner = ora("Installing git hooks in registered projects...").start();
|
|
755
|
-
let totalInstalled = 0;
|
|
756
|
-
let projectsUpdated = 0;
|
|
757
|
-
for (const { config } of projects) {
|
|
758
|
-
if (!existsSync(config.path)) continue;
|
|
759
|
-
const gitDirs = [];
|
|
760
|
-
if (existsSync(join(config.path, ".git")) && statSync(join(config.path, ".git")).isDirectory()) gitDirs.push(join(config.path, ".git"));
|
|
761
|
-
else try {
|
|
762
|
-
const entries = readdirSync(config.path);
|
|
763
|
-
for (const entry of entries) {
|
|
764
|
-
const gitPath = join(join(config.path, entry), ".git");
|
|
765
|
-
if (existsSync(gitPath) && statSync(gitPath).isDirectory()) gitDirs.push(gitPath);
|
|
766
|
-
}
|
|
767
|
-
} catch {}
|
|
768
|
-
for (const gitDir of gitDirs) {
|
|
769
|
-
const hooksTarget = join(gitDir, "hooks");
|
|
770
|
-
if (!existsSync(hooksTarget)) mkdirSync(hooksTarget, { recursive: true });
|
|
771
|
-
try {
|
|
772
|
-
const hooks = readdirSync(BUNDLED_GIT_HOOKS_DIR).filter((f) => statSync(join(BUNDLED_GIT_HOOKS_DIR, f)).isFile());
|
|
773
|
-
for (const hook of hooks) {
|
|
774
|
-
const source = join(BUNDLED_GIT_HOOKS_DIR, hook);
|
|
775
|
-
const target = join(hooksTarget, hook);
|
|
776
|
-
if (existsSync(target)) {
|
|
777
|
-
try {
|
|
778
|
-
const { readlinkSync } = await import("fs");
|
|
779
|
-
if (readlinkSync(target) === source) continue;
|
|
780
|
-
} catch {}
|
|
781
|
-
const { renameSync } = await import("fs");
|
|
782
|
-
try {
|
|
783
|
-
renameSync(target, `${target}.backup`);
|
|
784
|
-
} catch {}
|
|
785
|
-
}
|
|
786
|
-
try {
|
|
787
|
-
symlinkSync(source, target);
|
|
788
|
-
totalInstalled++;
|
|
789
|
-
} catch {}
|
|
790
|
-
}
|
|
791
|
-
projectsUpdated++;
|
|
792
|
-
} catch {}
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
if (totalInstalled > 0) gitHooksSpinner.succeed(`Installed git hooks in ${projectsUpdated} project(s)`);
|
|
796
|
-
else gitHooksSpinner.info("Git hooks already up to date");
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
//#endregion
|
|
800
132
|
//#region src/cli/commands/restore.ts
|
|
801
133
|
init_paths();
|
|
802
134
|
async function restoreCommand(timestamp) {
|
|
@@ -923,6 +255,8 @@ async function skillsCommand(options) {
|
|
|
923
255
|
}
|
|
924
256
|
//#endregion
|
|
925
257
|
//#region src/lib/prd-draft.ts
|
|
258
|
+
init_issue_id();
|
|
259
|
+
init_projects();
|
|
926
260
|
init_tmux();
|
|
927
261
|
init_hooks();
|
|
928
262
|
init_cv();
|
|
@@ -1171,7 +505,6 @@ function extractACFromDocument(doc) {
|
|
|
1171
505
|
}
|
|
1172
506
|
//#endregion
|
|
1173
507
|
//#region src/lib/cloister/work-agent-prompt.ts
|
|
1174
|
-
init_projects();
|
|
1175
508
|
init_io();
|
|
1176
509
|
init_config();
|
|
1177
510
|
const __dirname$1 = dirname(fileURLToPath(import.meta.url));
|
|
@@ -1460,7 +793,17 @@ function buildPolyrepoContext(issueId, workspacePath) {
|
|
|
1460
793
|
const teamPrefix = extractTeamPrefix(issueId);
|
|
1461
794
|
const projectConfig = teamPrefix ? findProjectByTeam(teamPrefix) : null;
|
|
1462
795
|
if (!projectConfig?.workspace?.type || projectConfig.workspace.type !== "polyrepo" || !projectConfig.workspace.repos) return "";
|
|
1463
|
-
const
|
|
796
|
+
const wsConfig = projectConfig.workspace;
|
|
797
|
+
const repos = wsConfig.repos;
|
|
798
|
+
const isProgressive = wsConfig.progressive && wsConfig.always_include;
|
|
799
|
+
let visibleRepos = repos;
|
|
800
|
+
if (isProgressive) {
|
|
801
|
+
const existingRepos = readdirSync(workspacePath).filter((f) => {
|
|
802
|
+
const fullPath = join(workspacePath, f);
|
|
803
|
+
return f !== ".planning" && f !== ".claude" && f !== ".pan" && f !== ".beads" && existsSync(fullPath);
|
|
804
|
+
});
|
|
805
|
+
visibleRepos = repos.filter((r) => existingRepos.includes(r.name));
|
|
806
|
+
}
|
|
1464
807
|
const lines = [
|
|
1465
808
|
"## Project Structure (Polyrepo)",
|
|
1466
809
|
"",
|
|
@@ -1470,12 +813,57 @@ function buildPolyrepoContext(issueId, workspacePath) {
|
|
|
1470
813
|
"| Directory | Purpose |",
|
|
1471
814
|
"|-----------|---------|"
|
|
1472
815
|
];
|
|
1473
|
-
for (const repo of
|
|
816
|
+
for (const repo of visibleRepos) {
|
|
817
|
+
const notes = [];
|
|
818
|
+
if (repo.readonly) notes.push("readonly");
|
|
819
|
+
if (repo.link_type === "symlink") notes.push("symlink");
|
|
820
|
+
const noteStr = notes.length > 0 ? ` (${notes.join(", ")})` : "";
|
|
821
|
+
lines.push(`| \`${repo.name}/\` | ${repo.path}${noteStr} |`);
|
|
822
|
+
}
|
|
1474
823
|
lines.push("");
|
|
1475
824
|
lines.push("**Git operations:**");
|
|
1476
825
|
lines.push("- Run `git status`, `git log`, etc. INSIDE the subdirectories (e.g., `cd fe && git status`)");
|
|
1477
826
|
lines.push(`- The workspace root (\`${workspacePath}\`) has no \`.git\` directory`);
|
|
1478
827
|
lines.push(`- Each subdirectory has its own branch: \`${repos[0]?.branch_prefix || "feature/"}${issueId.toLowerCase()}\``);
|
|
828
|
+
const prTargets = /* @__PURE__ */ new Set();
|
|
829
|
+
for (const repo of visibleRepos) {
|
|
830
|
+
const prTarget = repo.pr_target || wsConfig.pr_target;
|
|
831
|
+
if (prTarget) prTargets.add(prTarget);
|
|
832
|
+
}
|
|
833
|
+
if (prTargets.size > 0) {
|
|
834
|
+
lines.push("");
|
|
835
|
+
lines.push(`**PR target branch:** \`${[...prTargets].join("` or `")}\` (NOT main/master)`);
|
|
836
|
+
}
|
|
837
|
+
if (isProgressive) {
|
|
838
|
+
lines.push("");
|
|
839
|
+
lines.push("## Adding Repositories");
|
|
840
|
+
lines.push("");
|
|
841
|
+
lines.push("This is a **progressive** workspace. Only essential repos are included.");
|
|
842
|
+
lines.push("Use the `/workspace-add-repo` skill to add more repos when needed:");
|
|
843
|
+
lines.push("");
|
|
844
|
+
lines.push("```bash");
|
|
845
|
+
lines.push(`pan workspace add-repo ${issueId.toLowerCase()} <repo-name> [repo-name...]`);
|
|
846
|
+
lines.push("# Or add all repos in a group:");
|
|
847
|
+
lines.push(`pan workspace add-repo ${issueId.toLowerCase()} --group <group-name>`);
|
|
848
|
+
lines.push("```");
|
|
849
|
+
lines.push("");
|
|
850
|
+
lines.push("Available repos not yet in workspace:");
|
|
851
|
+
const existingRepoNames = visibleRepos.map((r) => r.name);
|
|
852
|
+
const missingRepos = repos.filter((r) => !existingRepoNames.includes(r.name));
|
|
853
|
+
for (const repo of missingRepos) {
|
|
854
|
+
const notes = [];
|
|
855
|
+
if (repo.readonly) notes.push("readonly");
|
|
856
|
+
if (repo.link_type === "symlink") notes.push("symlink");
|
|
857
|
+
const noteStr = notes.length > 0 ? ` (${notes.join(", ")})` : "";
|
|
858
|
+
lines.push(`- \`${repo.name}\`${noteStr} — ${repo.path}`);
|
|
859
|
+
}
|
|
860
|
+
const readonlyRepos = visibleRepos.filter((r) => r.readonly || r.link_type === "symlink");
|
|
861
|
+
if (readonlyRepos.length > 0) {
|
|
862
|
+
lines.push("");
|
|
863
|
+
lines.push("**Readonly repos** (do NOT commit changes):");
|
|
864
|
+
for (const repo of readonlyRepos) lines.push(`- \`${repo.name}/\` — ${repo.path}`);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
1479
867
|
lines.push("");
|
|
1480
868
|
return lines.join("\n");
|
|
1481
869
|
}
|
|
@@ -1613,7 +1001,7 @@ async function handleRemoteWorkspace(issueId, options, spinner) {
|
|
|
1613
1001
|
if (!remoteMetadata) {
|
|
1614
1002
|
spinner.text = "Remote workspace not found, creating...";
|
|
1615
1003
|
try {
|
|
1616
|
-
const { createRemoteWorkspace } = await import("../remote-workspace-
|
|
1004
|
+
const { createRemoteWorkspace } = await import("../remote-workspace-CA33UuVI.js");
|
|
1617
1005
|
remoteMetadata = await createRemoteWorkspace(issueId, { spinner });
|
|
1618
1006
|
} catch (error) {
|
|
1619
1007
|
spinner.fail(`Failed to create remote workspace: ${error.message}`);
|
|
@@ -1666,7 +1054,7 @@ async function handleRemoteWorkspace(issueId, options, spinner) {
|
|
|
1666
1054
|
} else if (isGitHubIssue(issueId)) {
|
|
1667
1055
|
const gh = resolveGitHubIssue(issueId);
|
|
1668
1056
|
if (gh.isGitHub) try {
|
|
1669
|
-
const { loadConfig: loadYamlConfig } = await import("../config-yaml-
|
|
1057
|
+
const { loadConfig: loadYamlConfig } = await import("../config-yaml-Dqt4FWQH.js");
|
|
1670
1058
|
const token = loadYamlConfig().config.trackerKeys?.github || process.env.GITHUB_TOKEN;
|
|
1671
1059
|
if (token) {
|
|
1672
1060
|
const { Octokit } = await import("@octokit/rest");
|
|
@@ -2758,7 +2146,8 @@ async function updateGitHubToInReview(issueId, comment) {
|
|
|
2758
2146
|
try {
|
|
2759
2147
|
const ghConfig = getGitHubConfig$1();
|
|
2760
2148
|
if (!ghConfig) return false;
|
|
2761
|
-
const number =
|
|
2149
|
+
const number = extractNumber(issueId);
|
|
2150
|
+
if (number === null) return false;
|
|
2762
2151
|
const { owner, repo } = ghConfig.repos.find((r) => r.prefix === "PAN") || ghConfig.repos[0];
|
|
2763
2152
|
const token = ghConfig.token;
|
|
2764
2153
|
const headers = {
|
|
@@ -2788,7 +2177,7 @@ async function doneCommand$1(id, options = {}) {
|
|
|
2788
2177
|
const issueId = id.replace(/^agent-/i, "").toUpperCase();
|
|
2789
2178
|
const agentId = `agent-${issueId.toLowerCase()}`;
|
|
2790
2179
|
if (!options.force) {
|
|
2791
|
-
const { getAgentState } = await import("../agents-
|
|
2180
|
+
const { getAgentState } = await import("../agents-D_2oRFVf.js");
|
|
2792
2181
|
const workspacePath = getAgentState(agentId)?.workspace;
|
|
2793
2182
|
if (workspacePath && existsSync(workspacePath)) {
|
|
2794
2183
|
const failures = [];
|
|
@@ -2882,7 +2271,7 @@ async function doneCommand$1(id, options = {}) {
|
|
|
2882
2271
|
else console.log(chalk.yellow(` ⚠ Failed to update Linear status`));
|
|
2883
2272
|
} else console.log(chalk.dim(" LINEAR_API_KEY not set - skipping status update"));
|
|
2884
2273
|
}
|
|
2885
|
-
const { getAgentState, saveAgentState } = await import("../agents-
|
|
2274
|
+
const { getAgentState, saveAgentState } = await import("../agents-D_2oRFVf.js");
|
|
2886
2275
|
const existingState = getAgentState(agentId);
|
|
2887
2276
|
if (existingState) {
|
|
2888
2277
|
existingState.status = "stopped";
|
|
@@ -2911,7 +2300,7 @@ async function doneCommand$1(id, options = {}) {
|
|
|
2911
2300
|
console.log(chalk.dim(` pan work approve ${issueId}`));
|
|
2912
2301
|
console.log("");
|
|
2913
2302
|
try {
|
|
2914
|
-
const { getDashboardApiUrl } = await import("../config-
|
|
2303
|
+
const { getDashboardApiUrl } = await import("../config-agyKgF5C.js");
|
|
2915
2304
|
const dashboardUrl = getDashboardApiUrl();
|
|
2916
2305
|
const http = await import("http");
|
|
2917
2306
|
const checkDashboard = () => new Promise((resolve) => {
|
|
@@ -2959,8 +2348,9 @@ async function doneCommand$1(id, options = {}) {
|
|
|
2959
2348
|
req.end();
|
|
2960
2349
|
});
|
|
2961
2350
|
let result = await reviewReq();
|
|
2962
|
-
if (!result.success && result.alreadyMerged) {
|
|
2963
|
-
|
|
2351
|
+
if (!result.success && (result.alreadyMerged || result.alreadyReviewed)) {
|
|
2352
|
+
const reason = result.alreadyMerged ? "previously merged" : "prior review blocked/failed";
|
|
2353
|
+
console.log(chalk.yellow(` ⚠ Issue was ${reason}. Resetting specialist states for re-review...`));
|
|
2964
2354
|
const resetReq = () => new Promise((resolve, reject) => {
|
|
2965
2355
|
const postData = JSON.stringify({});
|
|
2966
2356
|
const req = http.request(`${dashboardUrl}/api/workspaces/${issueId}/reset-review`, {
|
|
@@ -3392,7 +2782,7 @@ async function planCommand(id, options = {}) {
|
|
|
3392
2782
|
let issueData;
|
|
3393
2783
|
if (trackerType === "github" && ghResolution.isGitHub) {
|
|
3394
2784
|
spinner.text = "Fetching issue from GitHub...";
|
|
3395
|
-
const { loadConfig: loadYamlConfig } = await import("../config-yaml-
|
|
2785
|
+
const { loadConfig: loadYamlConfig } = await import("../config-yaml-Dqt4FWQH.js");
|
|
3396
2786
|
const token = loadYamlConfig().config.trackerKeys?.github || process.env.GITHUB_TOKEN;
|
|
3397
2787
|
if (!token) {
|
|
3398
2788
|
spinner.fail("GitHub token not found");
|
|
@@ -3417,10 +2807,10 @@ async function planCommand(id, options = {}) {
|
|
|
3417
2807
|
};
|
|
3418
2808
|
} else if (trackerType === "rally") {
|
|
3419
2809
|
spinner.text = "Fetching issue from Rally...";
|
|
3420
|
-
const { createTracker } = await import("../factory-
|
|
3421
|
-
const { resolveProjectFromIssue } = await import("../projects-
|
|
2810
|
+
const { createTracker } = await import("../factory-BRBGw6OB.js");
|
|
2811
|
+
const { resolveProjectFromIssue } = await import("../projects-DhU7rAVN.js");
|
|
3422
2812
|
const project = resolveProjectFromIssue(id);
|
|
3423
|
-
const rallyProject = project ? (await import("../projects-
|
|
2813
|
+
const rallyProject = project ? (await import("../projects-DhU7rAVN.js")).getProject(project.projectKey)?.rally_project : void 0;
|
|
3424
2814
|
try {
|
|
3425
2815
|
const rallyIssue = await createTracker({
|
|
3426
2816
|
type: "rally",
|
|
@@ -5185,7 +4575,7 @@ async function reopenCommand(id, options = {}) {
|
|
|
5185
4575
|
console.log(chalk.green(`✓ ${issue.identifier} reopened and ready for re-work`));
|
|
5186
4576
|
console.log("");
|
|
5187
4577
|
try {
|
|
5188
|
-
const { getAgentState } = await import("../agents-
|
|
4578
|
+
const { getAgentState } = await import("../agents-D_2oRFVf.js");
|
|
5189
4579
|
const agentState = getAgentState(`agent-${id.toLowerCase()}`);
|
|
5190
4580
|
if (agentState?.status === "running" || agentState?.status === "starting") {
|
|
5191
4581
|
console.log(chalk.dim("Agent is still running. Send it context about the re-work:"));
|
|
@@ -5295,6 +4685,7 @@ async function resetReviewCommand(id) {
|
|
|
5295
4685
|
//#endregion
|
|
5296
4686
|
//#region src/cli/commands/work/wipe.ts
|
|
5297
4687
|
init_projects();
|
|
4688
|
+
init_issue_id();
|
|
5298
4689
|
init_agents();
|
|
5299
4690
|
init_tmux();
|
|
5300
4691
|
init_config();
|
|
@@ -5381,7 +4772,11 @@ async function wipeCommand(issueId, options) {
|
|
|
5381
4772
|
console.log(chalk.green(` ✓ Deleted agent state: ${dir.replace(homedir(), "~")}`));
|
|
5382
4773
|
}
|
|
5383
4774
|
let projectPath;
|
|
5384
|
-
const prefix = issueId
|
|
4775
|
+
const prefix = extractPrefix(issueId);
|
|
4776
|
+
if (!prefix) {
|
|
4777
|
+
console.log(chalk.red(" ✗ Could not extract prefix from issue ID"));
|
|
4778
|
+
return;
|
|
4779
|
+
}
|
|
5385
4780
|
const projectsYamlPath = join(homedir(), ".panopticon", "projects.yaml");
|
|
5386
4781
|
if (existsSync(projectsYamlPath)) try {
|
|
5387
4782
|
const projectsConfig = (await import("js-yaml")).load(readFileSync(projectsYamlPath, "utf-8"));
|
|
@@ -6190,6 +5585,7 @@ async function syncMainCommand(id) {
|
|
|
6190
5585
|
*/
|
|
6191
5586
|
init_paths();
|
|
6192
5587
|
init_tmux();
|
|
5588
|
+
init_issue_id();
|
|
6193
5589
|
const execAsync$16 = promisify(exec);
|
|
6194
5590
|
/**
|
|
6195
5591
|
* Kill tmux sessions associated with an issue.
|
|
@@ -6219,7 +5615,7 @@ async function stopTldrDaemon(workspacePath) {
|
|
|
6219
5615
|
const venvPath = join(workspacePath, ".venv");
|
|
6220
5616
|
if (!existsSync(venvPath)) return stepSkipped(step, ["No .venv found"]);
|
|
6221
5617
|
try {
|
|
6222
|
-
const { getTldrDaemonService } = await import("../tldr-daemon-
|
|
5618
|
+
const { getTldrDaemonService } = await import("../tldr-daemon-D_EooADG.js");
|
|
6223
5619
|
await getTldrDaemonService(workspacePath, venvPath).stop();
|
|
6224
5620
|
return stepOk(step, ["Stopped TLDR daemon"]);
|
|
6225
5621
|
} catch {
|
|
@@ -6232,7 +5628,7 @@ async function stopTldrDaemon(workspacePath) {
|
|
|
6232
5628
|
async function stopDocker(workspacePath, projectName, issueLower) {
|
|
6233
5629
|
const step = "teardown:docker";
|
|
6234
5630
|
try {
|
|
6235
|
-
const { stopWorkspaceDocker } = await import("../workspace-manager-
|
|
5631
|
+
const { stopWorkspaceDocker } = await import("../workspace-manager-B9jS4Dsq.js");
|
|
6236
5632
|
await stopWorkspaceDocker(workspacePath, projectName, issueLower);
|
|
6237
5633
|
return stepOk(step, ["Stopped Docker containers"]);
|
|
6238
5634
|
} catch {
|
|
@@ -6417,7 +5813,7 @@ async function deleteBranches(projectPath, issueLower) {
|
|
|
6417
5813
|
async function clearShadowState(issueId) {
|
|
6418
5814
|
const step = "teardown:shadow-state";
|
|
6419
5815
|
try {
|
|
6420
|
-
const { removeShadowState } = await import("../shadow-state-
|
|
5816
|
+
const { removeShadowState } = await import("../shadow-state-BZzxfEGw.js");
|
|
6421
5817
|
if (removeShadowState(issueId).success) return stepOk(step, [`Cleared shadow state for ${issueId}`]);
|
|
6422
5818
|
return stepSkipped(step, ["No shadow state found"]);
|
|
6423
5819
|
} catch {
|
|
@@ -6477,7 +5873,7 @@ function buildPlaceholders(ctx, opts, workspacePath) {
|
|
|
6477
5873
|
async function removeTunnelConfig(tunnelConfig, placeholders) {
|
|
6478
5874
|
const step = "teardown:tunnel";
|
|
6479
5875
|
try {
|
|
6480
|
-
const { removeTunnelIngress } = await import("../tunnel-
|
|
5876
|
+
const { removeTunnelIngress } = await import("../tunnel-DXOJ1wMM.js");
|
|
6481
5877
|
return stepOk(step, (await removeTunnelIngress(tunnelConfig, placeholders)).steps || ["Removed tunnel ingress"]);
|
|
6482
5878
|
} catch (err) {
|
|
6483
5879
|
return stepSkipped(step, [`Tunnel cleanup warning: ${err.message}`]);
|
|
@@ -6489,7 +5885,7 @@ async function removeTunnelConfig(tunnelConfig, placeholders) {
|
|
|
6489
5885
|
async function removeHumeEviConfig(humeConfig, placeholders) {
|
|
6490
5886
|
const step = "teardown:hume";
|
|
6491
5887
|
try {
|
|
6492
|
-
const { deleteHumeConfig } = await import("../hume-
|
|
5888
|
+
const { deleteHumeConfig } = await import("../hume-9nv1VmMV.js");
|
|
6493
5889
|
return stepOk(step, (await deleteHumeConfig(humeConfig, placeholders)).steps || ["Removed Hume EVI config"]);
|
|
6494
5890
|
} catch (err) {
|
|
6495
5891
|
return stepSkipped(step, [`Hume cleanup warning: ${err.message}`]);
|
|
@@ -6513,7 +5909,7 @@ async function removeHumeEviConfig(humeConfig, placeholders) {
|
|
|
6513
5909
|
*/
|
|
6514
5910
|
async function teardownWorkspace(ctx, opts = {}) {
|
|
6515
5911
|
const issueLower = ctx.issueId.toLowerCase();
|
|
6516
|
-
const projName = opts.projectName || ctx.projectName || ctx.issueId
|
|
5912
|
+
const projName = opts.projectName || ctx.projectName || (extractPrefix(ctx.issueId)?.toLowerCase() ?? ctx.issueId);
|
|
6517
5913
|
const workspacePath = findWorkspacePath(ctx.projectPath, issueLower);
|
|
6518
5914
|
const shouldDeleteWorkspace = opts.deleteWorkspace !== false;
|
|
6519
5915
|
const results = [];
|
|
@@ -6608,7 +6004,7 @@ async function verifyBranchMerged(ctx) {
|
|
|
6608
6004
|
const branchName = `feature/${ctx.issueId.toLowerCase()}`;
|
|
6609
6005
|
try {
|
|
6610
6006
|
try {
|
|
6611
|
-
const { loadReviewStatuses } = await import("../review-status-
|
|
6007
|
+
const { loadReviewStatuses } = await import("../review-status-D6H2WOw8.js");
|
|
6612
6008
|
if (loadReviewStatuses()[ctx.issueId.toUpperCase()]?.mergeStatus === "merged") return stepOk(step, ["Merge specialist confirmed merge completed"]);
|
|
6613
6009
|
} catch {}
|
|
6614
6010
|
const { stdout: branchExists } = await execAsync$15(`git branch --list "${branchName}" 2>/dev/null || true`, {
|
|
@@ -6622,6 +6018,13 @@ async function verifyBranchMerged(ctx) {
|
|
|
6622
6018
|
});
|
|
6623
6019
|
return stepOk(step, ["All commits merged to main"]);
|
|
6624
6020
|
} catch {
|
|
6021
|
+
try {
|
|
6022
|
+
const { stdout: codeDiff } = await execAsync$15(`git diff main...${branchName} -- ':!.planning' ':!docs/prds' ':!.panopticon/prompts' 2>/dev/null || true`, {
|
|
6023
|
+
cwd: ctx.projectPath,
|
|
6024
|
+
encoding: "utf-8"
|
|
6025
|
+
});
|
|
6026
|
+
if (!codeDiff.trim()) return stepOk(step, ["Code changes squash-merged to main (only planning artifacts remain on branch)"]);
|
|
6027
|
+
} catch {}
|
|
6625
6028
|
const { stdout: unmerged } = await execAsync$15(`git log main..${branchName} --oneline 2>/dev/null || true`, {
|
|
6626
6029
|
cwd: ctx.projectPath,
|
|
6627
6030
|
encoding: "utf-8"
|
|
@@ -6641,6 +6044,13 @@ async function verifyBranchMerged(ctx) {
|
|
|
6641
6044
|
});
|
|
6642
6045
|
return stepOk(step, ["Remote branch fully merged"]);
|
|
6643
6046
|
} catch {
|
|
6047
|
+
try {
|
|
6048
|
+
const { stdout: codeDiff } = await execAsync$15(`git diff main...origin/${branchName} -- ':!.planning' ':!docs/prds' ':!.panopticon/prompts' 2>/dev/null || true`, {
|
|
6049
|
+
cwd: ctx.projectPath,
|
|
6050
|
+
encoding: "utf-8"
|
|
6051
|
+
});
|
|
6052
|
+
if (!codeDiff.trim()) return stepOk(step, ["Remote code changes squash-merged to main (only planning artifacts remain on branch)"]);
|
|
6053
|
+
} catch {}
|
|
6644
6054
|
const { stdout: remoteUnmerged } = await execAsync$15(`git log main..origin/${branchName} --oneline 2>/dev/null || true`, {
|
|
6645
6055
|
cwd: ctx.projectPath,
|
|
6646
6056
|
encoding: "utf-8"
|
|
@@ -6659,7 +6069,7 @@ async function verifyBranchMerged(ctx) {
|
|
|
6659
6069
|
async function clearReviewStatusStep(issueId) {
|
|
6660
6070
|
const step = "clear-review-status";
|
|
6661
6071
|
try {
|
|
6662
|
-
const { clearReviewStatus } = await import("../review-status-
|
|
6072
|
+
const { clearReviewStatus } = await import("../review-status-D6H2WOw8.js");
|
|
6663
6073
|
clearReviewStatus(issueId.toUpperCase());
|
|
6664
6074
|
return stepOk(step, ["Review status cleared"]);
|
|
6665
6075
|
} catch {
|
|
@@ -7022,6 +6432,7 @@ function removeWorktree(repoPath, worktreePath) {
|
|
|
7022
6432
|
}
|
|
7023
6433
|
//#endregion
|
|
7024
6434
|
//#region src/cli/commands/workspace.ts
|
|
6435
|
+
init_skills_merge();
|
|
7025
6436
|
init_agents();
|
|
7026
6437
|
init_projects();
|
|
7027
6438
|
init_workspace_manager();
|
|
@@ -7129,6 +6540,7 @@ function registerWorkspaceCommands(program) {
|
|
|
7129
6540
|
workspace.command("list").description("List all workspaces").option("--json", "Output as JSON").option("--all", "List workspaces across all registered projects").action(listCommand$2);
|
|
7130
6541
|
workspace.command("destroy <issueId>").description("Destroy workspace").option("--force", "Force removal even with uncommitted changes").option("--project <path>", "Explicit project path (overrides registry)").action(destroyCommand);
|
|
7131
6542
|
workspace.command("update <issueId>").description("Update skills/agents/rules in an existing workspace").option("--force", "Overwrite user-modified files").action(updateCommand$1);
|
|
6543
|
+
workspace.command("add-repo <workspaceId> <repoNames...>").description("Add repositories to a progressive polyrepo workspace").option("--dry-run", "Show what would be added").option("--group <groupName>", "Add all repos from a named group (from groups_file)").option("--project <path>", "Explicit project path (overrides registry)").action(addRepoCommand);
|
|
7132
6544
|
}
|
|
7133
6545
|
async function createCommand(issueId, options) {
|
|
7134
6546
|
const spinner = ora("Creating workspace...").start();
|
|
@@ -7923,14 +7335,117 @@ async function updateCommand$1(issueId, options) {
|
|
|
7923
7335
|
process.exit(1);
|
|
7924
7336
|
}
|
|
7925
7337
|
}
|
|
7338
|
+
/**
|
|
7339
|
+
* Load repo groups from the groups_file
|
|
7340
|
+
*/
|
|
7341
|
+
function loadRepoGroups(groupsFilePath) {
|
|
7342
|
+
const content = readFileSync(groupsFilePath, "utf8");
|
|
7343
|
+
return YAML.parse(content);
|
|
7344
|
+
}
|
|
7345
|
+
/**
|
|
7346
|
+
* Add repositories to a progressive polyrepo workspace
|
|
7347
|
+
*/
|
|
7348
|
+
async function addRepoCommand(workspaceId, repoNames, options) {
|
|
7349
|
+
const spinner = ora("Adding repositories...").start();
|
|
7350
|
+
try {
|
|
7351
|
+
const normalizedId = workspaceId.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
7352
|
+
const folderName = `feature-${normalizedId}`;
|
|
7353
|
+
let projectConfig = null;
|
|
7354
|
+
if (options.project) projectConfig = loadConfig$1().projects?.projects[options.project] || null;
|
|
7355
|
+
if (!projectConfig) {
|
|
7356
|
+
const allProjects = listProjects();
|
|
7357
|
+
for (const p of Object.values(allProjects)) if (p.workspace?.workspaces_dir) {
|
|
7358
|
+
if (existsSync(join(join(p.path, p.workspace.workspaces_dir), folderName))) {
|
|
7359
|
+
projectConfig = p;
|
|
7360
|
+
break;
|
|
7361
|
+
}
|
|
7362
|
+
}
|
|
7363
|
+
}
|
|
7364
|
+
if (!projectConfig) {
|
|
7365
|
+
spinner.fail(`No project found for workspace ${workspaceId}`);
|
|
7366
|
+
process.exit(1);
|
|
7367
|
+
}
|
|
7368
|
+
const workspaceConfig = projectConfig.workspace;
|
|
7369
|
+
if (!workspaceConfig || workspaceConfig.type !== "polyrepo") {
|
|
7370
|
+
spinner.fail(`Project ${projectConfig.name} does not use polyrepo workspace`);
|
|
7371
|
+
process.exit(1);
|
|
7372
|
+
}
|
|
7373
|
+
if (!workspaceConfig.progressive) spinner.warn("This workspace was not created with progressive mode — all repos already exist");
|
|
7374
|
+
let targetRepoNames = repoNames;
|
|
7375
|
+
if (options.group) {
|
|
7376
|
+
if (!workspaceConfig.groups_file) {
|
|
7377
|
+
spinner.fail("--group requires groups_file to be set in workspace config");
|
|
7378
|
+
process.exit(1);
|
|
7379
|
+
}
|
|
7380
|
+
const groupsFilePath = join(projectConfig.path, workspaceConfig.groups_file);
|
|
7381
|
+
if (!existsSync(groupsFilePath)) {
|
|
7382
|
+
spinner.fail(`Groups file not found: ${groupsFilePath}`);
|
|
7383
|
+
process.exit(1);
|
|
7384
|
+
}
|
|
7385
|
+
const groups = loadRepoGroups(groupsFilePath);
|
|
7386
|
+
if (options.group === "all" || groups.groups[options.group] === "*") targetRepoNames = workspaceConfig.repos.map((r) => r.name);
|
|
7387
|
+
else if (Array.isArray(groups.groups[options.group])) targetRepoNames = groups.groups[options.group];
|
|
7388
|
+
else {
|
|
7389
|
+
spinner.fail(`Unknown group: ${options.group}`);
|
|
7390
|
+
process.exit(1);
|
|
7391
|
+
}
|
|
7392
|
+
}
|
|
7393
|
+
if (targetRepoNames.length === 0) {
|
|
7394
|
+
spinner.fail("No repos to add");
|
|
7395
|
+
process.exit(1);
|
|
7396
|
+
}
|
|
7397
|
+
const result = await addReposToWorkspace({
|
|
7398
|
+
projectConfig,
|
|
7399
|
+
featureName: normalizedId,
|
|
7400
|
+
repoNames: targetRepoNames,
|
|
7401
|
+
dryRun: options.dryRun
|
|
7402
|
+
});
|
|
7403
|
+
if (!result.success) {
|
|
7404
|
+
spinner.fail(`Failed to add repos: ${result.errors.join(", ")}`);
|
|
7405
|
+
for (const step of result.steps) console.log(chalk.dim(` ${step}`));
|
|
7406
|
+
process.exit(1);
|
|
7407
|
+
}
|
|
7408
|
+
spinner.succeed(`Added ${targetRepoNames.length} repository(s) to workspace`);
|
|
7409
|
+
for (const step of result.steps) if (!step.includes("Skipped")) console.log(chalk.green(` ${step}`));
|
|
7410
|
+
else console.log(chalk.dim(` ${step}`));
|
|
7411
|
+
} catch (error) {
|
|
7412
|
+
spinner.fail(`Failed to add repos: ${error.message}`);
|
|
7413
|
+
process.exit(1);
|
|
7414
|
+
}
|
|
7415
|
+
}
|
|
7416
|
+
const YAML = { parse(content) {
|
|
7417
|
+
const result = { groups: {} };
|
|
7418
|
+
let currentSection = null;
|
|
7419
|
+
for (const line of content.split("\n")) {
|
|
7420
|
+
if (!line.trim() || line.trim().startsWith("#")) continue;
|
|
7421
|
+
line.search(/\S/);
|
|
7422
|
+
const trimmed = line.trim();
|
|
7423
|
+
if (trimmed.startsWith("groups:")) {
|
|
7424
|
+
currentSection = "groups";
|
|
7425
|
+
continue;
|
|
7426
|
+
}
|
|
7427
|
+
if (currentSection === "groups") {
|
|
7428
|
+
const match = trimmed.match(/^(\w+):\s*(.*)$/);
|
|
7429
|
+
if (match) {
|
|
7430
|
+
const [, key, value] = match;
|
|
7431
|
+
if (value.trim() === "" || value.trim() === "*") result.groups[key] = value.trim() === "*" ? "*" : [];
|
|
7432
|
+
else result.groups[key] = value.replace(/[\[\]]/g, "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
7433
|
+
}
|
|
7434
|
+
}
|
|
7435
|
+
}
|
|
7436
|
+
return result;
|
|
7437
|
+
} };
|
|
7926
7438
|
//#endregion
|
|
7927
7439
|
//#region src/lib/test-runner.ts
|
|
7440
|
+
init_platform();
|
|
7441
|
+
init_dns();
|
|
7928
7442
|
/**
|
|
7929
7443
|
* Test Runner
|
|
7930
7444
|
*
|
|
7931
7445
|
* Generic test runner that supports various test frameworks
|
|
7932
7446
|
* and can run tests inside or outside Docker containers.
|
|
7933
7447
|
*/
|
|
7448
|
+
init_workspace_config();
|
|
7934
7449
|
const execAsync$13 = promisify(exec);
|
|
7935
7450
|
/**
|
|
7936
7451
|
* Format duration in human-readable format
|
|
@@ -8677,13 +8192,12 @@ async function installCommand(options) {
|
|
|
8677
8192
|
console.log(chalk.green.bold("Installation complete!"));
|
|
8678
8193
|
console.log("");
|
|
8679
8194
|
console.log(chalk.bold("Next steps:"));
|
|
8680
|
-
console.log(` 1. Run ${chalk.cyan("pan sync")} to sync skills to ~/.claude/`);
|
|
8681
8195
|
if (!options.minimal) {
|
|
8682
|
-
console.log(`
|
|
8683
|
-
console.log(`
|
|
8196
|
+
console.log(` 1. Run ${chalk.cyan("pan up")} to start Traefik and dashboard (auto-syncs skills)`);
|
|
8197
|
+
console.log(` 2. Access dashboard at ${chalk.cyan(`https://${config.traefik?.domain || "pan.localhost"}`)}`);
|
|
8684
8198
|
} else {
|
|
8685
|
-
console.log(`
|
|
8686
|
-
console.log(`
|
|
8199
|
+
console.log(` 1. Run ${chalk.cyan("pan up")} to start the dashboard (auto-syncs skills)`);
|
|
8200
|
+
console.log(` 2. Access dashboard at ${chalk.cyan(`http://localhost:${config.dashboard.port}`)}`);
|
|
8687
8201
|
}
|
|
8688
8202
|
console.log(` 4. In each project root, initialize beads task tracking:`);
|
|
8689
8203
|
console.log(` ${chalk.cyan("cd /path/to/your-project && bd init --prefix <project-name>")}`);
|
|
@@ -10906,10 +10420,10 @@ async function checkOrphanedReviewStatuses() {
|
|
|
10906
10420
|
const workspace = getAgentState(agentIdForCheck)?.workspace;
|
|
10907
10421
|
if (workspace) {
|
|
10908
10422
|
const branch = `feature/${issueId.toLowerCase()}`;
|
|
10909
|
-
const { resolveProjectFromIssue } = await import("../projects-
|
|
10423
|
+
const { resolveProjectFromIssue } = await import("../projects-DhU7rAVN.js");
|
|
10910
10424
|
const resolved = resolveProjectFromIssue(issueId);
|
|
10911
10425
|
if (resolved) {
|
|
10912
|
-
const { spawnEphemeralSpecialist } = await import("../specialists-
|
|
10426
|
+
const { spawnEphemeralSpecialist } = await import("../specialists-Bfb9ATzw.js");
|
|
10913
10427
|
const result = await spawnEphemeralSpecialist(resolved.projectKey, "review-agent", {
|
|
10914
10428
|
issueId,
|
|
10915
10429
|
workspace,
|
|
@@ -10922,7 +10436,7 @@ async function checkOrphanedReviewStatuses() {
|
|
|
10922
10436
|
actions.push(`Re-dispatched pending review for ${issueId} via ${resolved.projectKey}/review-agent (deacon-orphan-recovery)`);
|
|
10923
10437
|
console.log(`[deacon] Re-dispatched review for ${issueId} after orphan/pending detection (project: ${resolved.projectKey})`);
|
|
10924
10438
|
} else if (result.error === "specialist_busy") {
|
|
10925
|
-
const { submitToSpecialistQueue } = await import("../specialists-
|
|
10439
|
+
const { submitToSpecialistQueue } = await import("../specialists-Bfb9ATzw.js");
|
|
10926
10440
|
submitToSpecialistQueue("review-agent", {
|
|
10927
10441
|
priority: "high",
|
|
10928
10442
|
source: "deacon-orphan-recovery",
|
|
@@ -10960,10 +10474,10 @@ async function checkOrphanedReviewStatuses() {
|
|
|
10960
10474
|
const workspace = getAgentState(`agent-${issueId.toLowerCase()}`)?.workspace;
|
|
10961
10475
|
if (workspace) {
|
|
10962
10476
|
const branch = `feature/${issueId.toLowerCase()}`;
|
|
10963
|
-
const { resolveProjectFromIssue } = await import("../projects-
|
|
10477
|
+
const { resolveProjectFromIssue } = await import("../projects-DhU7rAVN.js");
|
|
10964
10478
|
const resolved = resolveProjectFromIssue(issueId);
|
|
10965
10479
|
if (resolved) {
|
|
10966
|
-
const { spawnEphemeralSpecialist } = await import("../specialists-
|
|
10480
|
+
const { spawnEphemeralSpecialist } = await import("../specialists-Bfb9ATzw.js");
|
|
10967
10481
|
const result = await spawnEphemeralSpecialist(resolved.projectKey, "test-agent", {
|
|
10968
10482
|
issueId,
|
|
10969
10483
|
workspace,
|
|
@@ -10975,7 +10489,7 @@ async function checkOrphanedReviewStatuses() {
|
|
|
10975
10489
|
actions.push(`Re-dispatched orphaned test for ${issueId} via ${resolved.projectKey}/test-agent (deacon-orphan-recovery)`);
|
|
10976
10490
|
console.log(`[deacon] Re-dispatched test for ${issueId} after orphan detection (project: ${resolved.projectKey})`);
|
|
10977
10491
|
} else if (result.error === "specialist_busy") {
|
|
10978
|
-
const { submitToSpecialistQueue } = await import("../specialists-
|
|
10492
|
+
const { submitToSpecialistQueue } = await import("../specialists-Bfb9ATzw.js");
|
|
10979
10493
|
submitToSpecialistQueue("test-agent", {
|
|
10980
10494
|
priority: "high",
|
|
10981
10495
|
source: "deacon-orphan-recovery",
|
|
@@ -11031,7 +10545,7 @@ async function checkPostReviewCommits() {
|
|
|
11031
10545
|
const actions = [];
|
|
11032
10546
|
try {
|
|
11033
10547
|
const statuses = loadReviewStatuses();
|
|
11034
|
-
const { resolveProjectFromIssue } = await import("../projects-
|
|
10548
|
+
const { resolveProjectFromIssue } = await import("../projects-DhU7rAVN.js");
|
|
11035
10549
|
for (const [issueId, status] of Object.entries(statuses)) {
|
|
11036
10550
|
if (status.mergeStatus === "merged") continue;
|
|
11037
10551
|
if (!status.reviewedAtCommit) continue;
|
|
@@ -11344,9 +10858,9 @@ async function patrolWorkAgentResolutions() {
|
|
|
11344
10858
|
async function checkSpecialistQueues() {
|
|
11345
10859
|
const actions = [];
|
|
11346
10860
|
try {
|
|
11347
|
-
const { checkSpecialistQueue, spawnEphemeralSpecialist, getTmuxSessionName, isRunning } = await import("../specialists-
|
|
11348
|
-
const { getAgentRuntimeState } = await import("../agents-
|
|
11349
|
-
const { resolveProjectFromIssue } = await import("../projects-
|
|
10861
|
+
const { checkSpecialistQueue, spawnEphemeralSpecialist, getTmuxSessionName, isRunning } = await import("../specialists-Bfb9ATzw.js");
|
|
10862
|
+
const { getAgentRuntimeState } = await import("../agents-D_2oRFVf.js");
|
|
10863
|
+
const { resolveProjectFromIssue } = await import("../projects-DhU7rAVN.js");
|
|
11350
10864
|
for (const specialistType of [
|
|
11351
10865
|
"review-agent",
|
|
11352
10866
|
"test-agent",
|
|
@@ -11380,7 +10894,7 @@ async function checkSpecialistQueues() {
|
|
|
11380
10894
|
if (!isIdle) continue;
|
|
11381
10895
|
console.log(`[deacon] Dispatching queued ${specialistType} work for ${issueId} (project: ${resolved.projectKey})`);
|
|
11382
10896
|
try {
|
|
11383
|
-
const { findWorkspacePath } = await import("../archive-planning-
|
|
10897
|
+
const { findWorkspacePath } = await import("../archive-planning-DK90wn9Q.js");
|
|
11384
10898
|
const workspacePath = findWorkspacePath(resolved.projectPath, issueId.toLowerCase());
|
|
11385
10899
|
const queuePayload = item.payload;
|
|
11386
10900
|
await spawnEphemeralSpecialist(resolved.projectKey, specialistType, {
|
|
@@ -11516,7 +11030,7 @@ async function runPatrol() {
|
|
|
11516
11030
|
if (!existsSync(REVIEW_STATUS_FILE$1)) continue;
|
|
11517
11031
|
const statuses = JSON.parse(readFileSync(REVIEW_STATUS_FILE$1, "utf-8"));
|
|
11518
11032
|
if (statuses[issueId]?.mergeStatus === "merging") {
|
|
11519
|
-
const { resolveProjectFromIssue } = await import("../projects-
|
|
11033
|
+
const { resolveProjectFromIssue } = await import("../projects-DhU7rAVN.js");
|
|
11520
11034
|
const resolved = resolveProjectFromIssue(issueId);
|
|
11521
11035
|
if (resolved) {
|
|
11522
11036
|
const branch = `feature/${issueId.toLowerCase()}`;
|
|
@@ -11526,7 +11040,7 @@ async function runPatrol() {
|
|
|
11526
11040
|
statuses[issueId].mergeStatus = "merged";
|
|
11527
11041
|
statuses[issueId].readyForMerge = false;
|
|
11528
11042
|
writeFileSync(REVIEW_STATUS_FILE$1, JSON.stringify(statuses, null, 2), "utf-8");
|
|
11529
|
-
const { postMergeLifecycle } = await import("../merge-agent-
|
|
11043
|
+
const { postMergeLifecycle } = await import("../merge-agent-DlUiUanN.js");
|
|
11530
11044
|
postMergeLifecycle(issueId, resolved.projectPath).catch((err) => console.warn(`[deacon] postMergeLifecycle failed for ${issueId}: ${err}`));
|
|
11531
11045
|
actions.push(`Auto-completed stale merge for ${issueId}`);
|
|
11532
11046
|
} else {
|
|
@@ -11784,7 +11298,7 @@ var CloisterService = class {
|
|
|
11784
11298
|
}
|
|
11785
11299
|
try {
|
|
11786
11300
|
if (existsSync(AGENTS_DIR)) {
|
|
11787
|
-
const { isRunning: isSpecialistRunning } = await import("../specialists-
|
|
11301
|
+
const { isRunning: isSpecialistRunning } = await import("../specialists-Bfb9ATzw.js");
|
|
11788
11302
|
const specialistPattern = /^specialist-(.+)-(review-agent|test-agent|merge-agent)$/;
|
|
11789
11303
|
const entries = readdirSync(AGENTS_DIR, { withFileTypes: true });
|
|
11790
11304
|
for (const entry of entries) {
|
|
@@ -11815,8 +11329,8 @@ var CloisterService = class {
|
|
|
11815
11329
|
}
|
|
11816
11330
|
try {
|
|
11817
11331
|
const reviewStatuses = loadReviewStatuses();
|
|
11818
|
-
const { resolveProjectFromIssue } = await import("../projects-
|
|
11819
|
-
const { submitToSpecialistQueue, getTmuxSessionName, getAllProjectSpecialistStatuses } = await import("../specialists-
|
|
11332
|
+
const { resolveProjectFromIssue } = await import("../projects-DhU7rAVN.js");
|
|
11333
|
+
const { submitToSpecialistQueue, getTmuxSessionName, getAllProjectSpecialistStatuses } = await import("../specialists-Bfb9ATzw.js");
|
|
11820
11334
|
const activeReviewIssues = /* @__PURE__ */ new Set();
|
|
11821
11335
|
try {
|
|
11822
11336
|
const projSpecs = await getAllProjectSpecialistStatuses();
|
|
@@ -12040,7 +11554,7 @@ var CloisterService = class {
|
|
|
12040
11554
|
const retryCount = this.processedCompletions.get(dir.name) || 0;
|
|
12041
11555
|
if (retryCount >= 3) continue;
|
|
12042
11556
|
const issueId = dir.name.replace("agent-", "").toUpperCase();
|
|
12043
|
-
const { getReviewStatus } = await import("../review-status-
|
|
11557
|
+
const { getReviewStatus } = await import("../review-status-D6H2WOw8.js");
|
|
12044
11558
|
const existingReview = getReviewStatus(issueId);
|
|
12045
11559
|
if (existingReview && ["reviewing", "passed"].includes(existingReview.reviewStatus || "")) {
|
|
12046
11560
|
console.log(`🔔 Cloister: Completion marker for ${issueId} — review already ${existingReview.reviewStatus}, marking processed`);
|
|
@@ -12633,7 +12147,7 @@ async function statusCommand$3(options) {
|
|
|
12633
12147
|
console.log(` - Poke on warning: ${status.config.auto_actions.poke_on_warning ? "enabled" : "disabled"}`);
|
|
12634
12148
|
console.log(` - Kill on stuck: ${status.config.auto_actions.kill_on_stuck ? chalk.red("enabled") : "disabled"}`);
|
|
12635
12149
|
try {
|
|
12636
|
-
const { getAppStatus } = await import("../github-app-
|
|
12150
|
+
const { getAppStatus } = await import("../github-app-DykduJ0X.js");
|
|
12637
12151
|
const appStatus = getAppStatus();
|
|
12638
12152
|
console.log("");
|
|
12639
12153
|
console.log(chalk.bold("GitHub App:"));
|
|
@@ -13501,7 +13015,7 @@ const execAsync$6 = promisify(exec);
|
|
|
13501
13015
|
*/
|
|
13502
13016
|
async function listLogsCommand(project, type, options) {
|
|
13503
13017
|
try {
|
|
13504
|
-
const { listRunLogs } = await import("../specialist-logs-
|
|
13018
|
+
const { listRunLogs } = await import("../specialist-logs-DQKKQV9B.js");
|
|
13505
13019
|
const runs = listRunLogs(project, type, { limit: options.limit ? parseInt(options.limit) : 10 });
|
|
13506
13020
|
if (options.json) {
|
|
13507
13021
|
console.log(JSON.stringify(runs, null, 2));
|
|
@@ -13540,7 +13054,7 @@ async function listLogsCommand(project, type, options) {
|
|
|
13540
13054
|
*/
|
|
13541
13055
|
async function viewLogCommand(project, type, runId, options) {
|
|
13542
13056
|
try {
|
|
13543
|
-
const { getRunLog, parseLogMetadata, getRunLogPath } = await import("../specialist-logs-
|
|
13057
|
+
const { getRunLog, parseLogMetadata, getRunLogPath } = await import("../specialist-logs-DQKKQV9B.js");
|
|
13544
13058
|
const content = getRunLog(project, type, runId);
|
|
13545
13059
|
if (!content) {
|
|
13546
13060
|
console.error(`❌ Run log not found: ${runId}`);
|
|
@@ -13571,8 +13085,8 @@ async function viewLogCommand(project, type, runId, options) {
|
|
|
13571
13085
|
*/
|
|
13572
13086
|
async function tailLogCommand(project, type) {
|
|
13573
13087
|
try {
|
|
13574
|
-
const { getRunLogPath } = await import("../specialist-logs-
|
|
13575
|
-
const { getProjectSpecialistMetadata } = await import("../specialists-
|
|
13088
|
+
const { getRunLogPath } = await import("../specialist-logs-DQKKQV9B.js");
|
|
13089
|
+
const { getProjectSpecialistMetadata } = await import("../specialists-Bfb9ATzw.js");
|
|
13576
13090
|
const metadata = getProjectSpecialistMetadata(project, type);
|
|
13577
13091
|
if (!metadata.currentRun) {
|
|
13578
13092
|
console.error(`❌ No active run for ${project}/${type}`);
|
|
@@ -13639,7 +13153,7 @@ async function cleanupLogsCommand(projectOrAll, type, options) {
|
|
|
13639
13153
|
console.log(" Use --force to confirm.");
|
|
13640
13154
|
process.exit(1);
|
|
13641
13155
|
}
|
|
13642
|
-
const { cleanupAllLogs } = await import("../specialist-logs-
|
|
13156
|
+
const { cleanupAllLogs } = await import("../specialist-logs-DQKKQV9B.js");
|
|
13643
13157
|
console.log("🧹 Cleaning up old logs for all projects...\n");
|
|
13644
13158
|
const results = cleanupAllLogs();
|
|
13645
13159
|
console.log(`\n✅ Cleanup complete: deleted ${results.totalDeleted} old logs\n`);
|
|
@@ -13660,8 +13174,8 @@ async function cleanupLogsCommand(projectOrAll, type, options) {
|
|
|
13660
13174
|
console.log(" Use --force to confirm.");
|
|
13661
13175
|
process.exit(1);
|
|
13662
13176
|
}
|
|
13663
|
-
const { cleanupOldLogs } = await import("../specialist-logs-
|
|
13664
|
-
const { getSpecialistRetention } = await import("../projects-
|
|
13177
|
+
const { cleanupOldLogs } = await import("../specialist-logs-DQKKQV9B.js");
|
|
13178
|
+
const { getSpecialistRetention } = await import("../projects-DhU7rAVN.js");
|
|
13665
13179
|
const retention = getSpecialistRetention(projectOrAll);
|
|
13666
13180
|
console.log(`🧹 Cleaning up old logs for ${projectOrAll}/${type}...`);
|
|
13667
13181
|
console.log(` Retention: ${retention.max_days} days or ${retention.max_runs} runs\n`);
|
|
@@ -14319,7 +13833,7 @@ async function projectAddCommand(projectPath, options = {}) {
|
|
|
14319
13833
|
}
|
|
14320
13834
|
const isPolyrepo = !hasRootGit && subRepos.length > 0;
|
|
14321
13835
|
try {
|
|
14322
|
-
const { preTrustDirectory } = await import("../workspace-manager-
|
|
13836
|
+
const { preTrustDirectory } = await import("../workspace-manager-B9jS4Dsq.js");
|
|
14323
13837
|
preTrustDirectory(fullPath);
|
|
14324
13838
|
} catch {}
|
|
14325
13839
|
let hooksInstalled = 0;
|
|
@@ -16621,9 +16135,26 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
|
|
|
16621
16135
|
console.log(chalk.yellow("Warning: Could not read config.toml"));
|
|
16622
16136
|
}
|
|
16623
16137
|
console.log(chalk.bold("Starting Panopticon...\n"));
|
|
16138
|
+
{
|
|
16139
|
+
const origWrite = process.stdout.write;
|
|
16140
|
+
const origErrWrite = process.stderr.write;
|
|
16141
|
+
try {
|
|
16142
|
+
const { syncCommand } = await import("../sync-TL6y-8K6.js");
|
|
16143
|
+
process.stdout.write = () => true;
|
|
16144
|
+
process.stderr.write = () => true;
|
|
16145
|
+
await syncCommand({});
|
|
16146
|
+
process.stdout.write = origWrite;
|
|
16147
|
+
process.stderr.write = origErrWrite;
|
|
16148
|
+
console.log(chalk.dim(" Auto-synced skills, hooks, and MCP config"));
|
|
16149
|
+
} catch {
|
|
16150
|
+
process.stdout.write = origWrite;
|
|
16151
|
+
process.stderr.write = origErrWrite;
|
|
16152
|
+
console.log(chalk.yellow("⚠ Auto-sync failed (non-fatal, continuing startup)"));
|
|
16153
|
+
}
|
|
16154
|
+
}
|
|
16624
16155
|
if (traefikEnabled && !options.skipTraefik) {
|
|
16625
16156
|
try {
|
|
16626
|
-
const { generatePanopticonTraefikConfig, ensureProjectCerts, generateTlsConfig, cleanupStaleTlsSections } = await import("../traefik-
|
|
16157
|
+
const { generatePanopticonTraefikConfig, ensureProjectCerts, generateTlsConfig, cleanupStaleTlsSections } = await import("../traefik-CgHl7Bge.js");
|
|
16627
16158
|
cleanupStaleTlsSections();
|
|
16628
16159
|
if (generatePanopticonTraefikConfig()) console.log(chalk.dim(" Regenerated Traefik config from template"));
|
|
16629
16160
|
const generatedDomains = ensureProjectCerts();
|
|
@@ -16633,7 +16164,7 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
|
|
|
16633
16164
|
console.log(chalk.yellow("Warning: Could not regenerate Traefik config"));
|
|
16634
16165
|
}
|
|
16635
16166
|
try {
|
|
16636
|
-
const { ensureBaseDomain, detectDnsSyncMethod, syncDnsToWindows } = await import("../dns-
|
|
16167
|
+
const { ensureBaseDomain, detectDnsSyncMethod, syncDnsToWindows } = await import("../dns-D_aKQJjb.js");
|
|
16637
16168
|
const dnsMethod = (existsSync(configFile) ? parse(readFileSync(configFile, "utf-8")).traefik?.dns_sync_method : null) || detectDnsSyncMethod();
|
|
16638
16169
|
ensureBaseDomain(dnsMethod, traefikDomain);
|
|
16639
16170
|
if (dnsMethod === "wsl2hosts") syncDnsToWindows().catch(() => {});
|
|
@@ -16776,7 +16307,7 @@ program.command("up").description("Start dashboard (and Traefik if enabled)").op
|
|
|
16776
16307
|
});
|
|
16777
16308
|
}
|
|
16778
16309
|
try {
|
|
16779
|
-
const { getTldrDaemonService } = await import("../tldr-daemon-
|
|
16310
|
+
const { getTldrDaemonService } = await import("../tldr-daemon-D_EooADG.js");
|
|
16780
16311
|
const projectRoot = process.cwd();
|
|
16781
16312
|
const venvPath = join(projectRoot, ".venv");
|
|
16782
16313
|
if (existsSync(venvPath)) {
|
|
@@ -16832,7 +16363,7 @@ program.command("down").description("Stop dashboard (and Traefik if enabled)").o
|
|
|
16832
16363
|
}
|
|
16833
16364
|
}
|
|
16834
16365
|
try {
|
|
16835
|
-
const { getTldrDaemonService } = await import("../tldr-daemon-
|
|
16366
|
+
const { getTldrDaemonService } = await import("../tldr-daemon-D_EooADG.js");
|
|
16836
16367
|
const { exec } = await import("child_process");
|
|
16837
16368
|
const { promisify } = await import("util");
|
|
16838
16369
|
promisify(exec);
|
|
@@ -16899,7 +16430,7 @@ program.command("serve").description("Start the dashboard server and open it in
|
|
|
16899
16430
|
setTimeout(async () => {
|
|
16900
16431
|
console.log(` ${chalk.cyan(url)}`);
|
|
16901
16432
|
try {
|
|
16902
|
-
const { openBrowser } = await import("../browser-
|
|
16433
|
+
const { openBrowser } = await import("../browser-CX7jXfXX.js");
|
|
16903
16434
|
await openBrowser(url);
|
|
16904
16435
|
} catch {
|
|
16905
16436
|
console.log(chalk.dim(` Open your browser to: ${url}`));
|