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.
Files changed (311) hide show
  1. package/README.md +2 -2
  2. package/dist/{agents-DfYify9s.js → agents-CfFDs52G.js} +14 -14
  3. package/dist/{agents-DfYify9s.js.map → agents-CfFDs52G.js.map} +1 -1
  4. package/dist/{agents-BKsVoIc9.js → agents-D_2oRFVf.js} +1 -1
  5. package/dist/{archive-planning-BJrZ3tmN.js → archive-planning-D97ziGec.js} +3 -3
  6. package/dist/{archive-planning-BJrZ3tmN.js.map → archive-planning-D97ziGec.js.map} +1 -1
  7. package/dist/{archive-planning-C3m3hfa5.js → archive-planning-DK90wn9Q.js} +1 -1
  8. package/dist/{browser-Cvdznzc0.js → browser-CX7jXfXX.js} +1 -1
  9. package/dist/{browser-Cvdznzc0.js.map → browser-CX7jXfXX.js.map} +1 -1
  10. package/dist/{clean-planning-DvhZAUv4.js → clean-planning-D_lz4aQq.js} +2 -2
  11. package/dist/{clean-planning-DvhZAUv4.js.map → clean-planning-D_lz4aQq.js.map} +1 -1
  12. package/dist/clean-planning-x1S-JdmO.js +2 -0
  13. package/dist/cli/index.js +291 -760
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/{close-issue-Dr7yZmrr.js → close-issue-CaFE0stN.js} +11 -7
  16. package/dist/close-issue-CaFE0stN.js.map +1 -0
  17. package/dist/close-issue-CjcfZI9s.js +2 -0
  18. package/dist/compact-beads-B0_qE1w3.js +2 -0
  19. package/dist/{compact-beads-BCOtIIRl.js → compact-beads-CjFkteSU.js} +2 -2
  20. package/dist/{compact-beads-BCOtIIRl.js.map → compact-beads-CjFkteSU.js.map} +1 -1
  21. package/dist/{config-CRzMQRgA.js → config-BQNKsi9G.js} +2 -2
  22. package/dist/{config-CRzMQRgA.js.map → config-BQNKsi9G.js.map} +1 -1
  23. package/dist/{config-BYgUzQ21.js → config-agyKgF5C.js} +1 -1
  24. package/dist/{config-yaml-BgOACZAB.js → config-yaml-DGbLSMCa.js} +1 -1
  25. package/dist/{config-yaml-BgOACZAB.js.map → config-yaml-DGbLSMCa.js.map} +1 -1
  26. package/dist/{config-yaml-fdyvyL0S.js → config-yaml-Dqt4FWQH.js} +1 -1
  27. package/dist/dashboard/{acceptance-criteria-e5iiHlRx.js → acceptance-criteria-Dk9hhiYj.js} +1 -1
  28. package/dist/dashboard/{acceptance-criteria-e5iiHlRx.js.map → acceptance-criteria-Dk9hhiYj.js.map} +1 -1
  29. package/dist/dashboard/{agent-enrichment-C67LJBgD.js → agent-enrichment-DdO7ZqjI.js} +11 -7
  30. package/dist/dashboard/agent-enrichment-DdO7ZqjI.js.map +1 -0
  31. package/dist/dashboard/{agent-enrichment-Cq0P1cNZ.js → agent-enrichment-dLeGE1fX.js} +1 -1
  32. package/dist/dashboard/{agents-YyO6t5Xa.js → agents-DCpQQ_W5.js} +14 -14
  33. package/dist/dashboard/{agents-YyO6t5Xa.js.map → agents-DCpQQ_W5.js.map} +1 -1
  34. package/dist/dashboard/{agents-BVBVCyat.js → agents-Dgh2TjSp.js} +1 -1
  35. package/dist/dashboard/{archive-planning-h-hAjk0P.js → archive-planning-BmW9UDTr.js} +3 -3
  36. package/dist/dashboard/{archive-planning-h-hAjk0P.js.map → archive-planning-BmW9UDTr.js.map} +1 -1
  37. package/dist/dashboard/{archive-planning-CScs1MOC.js → archive-planning-C3Ebf9yC.js} +1 -1
  38. package/dist/dashboard/{beads-qNB0yAHV.js → beads-Bv-AdX7G.js} +3 -3
  39. package/dist/dashboard/{beads-qNB0yAHV.js.map → beads-Bv-AdX7G.js.map} +1 -1
  40. package/dist/dashboard/{beads-D_FRedEJ.js → beads-By6-X07V.js} +1 -1
  41. package/dist/dashboard/clean-planning-D60L8rPY.js +2 -0
  42. package/dist/dashboard/{clean-planning-qafw99vY.js → clean-planning-VEJu5suh.js} +2 -2
  43. package/dist/dashboard/{clean-planning-qafw99vY.js.map → clean-planning-VEJu5suh.js.map} +1 -1
  44. package/dist/dashboard/close-issue-C2KeSKKJ.js +2 -0
  45. package/dist/dashboard/{close-issue-DfIggeZD.js → close-issue-DtKdsSTm.js} +11 -7
  46. package/dist/dashboard/close-issue-DtKdsSTm.js.map +1 -0
  47. package/dist/dashboard/compact-beads-C7BN5N11.js +2 -0
  48. package/dist/dashboard/{compact-beads-Dt0qTqsC.js → compact-beads-D8Vt3qyv.js} +2 -2
  49. package/dist/dashboard/{compact-beads-Dt0qTqsC.js.map → compact-beads-D8Vt3qyv.js.map} +1 -1
  50. package/dist/dashboard/{config-CUREjHP7.js → config-CDkGjnwy.js} +2 -2
  51. package/dist/dashboard/{config-CUREjHP7.js.map → config-CDkGjnwy.js.map} +1 -1
  52. package/dist/dashboard/{config-BeI3uy-8.js → config-CTXkBATQ.js} +1 -1
  53. package/dist/dashboard/{database-CozA13Wy.js → database-DhqASALP.js} +1 -1
  54. package/dist/dashboard/{database-C0y0hXBx.js → database-cxmQryoh.js} +2 -2
  55. package/dist/dashboard/{database-C0y0hXBx.js.map → database-cxmQryoh.js.map} +1 -1
  56. package/dist/dashboard/{dist-src-oG2iHzgI.js → dist-src-DTm11oQr.js} +1 -1
  57. package/dist/dashboard/{dist-src-oG2iHzgI.js.map → dist-src-DTm11oQr.js.map} +1 -1
  58. package/dist/dashboard/{event-store-D7kLBd07.js → event-store-VWWUmOfn.js} +1 -1
  59. package/dist/dashboard/{event-store-O9q0Gweh.js → event-store-vSmAA3Zp.js} +9 -4
  60. package/dist/dashboard/event-store-vSmAA3Zp.js.map +1 -0
  61. package/dist/dashboard/{factory-BnLdiQW-.js → factory-C8nhLGHB.js} +3 -3
  62. package/dist/dashboard/{factory-BnLdiQW-.js.map → factory-C8nhLGHB.js.map} +1 -1
  63. package/dist/dashboard/{feedback-writer-DyovUANg.js → feedback-writer-CudSe1WK.js} +2 -2
  64. package/dist/dashboard/{feedback-writer-DyovUANg.js.map → feedback-writer-CudSe1WK.js.map} +1 -1
  65. package/dist/dashboard/{feedback-writer-gSUv_W0h.js → feedback-writer-Wgv1cd1r.js} +1 -1
  66. package/dist/dashboard/{git-utils-BJRioREj.js → git-utils-C1m4SwAe.js} +1 -1
  67. package/dist/dashboard/{git-utils-BJRioREj.js.map → git-utils-C1m4SwAe.js.map} +1 -1
  68. package/dist/dashboard/{git-utils-BtCRddq3.js → git-utils-DQI8EYoj.js} +1 -1
  69. package/dist/dashboard/{github-app-XO-LBUGk.js → github-app-DClWjjHr.js} +1 -1
  70. package/dist/dashboard/{github-app-XO-LBUGk.js.map → github-app-DClWjjHr.js.map} +1 -1
  71. package/dist/dashboard/{health-events-db-584nYgJB.js → health-events-db-BMXQfInV.js} +1 -1
  72. package/dist/dashboard/{health-events-db-B3ChzN65.js → health-events-db-Do4NrOhC.js} +2 -2
  73. package/dist/dashboard/{health-events-db-B3ChzN65.js.map → health-events-db-Do4NrOhC.js.map} +1 -1
  74. package/dist/dashboard/{hooks-CKhs3N68.js → hooks-CB4T47NC.js} +1 -1
  75. package/dist/dashboard/{hooks-CErbP8Oq.js → hooks-CjqXOlNb.js} +2 -2
  76. package/dist/dashboard/{hooks-CErbP8Oq.js.map → hooks-CjqXOlNb.js.map} +1 -1
  77. package/dist/dashboard/hume-CA2pftu_.js +3 -0
  78. package/dist/dashboard/{hume-CX_U3Qha.js → hume-JsAlMOJC.js} +2 -2
  79. package/dist/dashboard/{hume-CX_U3Qha.js.map → hume-JsAlMOJC.js.map} +1 -1
  80. package/dist/dashboard/{inspect-agent-B57kGDUV.js → inspect-agent-7eour7EA.js} +3 -3
  81. package/dist/dashboard/{inspect-agent-B57kGDUV.js.map → inspect-agent-7eour7EA.js.map} +1 -1
  82. package/dist/dashboard/{io-yGovuG4U.js → io-CWlFW78i.js} +1 -1
  83. package/dist/dashboard/{io-AJg-mzFi.js → io-DKS6359z.js} +1 -1
  84. package/dist/dashboard/{io-AJg-mzFi.js.map → io-DKS6359z.js.map} +1 -1
  85. package/dist/dashboard/issue-id-vwYJdsf8.js +62 -0
  86. package/dist/dashboard/issue-id-vwYJdsf8.js.map +1 -0
  87. package/dist/dashboard/{issue-service-singleton-DQK42EqH.js → issue-service-singleton-Co__-6kL.js} +1 -1
  88. package/dist/dashboard/{issue-service-singleton-sb2HkB9f.js → issue-service-singleton-Wv4xBm3y.js} +7 -7
  89. package/dist/dashboard/{issue-service-singleton-sb2HkB9f.js.map → issue-service-singleton-Wv4xBm3y.js.map} +1 -1
  90. package/dist/dashboard/{label-cleanup-CZEsbtq9.js → label-cleanup-nVKTmIIW.js} +7 -4
  91. package/dist/dashboard/label-cleanup-nVKTmIIW.js.map +1 -0
  92. package/dist/dashboard/lifecycle-BcUmtkR4.js +7 -0
  93. package/dist/dashboard/{merge-agent-GLtMEsTu.js → merge-agent-CGN3TT0a.js} +1 -1
  94. package/dist/dashboard/{merge-agent-twroFuAh.js → merge-agent-yudQOPZc.js} +148 -46
  95. package/dist/dashboard/merge-agent-yudQOPZc.js.map +1 -0
  96. package/dist/dashboard/{paths-COdEvoXR.js → paths-BDyJ7BiV.js} +19 -2
  97. package/dist/dashboard/{paths-COdEvoXR.js.map → paths-BDyJ7BiV.js.map} +1 -1
  98. package/dist/dashboard/{pipeline-notifier-DM5AHG5Q.js → pipeline-notifier-CCSN-jar.js} +1 -1
  99. package/dist/dashboard/{pipeline-notifier-DM5AHG5Q.js.map → pipeline-notifier-CCSN-jar.js.map} +1 -1
  100. package/dist/dashboard/{plan-utils-BkCIhn3B.js → plan-utils-Bkcsqr_s.js} +3 -3
  101. package/dist/dashboard/{plan-utils-BkCIhn3B.js.map → plan-utils-Bkcsqr_s.js.map} +1 -1
  102. package/dist/dashboard/{prd-draft-D09Afalc.js → prd-draft-BD8oMkZ1.js} +2 -2
  103. package/dist/dashboard/{prd-draft-D09Afalc.js.map → prd-draft-BD8oMkZ1.js.map} +1 -1
  104. package/dist/dashboard/{projection-cache-DQ9zegkK.js → projection-cache-C0EL8s8h.js} +1 -1
  105. package/dist/dashboard/{projection-cache-DQ9zegkK.js.map → projection-cache-C0EL8s8h.js.map} +1 -1
  106. package/dist/dashboard/{projects-DyT3vSy-.js → projects-C5ozxjwP.js} +1 -1
  107. package/dist/dashboard/{projects-Cq3TWdPS.js → projects-CFVl4oHn.js} +25 -13
  108. package/dist/dashboard/projects-CFVl4oHn.js.map +1 -0
  109. package/dist/dashboard/{providers-Ck2sQd_F.js → providers-B5Y4H2Mg.js} +4 -4
  110. package/dist/dashboard/providers-B5Y4H2Mg.js.map +1 -0
  111. package/dist/dashboard/{providers-DVQnDekG.js → providers-csVZVPkE.js} +1 -1
  112. package/dist/dashboard/public/assets/{dist-CCJbQrSB.js → dist-CXaO6nOE.js} +1 -1
  113. package/dist/dashboard/public/assets/index-CzFZIb87.js +212 -0
  114. package/dist/dashboard/public/assets/index-OEEbThNN.css +1 -0
  115. package/dist/dashboard/public/index.html +2 -2
  116. package/dist/dashboard/rally-6McpKKRa.js +3 -0
  117. package/dist/dashboard/{rally-Cwuae-4C.js → rally-YjFRxIiC.js} +2 -2
  118. package/dist/dashboard/{rally-Cwuae-4C.js.map → rally-YjFRxIiC.js.map} +1 -1
  119. package/dist/dashboard/{rally-api-DSUxm7EO.js → rally-api-C0WqCSkT.js} +1 -1
  120. package/dist/dashboard/{rally-api-DSUxm7EO.js.map → rally-api-C0WqCSkT.js.map} +1 -1
  121. package/dist/dashboard/{rally-api-CEH5KZi4.js → rally-api-DNttdCW4.js} +1 -1
  122. package/dist/dashboard/{remote-BHTTMpJJ.js → remote-Cigqjj3f.js} +2 -2
  123. package/dist/dashboard/{remote-BXo_iIku.js → remote-ObpNZ7hF.js} +2 -2
  124. package/dist/dashboard/{remote-BXo_iIku.js.map → remote-ObpNZ7hF.js.map} +1 -1
  125. package/dist/dashboard/{remote-agents-CTKVhFFY.js → remote-agents-Bf3GuM7t.js} +1 -1
  126. package/dist/dashboard/{remote-agents-C0_0LLNd.js → remote-agents-DFyjT1Le.js} +1 -1
  127. package/dist/dashboard/{remote-agents-C0_0LLNd.js.map → remote-agents-DFyjT1Le.js.map} +1 -1
  128. package/dist/dashboard/{review-status-CK3eBGyb.js → review-status-BtXqWBhS.js} +1 -1
  129. package/dist/dashboard/{review-status-CV55Tl-n.js → review-status-Bymwzh2i.js} +44 -4
  130. package/dist/dashboard/{review-status-CV55Tl-n.js.map → review-status-Bymwzh2i.js.map} +1 -1
  131. package/dist/dashboard/server.js +559 -253
  132. package/dist/dashboard/server.js.map +1 -1
  133. package/dist/dashboard/{settings-CuHV-wcv.js → settings-BHlDG7TK.js} +2 -2
  134. package/dist/dashboard/settings-BHlDG7TK.js.map +1 -0
  135. package/dist/dashboard/settings-XWvDcj-D.js +2 -0
  136. package/dist/dashboard/{shadow-engineering-BUeZunaE.js → shadow-engineering-lIn1W_95.js} +1 -1
  137. package/dist/dashboard/{shadow-engineering-BUeZunaE.js.map → shadow-engineering-lIn1W_95.js.map} +1 -1
  138. package/dist/dashboard/{shadow-state-DHQ-kASN.js → shadow-state-BIexcxkv.js} +1 -1
  139. package/dist/dashboard/{shadow-state-DHQ-kASN.js.map → shadow-state-BIexcxkv.js.map} +1 -1
  140. package/dist/dashboard/{spawn-planning-session-8FFAqLdK.js → spawn-planning-session-33Jf-d5T.js} +6 -6
  141. package/dist/dashboard/{spawn-planning-session-8FFAqLdK.js.map → spawn-planning-session-33Jf-d5T.js.map} +1 -1
  142. package/dist/dashboard/{spawn-planning-session-U0Lqpjen.js → spawn-planning-session-D5hrVdWM.js} +1 -1
  143. package/dist/dashboard/{specialist-context-ColzlmGE.js → specialist-context-DGukHSn8.js} +6 -6
  144. package/dist/dashboard/{specialist-context-ColzlmGE.js.map → specialist-context-DGukHSn8.js.map} +1 -1
  145. package/dist/dashboard/{specialist-logs-BhmDpFIq.js → specialist-logs-CIw4qfTy.js} +1 -1
  146. package/dist/dashboard/{specialists-C6s3U6tX.js → specialists-B_zrayaP.js} +37 -36
  147. package/dist/dashboard/specialists-B_zrayaP.js.map +1 -0
  148. package/dist/dashboard/{specialists-Cny632-T.js → specialists-Cp-PgspS.js} +1 -1
  149. package/dist/dashboard/{test-agent-queue-tqI4VDsu.js → test-agent-queue-ypF_ecHo.js} +4 -4
  150. package/dist/dashboard/{test-agent-queue-tqI4VDsu.js.map → test-agent-queue-ypF_ecHo.js.map} +1 -1
  151. package/dist/dashboard/{tldr-daemon-BNFyS7W_.js → tldr-daemon-B_oLRD8z.js} +2 -2
  152. package/dist/dashboard/{tldr-daemon-BNFyS7W_.js.map → tldr-daemon-B_oLRD8z.js.map} +1 -1
  153. package/dist/dashboard/{tldr-daemon-A6JqC59u.js → tldr-daemon-Cfs0bXTi.js} +1 -1
  154. package/dist/dashboard/{tmux-DYGAVJfb.js → tmux-BzxdKItf.js} +1 -1
  155. package/dist/dashboard/{tmux-IlN1Slv-.js → tmux-LwG0tHhU.js} +2 -2
  156. package/dist/dashboard/{tmux-IlN1Slv-.js.map → tmux-LwG0tHhU.js.map} +1 -1
  157. package/dist/dashboard/{tracker-config-BzNLnmcE.js → tracker-config-BP59uH4V.js} +1 -1
  158. package/dist/dashboard/{tracker-config-CNM_5rEf.js → tracker-config-e7ph1QqT.js} +2 -2
  159. package/dist/dashboard/{tracker-config-CNM_5rEf.js.map → tracker-config-e7ph1QqT.js.map} +1 -1
  160. package/dist/dashboard/{tunnel-D2BkwU7k.js → tunnel-0RzzuXPf.js} +1 -1
  161. package/dist/dashboard/{tunnel-Dub2hiAA.js → tunnel-DldbBPWL.js} +2 -2
  162. package/dist/dashboard/{tunnel-Dub2hiAA.js.map → tunnel-DldbBPWL.js.map} +1 -1
  163. package/dist/dashboard/{types-CWA-o4UN.js → types-RKZjGE5N.js} +1 -1
  164. package/dist/dashboard/{types-CWA-o4UN.js.map → types-RKZjGE5N.js.map} +1 -1
  165. package/dist/dashboard/{vtt-parser-BAXygRf0.js → vtt-parser-99vFekRQ.js} +1 -1
  166. package/dist/dashboard/{vtt-parser-BAXygRf0.js.map → vtt-parser-99vFekRQ.js.map} +1 -1
  167. package/dist/dashboard/{work-agent-prompt-JYq_OugP.js → work-agent-prompt-fCg67nyo.js} +65 -10
  168. package/dist/dashboard/{work-agent-prompt-JYq_OugP.js.map → work-agent-prompt-fCg67nyo.js.map} +1 -1
  169. package/dist/dashboard/{work-type-router-Cxp8_ur2.js → work-type-router-CWVW2Wk_.js} +1 -1
  170. package/dist/dashboard/{work-type-router-Cxp8_ur2.js.map → work-type-router-CWVW2Wk_.js.map} +1 -1
  171. package/dist/dashboard/{work-type-router-Com2amST.js → work-type-router-Di5gCQwh.js} +1 -1
  172. package/dist/dashboard/{workflows-N1UTipYl.js → workflows-BSMipN07.js} +35 -17
  173. package/dist/dashboard/workflows-BSMipN07.js.map +1 -0
  174. package/dist/dashboard/workflows-DaYWQIS2.js +2 -0
  175. package/dist/dashboard/{workspace-config-cmp5_ipD.js → workspace-config-DVDR-Ukh.js} +1 -1
  176. package/dist/dashboard/workspace-config-DVDR-Ukh.js.map +1 -0
  177. package/dist/dashboard/{workspace-manager-CjpWPgzL.js → workspace-manager-BYfzs_t2.js} +1 -1
  178. package/dist/dashboard/{workspace-manager-D_y9ZmW_.js → workspace-manager-C7OfT62A.js} +44 -24
  179. package/dist/dashboard/workspace-manager-C7OfT62A.js.map +1 -0
  180. package/dist/{dns-BKzHm-2q.js → dns-D_aKQJjb.js} +1 -1
  181. package/dist/{dns-DZwOWvVO.js → dns-Yxq4NNS7.js} +1 -1
  182. package/dist/{dns-DZwOWvVO.js.map → dns-Yxq4NNS7.js.map} +1 -1
  183. package/dist/{factory-DFu3IT4r.js → factory-BRBGw6OB.js} +1 -1
  184. package/dist/{factory-DfzczxN1.js → factory-DzsOiZVc.js} +3 -3
  185. package/dist/{factory-DfzczxN1.js.map → factory-DzsOiZVc.js.map} +1 -1
  186. package/dist/{feedback-writer-CwdnOkPO.js → feedback-writer-ygXN5F9N.js} +2 -2
  187. package/dist/{feedback-writer-CwdnOkPO.js.map → feedback-writer-ygXN5F9N.js.map} +1 -1
  188. package/dist/{github-app-CHKwxOeQ.js → github-app-DykduJ0X.js} +1 -1
  189. package/dist/{github-app-CHKwxOeQ.js.map → github-app-DykduJ0X.js.map} +1 -1
  190. package/dist/hume-9nv1VmMV.js +3 -0
  191. package/dist/{hume-DnV-tDsh.js → hume-DoCbph2h.js} +2 -2
  192. package/dist/{hume-DnV-tDsh.js.map → hume-DoCbph2h.js.map} +1 -1
  193. package/dist/index.d.ts +17 -2
  194. package/dist/index.d.ts.map +1 -1
  195. package/dist/index.js +8 -7
  196. package/dist/issue-id-CAcekoIw.js +62 -0
  197. package/dist/issue-id-CAcekoIw.js.map +1 -0
  198. package/dist/{label-cleanup-31ElPqqv.js → label-cleanup-C8R9Rspn.js} +7 -4
  199. package/dist/label-cleanup-C8R9Rspn.js.map +1 -0
  200. package/dist/{manifest-DL0oDbpv.js → manifest-B4ghOD-V.js} +1 -1
  201. package/dist/{manifest-DL0oDbpv.js.map → manifest-B4ghOD-V.js.map} +1 -1
  202. package/dist/{merge-agent-VQH9z9t8.js → merge-agent-DlUiUanN.js} +86 -33
  203. package/dist/merge-agent-DlUiUanN.js.map +1 -0
  204. package/dist/{paths-lMaxrYtT.js → paths-CDJ_HsbN.js} +19 -2
  205. package/dist/{paths-lMaxrYtT.js.map → paths-CDJ_HsbN.js.map} +1 -1
  206. package/dist/{pipeline-notifier-OJ-d3Y60.js → pipeline-notifier-XgDdCdvT.js} +1 -1
  207. package/dist/{pipeline-notifier-OJ-d3Y60.js.map → pipeline-notifier-XgDdCdvT.js.map} +1 -1
  208. package/dist/{projects-CvLepaxC.js → projects-Bk-5QhFQ.js} +25 -13
  209. package/dist/projects-Bk-5QhFQ.js.map +1 -0
  210. package/dist/{projects-DMWmPeIU.js → projects-DhU7rAVN.js} +1 -1
  211. package/dist/{providers-DcCPZ5K4.js → providers-DSU1vfQF.js} +4 -4
  212. package/dist/providers-DSU1vfQF.js.map +1 -0
  213. package/dist/rally-DdPvGa-w.js +3 -0
  214. package/dist/{rally-uUUZXp1h.js → rally-Dy00NElU.js} +1 -1
  215. package/dist/{rally-uUUZXp1h.js.map → rally-Dy00NElU.js.map} +1 -1
  216. package/dist/{remote-CkLBqLJc.js → remote-CYiOJg0q.js} +2 -2
  217. package/dist/{remote-CkLBqLJc.js.map → remote-CYiOJg0q.js.map} +1 -1
  218. package/dist/{remote-agents-C5Bd2fgt.js → remote-agents-CZXrUF4f.js} +1 -1
  219. package/dist/{remote-agents-C5Bd2fgt.js.map → remote-agents-CZXrUF4f.js.map} +1 -1
  220. package/dist/{remote-agents-BTzD-wMQ.js → remote-agents-ycHHVsgf.js} +1 -1
  221. package/dist/{remote-workspace-Dxghqiti.js → remote-workspace-CA33UuVI.js} +4 -4
  222. package/dist/{remote-workspace-Dxghqiti.js.map → remote-workspace-CA33UuVI.js.map} +1 -1
  223. package/dist/{review-status-2TdtHNcs.js → review-status-D6H2WOw8.js} +1 -1
  224. package/dist/{review-status-Bm1bWNEa.js → review-status-DEDvCKMP.js} +44 -4
  225. package/dist/{review-status-Bm1bWNEa.js.map → review-status-DEDvCKMP.js.map} +1 -1
  226. package/dist/{tracker-C_62ukEq.js → settings-BcWPTrua.js} +7 -199
  227. package/dist/settings-BcWPTrua.js.map +1 -0
  228. package/dist/shadow-state-BZzxfEGw.js +2 -0
  229. package/dist/{shadow-state-CFFHf05M.js → shadow-state-CE3dQfll.js} +1 -1
  230. package/dist/{shadow-state-CFFHf05M.js.map → shadow-state-CE3dQfll.js.map} +1 -1
  231. package/dist/{specialist-context-BdNFsfMG.js → specialist-context-BAUWL1Fl.js} +6 -6
  232. package/dist/{specialist-context-BdNFsfMG.js.map → specialist-context-BAUWL1Fl.js.map} +1 -1
  233. package/dist/{specialist-logs-CLztE_bE.js → specialist-logs-DQKKQV9B.js} +1 -1
  234. package/dist/{specialists-aUoUVWsN.js → specialists-Bfb9ATzw.js} +1 -1
  235. package/dist/{specialists-DEKqgkxp.js → specialists-D7Kj5o6s.js} +35 -34
  236. package/dist/specialists-D7Kj5o6s.js.map +1 -0
  237. package/dist/sync-DMfgd389.js +693 -0
  238. package/dist/sync-DMfgd389.js.map +1 -0
  239. package/dist/sync-TL6y-8K6.js +2 -0
  240. package/dist/{tldr-daemon-BCEFPItr.js → tldr-daemon-CFx4LXAl.js} +2 -2
  241. package/dist/{tldr-daemon-BCEFPItr.js.map → tldr-daemon-CFx4LXAl.js.map} +1 -1
  242. package/dist/{tldr-daemon-xBAx4cBE.js → tldr-daemon-D_EooADG.js} +1 -1
  243. package/dist/{tmux-DN6H886Y.js → tmux-CBtui_Cl.js} +1 -1
  244. package/dist/{tmux-CKdNxxJx.js → tmux-D6Ah4I8z.js} +2 -2
  245. package/dist/{tmux-CKdNxxJx.js.map → tmux-D6Ah4I8z.js.map} +1 -1
  246. package/dist/tracker-BhYYvU3p.js +198 -0
  247. package/dist/tracker-BhYYvU3p.js.map +1 -0
  248. package/dist/{tracker-utils-CVU2W1sX.js → tracker-utils-ChQyut8w.js} +34 -12
  249. package/dist/tracker-utils-ChQyut8w.js.map +1 -0
  250. package/dist/{traefik-DHgBoWXX.js → traefik-C80EbDu_.js} +4 -4
  251. package/dist/{traefik-DHgBoWXX.js.map → traefik-C80EbDu_.js.map} +1 -1
  252. package/dist/{traefik-BR-edbZv.js → traefik-CgHl7Bge.js} +1 -1
  253. package/dist/{tunnel-BZO9Q5oe.js → tunnel-DXOJ1wMM.js} +1 -1
  254. package/dist/{tunnel-Bl1qNSyQ.js → tunnel-DzXEPwIc.js} +2 -2
  255. package/dist/{tunnel-Bl1qNSyQ.js.map → tunnel-DzXEPwIc.js.map} +1 -1
  256. package/dist/{types-DewGdaIP.js → types-BhJj1SP1.js} +1 -1
  257. package/dist/{types-DewGdaIP.js.map → types-BhJj1SP1.js.map} +1 -1
  258. package/dist/{work-type-router-CS2BB1vS.js → work-type-router-CHjciPyS.js} +3 -3
  259. package/dist/{work-type-router-CS2BB1vS.js.map → work-type-router-CHjciPyS.js.map} +1 -1
  260. package/dist/{workspace-config-CNXOpKuj.js → workspace-config-fUafvYMp.js} +1 -1
  261. package/dist/workspace-config-fUafvYMp.js.map +1 -0
  262. package/dist/workspace-manager-B9jS4Dsq.js +3 -0
  263. package/dist/{workspace-manager-CncdZkIy.js → workspace-manager-DuLhnzJV.js} +112 -27
  264. package/dist/workspace-manager-DuLhnzJV.js.map +1 -0
  265. package/package.json +2 -1
  266. package/scripts/post-merge-deploy.sh +25 -5
  267. package/scripts/record-cost-event.js +57 -7
  268. package/scripts/record-cost-event.js.map +1 -1
  269. package/skills/pan-help/SKILL.md +1 -1
  270. package/skills/pan-sync/SKILL.md +6 -6
  271. package/skills/workspace-add-repo/skill.md +46 -0
  272. package/templates/claude-md/sections/warnings.md +15 -2
  273. package/dist/clean-planning-sZXvy3Y5.js +0 -2
  274. package/dist/close-issue-Dml437qV.js +0 -2
  275. package/dist/close-issue-Dr7yZmrr.js.map +0 -1
  276. package/dist/compact-beads-iu218JcO.js +0 -2
  277. package/dist/dashboard/agent-enrichment-C67LJBgD.js.map +0 -1
  278. package/dist/dashboard/clean-planning-DCu3cOTu.js +0 -2
  279. package/dist/dashboard/close-issue-DfIggeZD.js.map +0 -1
  280. package/dist/dashboard/close-issue-DwdwYtar.js +0 -2
  281. package/dist/dashboard/compact-beads-DXY2fK2s.js +0 -2
  282. package/dist/dashboard/event-store-O9q0Gweh.js.map +0 -1
  283. package/dist/dashboard/hume-MZndNDVU.js +0 -3
  284. package/dist/dashboard/label-cleanup-CZEsbtq9.js.map +0 -1
  285. package/dist/dashboard/lifecycle-ZTYdrr2O.js +0 -7
  286. package/dist/dashboard/merge-agent-twroFuAh.js.map +0 -1
  287. package/dist/dashboard/projects-Cq3TWdPS.js.map +0 -1
  288. package/dist/dashboard/providers-Ck2sQd_F.js.map +0 -1
  289. package/dist/dashboard/public/assets/index-CpSmB2ts.css +0 -1
  290. package/dist/dashboard/public/assets/index-yarWhi0M.js +0 -214
  291. package/dist/dashboard/rally-CQ1OBJrJ.js +0 -3
  292. package/dist/dashboard/settings-CuHV-wcv.js.map +0 -1
  293. package/dist/dashboard/settings-DMeGBRsk.js +0 -2
  294. package/dist/dashboard/specialists-C6s3U6tX.js.map +0 -1
  295. package/dist/dashboard/workflows-B2ARUpOa.js +0 -2
  296. package/dist/dashboard/workflows-N1UTipYl.js.map +0 -1
  297. package/dist/dashboard/workspace-config-cmp5_ipD.js.map +0 -1
  298. package/dist/dashboard/workspace-manager-D_y9ZmW_.js.map +0 -1
  299. package/dist/hume-BjmwmJ9E.js +0 -3
  300. package/dist/label-cleanup-31ElPqqv.js.map +0 -1
  301. package/dist/merge-agent-VQH9z9t8.js.map +0 -1
  302. package/dist/projects-CvLepaxC.js.map +0 -1
  303. package/dist/providers-DcCPZ5K4.js.map +0 -1
  304. package/dist/rally-DR9x8--6.js +0 -3
  305. package/dist/shadow-state-p3jpGRPJ.js +0 -2
  306. package/dist/specialists-DEKqgkxp.js.map +0 -1
  307. package/dist/tracker-C_62ukEq.js.map +0 -1
  308. package/dist/tracker-utils-CVU2W1sX.js.map +0 -1
  309. package/dist/workspace-config-CNXOpKuj.js.map +0 -1
  310. package/dist/workspace-manager-CncdZkIy.js.map +0 -1
  311. 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 isDevMode, 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, W as init_paths, 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-lMaxrYtT.js";
