@dylanpiercey/work 0.0.222 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -31
- package/bin/work.mjs +121 -122
- package/dist/{_DNhDGBkH.js → _Bq7to522.js} +544 -254
- package/dist/_CkwTsHKB.js +2 -0
- package/dist/index.mjs +2813 -3240
- package/dist/public/assets/_1RHVsAcK.js +1 -0
- package/dist/public/assets/_4CShjaLP.js +1 -0
- package/dist/public/assets/_68JtNDO1.js +1 -0
- package/dist/public/assets/{_CtQ-4c6a.js → _8G2Mv7jG.js} +1 -1
- package/dist/public/assets/_8G2Mv7jG.js.br +0 -0
- package/dist/public/assets/{_DYBhy6q4.js → _8dvK2NDJ.js} +1 -1
- package/dist/public/assets/_8dvK2NDJ.js.br +0 -0
- package/dist/public/assets/_94L2SIJF.js +1 -0
- package/dist/public/assets/_9AnDb3YH.js +1 -0
- package/dist/public/assets/{_BJk5sqrB.js → _9kX9D09B.js} +1 -1
- package/dist/public/assets/_9kX9D09B.js.br +0 -0
- package/dist/public/assets/_9lErVegn.js +1 -0
- package/dist/public/assets/_B0oyGUU5.js +1 -0
- package/dist/public/assets/_B0oyGUU5.js.br +0 -0
- package/dist/public/assets/_B1mPnLlp.js +1 -0
- package/dist/public/assets/_B4fi2SSA.js +1 -0
- package/dist/public/assets/{_OZcBKgKS.js → _B582D2rg.js} +1 -1
- package/dist/public/assets/{_DYm1j3HZ.js → _B7GwDeKK.js} +1 -1
- package/dist/public/assets/_B7Qx25UP.js +1 -0
- package/dist/public/assets/_B7b8EVjA.js +1 -0
- package/dist/public/assets/{_Cp1dT7ox.js → _BBWaxDkO.js} +1 -1
- package/dist/public/assets/_BBWaxDkO.js.br +0 -0
- package/dist/public/assets/{_BYHfXvmU.js → _BDa-iwuj.js} +1 -1
- package/dist/public/assets/_BDa-iwuj.js.br +0 -0
- package/dist/public/assets/_BEKHKNmM.js +1 -0
- package/dist/public/assets/{_BHkMvOuI.js → _BE_Jyvqd.js} +1 -1
- package/dist/public/assets/_BE_Jyvqd.js.br +0 -0
- package/dist/public/assets/_BFU-kJkk.js +1 -0
- package/dist/public/assets/_BGCK5I_O.js +1 -0
- package/dist/public/assets/_BGCK5I_O.js.br +0 -0
- package/dist/public/assets/_BIJ2O2oU.js +1 -0
- package/dist/public/assets/_BJ59XAZ9.js +1 -0
- package/dist/public/assets/_BKqRYfOI.js +15 -0
- package/dist/public/assets/_BKqRYfOI.js.br +0 -0
- package/dist/public/assets/_BKr9Dzz1.js +1 -0
- package/dist/public/assets/_BN7xvxS_.js +1 -0
- package/dist/public/assets/_BNQTVBlH.js +1 -0
- package/dist/public/assets/{_DFiA_pht.js → _BNW5Jiec.js} +1 -1
- package/dist/public/assets/_BNW5Jiec.js.br +0 -0
- package/dist/public/assets/{_DW6AnxDW.js → _BOGkzMx9.js} +1 -1
- package/dist/public/assets/_BOGkzMx9.js.br +0 -0
- package/dist/public/assets/_BUEpqQ_m.js +1 -0
- package/dist/public/assets/{_BJIAaIh4.js → _BUvqweu0.js} +1 -1
- package/dist/public/assets/_BUvqweu0.js.br +0 -0
- package/dist/public/assets/_BZKB4fhr.js +1 -0
- package/dist/public/assets/_BZKB4fhr.js.br +0 -0
- package/dist/public/assets/_BZo9BjDF.js +1 -0
- package/dist/public/assets/{_4KGVbuYs.js → _BbbOvNRH.js} +1 -1
- package/dist/public/assets/_BbbOvNRH.js.br +0 -0
- package/dist/public/assets/_BdUNnSlC.js +1 -0
- package/dist/public/assets/{_KM7EGl2R.js → _Bf8WYPfh.js} +1 -1
- package/dist/public/assets/_Bf8WYPfh.js.br +0 -0
- package/dist/public/assets/{_buuWf96L.js → _Bhx319Hi.js} +1 -1
- package/dist/public/assets/_Bhx319Hi.js.br +0 -0
- package/dist/public/assets/{_BYgxEDpq.js → _Bm4SHrNp.js} +1 -1
- package/dist/public/assets/_Bm4SHrNp.js.br +0 -0
- package/dist/public/assets/_Bmrqq8Ro.js +2 -0
- package/dist/public/assets/_Bmrqq8Ro.js.br +0 -0
- package/dist/public/assets/_BnHZ6Npj.js +1 -0
- package/dist/public/assets/{_NGfZeYAt.js → _BoDxRJLS.js} +1 -1
- package/dist/public/assets/_BoDxRJLS.js.br +0 -0
- package/dist/public/assets/_Bo_Ru664.js +1 -0
- package/dist/public/assets/{_BxpaVKca.js → _Bp8-V8yl.js} +1 -1
- package/dist/public/assets/_Bp8-V8yl.js.br +0 -0
- package/dist/public/assets/{_Ct2VbISZ.js → _BpoeUr5j.js} +1 -1
- package/dist/public/assets/_BpoeUr5j.js.br +0 -0
- package/dist/public/assets/_Bq2G_Tid.js +1 -0
- package/dist/public/assets/_BsyoLB_D.js +1 -0
- package/dist/public/assets/{_CdWPIocC.js → _Bv3e3rg8.js} +1 -1
- package/dist/public/assets/_Bv3e3rg8.js.br +0 -0
- package/dist/public/assets/{_D74J3kwJ.js → _Bv3qNE1b.js} +1 -1
- package/dist/public/assets/{_BSliyqkf.js → _BvXp6HpX.js} +1 -1
- package/dist/public/assets/_BvXp6HpX.js.br +0 -0
- package/dist/public/assets/{_DNqoI_cd.js → _BwP07uVS.js} +1 -1
- package/dist/public/assets/_BwP07uVS.js.br +0 -0
- package/dist/public/assets/{_D93v6VDe.js → _Bx1CW-sF.js} +1 -1
- package/dist/public/assets/_Bx1CW-sF.js.br +0 -0
- package/dist/public/assets/{_DZLJGzpN.js → _BywcP-As.js} +1 -1
- package/dist/public/assets/_BywcP-As.js.br +0 -0
- package/dist/public/assets/_Bzgtwt3G.js +1 -0
- package/dist/public/assets/_Bzgtwt3G.js.br +0 -0
- package/dist/public/assets/{_U2n8Yyqy.js → _C0_s45qg.js} +1 -1
- package/dist/public/assets/_C0_s45qg.js.br +0 -0
- package/dist/public/assets/_C0ePgF6b.js +1 -0
- package/dist/public/assets/_C0oVtTqO.js +1 -0
- package/dist/public/assets/_C0oVtTqO.js.br +0 -0
- package/dist/public/assets/{_TxnhYSE5.js → _C654p96Z.js} +1 -1
- package/dist/public/assets/_C654p96Z.js.br +0 -0
- package/dist/public/assets/_C8_1Y2-z.js +1 -0
- package/dist/public/assets/_C8_1Y2-z.js.br +0 -0
- package/dist/public/assets/_C8v1AZFP.js +1 -0
- package/dist/public/assets/{_Dns259C4.js → _CAkPJLeF.js} +1 -1
- package/dist/public/assets/{_Dns259C4.js.br → _CAkPJLeF.js.br} +0 -0
- package/dist/public/assets/_CB0D5cRH.js +1 -0
- package/dist/public/assets/_CD05JUTh.js +1 -0
- package/dist/public/assets/{_BIul3uoC.js → _CEJUcePr.js} +1 -1
- package/dist/public/assets/_CEJUcePr.js.br +0 -0
- package/dist/public/assets/{_CN5iw4cA.js → _CEXHZd73.js} +1 -1
- package/dist/public/assets/_CEXHZd73.js.br +0 -0
- package/dist/public/assets/_CHcUMVR7.js +1 -0
- package/dist/public/assets/{_Dtx2usNe.js → _CHuLFr1f.js} +1 -1
- package/dist/public/assets/_CHuLFr1f.js.br +0 -0
- package/dist/public/assets/{_9xYWGqfi.js → _CIb7xw_1.js} +1 -1
- package/dist/public/assets/_CIb7xw_1.js.br +0 -0
- package/dist/public/assets/{_C1JRCVnT.js → _CMSBfO6u.js} +1 -1
- package/dist/public/assets/_CMSBfO6u.js.br +0 -0
- package/dist/public/assets/_CN7GPyBo.js +1 -0
- package/dist/public/assets/{_Cnl5owe1.js → _COcePo2y.js} +1 -1
- package/dist/public/assets/_COcePo2y.js.br +0 -0
- package/dist/public/assets/{_B7nG9Ktb.js → _CTINBWaG.js} +1 -1
- package/dist/public/assets/_CTINBWaG.js.br +0 -0
- package/dist/public/assets/_CTWrnAbz.js +1 -0
- package/dist/public/assets/{_CKwCTsbp.js → _CUXajOKj.js} +1 -1
- package/dist/public/assets/_CUXajOKj.js.br +0 -0
- package/dist/public/assets/{_BY6ayWBy.js → _CVru3vzC.js} +1 -1
- package/dist/public/assets/{_cSsv1ZjH.js → _CYjE__ml.js} +1 -1
- package/dist/public/assets/_CYjE__ml.js.br +0 -0
- package/dist/public/assets/{_BlSF31Ck.js → _CZ_OWtIT.js} +1 -1
- package/dist/public/assets/_CZ_OWtIT.js.br +0 -0
- package/dist/public/assets/{_CrV4JiE4.js → _C_37_B6u.js} +1 -1
- package/dist/public/assets/_C_37_B6u.js.br +0 -0
- package/dist/public/assets/_C_CIQL7J.js +1 -0
- package/dist/public/assets/_C_CIQL7J.js.br +0 -0
- package/dist/public/assets/_C_WdpYbK.js +1 -0
- package/dist/public/assets/_CaiH3VN9.js +1 -0
- package/dist/public/assets/{_BXU-ZvQb.js → _CamWDaoG.js} +1 -1
- package/dist/public/assets/_CamWDaoG.js.br +0 -0
- package/dist/public/assets/_CdDElA0V.js +1 -0
- package/dist/public/assets/_CfnsClzZ.js +1 -0
- package/dist/public/assets/_Cgo1fRhJ.js +1 -0
- package/dist/public/assets/_Cgo1fRhJ.js.br +0 -0
- package/dist/public/assets/_CjhGrlf3.js +1 -0
- package/dist/public/assets/_CjlbL4C_.js +1 -0
- package/dist/public/assets/_CjogTUXK.js +1 -0
- package/dist/public/assets/{_BS0AEB1V.js → _ClldMY37.js} +1 -1
- package/dist/public/assets/_ClldMY37.js.br +0 -0
- package/dist/public/assets/_CmFq6Gtp.js +1 -0
- package/dist/public/assets/_CoAPOKiP.js +1 -0
- package/dist/public/assets/_CoUUgh9P.js +1 -0
- package/dist/public/assets/{_BDCQoRmq.js → _CpjSCB1I.js} +1 -1
- package/dist/public/assets/_CpjSCB1I.js.br +0 -0
- package/dist/public/assets/{_CEvca0JK.js → _Ct3RF80L.js} +1 -1
- package/dist/public/assets/_Ct3RF80L.js.br +0 -0
- package/dist/public/assets/_CtYy5eZs.js +1 -0
- package/dist/public/assets/{_DvqvHR7_.js → _CxAPL49a.js} +1 -1
- package/dist/public/assets/_CxAPL49a.js.br +0 -0
- package/dist/public/assets/{_D_joWBEC.js → _CyBCIknf.js} +1 -1
- package/dist/public/assets/_CyBCIknf.js.br +0 -0
- package/dist/public/assets/{_KpWeECPp.js → _Cz5BPBG8.js} +1 -1
- package/dist/public/assets/_Cz5BPBG8.js.br +0 -0
- package/dist/public/assets/_D-eEFXaI.js +1 -0
- package/dist/public/assets/{_DPIQzOUl.js → _D0aoEFRx.js} +1 -1
- package/dist/public/assets/_D0aoEFRx.js.br +0 -0
- package/dist/public/assets/{_CluEtmrQ.js → _D1uRW1qz.js} +1 -1
- package/dist/public/assets/_D1uRW1qz.js.br +0 -0
- package/dist/public/assets/_D2oIr2T2.js +1 -0
- package/dist/public/assets/{_Bpf0Nyqk.js → _D2un443j.js} +1 -1
- package/dist/public/assets/_D2un443j.js.br +0 -0
- package/dist/public/assets/_D3MPx4-f.js +1 -0
- package/dist/public/assets/{_B-992FUw.js → _D4dJ2qEE.js} +1 -1
- package/dist/public/assets/{_CB-I9KUl.js → _D4q8XSMI.js} +1 -1
- package/dist/public/assets/_D4q8XSMI.js.br +0 -0
- package/dist/public/assets/{_BNPo3NaH.js → _D4quFMVQ.js} +1 -1
- package/dist/public/assets/_D4quFMVQ.js.br +0 -0
- package/dist/public/assets/{_6FNzwUcm.js → _D4rOX-Fa.js} +1 -1
- package/dist/public/assets/_D4rOX-Fa.js.br +0 -0
- package/dist/public/assets/_D5edrSyA.js +1 -0
- package/dist/public/assets/{_DJnXBrlD.js → _D6kktUFn.js} +1 -1
- package/dist/public/assets/_D6kktUFn.js.br +0 -0
- package/dist/public/assets/_D80-qtVY.js +1 -0
- package/dist/public/assets/_D9-3EVA4.js +1 -0
- package/dist/public/assets/{_Ca3bfNZI.js → _D9sS4J_w.js} +1 -1
- package/dist/public/assets/_D9sS4J_w.js.br +0 -0
- package/dist/public/assets/_DBLpxTDi.js +1 -0
- package/dist/public/assets/{_gP9nLV2Y.js → _DByHQ7nW.js} +117 -117
- package/dist/public/assets/_DByHQ7nW.js.br +0 -0
- package/dist/public/assets/{_C-oO7X9P.js → _DC-78WeM.js} +1 -1
- package/dist/public/assets/_DC-78WeM.js.br +0 -0
- package/dist/public/assets/{_SHB9zmh2.js → _DDl8KSWJ.js} +1 -1
- package/dist/public/assets/_DDl8KSWJ.js.br +0 -0
- package/dist/public/assets/{_CPMD0qdL.js → _DFWOMF-B.js} +1 -1
- package/dist/public/assets/_DFWOMF-B.js.br +0 -0
- package/dist/public/assets/_DKb-rt9n.js +1 -0
- package/dist/public/assets/_DMnSJCF_.js +1 -0
- package/dist/public/assets/_DOOIlrPh.js +1 -0
- package/dist/public/assets/_DPW-0yKP.js +1 -0
- package/dist/public/assets/_DR3BmvWU.js +1 -0
- package/dist/public/assets/{_BpLwQ1O8.js → _DSVLaMWS.js} +1 -1
- package/dist/public/assets/_DSVLaMWS.js.br +0 -0
- package/dist/public/assets/_DYNGNKLk.js +1 -0
- package/dist/public/assets/_DZnEgCbj.js +1 -0
- package/dist/public/assets/{_CgsPFJZy.js → _DaMVRI8f.js} +1 -1
- package/dist/public/assets/_DaMVRI8f.js.br +0 -0
- package/dist/public/assets/_DbvaGqOl.js +1 -0
- package/dist/public/assets/_DbvaGqOl.js.br +0 -0
- package/dist/public/assets/{_ItervcuA.js → _DcMIlvz-.js} +1 -1
- package/dist/public/assets/_DcMIlvz-.js.br +0 -0
- package/dist/public/assets/{_D5yRmwZD.js → _Dd6X3e7w.js} +1 -1
- package/dist/public/assets/_Dd6X3e7w.js.br +0 -0
- package/dist/public/assets/{_BxAKVWw-.js → _De7P3jUH.js} +1 -1
- package/dist/public/assets/_De7P3jUH.js.br +0 -0
- package/dist/public/assets/_DeiFEAar.js +1 -0
- package/dist/public/assets/{_tqD_68em.js → _DfI982PI.js} +1 -1
- package/dist/public/assets/_DfI982PI.js.br +0 -0
- package/dist/public/assets/_DfZ6emcw.js +1 -0
- package/dist/public/assets/{_M94yp4jo.js → _Dj1lZ1pa.js} +12 -12
- package/dist/public/assets/_Dj1lZ1pa.js.br +0 -0
- package/dist/public/assets/{_BCTeDxHC.js → _DkCaEf_h.js} +1 -1
- package/dist/public/assets/_DkCaEf_h.js.br +0 -0
- package/dist/public/assets/_DonAis0J.js +1 -0
- package/dist/public/assets/{_DktieTrd.js → _Dp3IZdH8.js} +1 -1
- package/dist/public/assets/_Dp3IZdH8.js.br +0 -0
- package/dist/public/assets/_DqYih4xk.js +1 -0
- package/dist/public/assets/_DqYih4xk.js.br +0 -0
- package/dist/public/assets/{_B9Ukk65G.js → _DqhphdU4.js} +1 -1
- package/dist/public/assets/_DqhphdU4.js.br +0 -0
- package/dist/public/assets/{_DLJu1hcD.js → _DrIgZJzN.js} +1 -1
- package/dist/public/assets/_DrIgZJzN.js.br +0 -0
- package/dist/public/assets/_Dt4hHR05.js +1 -0
- package/dist/public/assets/_DtTbTraA.js +1 -0
- package/dist/public/assets/_DwMxAJKP.js +1 -0
- package/dist/public/assets/{_LgS0G0uH.js → _DxEm-Gwj.js} +1 -1
- package/dist/public/assets/_DxEm-Gwj.js.br +0 -0
- package/dist/public/assets/{_C4KQv1VW.js → _Dytf99zx.js} +1 -1
- package/dist/public/assets/_Dytf99zx.js.br +0 -0
- package/dist/public/assets/_EAgv5jR9.js +1 -0
- package/dist/public/assets/_Iecpd0kS.js +1 -0
- package/dist/public/assets/_Iecpd0kS.js.br +0 -0
- package/dist/public/assets/{_QlXMW-cP.js → _MCwIJAuJ.js} +1 -1
- package/dist/public/assets/_MCwIJAuJ.js.br +0 -0
- package/dist/public/assets/_NM79Lu3L.js +6 -0
- package/dist/public/assets/_NM79Lu3L.js.br +0 -0
- package/dist/public/assets/_QpNKKuS9.js +1 -0
- package/dist/public/assets/{_B29iioj9.js → _SGDxiwE1.js} +1 -1
- package/dist/public/assets/_SGDxiwE1.js.br +0 -0
- package/dist/public/assets/_TA8pE7z9.js +1 -0
- package/dist/public/assets/_bE4sNDeU.js +1 -0
- package/dist/public/assets/{_Bk_g_9Bn.js → _bcsuBP7T.js} +1 -1
- package/dist/public/assets/_bcsuBP7T.js.br +0 -0
- package/dist/public/assets/_cdcAU4yY.js +1 -0
- package/dist/public/assets/{_aAORMS0u.js → _ch_yXAap.js} +1 -1
- package/dist/public/assets/_ch_yXAap.js.br +0 -0
- package/dist/public/assets/{_ByqDCoAZ.js → _d5u7EI97.js} +1 -1
- package/dist/public/assets/_d5u7EI97.js.br +0 -0
- package/dist/public/assets/{_i6oi77xC.js → _eoa1EOU-.js} +1 -1
- package/dist/public/assets/_eoa1EOU-.js.br +0 -0
- package/dist/public/assets/{_H7TtilBa.js → _j2tDSMvo.js} +1 -1
- package/dist/public/assets/_j2tDSMvo.js.br +0 -0
- package/dist/public/assets/_jNhIFgbc.js +1 -0
- package/dist/public/assets/_kDYiTaag.js +1 -0
- package/dist/public/assets/_lNMVVbUx.js +1 -0
- package/dist/public/assets/_nwJ7Hu3S.js +1 -0
- package/dist/public/assets/_tmDtUACa.js +1 -0
- package/dist/public/assets/_tmDtUACa.js.br +0 -0
- package/dist/public/assets/_wXDh-Z2N.js +1 -0
- package/dist/public/assets/_wXDh-Z2N.js.br +0 -0
- package/dist/public/assets/{_C3E24F_T.js → _wcshV0sZ.js} +1 -1
- package/dist/public/assets/_wcshV0sZ.js.br +0 -0
- package/dist/public/assets/_x-NwqgCn.js +1 -0
- package/dist/public/assets/{_DZD7yzH2.js → _xyw_DS5P.js} +1 -1
- package/dist/public/assets/_xyw_DS5P.js.br +0 -0
- package/dist/public/assets/{_CsicaM6z.js → _zSAfqXcm.js} +1 -1
- package/dist/public/assets/_zSAfqXcm.js.br +0 -0
- package/dist/public/assets/app-shell-ChQoVC5b.css +1 -0
- package/dist/public/assets/app-shell-ChQoVC5b.css.br +0 -0
- package/dist/public/assets/files-view-CLtLp_BW.js +2 -0
- package/dist/public/assets/files-view-CNHQapdI.css +1 -0
- package/dist/public/assets/files-view-CNHQapdI.css.br +0 -0
- package/dist/public/assets/group.css.ts-BG82htKb.css +1 -0
- package/dist/public/assets/group.css.ts-BG82htKb.css.br +0 -0
- package/dist/public/assets/icon-folder-DJOHuEpD.css +1 -0
- package/dist/public/assets/icon-folder-DJOHuEpD.css.br +0 -0
- package/dist/public/assets/{icon-search-C6A4IBPq.css → icon-search-DsJuFXUJ.css} +1 -1
- package/dist/public/assets/icon-search-DsJuFXUJ.css.br +0 -0
- package/dist/public/assets/manage-workspace-NBcFDyrB.js +2 -0
- package/dist/public/assets/manage-workspace-f_Np32TD.css +1 -0
- package/dist/public/assets/{modal-view-BY2E8mw2.css → modal-view-KVNBpNYi.css} +1 -1
- package/dist/public/assets/modal-view-KVNBpNYi.css.br +0 -0
- package/dist/public/assets/new-DHI77GvL.js +1 -0
- package/dist/public/assets/new-workspace-BFE-HpD_.css +1 -0
- package/dist/public/assets/new-workspace-BFE-HpD_.css.br +0 -0
- package/dist/public/assets/new-workspace-BRzimdd5.js +2 -0
- package/dist/public/assets/port-chip-CUUIDOVM.css +1 -0
- package/dist/public/assets/port-chip-CUUIDOVM.css.br +0 -0
- package/dist/public/assets/prompt-dialog-BGs6RXOV.css +1 -0
- package/dist/public/assets/prompt-dialog-BGs6RXOV.css.br +0 -0
- package/dist/public/assets/quick-open-Gx4so1bl.css +1 -0
- package/dist/public/assets/quick-open-Gx4so1bl.css.br +0 -0
- package/dist/public/assets/repo-picker-CUhd0vJN.css +1 -0
- package/dist/public/assets/repo-picker-CUhd0vJN.css.br +4 -0
- package/dist/public/assets/review-view-DFEK9VBa.js +2 -0
- package/dist/public/assets/review-view-deUY3OE5.css +1 -0
- package/dist/public/assets/review-view-deUY3OE5.css.br +0 -0
- package/dist/public/assets/section-CziSOSBR.css +1 -0
- package/dist/public/assets/section-CziSOSBR.css.br +0 -0
- package/dist/public/assets/settings-DHI77GvL.js +1 -0
- package/dist/public/assets/settings-page-OOtPOzIn.js +2 -0
- package/dist/public/assets/settings-page-wZhd7FLi.css +1 -0
- package/dist/public/assets/settings-page-wZhd7FLi.css.br +0 -0
- package/dist/public/assets/skill-row-BoCyFIXg.css +1 -0
- package/dist/public/assets/sso-auth-DV76tTpE.css +1 -0
- package/dist/public/assets/sso-auth-DV76tTpE.css.br +0 -0
- package/dist/public/assets/w-DHI77GvL.js +1 -0
- package/dist/public/assets/w._-DHI77GvL.js +1 -0
- package/dist/public/assets/w._-DsTgq3-C.js +1 -0
- package/dist/public/assets/w._-igEOSPR-.js +1 -0
- package/install.sh +1 -1
- package/lib/review/markdown.mjs +5 -5
- package/lib/setup/bridge.d.mts +10 -0
- package/lib/setup/bridge.mjs +84 -0
- package/lib/setup/catalog.d.mts +3 -0
- package/lib/setup/catalog.mjs +17 -0
- package/lib/setup/doctor.d.mts +6 -0
- package/lib/setup/doctor.mjs +50 -5
- package/lib/setup/install.d.mts +1 -0
- package/lib/setup/install.mjs +21 -1
- package/lib/setup/listen.mjs +2 -2
- package/lib/share/manifest.mjs +3 -2
- package/package.json +4 -5
- package/dist/_u9qRCTjI.js +0 -2
- package/dist/public/assets/_43qHqm_h.js +0 -1
- package/dist/public/assets/_4KGVbuYs.js.br +0 -0
- package/dist/public/assets/_4hbCil9D.js +0 -1
- package/dist/public/assets/_4hbCil9D.js.br +0 -0
- package/dist/public/assets/_69GBvJfT.js +0 -1
- package/dist/public/assets/_6FNzwUcm.js.br +0 -0
- package/dist/public/assets/_8SWI_CIk.js +0 -1
- package/dist/public/assets/_8SWI_CIk.js.br +0 -0
- package/dist/public/assets/_9fKCaxLn.js +0 -1
- package/dist/public/assets/_9xYWGqfi.js.br +0 -0
- package/dist/public/assets/_AKwHRUw2.js +0 -1
- package/dist/public/assets/_B29iioj9.js.br +0 -0
- package/dist/public/assets/_B3bcGOWb.js +0 -1
- package/dist/public/assets/_B3fa8s0p.js +0 -1
- package/dist/public/assets/_B6-AgBRx.js +0 -1
- package/dist/public/assets/_B6-AgBRx.js.br +0 -0
- package/dist/public/assets/_B68mxQgf.js +0 -15
- package/dist/public/assets/_B68mxQgf.js.br +0 -0
- package/dist/public/assets/_B7lNd0Fe.js +0 -1
- package/dist/public/assets/_B7nG9Ktb.js.br +0 -0
- package/dist/public/assets/_B9Ukk65G.js.br +0 -0
- package/dist/public/assets/_BCTeDxHC.js.br +0 -0
- package/dist/public/assets/_BDCQoRmq.js.br +0 -0
- package/dist/public/assets/_BHkMvOuI.js.br +0 -0
- package/dist/public/assets/_BIul3uoC.js.br +0 -0
- package/dist/public/assets/_BJIAaIh4.js.br +0 -5
- package/dist/public/assets/_BJk5sqrB.js.br +0 -0
- package/dist/public/assets/_BLOE-kpM.js +0 -1
- package/dist/public/assets/_BNK4RUnx.js +0 -1
- package/dist/public/assets/_BNPo3NaH.js.br +0 -0
- package/dist/public/assets/_BPMmLRzt.js +0 -1
- package/dist/public/assets/_BQ91qGf-.js +0 -1
- package/dist/public/assets/_BS0AEB1V.js.br +0 -0
- package/dist/public/assets/_BS66ieXF.js +0 -1
- package/dist/public/assets/_BSb0QOJN.js +0 -1
- package/dist/public/assets/_BSliyqkf.js.br +0 -0
- package/dist/public/assets/_BSydNGAC.js +0 -2
- package/dist/public/assets/_BSydNGAC.js.br +0 -0
- package/dist/public/assets/_BXU-ZvQb.js.br +0 -0
- package/dist/public/assets/_BYHfXvmU.js.br +0 -0
- package/dist/public/assets/_BYcB3W24.js +0 -1
- package/dist/public/assets/_BYgxEDpq.js.br +0 -0
- package/dist/public/assets/_BYi6z1C9.js +0 -1
- package/dist/public/assets/_BbM04KlN.js +0 -1
- package/dist/public/assets/_Bc5E_ez3.js +0 -1
- package/dist/public/assets/_BcWZ_-iA.js +0 -1
- package/dist/public/assets/_BkXPpVmm.js +0 -1
- package/dist/public/assets/_Bk_g_9Bn.js.br +0 -0
- package/dist/public/assets/_BlSF31Ck.js.br +0 -0
- package/dist/public/assets/_Bn4xIRpG.js +0 -1
- package/dist/public/assets/_BpLwQ1O8.js.br +0 -0
- package/dist/public/assets/_BpVNeKi-.js +0 -1
- package/dist/public/assets/_BpdpbMex.js +0 -1
- package/dist/public/assets/_Bpf0Nyqk.js.br +0 -0
- package/dist/public/assets/_BwBNAwDG.js +0 -1
- package/dist/public/assets/_BxAKVWw-.js.br +0 -0
- package/dist/public/assets/_BxpaVKca.js.br +0 -0
- package/dist/public/assets/_ByqDCoAZ.js.br +0 -0
- package/dist/public/assets/_Bzg_Rzcf.js +0 -1
- package/dist/public/assets/_C-oO7X9P.js.br +0 -0
- package/dist/public/assets/_C0KvehwH.js +0 -1
- package/dist/public/assets/_C1JRCVnT.js.br +0 -0
- package/dist/public/assets/_C2U9mANP.js +0 -1
- package/dist/public/assets/_C3E24F_T.js.br +0 -0
- package/dist/public/assets/_C4KQv1VW.js.br +0 -0
- package/dist/public/assets/_C5MTb3MY.js +0 -1
- package/dist/public/assets/_C7ha2DpU.js +0 -1
- package/dist/public/assets/_C7ha2DpU.js.br +0 -0
- package/dist/public/assets/_CAaW1fUv.js +0 -1
- package/dist/public/assets/_CB-I9KUl.js.br +0 -0
- package/dist/public/assets/_CEvca0JK.js.br +0 -0
- package/dist/public/assets/_CGZs9U_g.js +0 -1
- package/dist/public/assets/_CK6p4Zj1.js +0 -1
- package/dist/public/assets/_CK6p4Zj1.js.br +0 -0
- package/dist/public/assets/_CKwCTsbp.js.br +0 -0
- package/dist/public/assets/_CKyRgnW2.js +0 -1
- package/dist/public/assets/_CN5iw4cA.js.br +0 -0
- package/dist/public/assets/_CPAGQRmF.js +0 -1
- package/dist/public/assets/_CPMD0qdL.js.br +0 -0
- package/dist/public/assets/_CRi7-Tyh.js +0 -1
- package/dist/public/assets/_CU2T7o-W.js +0 -1
- package/dist/public/assets/_CVSAwdO1.js +0 -1
- package/dist/public/assets/_CZzsPgfD.js +0 -1
- package/dist/public/assets/_C_jQehPQ.js +0 -1
- package/dist/public/assets/_Ca3bfNZI.js.br +0 -0
- package/dist/public/assets/_CdWPIocC.js.br +0 -0
- package/dist/public/assets/_CeFqvzt1.js +0 -1
- package/dist/public/assets/_CgsPFJZy.js.br +0 -0
- package/dist/public/assets/_ClgoCZxV.js +0 -6
- package/dist/public/assets/_ClgoCZxV.js.br +0 -0
- package/dist/public/assets/_CluEtmrQ.js.br +0 -0
- package/dist/public/assets/_Cnl5owe1.js.br +0 -0
- package/dist/public/assets/_Cp1dT7ox.js.br +0 -0
- package/dist/public/assets/_Cpyx7Ldm.js +0 -1
- package/dist/public/assets/_Cq4-AZ6O.js +0 -1
- package/dist/public/assets/_CrV4JiE4.js.br +0 -0
- package/dist/public/assets/_Csdgg-p8.js +0 -1
- package/dist/public/assets/_Csdgg-p8.js.br +0 -0
- package/dist/public/assets/_CsicaM6z.js.br +0 -0
- package/dist/public/assets/_Ct2VbISZ.js.br +0 -0
- package/dist/public/assets/_CtQ-4c6a.js.br +0 -0
- package/dist/public/assets/_Cyfdf5Zc.js +0 -1
- package/dist/public/assets/_D1qsYd77.js +0 -1
- package/dist/public/assets/_D1qsYd77.js.br +0 -0
- package/dist/public/assets/_D5yRmwZD.js.br +0 -0
- package/dist/public/assets/_D78O__dl.js +0 -1
- package/dist/public/assets/_D93v6VDe.js.br +0 -0
- package/dist/public/assets/_DDfizRXp.js +0 -1
- package/dist/public/assets/_DDfizRXp.js.br +0 -0
- package/dist/public/assets/_DFiA_pht.js.br +0 -0
- package/dist/public/assets/_DGDsfGXN.js +0 -1
- package/dist/public/assets/_DGDsfGXN.js.br +0 -0
- package/dist/public/assets/_DJnXBrlD.js.br +0 -0
- package/dist/public/assets/_DKiEZYX8.js +0 -1
- package/dist/public/assets/_DLEnV6cR.js +0 -1
- package/dist/public/assets/_DLJu1hcD.js.br +0 -0
- package/dist/public/assets/_DL_rHJtD.js +0 -1
- package/dist/public/assets/_DNFF24hk.js +0 -1
- package/dist/public/assets/_DNqoI_cd.js.br +0 -0
- package/dist/public/assets/_DOLRYXID.js +0 -1
- package/dist/public/assets/_DPIQzOUl.js.br +0 -0
- package/dist/public/assets/_DQWcu2Z_.js +0 -1
- package/dist/public/assets/_DW6AnxDW.js.br +0 -0
- package/dist/public/assets/_DWYjkjOA.js +0 -1
- package/dist/public/assets/_DXE83VZw.js +0 -1
- package/dist/public/assets/_DYBhy6q4.js.br +0 -0
- package/dist/public/assets/_DYKZ1zvC.js +0 -1
- package/dist/public/assets/_DYbmgf-P.js +0 -1
- package/dist/public/assets/_DZD7yzH2.js.br +0 -0
- package/dist/public/assets/_DZLJGzpN.js.br +0 -0
- package/dist/public/assets/_D_joWBEC.js.br +0 -0
- package/dist/public/assets/_D_qiANiM.js +0 -1
- package/dist/public/assets/_D_qiANiM.js.br +0 -0
- package/dist/public/assets/_DhhUcrza.js +0 -1
- package/dist/public/assets/_Dik2fbTK.js +0 -1
- package/dist/public/assets/_Dik2fbTK.js.br +0 -0
- package/dist/public/assets/_DjGbHRs7.js +0 -1
- package/dist/public/assets/_DjdPagIm.js +0 -1
- package/dist/public/assets/_Djnp5vRt.js +0 -1
- package/dist/public/assets/_DktieTrd.js.br +0 -0
- package/dist/public/assets/_Dr2zRKuC.js +0 -1
- package/dist/public/assets/_Dtx2usNe.js.br +0 -0
- package/dist/public/assets/_DvnFb18d.js +0 -1
- package/dist/public/assets/_DvqvHR7_.js.br +0 -0
- package/dist/public/assets/_Dy57KGoU.js +0 -1
- package/dist/public/assets/_Dy57KGoU.js.br +0 -0
- package/dist/public/assets/_FdygZebO.js +0 -1
- package/dist/public/assets/_H7TtilBa.js.br +0 -0
- package/dist/public/assets/_HwOcVvTN.js +0 -1
- package/dist/public/assets/_ICJfUHY2.js +0 -1
- package/dist/public/assets/_ItervcuA.js.br +0 -0
- package/dist/public/assets/_JGwf6udl.js +0 -1
- package/dist/public/assets/_KM7EGl2R.js.br +0 -0
- package/dist/public/assets/_KpWeECPp.js.br +0 -0
- package/dist/public/assets/_LgS0G0uH.js.br +0 -0
- package/dist/public/assets/_M94yp4jo.js.br +0 -0
- package/dist/public/assets/_NGfZeYAt.js.br +0 -0
- package/dist/public/assets/_QlXMW-cP.js.br +0 -0
- package/dist/public/assets/_SHB9zmh2.js.br +0 -0
- package/dist/public/assets/_TSA_v82C.js +0 -1
- package/dist/public/assets/_TxnhYSE5.js.br +0 -0
- package/dist/public/assets/_U2n8Yyqy.js.br +0 -0
- package/dist/public/assets/_Vhpht63x.js +0 -1
- package/dist/public/assets/_Z9CaLBvo.js +0 -1
- package/dist/public/assets/__-FQNLs7.js +0 -1
- package/dist/public/assets/__CN8nA63.js +0 -1
- package/dist/public/assets/_aAORMS0u.js.br +0 -0
- package/dist/public/assets/_buuWf96L.js.br +0 -0
- package/dist/public/assets/_cSsv1ZjH.js.br +0 -0
- package/dist/public/assets/_gP9nLV2Y.js.br +0 -0
- package/dist/public/assets/_i6oi77xC.js.br +0 -0
- package/dist/public/assets/_jb3Fwzol.js +0 -1
- package/dist/public/assets/_lmVJ3O6t.js +0 -1
- package/dist/public/assets/_mloSZbwk.js +0 -1
- package/dist/public/assets/_sYOWcsEI.js +0 -1
- package/dist/public/assets/_tqD_68em.js.br +0 -0
- package/dist/public/assets/_y4SZiKqE.js +0 -1
- package/dist/public/assets/_y4SZiKqE.js.br +0 -0
- package/dist/public/assets/_zMYJngRw.js +0 -1
- package/dist/public/assets/_zTWXKPCk.js +0 -1
- package/dist/public/assets/app-shell-BXDHei7B.css +0 -1
- package/dist/public/assets/app-shell-BXDHei7B.css.br +0 -0
- package/dist/public/assets/files-view-BCnw4-08.js +0 -2
- package/dist/public/assets/files-view-Ds4k9TjY.css +0 -1
- package/dist/public/assets/files-view-Ds4k9TjY.css.br +0 -0
- package/dist/public/assets/group.css.ts-CZcH3cNI.css +0 -1
- package/dist/public/assets/group.css.ts-CZcH3cNI.css.br +0 -0
- package/dist/public/assets/icon-folder-De3LJVaT.css +0 -1
- package/dist/public/assets/icon-folder-De3LJVaT.css.br +0 -0
- package/dist/public/assets/icon-search-C6A4IBPq.css.br +0 -0
- package/dist/public/assets/manage-workspace-B2IJyc-s.js +0 -2
- package/dist/public/assets/manage-workspace-BYotHuev.css +0 -1
- package/dist/public/assets/modal-view-BY2E8mw2.css.br +0 -0
- package/dist/public/assets/new-workspace-9FQTNRn4.css +0 -1
- package/dist/public/assets/new-workspace-9FQTNRn4.css.br +0 -0
- package/dist/public/assets/new-workspace-B_6v9CYu.js +0 -2
- package/dist/public/assets/new-zQDWH4FQ.js +0 -1
- package/dist/public/assets/port-chip-V2q_q3UM.css +0 -1
- package/dist/public/assets/port-chip-V2q_q3UM.css.br +0 -0
- package/dist/public/assets/prompt-dialog-C_kDiYmC.css +0 -1
- package/dist/public/assets/prompt-dialog-C_kDiYmC.css.br +0 -0
- package/dist/public/assets/quick-open-IkoNJ7wT.css +0 -1
- package/dist/public/assets/quick-open-IkoNJ7wT.css.br +0 -0
- package/dist/public/assets/repo-picker-CMHPjNaZ.css +0 -1
- package/dist/public/assets/repo-picker-CMHPjNaZ.css.br +0 -0
- package/dist/public/assets/review-view-CqIbovDm.css +0 -1
- package/dist/public/assets/review-view-CqIbovDm.css.br +0 -0
- package/dist/public/assets/review-view-DJ3TxEP8.js +0 -2
- package/dist/public/assets/section-Bjoist2N.css +0 -1
- package/dist/public/assets/section-Bjoist2N.css.br +0 -0
- package/dist/public/assets/settings-page-CA4M6Hig.css +0 -1
- package/dist/public/assets/settings-page-CA4M6Hig.css.br +0 -0
- package/dist/public/assets/settings-page-Gf4hmpSr.js +0 -2
- package/dist/public/assets/settings-zQDWH4FQ.js +0 -1
- package/dist/public/assets/skill-row-y-AJuVyg.css +0 -1
- package/dist/public/assets/sso-auth-DCSrkI2L.css +0 -1
- package/dist/public/assets/sso-auth-DCSrkI2L.css.br +0 -0
- package/dist/public/assets/w-zQDWH4FQ.js +0 -1
- package/dist/public/assets/w._-B47BqhrV.js +0 -1
- package/dist/public/assets/w._-D0upu6g5.js +0 -1
- package/dist/public/assets/w._-zQDWH4FQ.js +0 -1
- package/scripts/migrate.mjs +0 -824
package/scripts/migrate.mjs
DELETED
|
@@ -1,824 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// migrate.mjs — one-shot cleanups for changes between versions, run by
|
|
3
|
-
// `work setup` and `work migrate` (update.sh) so the runtime stays free of
|
|
4
|
-
// legacy handling.
|
|
5
|
-
import crypto from "node:crypto";
|
|
6
|
-
import { execFileSync } from "node:child_process";
|
|
7
|
-
import fs from "node:fs";
|
|
8
|
-
import os from "node:os";
|
|
9
|
-
import path from "node:path";
|
|
10
|
-
import { DatabaseSync } from "node:sqlite";
|
|
11
|
-
import { dialHost } from "../lib/setup/listen.mjs";
|
|
12
|
-
|
|
13
|
-
const dataDir =
|
|
14
|
-
process.env.WORK_DATA_DIR ||
|
|
15
|
-
path.join(
|
|
16
|
-
process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share"),
|
|
17
|
-
"work",
|
|
18
|
-
);
|
|
19
|
-
const dbPath = path.join(dataDir, "work.db");
|
|
20
|
-
|
|
21
|
-
// Machine repairs that need no db come first: a fresh install, or one whose
|
|
22
|
-
// data dir this environment does not name, stops at the check below.
|
|
23
|
-
|
|
24
|
-
// `gh auth setup-git` bakes the absolute path of the gh binary into
|
|
25
|
-
// ~/.gitconfig, and git runs that string literally rather than looking gh up
|
|
26
|
-
// on PATH. Where gh came from a version manager that path dies on the next gh
|
|
27
|
-
// upgrade, and every https push fails with "could not read Username" — a
|
|
28
|
-
// break with no visible cause, since `gh` itself still works. Repoint any
|
|
29
|
-
// helper naming a gh that no longer exists at the launcher on PATH.
|
|
30
|
-
{
|
|
31
|
-
const versioned = /\/(installs|Cellar|versions|toolchains)\//;
|
|
32
|
-
const git = (args) => execFileSync("git", args, { encoding: "utf8" }).trim();
|
|
33
|
-
try {
|
|
34
|
-
let gh = "";
|
|
35
|
-
try {
|
|
36
|
-
// Quietly: with no gh there is nothing to repair, and this runs on
|
|
37
|
-
// every setup, fresh installs included.
|
|
38
|
-
gh = execFileSync("which", ["gh"], {
|
|
39
|
-
encoding: "utf8",
|
|
40
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
41
|
-
}).trim();
|
|
42
|
-
} catch {}
|
|
43
|
-
if (gh && !versioned.test(gh)) {
|
|
44
|
-
let lines = [];
|
|
45
|
-
try {
|
|
46
|
-
lines = git([
|
|
47
|
-
"config",
|
|
48
|
-
"--global",
|
|
49
|
-
"--get-regexp",
|
|
50
|
-
String.raw`^credential\..*\.helper$`,
|
|
51
|
-
])
|
|
52
|
-
.split("\n")
|
|
53
|
-
.filter(Boolean);
|
|
54
|
-
} catch {} // no such entries — nothing to repair
|
|
55
|
-
let fixed = 0;
|
|
56
|
-
for (const line of lines) {
|
|
57
|
-
const sp = line.indexOf(" ");
|
|
58
|
-
const [key, value] = [line.slice(0, sp), line.slice(sp + 1)];
|
|
59
|
-
const bin = /^!(\S+) auth git-credential$/.exec(value)?.[1];
|
|
60
|
-
if (!bin || bin === gh || fs.existsSync(bin)) continue;
|
|
61
|
-
git([
|
|
62
|
-
"config",
|
|
63
|
-
"--global",
|
|
64
|
-
"--replace-all",
|
|
65
|
-
key,
|
|
66
|
-
`!${gh} auth git-credential`,
|
|
67
|
-
"auth git-credential",
|
|
68
|
-
]);
|
|
69
|
-
fixed++;
|
|
70
|
-
}
|
|
71
|
-
if (fixed)
|
|
72
|
-
console.log(
|
|
73
|
-
`==> migrate: repaired ${fixed} stale gh credential helper(s)`,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
} catch {}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Grok's hook registry ($GROK_HOME/hooks-paths) names work's hook file by
|
|
80
|
-
// absolute path. A line left by a data dir since moved or removed (a
|
|
81
|
-
// scratch server's temp dir, an uninstall) names nothing, and Grok's
|
|
82
|
-
// sandbox refuses to start while one does. The app drops them as it
|
|
83
|
-
// registers; this reaches machines that stopped launching Grok. Keep in
|
|
84
|
-
// sync with registerHooks in src/agents/grok/index.ts.
|
|
85
|
-
{
|
|
86
|
-
try {
|
|
87
|
-
const registry = path.join(
|
|
88
|
-
process.env.GROK_HOME || path.join(os.homedir(), ".grok"),
|
|
89
|
-
"hooks-paths",
|
|
90
|
-
);
|
|
91
|
-
const current = fs.readFileSync(registry, "utf8");
|
|
92
|
-
const lines = current.split("\n");
|
|
93
|
-
const kept = lines.filter((line) => {
|
|
94
|
-
const target = line.trim();
|
|
95
|
-
return !target.endsWith("/grok-hooks.json") || fs.existsSync(target);
|
|
96
|
-
});
|
|
97
|
-
if (kept.length !== lines.length) {
|
|
98
|
-
fs.writeFileSync(registry, kept.join("\n"));
|
|
99
|
-
console.log(
|
|
100
|
-
`==> migrate: dropped ${lines.length - kept.length} stale Grok hook registry line(s)`,
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
} catch {} // no registry — nothing to clean
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (!fs.existsSync(dbPath)) process.exit(0);
|
|
107
|
-
const db = new DatabaseSync(dbPath, { readOnly: true });
|
|
108
|
-
|
|
109
|
-
/** A write connection that waits out the running server's transactions, as
|
|
110
|
-
* db.ts does: setup and update.sh migrate while the old server still runs,
|
|
111
|
-
* and a lock thrown here would end the script before every later sweep. */
|
|
112
|
-
function writer() {
|
|
113
|
-
const wr = new DatabaseSync(dbPath);
|
|
114
|
-
wr.exec("PRAGMA busy_timeout = 5000");
|
|
115
|
-
return wr;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Pre-scrape versions wrote agent hook files into every workspace
|
|
119
|
-
// (identified by their agent-state callback); state now comes from
|
|
120
|
-
// terminal scraping and launch flags, so sweep them out.
|
|
121
|
-
const LEGACY_HOOK_FILES = [
|
|
122
|
-
".claude/settings.json",
|
|
123
|
-
".codex/hooks.json",
|
|
124
|
-
".cursor/hooks.json",
|
|
125
|
-
".cursor/hooks/work-working.sh",
|
|
126
|
-
".cursor/hooks/work-done.sh",
|
|
127
|
-
".github/hooks/work-agent-state.json",
|
|
128
|
-
];
|
|
129
|
-
|
|
130
|
-
let removed = 0;
|
|
131
|
-
for (const { path: wsPath } of db
|
|
132
|
-
.prepare("SELECT path FROM workspaces")
|
|
133
|
-
.all()) {
|
|
134
|
-
for (const rel of LEGACY_HOOK_FILES) {
|
|
135
|
-
const file = path.join(wsPath, rel);
|
|
136
|
-
try {
|
|
137
|
-
const text = fs.readFileSync(file, "utf8");
|
|
138
|
-
if (
|
|
139
|
-
!text.includes("/api/agent-state") &&
|
|
140
|
-
!text.includes(".cursor/hooks/work-")
|
|
141
|
-
) {
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
fs.rmSync(file);
|
|
145
|
-
removed++;
|
|
146
|
-
// Prune now-empty dirs the old version created.
|
|
147
|
-
for (
|
|
148
|
-
let dir = path.dirname(file);
|
|
149
|
-
dir !== wsPath && !fs.readdirSync(dir).length;
|
|
150
|
-
dir = path.dirname(dir)
|
|
151
|
-
) {
|
|
152
|
-
fs.rmdirSync(dir);
|
|
153
|
-
}
|
|
154
|
-
} catch {}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
if (removed) console.log(`==> migrate: removed ${removed} legacy hook file(s)`);
|
|
158
|
-
|
|
159
|
-
// A workspace's AGENTS.md is only rewritten when its repos change, so
|
|
160
|
-
// existing ones never learn that the stash is shared between worktrees of
|
|
161
|
-
// the same bare cache. Splice the bullet in ahead of the push one (keep in
|
|
162
|
-
// sync with writeAgentsMd in src/server/workspaces.ts).
|
|
163
|
-
const STASH_BULLET =
|
|
164
|
-
"- **No `git stash`:** every workspace using a repo shares one stash stack, so\n" +
|
|
165
|
-
" a pop can take another workspace's work. Commit WIP to your branch instead.\n";
|
|
166
|
-
let noted = 0;
|
|
167
|
-
for (const { path: wsPath } of db
|
|
168
|
-
.prepare("SELECT path FROM workspaces")
|
|
169
|
-
.all()) {
|
|
170
|
-
const file = path.join(wsPath, "AGENTS.md");
|
|
171
|
-
try {
|
|
172
|
-
const text = fs.readFileSync(file, "utf8");
|
|
173
|
-
const at = text.indexOf("- **Push:**");
|
|
174
|
-
if (at < 0 || text.includes("git stash")) continue;
|
|
175
|
-
fs.writeFileSync(file, text.slice(0, at) + STASH_BULLET + text.slice(at));
|
|
176
|
-
noted++;
|
|
177
|
-
} catch {}
|
|
178
|
-
}
|
|
179
|
-
if (noted)
|
|
180
|
-
console.log(`==> migrate: noted the shared stash in ${noted} AGENTS.md`);
|
|
181
|
-
|
|
182
|
-
// The review is commit-to-commit by default; fold that into the stash
|
|
183
|
-
// bullet rather than appending another one. Keep in sync with writeAgentsMd.
|
|
184
|
-
const OLD_STASH_END = "Commit WIP to your branch instead.";
|
|
185
|
-
const NEW_STASH_END =
|
|
186
|
-
"Commit as you go — uncommitted work isn't part of the review.";
|
|
187
|
-
let restated = 0;
|
|
188
|
-
for (const { path: wsPath } of db
|
|
189
|
-
.prepare("SELECT path FROM workspaces")
|
|
190
|
-
.all()) {
|
|
191
|
-
const file = path.join(wsPath, "AGENTS.md");
|
|
192
|
-
try {
|
|
193
|
-
const text = fs.readFileSync(file, "utf8");
|
|
194
|
-
if (!text.includes(OLD_STASH_END)) continue;
|
|
195
|
-
fs.writeFileSync(file, text.replace(OLD_STASH_END, NEW_STASH_END));
|
|
196
|
-
restated++;
|
|
197
|
-
} catch {}
|
|
198
|
-
}
|
|
199
|
-
if (restated)
|
|
200
|
-
console.log(
|
|
201
|
-
`==> migrate: restated the stash bullet in ${restated} AGENTS.md`,
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
// Same rewrite-on-create-only problem: existing AGENTS.md never learn to
|
|
205
|
-
// rebase after a squash-merge. Keep in sync with writeAgentsMd.
|
|
206
|
-
const REBASE_BULLET =
|
|
207
|
-
"- **Rebase after merge:** when `origin/<base>` (or a stacked parent) moves,\n" +
|
|
208
|
-
" rebase onto it. A squash-merge does not move the fork point, so the review\n" +
|
|
209
|
-
" keeps showing landed work until you do.\n";
|
|
210
|
-
let rebased = 0;
|
|
211
|
-
for (const { path: wsPath } of db
|
|
212
|
-
.prepare("SELECT path FROM workspaces")
|
|
213
|
-
.all()) {
|
|
214
|
-
const file = path.join(wsPath, "AGENTS.md");
|
|
215
|
-
try {
|
|
216
|
-
const text = fs.readFileSync(file, "utf8");
|
|
217
|
-
const at = text.indexOf("- **PRs:**");
|
|
218
|
-
if (at < 0 || text.includes("Rebase after merge")) continue;
|
|
219
|
-
fs.writeFileSync(file, text.slice(0, at) + REBASE_BULLET + text.slice(at));
|
|
220
|
-
rebased++;
|
|
221
|
-
} catch {}
|
|
222
|
-
}
|
|
223
|
-
if (rebased)
|
|
224
|
-
console.log(`==> migrate: noted rebase-after-merge in ${rebased} AGENTS.md`);
|
|
225
|
-
|
|
226
|
-
// Branch rules: stay on the workspace branch; reset it after it lands;
|
|
227
|
-
// topic lanes only when that branch must stay open. Replaces both the
|
|
228
|
-
// original "cut a lane per PR" parallel text and the later "need more
|
|
229
|
-
// than one? stack" wording. Keep in sync with writeAgentsMd.
|
|
230
|
-
let restatedBranches = 0;
|
|
231
|
-
for (const { path: wsPath } of db
|
|
232
|
-
.prepare("SELECT path FROM workspaces")
|
|
233
|
-
.all()) {
|
|
234
|
-
const file = path.join(wsPath, "AGENTS.md");
|
|
235
|
-
try {
|
|
236
|
-
let text = fs.readFileSync(file, "utf8");
|
|
237
|
-
const found = text.match(/Workspace branch: \*\*`([^`]+)`\*\*/);
|
|
238
|
-
if (!found || text.includes("must stay unmerged")) continue;
|
|
239
|
-
const branch = found[1];
|
|
240
|
-
const branches =
|
|
241
|
-
`- **Branches:** stay on \`${branch}\` and keep pushing it — one open PR, more\n` +
|
|
242
|
-
` commits. After it lands, \`git fetch\` and reset \`${branch}\` to\n` +
|
|
243
|
-
` \`origin/<base>\` so the next change reuses this branch. Do not cut a\n` +
|
|
244
|
-
` \`${branch}-<topic>\` just to start the next piece of work.\n` +
|
|
245
|
-
` A topic lane is only for when \`${branch}\` must stay unmerged (a larger\n` +
|
|
246
|
-
` change) and you need a second PR on top of it. Then push every repo's\n` +
|
|
247
|
-
` workspace branch first, cut from the parent —\n` +
|
|
248
|
-
` \`git switch -c ${branch}-<topic> origin/${branch}\` — and keep the prefix.\n` +
|
|
249
|
-
` Only two levels: never \`${branch}-a-b\`. Tooling finds PRs by that prefix,\n` +
|
|
250
|
-
` so a branch named anything else is invisible: never invent one.\n`;
|
|
251
|
-
const rebase =
|
|
252
|
-
`- **Rebase after merge:** when \`${branch}\` is still open and \`origin/<base>\`\n` +
|
|
253
|
-
" moves, rebase onto it — a squash-merge does not move the fork point, so the\n" +
|
|
254
|
-
" review keeps showing landed work until you do. On a topic lane, rebase onto\n" +
|
|
255
|
-
` \`${branch}\` when the parent moves; after the parent merges: \`git fetch\n` +
|
|
256
|
-
" --prune`, rebase onto `origin/<base>`, and retarget (`gh pr edit --base\n" +
|
|
257
|
-
" <base>`).\n";
|
|
258
|
-
const prs =
|
|
259
|
-
"- **PRs:** the description covers only what is in the diff — a few sentences on\n" +
|
|
260
|
-
" what changed and why. No verification logs or file-by-file detail. A topic\n" +
|
|
261
|
-
` lane's PR is \`gh pr create --base ${branch}\` — GitHub will otherwise target\n` +
|
|
262
|
-
" the repo default, and the local review will disagree with the files tab.\n";
|
|
263
|
-
const next = text
|
|
264
|
-
.replace(/- \*\*Branches:\*\*[\s\S]*?never invent one.\n/, branches)
|
|
265
|
-
.replace(/- \*\*PRs:\*\*[\s\S]*?file-by-file detail\.\n/, prs);
|
|
266
|
-
const withRebase = next.includes("- **Rebase after merge:**")
|
|
267
|
-
? next.replace(
|
|
268
|
-
/- \*\*Rebase after merge:\*\*[\s\S]*?(?:until you do|<base>`\)\.)\n/,
|
|
269
|
-
rebase,
|
|
270
|
-
)
|
|
271
|
-
: next;
|
|
272
|
-
if (withRebase === text) continue;
|
|
273
|
-
fs.writeFileSync(file, withRebase);
|
|
274
|
-
restatedBranches++;
|
|
275
|
-
} catch {}
|
|
276
|
-
}
|
|
277
|
-
if (restatedBranches) {
|
|
278
|
-
console.log(
|
|
279
|
-
`==> migrate: restated branch rules in ${restatedBranches} AGENTS.md`,
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// Topic lanes come in two kinds: stacked on the workspace branch, or
|
|
284
|
-
// independent, cut from the base (a separate fix that lands on its own).
|
|
285
|
-
// Existing AGENTS.md only describe stacked lanes, whose PR targets the
|
|
286
|
-
// workspace branch. Keep in sync with writeAgentsMd.
|
|
287
|
-
let twoLaneKinds = 0;
|
|
288
|
-
for (const { path: wsPath } of db
|
|
289
|
-
.prepare("SELECT path FROM workspaces")
|
|
290
|
-
.all()) {
|
|
291
|
-
const file = path.join(wsPath, "AGENTS.md");
|
|
292
|
-
try {
|
|
293
|
-
const text = fs.readFileSync(file, "utf8");
|
|
294
|
-
const found = text.match(/Workspace branch: \*\*`([^`]+)`\*\*/);
|
|
295
|
-
if (!found || text.includes("**Independent**")) continue;
|
|
296
|
-
const branch = found[1];
|
|
297
|
-
const lanes =
|
|
298
|
-
" A topic lane is a second change beside it, and is one of two kinds.\n" +
|
|
299
|
-
` **Stacked**: it needs \`${branch}\`, which must stay unmerged (a larger\n` +
|
|
300
|
-
" change). Push every repo's workspace branch first, then cut from it\n" +
|
|
301
|
-
` (\`git switch -c ${branch}-<topic> origin/${branch}\`).\n` +
|
|
302
|
-
" **Independent**: it stands on its own and can land before or without\n" +
|
|
303
|
-
` \`${branch}\` (a separate fix found along the way). Cut from the base\n` +
|
|
304
|
-
` (\`git switch -c ${branch}-<topic> origin/<base>\`).\n` +
|
|
305
|
-
" Keep the prefix either way: tooling finds branches by it and tells the\n" +
|
|
306
|
-
" two kinds apart from their history, so a branch named anything else is\n" +
|
|
307
|
-
` invisible: never invent one. Only two levels: never \`${branch}-a-b\`.\n`;
|
|
308
|
-
const rebaseLanes =
|
|
309
|
-
"An independent lane\n" +
|
|
310
|
-
" rebases onto `origin/<base>` the same way. A stacked lane rebases onto\n" +
|
|
311
|
-
` \`${branch}\` when the parent moves; after the parent merges: \`git fetch\n` +
|
|
312
|
-
" --prune`, rebase onto `origin/<base>`, and retarget (`gh pr edit --base\n" +
|
|
313
|
-
" <base>`).\n";
|
|
314
|
-
const prLanes =
|
|
315
|
-
"A stacked\n" +
|
|
316
|
-
` lane's PR is \`gh pr create --base ${branch}\`: GitHub would otherwise\n` +
|
|
317
|
-
" target the repo default, and the local review would disagree with the\n" +
|
|
318
|
-
" files tab. An independent lane's PR targets the base, GitHub's default.\n";
|
|
319
|
-
const next = text
|
|
320
|
-
// The lane sentences of the branch bullet, up to its last line.
|
|
321
|
-
.replace(
|
|
322
|
-
/ A topic lane is only for when[\s\S]*?never invent one\.\n/,
|
|
323
|
-
lanes,
|
|
324
|
-
)
|
|
325
|
-
.replace(
|
|
326
|
-
/On a topic lane, rebase onto\n[\s\S]*?<base>`\)\.\n/,
|
|
327
|
-
rebaseLanes,
|
|
328
|
-
)
|
|
329
|
-
.replace(
|
|
330
|
-
/A topic\n lane's PR is `gh pr create --base [^`]+`[\s\S]*?files tab\.\n/,
|
|
331
|
-
prLanes,
|
|
332
|
-
);
|
|
333
|
-
if (next === text) continue;
|
|
334
|
-
fs.writeFileSync(file, next);
|
|
335
|
-
twoLaneKinds++;
|
|
336
|
-
} catch {}
|
|
337
|
-
}
|
|
338
|
-
if (twoLaneKinds) {
|
|
339
|
-
console.log(
|
|
340
|
-
`==> migrate: described independent lanes in ${twoLaneKinds} AGENTS.md`,
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
// Default review base/algorithm changed (workspace branch vs origin/<base>,
|
|
345
|
-
// containment empty-check, then commit-to-commit). Existing comments and
|
|
346
|
-
// viewed flags are keyed only by path+line, so they would silently
|
|
347
|
-
// re-anchor. Wipe once — this script runs on every update. db.ts sets the
|
|
348
|
-
// flag on a db it creates, which has no such comments to wipe.
|
|
349
|
-
{
|
|
350
|
-
const wr = writer();
|
|
351
|
-
try {
|
|
352
|
-
const FLAG = "review-cleared-diff-v2";
|
|
353
|
-
const seen = wr.prepare("SELECT 1 FROM settings WHERE key = ?").get(FLAG);
|
|
354
|
-
if (!seen) {
|
|
355
|
-
const comments = wr.prepare("DELETE FROM review_comments").run();
|
|
356
|
-
const viewed = wr.prepare("DELETE FROM review_viewed").run();
|
|
357
|
-
wr.prepare("INSERT INTO settings (key, value) VALUES (?, '1')").run(FLAG);
|
|
358
|
-
if (comments.changes || viewed.changes) {
|
|
359
|
-
console.log(
|
|
360
|
-
`==> migrate: cleared ${comments.changes} review comment(s) and ${viewed.changes} viewed flag(s)`,
|
|
361
|
-
);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
} finally {
|
|
365
|
-
wr.close();
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// The review flagged what moved since the reviewer's last visit, from a
|
|
370
|
-
// head per section kept in `review.seen:<ws>`. Viewed marks replace it
|
|
371
|
-
// (review_marks, src/server/viewed.ts): each head becomes a visit to its
|
|
372
|
-
// section's branch, which the server turns into per-file marks at that
|
|
373
|
-
// head when it next shows the section (a PR's under `#<number>`, the
|
|
374
|
-
// only name its section had). The working-tree hashes beside the heads
|
|
375
|
-
// name no branch's change and go. So does the table of the flags the
|
|
376
|
-
// sweep above cleared, which nothing reads.
|
|
377
|
-
{
|
|
378
|
-
const wr = writer();
|
|
379
|
-
try {
|
|
380
|
-
// Keep in sync with src/server/db.ts: the server running this update
|
|
381
|
-
// may predate the table.
|
|
382
|
-
wr.exec(`CREATE TABLE IF NOT EXISTS review_marks (
|
|
383
|
-
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
384
|
-
worktree TEXT NOT NULL,
|
|
385
|
-
branch TEXT NOT NULL,
|
|
386
|
-
path TEXT NOT NULL,
|
|
387
|
-
fingerprint TEXT NOT NULL,
|
|
388
|
-
PRIMARY KEY (workspace_id, worktree, branch, path)
|
|
389
|
-
)`);
|
|
390
|
-
const insert = wr.prepare(
|
|
391
|
-
"INSERT OR IGNORE INTO review_marks (workspace_id, worktree, branch, path, fingerprint) VALUES (?, ?, ?, '', ?)",
|
|
392
|
-
);
|
|
393
|
-
let visits = 0;
|
|
394
|
-
for (const { key, value } of wr
|
|
395
|
-
.prepare("SELECT key, value FROM settings WHERE key GLOB 'review.seen:*'")
|
|
396
|
-
.all()) {
|
|
397
|
-
const id = key.slice("review.seen:".length);
|
|
398
|
-
const ws = wr
|
|
399
|
-
.prepare("SELECT branch FROM workspaces WHERE id = ?")
|
|
400
|
-
.get(id);
|
|
401
|
-
let heads = {};
|
|
402
|
-
try {
|
|
403
|
-
heads = JSON.parse(value)?.heads ?? {};
|
|
404
|
-
} catch {}
|
|
405
|
-
for (const [section, head] of Object.entries(ws ? heads : {})) {
|
|
406
|
-
// `worktree`, `worktree@topic` or `worktree#pr`.
|
|
407
|
-
const m = /^([^@#]+)(?:@(.+)|#(\d+))?$/.exec(section);
|
|
408
|
-
if (!m || typeof head !== "string" || !/^[0-9a-f]{40,64}$/.test(head))
|
|
409
|
-
continue;
|
|
410
|
-
const branch = m[2]
|
|
411
|
-
? `${ws.branch}-${m[2]}`
|
|
412
|
-
: m[3]
|
|
413
|
-
? `#${m[3]}`
|
|
414
|
-
: ws.branch;
|
|
415
|
-
insert.run(id, m[1], branch, `seen:${head}`);
|
|
416
|
-
visits++;
|
|
417
|
-
}
|
|
418
|
-
wr.prepare("DELETE FROM settings WHERE key = ?").run(key);
|
|
419
|
-
}
|
|
420
|
-
if (visits)
|
|
421
|
-
console.log(
|
|
422
|
-
`==> migrate: carried ${visits} review visit(s) over to Viewed marks`,
|
|
423
|
-
);
|
|
424
|
-
wr.exec("DROP TABLE IF EXISTS review_viewed");
|
|
425
|
-
} finally {
|
|
426
|
-
wr.close();
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// Backfill the push-signal hook into bare caches that predate it (new
|
|
431
|
-
// caches get it from ensureBare — keep this script in sync with
|
|
432
|
-
// src/server/repo-events.ts).
|
|
433
|
-
const workRoot = process.env.WORK_ROOT || path.join(os.homedir(), "work");
|
|
434
|
-
const gitHost = "github.com";
|
|
435
|
-
const appPort = Number(process.env.WORK_APP_PORT || 7171);
|
|
436
|
-
// Same token file the server uses (src/server/hook-token.ts) — hooks ride
|
|
437
|
-
// the public port and the endpoint refuses pings without it. dataDir is
|
|
438
|
-
// declared at the top of this script.
|
|
439
|
-
const tokenFile = path.join(dataDir, "hook-token");
|
|
440
|
-
let hookTokenValue = "";
|
|
441
|
-
try {
|
|
442
|
-
hookTokenValue = fs.readFileSync(tokenFile, "utf8").trim();
|
|
443
|
-
} catch {}
|
|
444
|
-
if (!hookTokenValue) {
|
|
445
|
-
hookTokenValue = crypto.randomBytes(16).toString("hex");
|
|
446
|
-
fs.mkdirSync(dataDir, { recursive: true });
|
|
447
|
-
fs.writeFileSync(tokenFile, `${hookTokenValue}\n`, { mode: 0o600 });
|
|
448
|
-
}
|
|
449
|
-
const cacheHost = path.join(workRoot, ".cache", gitHost);
|
|
450
|
-
let hooked = 0;
|
|
451
|
-
try {
|
|
452
|
-
for (const owner of fs.readdirSync(cacheHost)) {
|
|
453
|
-
const ownerDir = path.join(cacheHost, owner);
|
|
454
|
-
for (const repoDir of fs.readdirSync(ownerDir)) {
|
|
455
|
-
if (!repoDir.endsWith(".git")) continue;
|
|
456
|
-
const fullName = `${owner}/${repoDir.slice(0, -4)}`;
|
|
457
|
-
const script =
|
|
458
|
-
`#!/bin/sh\n` +
|
|
459
|
-
`# installed by work: signals ref updates to the app server.\n` +
|
|
460
|
-
`[ "$1" = "committed" ] || exit 0\n` +
|
|
461
|
-
`refs=$(cat)\n` +
|
|
462
|
-
`case "$refs" in *"refs/remotes/origin/"*) ;; *) exit 0 ;; esac\n` +
|
|
463
|
-
`printf '%s\\n' "$refs" | curl -sf -m 2 -X POST --data-binary @- "http://${dialHost(process.env.WORK_LISTEN)}:${appPort}` +
|
|
464
|
-
`/api/repo-pushed?repo=${encodeURIComponent(fullName)}&token=${hookTokenValue}" >/dev/null 2>&1 &\n` +
|
|
465
|
-
`exit 0\n`;
|
|
466
|
-
const file = path.join(
|
|
467
|
-
ownerDir,
|
|
468
|
-
repoDir,
|
|
469
|
-
"hooks",
|
|
470
|
-
"reference-transaction",
|
|
471
|
-
);
|
|
472
|
-
try {
|
|
473
|
-
if (fs.readFileSync(file, "utf8") === script) continue;
|
|
474
|
-
} catch {}
|
|
475
|
-
try {
|
|
476
|
-
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
477
|
-
fs.writeFileSync(file, script, { mode: 0o755 });
|
|
478
|
-
hooked++;
|
|
479
|
-
} catch {}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
} catch {}
|
|
483
|
-
if (hooked)
|
|
484
|
-
console.log(`==> migrate: installed push hook in ${hooked} cache repo(s)`);
|
|
485
|
-
|
|
486
|
-
// Lane branches used to accumulate in the bare caches: nothing deleted one
|
|
487
|
-
// when its PR finished, only removing the repo or the whole workspace did,
|
|
488
|
-
// and a long-lived workspace here reached 66 of them against a single live
|
|
489
|
-
// branch. The app now prunes a lane when its merged PR is dismissed (see
|
|
490
|
-
// pruneLaneBranch in src/server/workspaces.ts), which only reaches lanes
|
|
491
|
-
// finished from here on — so sweep the backlog once, with the same guards.
|
|
492
|
-
// Best-effort: without gh, a token, or the network this does nothing.
|
|
493
|
-
const laneWorkspaces = db
|
|
494
|
-
.prepare("SELECT id, branch FROM workspaces")
|
|
495
|
-
.all()
|
|
496
|
-
.map((w) => ({ ...w, repos: [] }));
|
|
497
|
-
for (const row of db
|
|
498
|
-
.prepare("SELECT workspace_id, full_name FROM repos")
|
|
499
|
-
.all()) {
|
|
500
|
-
laneWorkspaces
|
|
501
|
-
.find((w) => w.id === row.workspace_id)
|
|
502
|
-
?.repos.push(row.full_name);
|
|
503
|
-
}
|
|
504
|
-
const ownsRef = (ref, prefix) => ref === prefix || ref.startsWith(`${prefix}-`);
|
|
505
|
-
const gitIn = (dir, args) =>
|
|
506
|
-
execFileSync("git", ["-C", dir, ...args], {
|
|
507
|
-
encoding: "utf8",
|
|
508
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
// Candidate lanes: owned by a workspace branch, not the branch itself, not
|
|
512
|
-
// claimed by another workspace whose branch extends this one's prefix, and
|
|
513
|
-
// not checked out in a worktree.
|
|
514
|
-
const candidates = [];
|
|
515
|
-
for (const ws of laneWorkspaces) {
|
|
516
|
-
const others = laneWorkspaces
|
|
517
|
-
.filter((w) => w.id !== ws.id)
|
|
518
|
-
.map((w) => w.branch);
|
|
519
|
-
for (const fullName of ws.repos) {
|
|
520
|
-
const bare = path.join(cacheHost, `${fullName}.git`);
|
|
521
|
-
let refs, checkedOut;
|
|
522
|
-
try {
|
|
523
|
-
refs = gitIn(bare, [
|
|
524
|
-
"for-each-ref",
|
|
525
|
-
"--format=%(refname:short) %(objectname)",
|
|
526
|
-
"refs/heads/",
|
|
527
|
-
])
|
|
528
|
-
.split("\n")
|
|
529
|
-
.filter(Boolean)
|
|
530
|
-
.map((line) => line.split(" "));
|
|
531
|
-
checkedOut = new Set(
|
|
532
|
-
gitIn(bare, ["worktree", "list", "--porcelain"])
|
|
533
|
-
.split("\n")
|
|
534
|
-
.filter((l) => l.startsWith("branch refs/heads/"))
|
|
535
|
-
.map((l) => l.slice("branch refs/heads/".length)),
|
|
536
|
-
);
|
|
537
|
-
} catch {
|
|
538
|
-
continue;
|
|
539
|
-
}
|
|
540
|
-
for (const [lane, oid] of refs) {
|
|
541
|
-
if (lane === ws.branch || !ownsRef(lane, ws.branch)) continue;
|
|
542
|
-
if (others.some((b) => ownsRef(lane, b)) || checkedOut.has(lane))
|
|
543
|
-
continue;
|
|
544
|
-
candidates.push({ bare, fullName, lane, oid });
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
let pruned = 0;
|
|
550
|
-
for (let i = 0; i < candidates.length; i += 40) {
|
|
551
|
-
const chunk = candidates.slice(i, i + 40);
|
|
552
|
-
// One aliased query per chunk rather than a request per lane.
|
|
553
|
-
const query =
|
|
554
|
-
"query {" +
|
|
555
|
-
chunk
|
|
556
|
-
.map(({ fullName, lane }, n) => {
|
|
557
|
-
const [owner, name] = fullName.split("/");
|
|
558
|
-
return (
|
|
559
|
-
`l${n}: repository(owner: ${JSON.stringify(owner)}, name: ${JSON.stringify(name)}) {` +
|
|
560
|
-
` pullRequests(headRefName: ${JSON.stringify(lane)}, first: 5) {` +
|
|
561
|
-
" nodes { state headRefOid } } }"
|
|
562
|
-
);
|
|
563
|
-
})
|
|
564
|
-
.join(" ") +
|
|
565
|
-
"}";
|
|
566
|
-
let data;
|
|
567
|
-
try {
|
|
568
|
-
data = JSON.parse(
|
|
569
|
-
execFileSync("gh", ["api", "graphql", "-f", `query=${query}`], {
|
|
570
|
-
encoding: "utf8",
|
|
571
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
572
|
-
}),
|
|
573
|
-
).data;
|
|
574
|
-
} catch {
|
|
575
|
-
break;
|
|
576
|
-
}
|
|
577
|
-
chunk.forEach((c, n) => {
|
|
578
|
-
const nodes = data?.[`l${n}`]?.pullRequests?.nodes;
|
|
579
|
-
if (!nodes?.length || nodes.some((p) => p.state === "OPEN")) return;
|
|
580
|
-
// The lane has to still be sitting on the finished PR's head: anything
|
|
581
|
-
// further along is work that PR never carried, and deleting it here
|
|
582
|
-
// would be the only copy.
|
|
583
|
-
if (!nodes.some((p) => p.state !== "OPEN" && p.headRefOid === c.oid))
|
|
584
|
-
return;
|
|
585
|
-
try {
|
|
586
|
-
gitIn(c.bare, ["branch", "-D", c.lane]);
|
|
587
|
-
pruned++;
|
|
588
|
-
} catch {}
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
if (pruned)
|
|
592
|
-
console.log(`==> migrate: pruned ${pruned} finished lane branch(es)`);
|
|
593
|
-
|
|
594
|
-
// Caches made with `git clone --bare` (every cache before init+fetch in
|
|
595
|
-
// ensureBare) copied each remote branch into refs/heads, so a cache carries
|
|
596
|
-
// every branch anyone ever pushed as a local head of its own. Drop the
|
|
597
|
-
// mirrors: a head that no worktree checks out, no workspace here owns,
|
|
598
|
-
// and that still sits exactly on its origin counterpart — the last guard
|
|
599
|
-
// keeps anything with local-only commits, whoever made it.
|
|
600
|
-
const ownedPrefixes = db
|
|
601
|
-
.prepare("SELECT branch FROM workspaces")
|
|
602
|
-
.all()
|
|
603
|
-
.map((w) => w.branch);
|
|
604
|
-
let mirrors = 0;
|
|
605
|
-
try {
|
|
606
|
-
const cacheRoot = path.join(workRoot, ".cache");
|
|
607
|
-
for (const host of fs.readdirSync(cacheRoot)) {
|
|
608
|
-
const hostDir = path.join(cacheRoot, host);
|
|
609
|
-
if (!fs.statSync(hostDir).isDirectory()) continue;
|
|
610
|
-
for (const owner of fs.readdirSync(hostDir)) {
|
|
611
|
-
const ownerDir = path.join(hostDir, owner);
|
|
612
|
-
if (!fs.statSync(ownerDir).isDirectory()) continue;
|
|
613
|
-
for (const repoDir of fs.readdirSync(ownerDir)) {
|
|
614
|
-
if (!repoDir.endsWith(".git")) continue;
|
|
615
|
-
const bare = path.join(ownerDir, repoDir);
|
|
616
|
-
let heads, remotes, checkedOut;
|
|
617
|
-
try {
|
|
618
|
-
const refLines = (glob) =>
|
|
619
|
-
gitIn(bare, [
|
|
620
|
-
"for-each-ref",
|
|
621
|
-
"--format=%(refname) %(objectname)",
|
|
622
|
-
glob,
|
|
623
|
-
])
|
|
624
|
-
.split("\n")
|
|
625
|
-
.filter(Boolean)
|
|
626
|
-
.map((l) => l.split(" "));
|
|
627
|
-
heads = refLines("refs/heads/");
|
|
628
|
-
remotes = new Map(
|
|
629
|
-
refLines("refs/remotes/origin/").map(([ref, oid]) => [
|
|
630
|
-
ref.slice("refs/remotes/origin/".length),
|
|
631
|
-
oid,
|
|
632
|
-
]),
|
|
633
|
-
);
|
|
634
|
-
checkedOut = new Set(
|
|
635
|
-
gitIn(bare, ["worktree", "list", "--porcelain"])
|
|
636
|
-
.split("\n")
|
|
637
|
-
.filter((l) => l.startsWith("branch refs/heads/"))
|
|
638
|
-
.map((l) => l.slice("branch refs/heads/".length)),
|
|
639
|
-
);
|
|
640
|
-
} catch {
|
|
641
|
-
continue;
|
|
642
|
-
}
|
|
643
|
-
for (const [ref, oid] of heads) {
|
|
644
|
-
const name = ref.slice("refs/heads/".length);
|
|
645
|
-
if (checkedOut.has(name)) continue;
|
|
646
|
-
if (ownedPrefixes.some((b) => ownsRef(name, b))) continue;
|
|
647
|
-
if (remotes.get(name) !== oid) continue;
|
|
648
|
-
try {
|
|
649
|
-
gitIn(bare, ["branch", "-D", name]);
|
|
650
|
-
mirrors++;
|
|
651
|
-
} catch {}
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
} catch {}
|
|
657
|
-
if (mirrors)
|
|
658
|
-
console.log(`==> migrate: dropped ${mirrors} mirrored remote branch(es)`);
|
|
659
|
-
|
|
660
|
-
// Existing AGENTS.md never learn about the `work` CLI read commands. Keep in
|
|
661
|
-
// sync with writeAgentsMd.
|
|
662
|
-
const WORK_CLI_BULLET =
|
|
663
|
-
"- **Ask `work` for facts:** the `work` CLI answers from the same data as\n" +
|
|
664
|
-
" the app: `work workspace` (this workspace: repos, base branches, open PRs,\n" +
|
|
665
|
-
" sessions, running procs/ports), `work repos`, `work procs`,\n" +
|
|
666
|
-
" `work workspaces`, `work doctor` (installed tools / agents / GitHub\n" +
|
|
667
|
-
" sign-in), `work usage` (agent plan quotas). Add `--json` for machine\n" +
|
|
668
|
-
" output. Prefer these over guessing from the filesystem or calling GitHub.\n";
|
|
669
|
-
let cliNoted = 0;
|
|
670
|
-
for (const { path: wsPath } of db
|
|
671
|
-
.prepare("SELECT path FROM workspaces")
|
|
672
|
-
.all()) {
|
|
673
|
-
const file = path.join(wsPath, "AGENTS.md");
|
|
674
|
-
try {
|
|
675
|
-
const text = fs.readFileSync(file, "utf8");
|
|
676
|
-
if (text.includes("Ask `work` for facts")) continue;
|
|
677
|
-
fs.writeFileSync(file, text.trimEnd() + "\n" + WORK_CLI_BULLET);
|
|
678
|
-
cliNoted++;
|
|
679
|
-
} catch {}
|
|
680
|
-
}
|
|
681
|
-
if (cliNoted)
|
|
682
|
-
console.log(`==> migrate: pointed ${cliNoted} AGENTS.md at the work CLI`);
|
|
683
|
-
|
|
684
|
-
// Existing AGENTS.md never learn that a repo's own agents file is required
|
|
685
|
-
// reading. Splice it in after the repo list (ahead of the stash bullet), so
|
|
686
|
-
// it sits with the repos it is about. Keep in sync with writeAgentsMd.
|
|
687
|
-
const REPO_AGENTS_BULLET =
|
|
688
|
-
"- **Repo agents files:** you **MUST** read a repo's `AGENTS.md` (or\n" +
|
|
689
|
-
" `CLAUDE.md`) before doing any work in it. It is not loaded for you.\n";
|
|
690
|
-
let repoNoted = 0;
|
|
691
|
-
for (const { path: wsPath } of db
|
|
692
|
-
.prepare("SELECT path FROM workspaces")
|
|
693
|
-
.all()) {
|
|
694
|
-
const file = path.join(wsPath, "AGENTS.md");
|
|
695
|
-
try {
|
|
696
|
-
const text = fs.readFileSync(file, "utf8");
|
|
697
|
-
const at = text.indexOf("- **No `git stash`:**");
|
|
698
|
-
if (at < 0 || text.includes("**Repo agents files:**")) continue;
|
|
699
|
-
fs.writeFileSync(
|
|
700
|
-
file,
|
|
701
|
-
text.slice(0, at) + REPO_AGENTS_BULLET + text.slice(at),
|
|
702
|
-
);
|
|
703
|
-
repoNoted++;
|
|
704
|
-
} catch {}
|
|
705
|
-
}
|
|
706
|
-
if (repoNoted)
|
|
707
|
-
console.log(
|
|
708
|
-
`==> migrate: required repo agents files in ${repoNoted} AGENTS.md`,
|
|
709
|
-
);
|
|
710
|
-
|
|
711
|
-
// Per-workspace UI prefs were never swept on delete; they ride every SSR
|
|
712
|
-
// document via allPrefs(). Prune orphans once — runtime delete handles new ones.
|
|
713
|
-
{
|
|
714
|
-
const wr = writer();
|
|
715
|
-
try {
|
|
716
|
-
const live = new Set(
|
|
717
|
-
wr
|
|
718
|
-
.prepare("SELECT id FROM workspaces")
|
|
719
|
-
.all()
|
|
720
|
-
.map((r) => r.id),
|
|
721
|
-
);
|
|
722
|
-
// Kept equal to WORKSPACE_PREFS in src/server/settings.ts, a .ts file
|
|
723
|
-
// this plain script cannot import.
|
|
724
|
-
const prefixes = [
|
|
725
|
-
"tab",
|
|
726
|
-
"diff-filter",
|
|
727
|
-
"diff-folded",
|
|
728
|
-
"diff-collapsed",
|
|
729
|
-
"diff-focus",
|
|
730
|
-
"diff-pos",
|
|
731
|
-
"files-recent",
|
|
732
|
-
].map((name) => `ui.${name}:`);
|
|
733
|
-
let pruned = 0;
|
|
734
|
-
for (const prefix of prefixes) {
|
|
735
|
-
for (const { key } of wr
|
|
736
|
-
.prepare("SELECT key FROM settings WHERE key GLOB ?")
|
|
737
|
-
.all(prefix + "*")) {
|
|
738
|
-
if (live.has(key.slice(prefix.length))) continue;
|
|
739
|
-
wr.prepare("DELETE FROM settings WHERE key = ?").run(key);
|
|
740
|
-
pruned++;
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
if (pruned)
|
|
744
|
-
console.log(`==> migrate: pruned ${pruned} orphaned ui pref(s)`);
|
|
745
|
-
} finally {
|
|
746
|
-
wr.close();
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
// The review's two-way toggle (`ui.diff-uncommitted`) became the three-way
|
|
751
|
-
// `diff-scope` pref, and nothing reads the old row: drop it, since it rides
|
|
752
|
-
// every SSR prefs payload. Not folded into the scope: that would switch
|
|
753
|
-
// long-time users to uncommitted changes without their asking.
|
|
754
|
-
{
|
|
755
|
-
const wr = writer();
|
|
756
|
-
try {
|
|
757
|
-
const dropped = wr
|
|
758
|
-
.prepare(
|
|
759
|
-
"DELETE FROM settings WHERE key IN ('ui.diff-uncommitted', 'diff-uncommitted')",
|
|
760
|
-
)
|
|
761
|
-
.run();
|
|
762
|
-
if (dropped.changes)
|
|
763
|
-
console.log("==> migrate: dropped the old diff-uncommitted pref");
|
|
764
|
-
} finally {
|
|
765
|
-
wr.close();
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
// The terminal's two text sizes were one JSON pref (`term-font`), which a
|
|
770
|
-
// device rewrote whole from a stale copy when it set its own size. Split
|
|
771
|
-
// it into the per-device prefs once (keep in sync with termFontPref in
|
|
772
|
-
// src/client/prefs.ts).
|
|
773
|
-
{
|
|
774
|
-
const wr = writer();
|
|
775
|
-
try {
|
|
776
|
-
const legacy = wr
|
|
777
|
-
.prepare("SELECT value FROM settings WHERE key = 'ui.term-font'")
|
|
778
|
-
.get();
|
|
779
|
-
if (legacy) {
|
|
780
|
-
let sizes = {};
|
|
781
|
-
try {
|
|
782
|
-
sizes = JSON.parse(legacy.value) ?? {};
|
|
783
|
-
} catch {}
|
|
784
|
-
for (const [field, key] of [
|
|
785
|
-
["desktop", "ui.term-font-desktop"],
|
|
786
|
-
["touch", "ui.term-font-touch"],
|
|
787
|
-
]) {
|
|
788
|
-
if (!Number.isInteger(sizes[field])) continue;
|
|
789
|
-
wr.prepare(
|
|
790
|
-
"INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)",
|
|
791
|
-
).run(key, String(sizes[field]));
|
|
792
|
-
}
|
|
793
|
-
wr.prepare("DELETE FROM settings WHERE key = 'ui.term-font'").run();
|
|
794
|
-
console.log("==> migrate: split term-font into per-device prefs");
|
|
795
|
-
}
|
|
796
|
-
} finally {
|
|
797
|
-
wr.close();
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
// The phone pad's pref was once a bare list of the keys after the pad's
|
|
802
|
-
// own nine. It is `{ base, extra }` now, and a change to one key
|
|
803
|
-
// (src/client/pref-change.ts) finds no `extra` in a list, so it would
|
|
804
|
-
// start the pad afresh. Wrap such a list once.
|
|
805
|
-
{
|
|
806
|
-
const wr = writer();
|
|
807
|
-
try {
|
|
808
|
-
const row = wr
|
|
809
|
-
.prepare("SELECT value FROM settings WHERE key = 'ui.phone-keys'")
|
|
810
|
-
.get();
|
|
811
|
-
let keys;
|
|
812
|
-
try {
|
|
813
|
-
keys = row && JSON.parse(row.value);
|
|
814
|
-
} catch {}
|
|
815
|
-
if (Array.isArray(keys)) {
|
|
816
|
-
wr.prepare(
|
|
817
|
-
"UPDATE settings SET value = ? WHERE key = 'ui.phone-keys'",
|
|
818
|
-
).run(JSON.stringify({ base: [], extra: keys }));
|
|
819
|
-
console.log("==> migrate: moved the phone pad's keys into its new shape");
|
|
820
|
-
}
|
|
821
|
-
} finally {
|
|
822
|
-
wr.close();
|
|
823
|
-
}
|
|
824
|
-
}
|