4
- import { a as init_config, i as getDevrootPath, n as getDashboardApiUrl, o as loadConfig$1, r as getDefaultConfig, s as saveConfig } from "../config-CRzMQRgA.js";
5
- import { D as detectShell, E as addAlias, O as getAliasInstructions, S as createBackup, T as restoreBackup, _ as planSync, b as syncStatusline, g as planHooksSync, h as migrateStalePersonalContent, k as getShellRcFile, p as executeSync, u as loadSettings, v as refreshCache, w as listBackups, x as cleanOldBackups, y as syncHooks } from "../tracker-C_62ukEq.js";
6
- 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-CvLepaxC.js";
7
- import { n as init_workspace_config, r as replacePlaceholders } from "../workspace-config-CNXOpKuj.js";
8
- import { a as detectDnsSyncMethod, f as syncDnsToWindows, m as init_platform, o as ensureBaseDomain, p as detectPlatform$1, s as init_dns } from "../dns-DZwOWvVO.js";
9
- import { c as applyProjectTemplateOverlay, i as migratePanopticonToPan, l as init_skills_merge, o as removeWorkspace, r as init_workspace_manager, t as createWorkspace, u as mergeSkillsIntoWorkspace } from "../workspace-manager-CncdZkIy.js";
10
- import { d as sessionExists, i as createSession, l as sendKeys, o as init_tmux, s as killSession, u as sendKeysAsync } from "../tmux-CKdNxxJx.js";
11
- 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-CS2BB1vS.js";
12
- 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-DfYify9s.js";
13
- import { n as init_config_yaml, r as loadConfig$2 } from "../config-yaml-BgOACZAB.js";
14
- import { i as NotImplementedError, o as init_interface } from "../rally-uUUZXp1h.js";
15
- import { n as createTrackerFromConfig, o as init_factory, t as createTracker } from "../factory-DfzczxN1.js";
16
- import { n as resolveGitHubIssue, r as resolveTrackerType, t as isGitHubIssue } from "../tracker-utils-CVU2W1sX.js";
17
- 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-CFFHf05M.js";
18
- 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-CkLBqLJc.js";
19
- import { a as spawnRemoteAgent, n as isRemoteAgentRunning, o as createFlyProvider } from "../remote-agents-C5Bd2fgt.js";
20
- 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-DEKqgkxp.js";
21
- import { i as init_tldr_daemon, n as getTldrDaemonService, r as getTldrMetrics } from "../tldr-daemon-BCEFPItr.js";
22
- 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-Bm1bWNEa.js";
23
- import { i as stepSkipped, n as stepFailed, r as stepOk } from "../types-DewGdaIP.js";
24
- import { r as findWorkspacePath, t as archivePlanning } from "../archive-planning-BJrZ3tmN.js";
25
- import "../clean-planning-DvhZAUv4.js";
26
- import { t as closeIssue } from "../close-issue-Dr7yZmrr.js";
27
- import "../compact-beads-BCOtIIRl.js";
28
- import { a as generateTlsConfig, i as generatePanopticonTraefikConfig, n as cleanupTemplateFiles, r as ensureProjectCerts } from "../traefik-DHgBoWXX.js";
29
- import { appendFileSync, chmodSync, copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "fs";
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. Run: pan sync"));
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 repos = projectConfig.workspace.repos;
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 repos) lines.push(`| \`${repo.name}/\` | Git worktree for ${repo.path} |`);
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-Dxghqiti.js");
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-fdyvyL0S.js");
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 = parseInt(issueId.split("-")[1], 10);
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-BKsVoIc9.js");
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-BKsVoIc9.js");
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-BYgUzQ21.js");
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
- console.log(chalk.yellow(` ⚠ Issue was previously merged. Resetting specialist states for re-review...`));
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-fdyvyL0S.js");
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-DFu3IT4r.js");
3421
- const { resolveProjectFromIssue } = await import("../projects-DMWmPeIU.js");
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-DMWmPeIU.js")).getProject(project.projectKey)?.rally_project : void 0;
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-BKsVoIc9.js");
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.split("-")[0].toUpperCase();
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-xBAx4cBE.js");
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-Cx0r2Jnv.js");
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-p3jpGRPJ.js");
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-BZO9Q5oe.js");
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-BjmwmJ9E.js");
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.split("-")[0].toLowerCase();
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-2TdtHNcs.js");
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-2TdtHNcs.js");
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(` 2. Run ${chalk.cyan("pan up")} to start Traefik and dashboard`);
8683
- console.log(` 3. Access dashboard at ${chalk.cyan(`https://${config.traefik?.domain || "pan.localhost"}`)}`);
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(` 2. Run ${chalk.cyan("pan up")} to start the dashboard`);
8686
- console.log(` 3. Access dashboard at ${chalk.cyan(`http://localhost:${config.dashboard.port}`)}`);
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-DMWmPeIU.js");
10423
+ const { resolveProjectFromIssue } = await import("../projects-DhU7rAVN.js");
10910
10424
  const resolved = resolveProjectFromIssue(issueId);
10911
10425
  if (resolved) {
10912
- const { spawnEphemeralSpecialist } = await import("../specialists-aUoUVWsN.js");
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-aUoUVWsN.js");
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-DMWmPeIU.js");
10477
+ const { resolveProjectFromIssue } = await import("../projects-DhU7rAVN.js");
10964
10478
  const resolved = resolveProjectFromIssue(issueId);
10965
10479
  if (resolved) {
10966
- const { spawnEphemeralSpecialist } = await import("../specialists-aUoUVWsN.js");
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-aUoUVWsN.js");
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-DMWmPeIU.js");
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-aUoUVWsN.js");
11348
- const { getAgentRuntimeState } = await import("../agents-BKsVoIc9.js");
11349
- const { resolveProjectFromIssue } = await import("../projects-DMWmPeIU.js");
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-C3m3hfa5.js");
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-DMWmPeIU.js");
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-VQH9z9t8.js");
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-aUoUVWsN.js");
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-DMWmPeIU.js");
11819
- const { submitToSpecialistQueue, getTmuxSessionName, getAllProjectSpecialistStatuses } = await import("../specialists-aUoUVWsN.js");
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-2TdtHNcs.js");
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-CHKwxOeQ.js");
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-CLztE_bE.js");
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-CLztE_bE.js");
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-CLztE_bE.js");
13575
- const { getProjectSpecialistMetadata } = await import("../specialists-aUoUVWsN.js");
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-CLztE_bE.js");
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-CLztE_bE.js");
13664
- const { getSpecialistRetention } = await import("../projects-DMWmPeIU.js");
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-Cx0r2Jnv.js");
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-BR-edbZv.js");
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-BKzHm-2q.js");
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-xBAx4cBE.js");
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-xBAx4cBE.js");
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-Cvdznzc0.js");
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}`));