@iloom/cli 0.10.1 → 0.11.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/LICENSE +1 -1
- package/README.md +4 -2
- package/dist/{BranchNamingService-25KSZAEM.js → BranchNamingService-XBCO747L.js} +4 -4
- package/dist/ClaudeContextManager-SXDCWDJA.js +14 -0
- package/dist/ClaudeService-6E6MCGJE.js +13 -0
- package/dist/GitHubService-2R5GQG4K.js +12 -0
- package/dist/IssueTrackerFactory-XN6MQ4UN.js +14 -0
- package/dist/{LoomLauncher-TDLZSYG2.js → LoomLauncher-5AZU2F5I.js} +15 -12
- package/dist/LoomLauncher-5AZU2F5I.js.map +1 -0
- package/dist/MetadataManager-CMQQTFLQ.js +10 -0
- package/dist/ProjectCapabilityDetector-IC6NAFGY.js +11 -0
- package/dist/{PromptTemplateManager-YOE2SIPG.js → PromptTemplateManager-T5VTLJP3.js} +3 -3
- package/dist/README.md +4 -2
- package/dist/{SettingsManager-FNKCOZMQ.js → SettingsManager-WQ5NSGAH.js} +3 -3
- package/dist/SettingsMigrationManager-S6J7OHUH.js +10 -0
- package/dist/agents/iloom-code-reviewer.md +50 -8
- package/dist/agents/iloom-issue-analyze-and-plan.md +10 -0
- package/dist/agents/iloom-issue-analyzer.md +13 -0
- package/dist/agents/iloom-issue-complexity-evaluator.md +8 -1
- package/dist/agents/iloom-issue-enhancer.md +8 -1
- package/dist/agents/iloom-issue-planner.md +5 -0
- package/dist/build-OLS6J5KZ.js +27 -0
- package/dist/{chunk-WWKOVDWC.js → chunk-3GTUXW26.js} +3 -3
- package/dist/{chunk-4FGEGQW4.js → chunk-3RXYOBME.js} +5 -5
- package/dist/{chunk-HEXKPKCK.js → chunk-5LTID2AF.js} +6 -6
- package/dist/{chunk-G5V75JD5.js → chunk-5PNZBH6V.js} +2 -2
- package/dist/{chunk-SKSYYBCU.js → chunk-5UFGO4ZT.js} +24 -3
- package/dist/{chunk-SKSYYBCU.js.map → chunk-5UFGO4ZT.js.map} +1 -1
- package/dist/{chunk-E6KOWMKA.js → chunk-6YVJVUR4.js} +3 -3
- package/dist/{chunk-RJ3VBUFK.js → chunk-7FIXNAUO.js} +36 -7
- package/dist/chunk-7FIXNAUO.js.map +1 -0
- package/dist/{chunk-QVLPWNE3.js → chunk-7NFCGKZT.js} +3 -3
- package/dist/{chunk-433MOLAU.js → chunk-7OCGBJLR.js} +2 -2
- package/dist/{chunk-KVHIAWVT.js → chunk-ABVMUNCD.js} +8 -8
- package/dist/{chunk-7JDMYTFZ.js → chunk-CV47VCMQ.js} +2 -2
- package/dist/{chunk-7VHJNVLF.js → chunk-ET6A2JR4.js} +8 -6
- package/dist/chunk-ET6A2JR4.js.map +1 -0
- package/dist/{chunk-MORRVYPT.js → chunk-G2MNSPA4.js} +2 -2
- package/dist/{chunk-RSYT7MVI.js → chunk-GMDSYLI6.js} +36 -3
- package/dist/chunk-GMDSYLI6.js.map +1 -0
- package/dist/{chunk-VT4PDUYT.js → chunk-H2SSF24U.js} +284 -209
- package/dist/chunk-H2SSF24U.js.map +1 -0
- package/dist/{chunk-LLHXQS3C.js → chunk-HLDY5S4C.js} +3 -3
- package/dist/{chunk-BYUMEDDD.js → chunk-IDCE26KD.js} +3 -3
- package/dist/{chunk-OTGH2HRS.js → chunk-IR74O2F6.js} +221 -88
- package/dist/chunk-IR74O2F6.js.map +1 -0
- package/dist/{chunk-O7VL5N6S.js → chunk-K7R5QY6C.js} +2 -2
- package/dist/{chunk-S7PZA6IV.js → chunk-KQFIGI37.js} +5 -5
- package/dist/{chunk-I5T677EA.js → chunk-LE2NOUTN.js} +3 -3
- package/dist/{chunk-KXDRI47U.js → chunk-LHDD4JHC.js} +6 -6
- package/dist/{chunk-5FJWO4IT.js → chunk-LL6TOX3G.js} +9 -9
- package/dist/{chunk-YQ57ORTV.js → chunk-NCPZYQ4B.js} +2 -2
- package/dist/{chunk-EWJFUFPT.js → chunk-NDSGJZI2.js} +2 -2
- package/dist/{chunk-VG45TUYK.js → chunk-NH3QZYE5.js} +2 -2
- package/dist/{chunk-KKV5WH5M.js → chunk-NN5RYWXA.js} +7 -7
- package/dist/chunk-NOMQ5RFG.js +118 -0
- package/dist/chunk-NOMQ5RFG.js.map +1 -0
- package/dist/{chunk-KIK2ZFAL.js → chunk-QNHZM5ZV.js} +3 -3
- package/dist/{chunk-EVPZFV3K.js → chunk-QR4FU53I.js} +8 -8
- package/dist/{chunk-FXDYIV3K.js → chunk-QVAA5KHK.js} +2 -2
- package/dist/{chunk-NGJZ4TOU.js → chunk-RBYTXYGD.js} +2 -2
- package/dist/{chunk-SWSJWA2S.js → chunk-RMLADZRY.js} +12 -9
- package/dist/chunk-RMLADZRY.js.map +1 -0
- package/dist/{chunk-CVCTIDDK.js → chunk-RVI6C2H5.js} +5 -5
- package/dist/{chunk-Q7POFB5Q.js → chunk-SQYHPBFP.js} +2 -2
- package/dist/{chunk-GRISNU6G.js → chunk-TEJAGQX2.js} +64 -40
- package/dist/chunk-TEJAGQX2.js.map +1 -0
- package/dist/{chunk-QZWEJVWV.js → chunk-TZNNJLGT.js} +6 -6
- package/dist/{chunk-63QWFWH3.js → chunk-UDCI3QTS.js} +2 -2
- package/dist/{chunk-UKBAJ2QQ.js → chunk-UHIBKD73.js} +7 -7
- package/dist/{chunk-WXIM2WS7.js → chunk-V4STTBQD.js} +10 -10
- package/dist/{chunk-P4O6EH46.js → chunk-VMZG66UV.js} +5 -5
- package/dist/{chunk-C6HNNJIV.js → chunk-VNYWBHKR.js} +34 -4
- package/dist/chunk-VNYWBHKR.js.map +1 -0
- package/dist/{chunk-5RPBYK5Q.js → chunk-VUUN3KE4.js} +10 -10
- package/dist/chunk-VUUN3KE4.js.map +1 -0
- package/dist/{chunk-UUEW5KWB.js → chunk-WG4MLJ6J.js} +15 -10
- package/dist/chunk-WG4MLJ6J.js.map +1 -0
- package/dist/{chunk-ZNMPGMHY.js → chunk-XFQGI2E3.js} +66 -43
- package/dist/chunk-XFQGI2E3.js.map +1 -0
- package/dist/{chunk-LUKXJSRI.js → chunk-XXFSOVL3.js} +4 -4
- package/dist/{chunk-UR5DGNUO.js → chunk-Y3RX7LZT.js} +11 -8
- package/dist/chunk-Y3RX7LZT.js.map +1 -0
- package/dist/{chunk-KB64WNBZ.js → chunk-YRCEOQPX.js} +4 -2
- package/dist/chunk-YRCEOQPX.js.map +1 -0
- package/dist/{chunk-6MLEBAYZ.js → chunk-ZAXRQLK3.js} +2 -2
- package/dist/{claude-7GGEWVEM.js → claude-ONQTDWV3.js} +4 -4
- package/dist/{cleanup-6PVAC4NI.js → cleanup-YOM6PQCN.js} +35 -34
- package/dist/{cleanup-6PVAC4NI.js.map → cleanup-YOM6PQCN.js.map} +1 -1
- package/dist/cli.js +235 -147
- package/dist/cli.js.map +1 -1
- package/dist/{color-4TJ4P5EY.js → color-VQD52LOI.js} +3 -3
- package/dist/{commit-FZR5XDQG.js → commit-DC2Q5CDY.js} +15 -15
- package/dist/{compile-7ALJHZ4N.js → compile-4NCQECKE.js} +11 -11
- package/dist/{contribute-5GKLK3BQ.js → contribute-M5UWXCAV.js} +12 -12
- package/dist/darwin-5BHWRJ7D.js +10 -0
- package/dist/{dev-server-7SMIB7OF.js → dev-server-CYRP6M73.js} +19 -19
- package/dist/{feedback-G2GJFN2F.js → feedback-BMAZGKRW.js} +16 -16
- package/dist/{git-GTLKAZRJ.js → git-BXUD6CL5.js} +6 -6
- package/dist/ignite-IO4LXVXJ.js +35 -0
- package/dist/index.d.ts +39 -65
- package/dist/index.js +637 -110
- package/dist/index.js.map +1 -1
- package/dist/{init-32YOKXRL.js → init-CI43GJHV.js} +17 -17
- package/dist/{init-32YOKXRL.js.map → init-CI43GJHV.js.map} +1 -1
- package/dist/install-deps-SRTM5U7D.js +43 -0
- package/dist/install-deps-SRTM5U7D.js.map +1 -0
- package/dist/{installation-detector-MMFWLJYN.js → installation-detector-HF6QN7KP.js} +3 -3
- package/dist/{issues-4UUAQ5K6.js → issues-DMRQJH7E.js} +15 -15
- package/dist/lint-BSWRMGPZ.js +27 -0
- package/dist/linux-RYLOP2LY.js +103 -0
- package/dist/linux-RYLOP2LY.js.map +1 -0
- package/dist/mcp/chunk-PIIRD4LO.js +373 -0
- package/dist/mcp/chunk-PIIRD4LO.js.map +1 -0
- package/dist/mcp/darwin-3JFFE3W2.js +10 -0
- package/dist/mcp/issue-management-server.js +23 -127
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/mcp/linux-JBVS4R3A.js +103 -0
- package/dist/mcp/linux-JBVS4R3A.js.map +1 -0
- package/dist/mcp/tmux-RYBLEHUZ.js +156 -0
- package/dist/mcp/tmux-RYBLEHUZ.js.map +1 -0
- package/dist/mcp/wsl-4QZIQLLE.js +78 -0
- package/dist/mcp/wsl-4QZIQLLE.js.map +1 -0
- package/dist/neon-helpers-HWIYRKOW.js +11 -0
- package/dist/{open-FXWW3VI4.js → open-2Y7GSUTJ.js} +19 -19
- package/dist/{plan-RQ5FPIGF.js → plan-SWFPLNJE.js} +47 -46
- package/dist/{plan-RQ5FPIGF.js.map → plan-SWFPLNJE.js.map} +1 -1
- package/dist/{projects-2UOXFLNZ.js → projects-IUSUXD5D.js} +6 -6
- package/dist/{prompt-ONNPSNKM.js → prompt-7LZB4PAT.js} +3 -3
- package/dist/prompts/init-prompt.txt +56 -107
- package/dist/prompts/issue-prompt.txt +57 -11
- package/dist/prompts/pr-prompt.txt +154 -4
- package/dist/prompts/regular-prompt.txt +20 -3
- package/dist/prompts/swarm-orchestrator-prompt.txt +134 -14
- package/dist/{rebase-6NVLX5V7.js → rebase-S6OHAOOF.js} +12 -12
- package/dist/{recap-OMBOKJST.js → recap-GGVCG5VH.js} +9 -9
- package/dist/{remote-IJAMOEAP.js → remote-MZTFHHTU.js} +3 -3
- package/dist/remote-MZTFHHTU.js.map +1 -0
- package/dist/{run-BBXLRIZB.js → run-ST3FR75O.js} +19 -19
- package/dist/schema/settings.schema.json +8 -49
- package/dist/{shell-RF7LTND5.js → shell-W4SBQPTE.js} +8 -8
- package/dist/{summary-WTQZ7XG2.js → summary-P2JCIIJO.js} +17 -17
- package/dist/test-6JH4FE2X.js +27 -0
- package/dist/{test-git-XM4TM65W.js → test-git-2KFFAQ6B.js} +6 -6
- package/dist/{test-jira-LDTOYFSD.js → test-jira-FKDKG6CD.js} +8 -8
- package/dist/{test-prefix-GBO37XCN.js → test-prefix-GP2DAX37.js} +11 -11
- package/dist/test-prefix-GP2DAX37.js.map +1 -0
- package/dist/{test-tabs-D3POYOJ5.js → test-tabs-YDWMWTVA.js} +3 -3
- package/dist/{test-webserver-NZ3JTVLL.js → test-webserver-QI3QQFZ3.js} +8 -8
- package/dist/tmux-7ZTA3BDI.js +156 -0
- package/dist/tmux-7ZTA3BDI.js.map +1 -0
- package/dist/{update-HJKDYA3F.js → update-XLW7R7FL.js} +4 -4
- package/dist/{update-notifier-LBAUOOLM.js → update-notifier-EYLAXZAA.js} +3 -3
- package/dist/update-notifier-EYLAXZAA.js.map +1 -0
- package/dist/{vscode-6XUGHJKL.js → vscode-TOGE5N67.js} +13 -13
- package/dist/{vscode-announcement-EQ2SKK3T.js → vscode-announcement-NIX7O2MG.js} +3 -3
- package/dist/wsl-Y4GUTOQ7.js +78 -0
- package/dist/wsl-Y4GUTOQ7.js.map +1 -0
- package/package.json +4 -2
- package/dist/ClaudeContextManager-66GR4BGM.js +0 -14
- package/dist/ClaudeService-7KM5NA5Z.js +0 -13
- package/dist/GitHubService-MEHKHUQP.js +0 -12
- package/dist/IssueTrackerFactory-NG53YX5S.js +0 -14
- package/dist/LoomLauncher-TDLZSYG2.js.map +0 -1
- package/dist/MetadataManager-5QZSTKNN.js +0 -10
- package/dist/ProjectCapabilityDetector-5KSYUTBJ.js +0 -11
- package/dist/SettingsMigrationManager-LEBMJP3B.js +0 -10
- package/dist/build-VHGEMXBA.js +0 -27
- package/dist/chunk-5RPBYK5Q.js.map +0 -1
- package/dist/chunk-7VHJNVLF.js.map +0 -1
- package/dist/chunk-C6HNNJIV.js.map +0 -1
- package/dist/chunk-GRISNU6G.js.map +0 -1
- package/dist/chunk-KB64WNBZ.js.map +0 -1
- package/dist/chunk-OTGH2HRS.js.map +0 -1
- package/dist/chunk-RJ3VBUFK.js.map +0 -1
- package/dist/chunk-RSYT7MVI.js.map +0 -1
- package/dist/chunk-SWSJWA2S.js.map +0 -1
- package/dist/chunk-UR5DGNUO.js.map +0 -1
- package/dist/chunk-UUEW5KWB.js.map +0 -1
- package/dist/chunk-VT4PDUYT.js.map +0 -1
- package/dist/chunk-ZNMPGMHY.js.map +0 -1
- package/dist/ignite-H2O5Y5A2.js +0 -34
- package/dist/lint-AAN2NZWG.js +0 -27
- package/dist/neon-helpers-CQN2PB4S.js +0 -11
- package/dist/test-SGO6I5Z7.js +0 -27
- package/dist/test-prefix-GBO37XCN.js.map +0 -1
- /package/dist/{BranchNamingService-25KSZAEM.js.map → BranchNamingService-XBCO747L.js.map} +0 -0
- /package/dist/{ClaudeContextManager-66GR4BGM.js.map → ClaudeContextManager-SXDCWDJA.js.map} +0 -0
- /package/dist/{ClaudeService-7KM5NA5Z.js.map → ClaudeService-6E6MCGJE.js.map} +0 -0
- /package/dist/{GitHubService-MEHKHUQP.js.map → GitHubService-2R5GQG4K.js.map} +0 -0
- /package/dist/{IssueTrackerFactory-NG53YX5S.js.map → IssueTrackerFactory-XN6MQ4UN.js.map} +0 -0
- /package/dist/{MetadataManager-5QZSTKNN.js.map → MetadataManager-CMQQTFLQ.js.map} +0 -0
- /package/dist/{ProjectCapabilityDetector-5KSYUTBJ.js.map → ProjectCapabilityDetector-IC6NAFGY.js.map} +0 -0
- /package/dist/{PromptTemplateManager-YOE2SIPG.js.map → PromptTemplateManager-T5VTLJP3.js.map} +0 -0
- /package/dist/{SettingsManager-FNKCOZMQ.js.map → SettingsManager-WQ5NSGAH.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-LEBMJP3B.js.map → SettingsMigrationManager-S6J7OHUH.js.map} +0 -0
- /package/dist/{build-VHGEMXBA.js.map → build-OLS6J5KZ.js.map} +0 -0
- /package/dist/{chunk-WWKOVDWC.js.map → chunk-3GTUXW26.js.map} +0 -0
- /package/dist/{chunk-4FGEGQW4.js.map → chunk-3RXYOBME.js.map} +0 -0
- /package/dist/{chunk-HEXKPKCK.js.map → chunk-5LTID2AF.js.map} +0 -0
- /package/dist/{chunk-G5V75JD5.js.map → chunk-5PNZBH6V.js.map} +0 -0
- /package/dist/{chunk-E6KOWMKA.js.map → chunk-6YVJVUR4.js.map} +0 -0
- /package/dist/{chunk-QVLPWNE3.js.map → chunk-7NFCGKZT.js.map} +0 -0
- /package/dist/{chunk-433MOLAU.js.map → chunk-7OCGBJLR.js.map} +0 -0
- /package/dist/{chunk-KVHIAWVT.js.map → chunk-ABVMUNCD.js.map} +0 -0
- /package/dist/{chunk-7JDMYTFZ.js.map → chunk-CV47VCMQ.js.map} +0 -0
- /package/dist/{chunk-MORRVYPT.js.map → chunk-G2MNSPA4.js.map} +0 -0
- /package/dist/{chunk-LLHXQS3C.js.map → chunk-HLDY5S4C.js.map} +0 -0
- /package/dist/{chunk-BYUMEDDD.js.map → chunk-IDCE26KD.js.map} +0 -0
- /package/dist/{chunk-O7VL5N6S.js.map → chunk-K7R5QY6C.js.map} +0 -0
- /package/dist/{chunk-S7PZA6IV.js.map → chunk-KQFIGI37.js.map} +0 -0
- /package/dist/{chunk-I5T677EA.js.map → chunk-LE2NOUTN.js.map} +0 -0
- /package/dist/{chunk-KXDRI47U.js.map → chunk-LHDD4JHC.js.map} +0 -0
- /package/dist/{chunk-5FJWO4IT.js.map → chunk-LL6TOX3G.js.map} +0 -0
- /package/dist/{chunk-YQ57ORTV.js.map → chunk-NCPZYQ4B.js.map} +0 -0
- /package/dist/{chunk-EWJFUFPT.js.map → chunk-NDSGJZI2.js.map} +0 -0
- /package/dist/{chunk-VG45TUYK.js.map → chunk-NH3QZYE5.js.map} +0 -0
- /package/dist/{chunk-KKV5WH5M.js.map → chunk-NN5RYWXA.js.map} +0 -0
- /package/dist/{chunk-KIK2ZFAL.js.map → chunk-QNHZM5ZV.js.map} +0 -0
- /package/dist/{chunk-EVPZFV3K.js.map → chunk-QR4FU53I.js.map} +0 -0
- /package/dist/{chunk-FXDYIV3K.js.map → chunk-QVAA5KHK.js.map} +0 -0
- /package/dist/{chunk-NGJZ4TOU.js.map → chunk-RBYTXYGD.js.map} +0 -0
- /package/dist/{chunk-CVCTIDDK.js.map → chunk-RVI6C2H5.js.map} +0 -0
- /package/dist/{chunk-Q7POFB5Q.js.map → chunk-SQYHPBFP.js.map} +0 -0
- /package/dist/{chunk-QZWEJVWV.js.map → chunk-TZNNJLGT.js.map} +0 -0
- /package/dist/{chunk-63QWFWH3.js.map → chunk-UDCI3QTS.js.map} +0 -0
- /package/dist/{chunk-UKBAJ2QQ.js.map → chunk-UHIBKD73.js.map} +0 -0
- /package/dist/{chunk-WXIM2WS7.js.map → chunk-V4STTBQD.js.map} +0 -0
- /package/dist/{chunk-P4O6EH46.js.map → chunk-VMZG66UV.js.map} +0 -0
- /package/dist/{chunk-LUKXJSRI.js.map → chunk-XXFSOVL3.js.map} +0 -0
- /package/dist/{chunk-6MLEBAYZ.js.map → chunk-ZAXRQLK3.js.map} +0 -0
- /package/dist/{claude-7GGEWVEM.js.map → claude-ONQTDWV3.js.map} +0 -0
- /package/dist/{color-4TJ4P5EY.js.map → color-VQD52LOI.js.map} +0 -0
- /package/dist/{commit-FZR5XDQG.js.map → commit-DC2Q5CDY.js.map} +0 -0
- /package/dist/{compile-7ALJHZ4N.js.map → compile-4NCQECKE.js.map} +0 -0
- /package/dist/{contribute-5GKLK3BQ.js.map → contribute-M5UWXCAV.js.map} +0 -0
- /package/dist/{git-GTLKAZRJ.js.map → darwin-5BHWRJ7D.js.map} +0 -0
- /package/dist/{dev-server-7SMIB7OF.js.map → dev-server-CYRP6M73.js.map} +0 -0
- /package/dist/{feedback-G2GJFN2F.js.map → feedback-BMAZGKRW.js.map} +0 -0
- /package/dist/{ignite-H2O5Y5A2.js.map → git-BXUD6CL5.js.map} +0 -0
- /package/dist/{installation-detector-MMFWLJYN.js.map → ignite-IO4LXVXJ.js.map} +0 -0
- /package/dist/{neon-helpers-CQN2PB4S.js.map → installation-detector-HF6QN7KP.js.map} +0 -0
- /package/dist/{issues-4UUAQ5K6.js.map → issues-DMRQJH7E.js.map} +0 -0
- /package/dist/{lint-AAN2NZWG.js.map → lint-BSWRMGPZ.js.map} +0 -0
- /package/dist/{prompt-ONNPSNKM.js.map → mcp/darwin-3JFFE3W2.js.map} +0 -0
- /package/dist/{remote-IJAMOEAP.js.map → neon-helpers-HWIYRKOW.js.map} +0 -0
- /package/dist/{open-FXWW3VI4.js.map → open-2Y7GSUTJ.js.map} +0 -0
- /package/dist/{projects-2UOXFLNZ.js.map → projects-IUSUXD5D.js.map} +0 -0
- /package/dist/{update-notifier-LBAUOOLM.js.map → prompt-7LZB4PAT.js.map} +0 -0
- /package/dist/{rebase-6NVLX5V7.js.map → rebase-S6OHAOOF.js.map} +0 -0
- /package/dist/{recap-OMBOKJST.js.map → recap-GGVCG5VH.js.map} +0 -0
- /package/dist/{run-BBXLRIZB.js.map → run-ST3FR75O.js.map} +0 -0
- /package/dist/{shell-RF7LTND5.js.map → shell-W4SBQPTE.js.map} +0 -0
- /package/dist/{summary-WTQZ7XG2.js.map → summary-P2JCIIJO.js.map} +0 -0
- /package/dist/{test-SGO6I5Z7.js.map → test-6JH4FE2X.js.map} +0 -0
- /package/dist/{test-git-XM4TM65W.js.map → test-git-2KFFAQ6B.js.map} +0 -0
- /package/dist/{test-jira-LDTOYFSD.js.map → test-jira-FKDKG6CD.js.map} +0 -0
- /package/dist/{test-tabs-D3POYOJ5.js.map → test-tabs-YDWMWTVA.js.map} +0 -0
- /package/dist/{test-webserver-NZ3JTVLL.js.map → test-webserver-QI3QQFZ3.js.map} +0 -0
- /package/dist/{update-HJKDYA3F.js.map → update-XLW7R7FL.js.map} +0 -0
- /package/dist/{vscode-6XUGHJKL.js.map → vscode-TOGE5N67.js.map} +0 -0
- /package/dist/{vscode-announcement-EQ2SKK3T.js.map → vscode-announcement-NIX7O2MG.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/MetadataManager.ts"],"sourcesContent":["import path from 'path'\nimport os from 'os'\nimport fs from 'fs-extra'\nimport { getLogger } from '../utils/logger-context.js'\nimport type { ProjectCapability } from '../types/loom.js'\nimport type { ComplexityOverride, OneShotMode } from '../types/index.js'\n\nexport type SwarmState = 'pending' | 'in_progress' | 'code_review' | 'done' | 'failed'\n\n/**\n * Schema for metadata JSON file\n * Stored in ~/.config/iloom-ai/looms/\n */\nexport interface MetadataFile {\n description: string\n created_at?: string\n version: number\n // Additional metadata fields (v2)\n branchName?: string\n worktreePath?: string\n issueType?: 'branch' | 'issue' | 'pr' | 'epic'\n issueKey?: string // Canonical, properly-cased issue key (e.g., \"PROJ-123\")\n issue_numbers?: string[]\n pr_numbers?: string[]\n issueTracker?: string\n colorHex?: string // Stored hex color (e.g., \"#dcebff\") - robust against palette changes\n sessionId?: string // Claude Code session ID for resume support\n projectPath?: string // Main worktree path (project root) - enables project identification\n issueUrls?: Record<string, string> // Map of issue ID to URL in the issue tracker\n prUrls?: Record<string, string> // Map of PR number to URL in the issue tracker\n draftPrNumber?: number // Draft PR number if github-draft-pr mode was used\n oneShot?: OneShotMode // One-shot automation mode stored during loom creation\n complexity?: ComplexityOverride // Complexity override stored during loom creation\n capabilities?: ProjectCapability[] // Detected project capabilities\n state?: SwarmState // Swarm mode lifecycle state\n childIssueNumbers?: string[] // Child issue numbers for epic looms\n parentLoom?: {\n type: 'issue' | 'pr' | 'branch' | 'epic'\n identifier: string | number\n branchName: string\n worktreePath: string\n databaseBranch?: string\n }\n // Epic/swarm child issue data (populated during spin setup)\n childIssues?: Array<{\n number: string // Prefixed: \"#123\" for GitHub, \"ENG-123\" for Linear\n title: string\n body: string\n url: string\n }>\n dependencyMap?: Record<string, string[]> // issueNumber -> array of blocking issueNumbers\n mcpConfigPath?: string // Path to per-loom MCP config file (for swarm claude -p commands)\n}\n\n/**\n * Input for writing metadata (all fields except version and created_at)\n * Note: issueTracker is required because every loom should have an associated\n * issue tracker provider (defaults to 'github' via IssueTrackerFactory)\n */\nexport interface WriteMetadataInput {\n description: string\n branchName: string\n worktreePath: string\n issueType: 'branch' | 'issue' | 'pr' | 'epic'\n issueKey?: string // Canonical, properly-cased issue key (e.g., \"PROJ-123\")\n issue_numbers: string[]\n pr_numbers: string[]\n issueTracker: string\n colorHex: string // Hex color (e.g., \"#dcebff\") - robust against palette changes\n sessionId: string // Claude Code session ID for resume support (required for new looms)\n projectPath: string // Main worktree path (project root) - required for new looms\n issueUrls: Record<string, string> // Map of issue ID to URL in the issue tracker\n prUrls: Record<string, string> // Map of PR number to URL in the issue tracker\n draftPrNumber?: number // Draft PR number for github-draft-pr mode\n oneShot?: OneShotMode // One-shot automation mode to persist\n complexity?: ComplexityOverride // Complexity override to persist\n capabilities: ProjectCapability[] // Detected project capabilities (required for new looms)\n state?: SwarmState // Swarm mode lifecycle state\n childIssueNumbers?: string[] // Child issue numbers for epic looms\n parentLoom?: {\n type: 'issue' | 'pr' | 'branch' | 'epic'\n identifier: string | number\n branchName: string\n worktreePath: string\n databaseBranch?: string\n }\n // Epic/swarm child issue data (populated during spin setup)\n childIssues?: Array<{\n number: string // Prefixed: \"#123\" for GitHub, \"ENG-123\" for Linear\n title: string\n body: string\n url: string\n }>\n dependencyMap?: Record<string, string[]> // issueNumber -> array of blocking issueNumbers\n mcpConfigPath?: string // Path to per-loom MCP config file (for swarm claude -p commands)\n}\n\n/**\n * Result of reading metadata for a worktree\n */\nexport interface LoomMetadata {\n status?: 'active' | 'finished'\n finishedAt?: string | null\n description: string\n created_at: string | null\n branchName: string | null\n worktreePath: string | null\n issueType: 'branch' | 'issue' | 'pr' | 'epic' | null\n issueKey: string | null // Canonical, properly-cased issue key (e.g., \"PROJ-123\")\n issue_numbers: string[]\n pr_numbers: string[]\n issueTracker: string | null\n colorHex: string | null // Hex color (e.g., \"#dcebff\") - robust against palette changes\n sessionId: string | null // Claude Code session ID (null for legacy looms)\n projectPath: string | null // Main worktree path (null for legacy looms)\n issueUrls: Record<string, string> // Map of issue ID to URL ({} for legacy looms)\n prUrls: Record<string, string> // Map of PR number to URL ({} for legacy looms)\n draftPrNumber: number | null // Draft PR number (null if not draft mode)\n oneShot: OneShotMode | null // One-shot mode (null for legacy looms)\n complexity: ComplexityOverride | null // Complexity override (null when not overridden)\n capabilities: ProjectCapability[] // Detected project capabilities (empty for legacy looms)\n state: SwarmState | null // Swarm mode lifecycle state (null for non-swarm looms)\n childIssueNumbers: string[] // Child issue numbers for epic looms (empty for non-epic looms)\n parentLoom: {\n type: 'issue' | 'pr' | 'branch' | 'epic'\n identifier: string | number\n branchName: string\n worktreePath: string\n databaseBranch?: string\n } | null\n // Epic/swarm child issue data (empty arrays/objects for non-epic looms)\n childIssues: Array<{\n number: string\n title: string\n body: string\n url: string\n }>\n dependencyMap: Record<string, string[]>\n mcpConfigPath: string | null // Path to per-loom MCP config file (null for non-swarm looms)\n}\n\n/**\n * MetadataManager: Manage loom metadata persistence\n *\n * Stores loom metadata in ~/.config/iloom-ai/looms/ directory.\n * Each worktree gets a JSON file named by slugifying its absolute path.\n *\n * Per spec section 2.2:\n * - Filename derived from worktree absolute path\n * - Path separators replaced with double underscores\n * - Non-alphanumeric chars (except _ and -) replaced with hyphens\n */\nexport class MetadataManager {\n private readonly loomsDir: string\n private readonly finishedDir: string\n\n constructor() {\n this.loomsDir = path.join(os.homedir(), '.config', 'iloom-ai', 'looms')\n this.finishedDir = path.join(this.loomsDir, 'finished')\n }\n\n /**\n * Convert MetadataFile to LoomMetadata with default values for optional fields\n */\n private toMetadata(data: MetadataFile): LoomMetadata {\n return {\n description: data.description,\n created_at: data.created_at ?? null,\n branchName: data.branchName ?? null,\n worktreePath: data.worktreePath ?? null,\n issueType: data.issueType ?? null,\n issueKey: data.issueKey ?? null,\n issue_numbers: data.issue_numbers ?? [],\n pr_numbers: data.pr_numbers ?? [],\n issueTracker: data.issueTracker ?? null,\n colorHex: data.colorHex ?? null,\n sessionId: data.sessionId ?? null,\n projectPath: data.projectPath ?? null,\n issueUrls: data.issueUrls ?? {},\n prUrls: data.prUrls ?? {},\n draftPrNumber: data.draftPrNumber ?? null,\n oneShot: data.oneShot ?? null,\n complexity: data.complexity ?? null,\n capabilities: data.capabilities ?? [],\n state: data.state ?? null,\n childIssueNumbers: data.childIssueNumbers ?? [],\n parentLoom: data.parentLoom ?? null,\n childIssues: data.childIssues ?? [],\n dependencyMap: data.dependencyMap ?? {},\n mcpConfigPath: data.mcpConfigPath ?? null,\n }\n }\n\n /**\n * Convert worktree path to filename slug per spec section 2.2\n *\n * Algorithm:\n * 1. Trim trailing slashes\n * 2. Replace all path separators (/ or \\) with __ (double underscore)\n * 3. Replace any other non-alphanumeric characters (except _ and -) with -\n * 4. Append .json\n *\n * Example:\n * - Worktree: /Users/jane/dev/repo\n * - Filename: _Users__jane__dev__repo.json\n */\n slugifyPath(worktreePath: string): string {\n // 1. Trim trailing slashes\n let slug = worktreePath.replace(/[/\\\\]+$/, '')\n\n // 2. Replace path separators with triple underscores\n slug = slug.replace(/[/\\\\]/g, '___')\n\n // 3. Replace non-alphanumeric chars (except _ and -) with hyphens\n slug = slug.replace(/[^a-zA-Z0-9_-]/g, '-')\n\n // 4. Append .json\n return `${slug}.json`\n }\n\n /**\n * Get the full path to the metadata file for a worktree\n */\n private getFilePath(worktreePath: string): string {\n const filename = this.slugifyPath(worktreePath)\n return path.join(this.loomsDir, filename)\n }\n\n /**\n * Get the full path to the metadata file for a worktree (public API)\n * Used by other services that need to reference the metadata file location\n * (e.g., MCP servers that need to read loom context)\n */\n getMetadataFilePath(worktreePath: string): string {\n return this.getFilePath(worktreePath)\n }\n\n /**\n * Write metadata for a worktree (spec section 3.1)\n *\n * @param worktreePath - Absolute path to the worktree (used for file naming)\n * @param input - Metadata to write (description plus additional fields)\n */\n async writeMetadata(worktreePath: string, input: WriteMetadataInput): Promise<void> {\n try {\n // 1. Ensure looms directory exists\n await fs.ensureDir(this.loomsDir, { mode: 0o755 })\n\n // 2. Create JSON content\n const content: MetadataFile = {\n description: input.description,\n created_at: new Date().toISOString(),\n version: 1,\n branchName: input.branchName,\n worktreePath: input.worktreePath,\n issueType: input.issueType,\n ...(input.issueKey && { issueKey: input.issueKey }),\n issue_numbers: input.issue_numbers,\n pr_numbers: input.pr_numbers,\n issueTracker: input.issueTracker,\n colorHex: input.colorHex,\n sessionId: input.sessionId,\n projectPath: input.projectPath,\n issueUrls: input.issueUrls,\n prUrls: input.prUrls,\n capabilities: input.capabilities,\n ...(input.draftPrNumber && { draftPrNumber: input.draftPrNumber }),\n ...(input.oneShot && { oneShot: input.oneShot }),\n ...(input.complexity && { complexity: input.complexity }),\n ...(input.state && { state: input.state }),\n ...(input.childIssueNumbers && input.childIssueNumbers.length > 0 && { childIssueNumbers: input.childIssueNumbers }),\n ...(input.parentLoom && { parentLoom: input.parentLoom }),\n ...(input.childIssues && input.childIssues.length > 0 && { childIssues: input.childIssues }),\n ...(input.dependencyMap && Object.keys(input.dependencyMap).length > 0 && { dependencyMap: input.dependencyMap }),\n ...(input.mcpConfigPath && { mcpConfigPath: input.mcpConfigPath }),\n }\n\n // 3. Write to slugified filename\n const filePath = this.getFilePath(worktreePath)\n await fs.writeFile(filePath, JSON.stringify(content, null, 2), { mode: 0o644 })\n\n getLogger().debug(`Metadata written for worktree: ${worktreePath}`)\n } catch (error) {\n // Log warning but don't throw - metadata is supplementary\n getLogger().warn(\n `Failed to write metadata for worktree: ${error instanceof Error ? error.message : String(error)}`\n )\n }\n }\n\n /**\n * Read metadata for a worktree (spec section 3.2)\n *\n * @param worktreePath - Absolute path to the worktree\n * @returns The metadata object with all fields, or null if not found/invalid\n */\n async readMetadata(worktreePath: string): Promise<LoomMetadata | null> {\n try {\n const filePath = this.getFilePath(worktreePath)\n\n // Check if file exists\n if (!(await fs.pathExists(filePath))) {\n return null\n }\n\n // Read and parse JSON\n const content = await fs.readFile(filePath, 'utf8')\n const data: MetadataFile = JSON.parse(content)\n\n if (!data.description) {\n return null\n }\n\n return this.toMetadata(data)\n } catch (error) {\n // Return null on any error (graceful degradation per spec)\n getLogger().debug(\n `Could not read metadata for worktree ${worktreePath}: ${error instanceof Error ? error.message : String(error)}`\n )\n return null\n }\n }\n\n /**\n * List all stored loom metadata files\n *\n * Returns an array of LoomMetadata objects for all valid metadata files\n * in the looms directory. Invalid or unreadable files are skipped.\n *\n * @returns Array of LoomMetadata objects from all stored files\n */\n async listAllMetadata(): Promise<LoomMetadata[]> {\n const results: LoomMetadata[] = []\n\n try {\n // Check if looms directory exists\n if (!(await fs.pathExists(this.loomsDir))) {\n return results\n }\n\n // Read all files in looms directory\n const files = await fs.readdir(this.loomsDir)\n\n // Filter to only .json files and read each\n for (const file of files) {\n if (!file.endsWith('.json')) {\n continue\n }\n\n try {\n const filePath = path.join(this.loomsDir, file)\n const content = await fs.readFile(filePath, 'utf8')\n const data: MetadataFile = JSON.parse(content)\n\n // Skip files without required description field\n if (!data.description) {\n continue\n }\n\n results.push(this.toMetadata(data))\n } catch (error) {\n // Skip individual files that fail to parse (graceful degradation)\n getLogger().debug(\n `Skipping metadata file ${file}: ${error instanceof Error ? error.message : String(error)}`\n )\n }\n }\n } catch (error) {\n // Log error but return empty array (graceful degradation)\n getLogger().debug(\n `Could not list metadata files: ${error instanceof Error ? error.message : String(error)}`\n )\n }\n\n return results\n }\n\n /**\n * Update existing metadata for a worktree by merging new fields\n *\n * Reads the existing metadata file, merges the provided updates,\n * and writes back. Only provided fields are overwritten.\n *\n * @param worktreePath - Absolute path to the worktree\n * @param updates - Partial metadata fields to merge\n */\n async updateMetadata(worktreePath: string, updates: Partial<MetadataFile>): Promise<void> {\n try {\n const filePath = this.getFilePath(worktreePath)\n\n // Check if file exists\n if (!(await fs.pathExists(filePath))) {\n getLogger().warn(`No metadata file to update for worktree: ${worktreePath}`)\n return\n }\n\n // Read existing data\n const content = await fs.readFile(filePath, 'utf8')\n const data: MetadataFile = JSON.parse(content)\n\n // Merge updates\n const merged = { ...data, ...updates }\n\n // Write back\n await fs.writeFile(filePath, JSON.stringify(merged, null, 2), { mode: 0o644 })\n\n getLogger().debug(`Metadata updated for worktree: ${worktreePath}`)\n } catch (error) {\n getLogger().warn(\n `Failed to update metadata for worktree: ${error instanceof Error ? error.message : String(error)}`\n )\n throw error\n }\n }\n\n /**\n * Delete metadata for a worktree (spec section 3.3)\n *\n * Idempotent: silently succeeds if file doesn't exist\n * Non-fatal: logs warning on permission errors but doesn't throw\n *\n * @param worktreePath - Absolute path to the worktree\n */\n async deleteMetadata(worktreePath: string): Promise<void> {\n try {\n const filePath = this.getFilePath(worktreePath)\n\n // Check if file exists - silently return if not\n if (!(await fs.pathExists(filePath))) {\n getLogger().debug(`No metadata file to delete for worktree: ${worktreePath}`)\n return\n }\n\n // Delete the file\n await fs.unlink(filePath)\n getLogger().debug(`Metadata deleted for worktree: ${worktreePath}`)\n } catch (error) {\n // Log warning on permission error but don't throw (per spec section 3.3)\n getLogger().warn(\n `Failed to delete metadata for worktree: ${error instanceof Error ? error.message : String(error)}`\n )\n }\n }\n\n /**\n * Archive metadata for a finished worktree\n *\n * Moves the metadata file to the finished/ subdirectory and adds\n * status: 'finished' and finishedAt timestamp fields.\n *\n * Idempotent: silently succeeds if source file doesn't exist\n * Non-fatal: logs warning on errors but doesn't throw\n *\n * @param worktreePath - Absolute path to the worktree\n */\n async archiveMetadata(worktreePath: string): Promise<void> {\n try {\n const filename = this.slugifyPath(worktreePath)\n const sourcePath = path.join(this.loomsDir, filename)\n\n // Check if source file exists - silently return if not (idempotent)\n if (!(await fs.pathExists(sourcePath))) {\n getLogger().debug(`No metadata file to archive for worktree: ${worktreePath}`)\n return\n }\n\n // Read existing metadata\n const content = await fs.readFile(sourcePath, 'utf8')\n const data: MetadataFile = JSON.parse(content)\n\n // Add finished status and timestamp\n const finishedData = {\n ...data,\n status: 'finished' as const,\n finishedAt: new Date().toISOString(),\n }\n\n // Ensure finished directory exists\n await fs.ensureDir(this.finishedDir, { mode: 0o755 })\n\n // Write to finished subdirectory\n const destPath = path.join(this.finishedDir, filename)\n await fs.writeFile(destPath, JSON.stringify(finishedData, null, 2), { mode: 0o644 })\n\n // Delete original file\n await fs.unlink(sourcePath)\n\n getLogger().debug(`Metadata archived for worktree: ${worktreePath}`)\n } catch (error) {\n // Log warning but don't throw - archiving is supplementary\n getLogger().warn(\n `Failed to archive metadata for worktree: ${error instanceof Error ? error.message : String(error)}`\n )\n }\n }\n\n /**\n * List all finished loom metadata files\n *\n * Returns an array of LoomMetadata objects for all finished looms\n * in the finished/ subdirectory, sorted by finishedAt in descending order\n * (most recently finished first).\n *\n * @returns Array of LoomMetadata objects from finished files, sorted by finishedAt desc\n */\n async listFinishedMetadata(): Promise<LoomMetadata[]> {\n const results: LoomMetadata[] = []\n\n try {\n // Check if finished directory exists\n if (!(await fs.pathExists(this.finishedDir))) {\n return results\n }\n\n // Read all files in finished directory\n const files = await fs.readdir(this.finishedDir)\n\n // Filter to only .json files and read each\n for (const file of files) {\n if (!file.endsWith('.json')) {\n continue\n }\n\n try {\n const filePath = path.join(this.finishedDir, file)\n const content = await fs.readFile(filePath, 'utf8')\n const data = JSON.parse(content) as MetadataFile & { status?: string; finishedAt?: string }\n\n // Skip files without required description field\n if (!data.description) {\n continue\n }\n\n const metadata = this.toMetadata(data)\n // Add finished-specific fields\n metadata.status = (data.status as 'active' | 'finished') ?? 'finished'\n metadata.finishedAt = data.finishedAt ?? null\n\n results.push(metadata)\n } catch (error) {\n // Skip individual files that fail to parse (graceful degradation)\n getLogger().warn(\n `Skipping finished metadata file ${file}: ${error instanceof Error ? error.message : String(error)}`\n )\n }\n }\n\n // Sort by finishedAt descending (most recently finished first)\n results.sort((a, b) => {\n const aTime = a.finishedAt ? new Date(a.finishedAt).getTime() : 0\n const bTime = b.finishedAt ? new Date(b.finishedAt).getTime() : 0\n return bTime - aTime\n })\n } catch (error) {\n // Log error but return empty array (graceful degradation)\n getLogger().warn(\n `Could not list finished metadata files: ${error instanceof Error ? error.message : String(error)}`\n )\n }\n\n return results\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
logger
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-H2SSF24U.js";
|
|
5
5
|
|
|
6
6
|
// src/utils/logger-context.ts
|
|
7
7
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -17,4 +17,4 @@ export {
|
|
|
17
17
|
getLogger,
|
|
18
18
|
withLogger
|
|
19
19
|
};
|
|
20
|
-
//# sourceMappingURL=chunk-
|
|
20
|
+
//# sourceMappingURL=chunk-ZAXRQLK3.js.map
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
getClaudeVersion,
|
|
8
8
|
launchClaude,
|
|
9
9
|
launchClaudeInNewTerminalWindow
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-Y3RX7LZT.js";
|
|
11
|
+
import "./chunk-ZAXRQLK3.js";
|
|
12
|
+
import "./chunk-H2SSF24U.js";
|
|
13
13
|
export {
|
|
14
14
|
detectClaudeCli,
|
|
15
15
|
generateBranchName,
|
|
@@ -19,4 +19,4 @@ export {
|
|
|
19
19
|
launchClaude,
|
|
20
20
|
launchClaudeInNewTerminalWindow
|
|
21
21
|
};
|
|
22
|
-
//# sourceMappingURL=claude-
|
|
22
|
+
//# sourceMappingURL=claude-ONQTDWV3.js.map
|
|
@@ -1,58 +1,59 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ResourceCleanup
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-7FIXNAUO.js";
|
|
5
|
+
import "./chunk-XXFSOVL3.js";
|
|
6
6
|
import {
|
|
7
7
|
CLIIsolationManager,
|
|
8
8
|
DatabaseManager,
|
|
9
9
|
EnvironmentManager,
|
|
10
10
|
LoomManager
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-XFQGI2E3.js";
|
|
12
|
+
import "./chunk-ABVMUNCD.js";
|
|
13
|
+
import "./chunk-NOMQ5RFG.js";
|
|
14
|
+
import "./chunk-RMLADZRY.js";
|
|
14
15
|
import "./chunk-4232AHNQ.js";
|
|
15
16
|
import {
|
|
16
17
|
ProcessManager
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-LLHXQS3C.js";
|
|
19
|
-
import "./chunk-WWKOVDWC.js";
|
|
18
|
+
} from "./chunk-5PNZBH6V.js";
|
|
20
19
|
import {
|
|
21
20
|
IdentifierParser
|
|
22
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-UDCI3QTS.js";
|
|
22
|
+
import "./chunk-YETJNRQM.js";
|
|
23
|
+
import "./chunk-HLDY5S4C.js";
|
|
24
|
+
import "./chunk-3GTUXW26.js";
|
|
25
|
+
import "./chunk-NCPZYQ4B.js";
|
|
23
26
|
import {
|
|
24
27
|
createNeonProviderFromSettings
|
|
25
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-VMZG66UV.js";
|
|
26
29
|
import {
|
|
27
30
|
TelemetryService
|
|
28
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-GMDSYLI6.js";
|
|
29
32
|
import {
|
|
30
33
|
GitWorktreeManager
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import "./chunk-
|
|
33
|
-
import "./chunk-
|
|
34
|
-
import "./chunk-
|
|
35
|
-
import
|
|
36
|
-
|
|
34
|
+
} from "./chunk-LE2NOUTN.js";
|
|
35
|
+
import "./chunk-5LTID2AF.js";
|
|
36
|
+
import "./chunk-LHDD4JHC.js";
|
|
37
|
+
import "./chunk-NH3QZYE5.js";
|
|
38
|
+
import {
|
|
39
|
+
promptConfirmation
|
|
40
|
+
} from "./chunk-CV47VCMQ.js";
|
|
41
|
+
import "./chunk-7OCGBJLR.js";
|
|
42
|
+
import "./chunk-QVAA5KHK.js";
|
|
43
|
+
import "./chunk-Y3RX7LZT.js";
|
|
44
|
+
import "./chunk-3RXYOBME.js";
|
|
37
45
|
import {
|
|
38
46
|
SettingsManager
|
|
39
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-ET6A2JR4.js";
|
|
40
48
|
import {
|
|
41
49
|
MetadataManager
|
|
42
|
-
} from "./chunk-
|
|
43
|
-
import "./chunk-HEXKPKCK.js";
|
|
44
|
-
import "./chunk-KXDRI47U.js";
|
|
45
|
-
import "./chunk-VG45TUYK.js";
|
|
50
|
+
} from "./chunk-YRCEOQPX.js";
|
|
46
51
|
import {
|
|
47
52
|
getLogger
|
|
48
|
-
} from "./chunk-
|
|
49
|
-
import {
|
|
50
|
-
promptConfirmation
|
|
51
|
-
} from "./chunk-7JDMYTFZ.js";
|
|
52
|
-
import "./chunk-433MOLAU.js";
|
|
53
|
+
} from "./chunk-ZAXRQLK3.js";
|
|
53
54
|
import {
|
|
54
55
|
loadEnvIntoProcess
|
|
55
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-H2SSF24U.js";
|
|
56
57
|
|
|
57
58
|
// src/commands/cleanup.ts
|
|
58
59
|
function trackLoomAbandoned(metadata) {
|
|
@@ -103,10 +104,10 @@ var CleanupCommand = class {
|
|
|
103
104
|
cliIsolationManager
|
|
104
105
|
);
|
|
105
106
|
if (!this.loomManager) {
|
|
106
|
-
const { IssueTrackerFactory } = await import("./IssueTrackerFactory-
|
|
107
|
-
const { ClaudeContextManager } = await import("./ClaudeContextManager-
|
|
108
|
-
const { ProjectCapabilityDetector } = await import("./ProjectCapabilityDetector-
|
|
109
|
-
const { DefaultBranchNamingService } = await import("./BranchNamingService-
|
|
107
|
+
const { IssueTrackerFactory } = await import("./IssueTrackerFactory-XN6MQ4UN.js");
|
|
108
|
+
const { ClaudeContextManager } = await import("./ClaudeContextManager-SXDCWDJA.js");
|
|
109
|
+
const { ProjectCapabilityDetector } = await import("./ProjectCapabilityDetector-IC6NAFGY.js");
|
|
110
|
+
const { DefaultBranchNamingService } = await import("./BranchNamingService-XBCO747L.js");
|
|
110
111
|
this.loomManager = new LoomManager(
|
|
111
112
|
this.gitWorktreeManager,
|
|
112
113
|
IssueTrackerFactory.create(settings),
|
|
@@ -310,7 +311,7 @@ var CleanupCommand = class {
|
|
|
310
311
|
const { force, dryRun } = parsed.options;
|
|
311
312
|
let parsedInput = await this.identifierParser.parseForPatternDetection(identifier);
|
|
312
313
|
if (parsedInput.type === "branch" && parsedInput.branchName) {
|
|
313
|
-
const { extractIssueNumber } = await import("./git-
|
|
314
|
+
const { extractIssueNumber } = await import("./git-BXUD6CL5.js");
|
|
314
315
|
const extractedNumber = extractIssueNumber(parsedInput.branchName);
|
|
315
316
|
if (extractedNumber !== null) {
|
|
316
317
|
parsedInput = {
|
|
@@ -540,4 +541,4 @@ var CleanupCommand = class {
|
|
|
540
541
|
export {
|
|
541
542
|
CleanupCommand
|
|
542
543
|
};
|
|
543
|
-
//# sourceMappingURL=cleanup-
|
|
544
|
+
//# sourceMappingURL=cleanup-YOM6PQCN.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/cleanup.ts"],"sourcesContent":["import { getLogger } from '../utils/logger-context.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { ResourceCleanup } from '../lib/ResourceCleanup.js'\nimport { ProcessManager } from '../lib/process/ProcessManager.js'\nimport { DatabaseManager } from '../lib/DatabaseManager.js'\nimport { EnvironmentManager } from '../lib/EnvironmentManager.js'\nimport { CLIIsolationManager } from '../lib/CLIIsolationManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { promptConfirmation } from '../utils/prompt.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport { createNeonProviderFromSettings } from '../utils/neon-helpers.js'\nimport { LoomManager } from '../lib/LoomManager.js'\nimport { TelemetryService } from '../lib/TelemetryService.js'\nimport { MetadataManager } from '../lib/MetadataManager.js'\nimport type { LoomMetadata } from '../lib/MetadataManager.js'\n\nfunction trackLoomAbandoned(metadata: LoomMetadata): void {\n\ttry {\n\t\tconst durationMinutes = metadata.created_at\n\t\t\t? Math.round((Date.now() - new Date(metadata.created_at).getTime()) / 60000)\n\t\t\t: 0\n\t\tTelemetryService.getInstance().track('loom.abandoned', {\n\t\t\tduration_minutes: isNaN(durationMinutes) ? 0 : durationMinutes,\n\t\t\tphase_reached: metadata.state ?? 'unknown',\n\t\t})\n\t} catch (error: unknown) {\n\t\tgetLogger().debug(`Failed to track loom.abandoned telemetry: ${error instanceof Error ? error.message : String(error)}`)\n\t}\n}\nimport type { CleanupOptions } from '../types/index.js'\nimport type { CleanupResult } from '../types/cleanup.js'\nimport type { ParsedInput } from './start.js'\n\n/**\n * Input structure for CleanupCommand.execute()\n */\nexport interface CleanupCommandInput {\n identifier?: string\n options: CleanupOptions\n}\n\n/**\n * Parsed and validated cleanup command input\n * Mode determines which cleanup operation to perform\n */\nexport interface ParsedCleanupInput {\n mode: 'list' | 'single' | 'issue' | 'all'\n identifier?: string\n issueNumber?: string | number\n branchName?: string\n originalInput?: string\n options: CleanupOptions\n}\n\n/**\n * Manages cleanup command execution with option parsing and validation\n * Follows the command pattern established by StartCommand\n *\n * This implementation handles ONLY parsing, validation, and mode determination.\n * Actual cleanup operations are deferred to subsequent sub-issues.\n */\nexport class CleanupCommand {\n private readonly gitWorktreeManager: GitWorktreeManager\n private resourceCleanup?: ResourceCleanup\n private loomManager?: import('../lib/LoomManager.js').LoomManager\n private readonly identifierParser: IdentifierParser\n\n constructor(\n gitWorktreeManager?: GitWorktreeManager,\n resourceCleanup?: ResourceCleanup\n ) {\n // Load environment variables first\n const envResult = loadEnvIntoProcess()\n if (envResult.error) {\n getLogger().debug(`Environment loading warning: ${envResult.error.message}`)\n }\n if (envResult.parsed) {\n getLogger().debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`)\n }\n\n this.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager()\n\n // Initialize ResourceCleanup with DatabaseManager and CLIIsolationManager\n // ResourceCleanup will be initialized lazily with proper configuration\n if (resourceCleanup) {\n this.resourceCleanup = resourceCleanup\n }\n\n // Initialize IdentifierParser for pattern-based detection\n this.identifierParser = new IdentifierParser(this.gitWorktreeManager)\n }\n\n /**\n * Lazy initialization of ResourceCleanup and LoomManager with properly configured DatabaseManager\n */\n private async ensureResourceCleanup(): Promise<void> {\n if (this.resourceCleanup && this.loomManager) {\n return\n }\n\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const databaseUrlEnvVarName = settings.capabilities?.database?.databaseUrlEnvVarName ?? 'DATABASE_URL'\n\n const environmentManager = new EnvironmentManager()\n const neonProvider = createNeonProviderFromSettings(settings)\n const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName)\n const cliIsolationManager = new CLIIsolationManager()\n\n this.resourceCleanup ??= new ResourceCleanup(\n this.gitWorktreeManager,\n new ProcessManager(),\n databaseManager,\n cliIsolationManager\n )\n\n // Initialize LoomManager if not provided (for child loom detection)\n if (!this.loomManager) {\n const { IssueTrackerFactory } = await import('../lib/IssueTrackerFactory.js')\n const { ClaudeContextManager } = await import('../lib/ClaudeContextManager.js')\n const { ProjectCapabilityDetector } = await import('../lib/ProjectCapabilityDetector.js')\n const { DefaultBranchNamingService } = await import('../lib/BranchNamingService.js')\n\n this.loomManager = new LoomManager(\n this.gitWorktreeManager,\n IssueTrackerFactory.create(settings),\n new DefaultBranchNamingService({ useClaude: true }),\n environmentManager,\n new ClaudeContextManager(),\n new ProjectCapabilityDetector(),\n cliIsolationManager,\n settingsManager,\n databaseManager\n )\n }\n }\n\n /**\n * Check for child looms and exit gracefully if any exist\n * Always checks the TARGET loom (the one being cleaned up), not the current directory's loom\n *\n * @param parsed - The parsed input identifying the loom being cleaned up\n */\n private async checkForChildLooms(parsed: ParsedCleanupInput): Promise<void> {\n await this.ensureResourceCleanup()\n if (!this.loomManager) {\n throw new Error('Failed to initialize LoomManager')\n }\n\n // Determine which branch is being cleaned up based on parsed input\n let targetBranch: string | undefined\n\n if (parsed.branchName) {\n targetBranch = parsed.branchName\n } else if (parsed.mode === 'issue' && parsed.issueNumber !== undefined) {\n // For issues, try to find the worktree by issue number to get the branch name\n const worktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.issueNumber)\n targetBranch = worktree?.branch\n }\n\n // If we can't determine the target branch, skip the check\n if (!targetBranch) {\n getLogger().debug(`Cannot determine target branch for child loom check`)\n return\n }\n\n // Check if the TARGET loom has any child looms\n const hasChildLooms = await this.loomManager.checkAndWarnChildLooms(targetBranch)\n if (hasChildLooms) {\n throw new Error('Cannot cleanup loom while child looms exist. Please \\'finish\\' or \\'cleanup\\' child looms first.')\n }\n }\n\n /**\n * Main entry point for the cleanup command\n * Parses input, validates options, and determines operation mode\n */\n public async execute(input: CleanupCommandInput): Promise<CleanupResult | void> {\n // Step 1: Parse input and determine mode\n const parsed = this.parseInput(input)\n\n // Step 2: Validate option combinations (fail fast before any delay)\n this.validateInput(parsed)\n\n // Note: JSON mode auto-skips routine confirmations (programmatic use can't interact)\n // Safety checks still require --force to bypass (ResourceCleanup.validateWorktreeSafety throws errors)\n\n // Step 3: Check for child looms AFTER parsing input\n // This ensures we only block when cleaning the CURRENT loom (parent), not a child\n await this.checkForChildLooms(parsed)\n\n // Step 4: Handle deferred execution (after all validation passes)\n if (input.options.defer) {\n getLogger().info(`Waiting ${input.options.defer}ms before cleanup...`)\n await new Promise(resolve => globalThis.setTimeout(resolve, input.options.defer))\n }\n\n // Step 5: Execute based on mode\n getLogger().info(`Cleanup mode: ${parsed.mode}`)\n\n if (parsed.mode === 'single') {\n return await this.executeSingleCleanup(parsed)\n } else if (parsed.mode === 'list') {\n getLogger().info('Would list all worktrees') // TODO: Implement in Sub-issue #2\n getLogger().success('Command parsing and validation successful')\n return {\n identifier: 'list',\n success: true,\n dryRun: parsed.options.dryRun ?? false,\n operations: [],\n errors: [],\n rollbackRequired: false,\n }\n } else if (parsed.mode === 'all') {\n getLogger().info('Would remove all worktrees') // TODO: Implement in Sub-issue #5\n getLogger().success('Command parsing and validation successful')\n return {\n identifier: 'all',\n success: true,\n dryRun: parsed.options.dryRun ?? false,\n operations: [],\n errors: [],\n rollbackRequired: false,\n }\n } else if (parsed.mode === 'issue') {\n return await this.executeIssueCleanup(parsed)\n }\n }\n\n /**\n * Parse input to determine cleanup mode and extract relevant data\n * Implements auto-detection: numeric input = issue number, non-numeric = branch name\n *\n * @private\n */\n private parseInput(input: CleanupCommandInput): ParsedCleanupInput {\n const { identifier, options } = input\n\n // Trim identifier if present\n const trimmedIdentifier = identifier?.trim() ?? undefined\n\n // Mode: List (takes priority - it's informational only)\n if (options.list) {\n const result: ParsedCleanupInput = {\n mode: 'list',\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n return result\n }\n\n // Mode: All (remove everything)\n if (options.all) {\n const result: ParsedCleanupInput = {\n mode: 'all',\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n if (options.issue !== undefined) {\n result.issueNumber = options.issue\n }\n return result\n }\n\n // Mode: Explicit issue number via --issue flag\n if (options.issue !== undefined) {\n // Need to determine if identifier is branch or numeric to set branchName\n if (trimmedIdentifier) {\n const numericPattern = /^[0-9]+$/\n if (!numericPattern.test(trimmedIdentifier)) {\n // Identifier is a branch name with explicit --issue flag\n return {\n mode: 'issue',\n issueNumber: options.issue,\n branchName: trimmedIdentifier,\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n }\n }\n const result: ParsedCleanupInput = {\n mode: 'issue',\n issueNumber: options.issue,\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n return result\n }\n\n // Mode: Auto-detect from identifier\n if (!trimmedIdentifier) {\n throw new Error('Missing required argument: identifier. Use --all to remove all worktrees or --list to list them.')\n }\n\n // Auto-detection: Check if identifier is purely numeric\n // Pattern from bash script line 364: ^[0-9]+$\n const numericPattern = /^[0-9]+$/\n if (numericPattern.test(trimmedIdentifier)) {\n // Numeric input = issue number\n return {\n mode: 'issue',\n issueNumber: parseInt(trimmedIdentifier, 10),\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n } else {\n // Non-numeric = branch name\n return {\n mode: 'single',\n branchName: trimmedIdentifier,\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n }\n }\n\n /**\n * Validate parsed input for option conflicts\n * Throws descriptive errors for invalid option combinations\n *\n * @private\n */\n private validateInput(parsed: ParsedCleanupInput): void {\n const { mode, options, branchName } = parsed\n\n // Conflict: --list is informational only, incompatible with destructive operations\n if (mode === 'list') {\n if (options.all) {\n throw new Error('Cannot use --list with --all (list is informational only)')\n }\n if (options.issue !== undefined) {\n throw new Error('Cannot use --list with --issue (list is informational only)')\n }\n if (parsed.identifier) {\n throw new Error('Cannot use --list with a specific identifier (list shows all worktrees)')\n }\n }\n\n // Conflict: --all removes everything, can't combine with specific identifier or --issue\n if (mode === 'all') {\n if (parsed.identifier) {\n throw new Error('Cannot use --all with a specific identifier. Use one or the other.')\n }\n if (parsed.issueNumber !== undefined) {\n throw new Error('Cannot use --all with a specific identifier. Use one or the other.')\n }\n }\n\n // Conflict: explicit --issue flag with branch name identifier\n // (This prevents confusion when user provides both)\n if (options.issue !== undefined && branchName) {\n throw new Error('Cannot use --issue flag with branch name identifier. Use numeric identifier or --issue flag alone.')\n }\n\n // Note: --force and --dry-run are compatible with all modes (no conflicts)\n }\n\n /**\n * Execute cleanup for single worktree\n * Implements two-stage confirmation: worktree removal, then branch deletion\n * Uses IdentifierParser for pattern-based detection without GitHub API calls\n */\n private async executeSingleCleanup(parsed: ParsedCleanupInput): Promise<CleanupResult> {\n const identifier = parsed.branchName ?? parsed.identifier ?? ''\n if (!identifier) {\n throw new Error('No identifier found for cleanup')\n }\n const { force, dryRun } = parsed.options\n\n // Step 1: Parse identifier using pattern-based detection\n let parsedInput: ParsedInput = await this.identifierParser.parseForPatternDetection(identifier)\n\n // If type is 'branch', try to extract issue number for CLI symlink cleanup\n if (parsedInput.type === 'branch' && parsedInput.branchName) {\n const { extractIssueNumber } = await import('../utils/git.js')\n const extractedNumber = extractIssueNumber(parsedInput.branchName)\n if (extractedNumber !== null) {\n parsedInput = {\n ...parsedInput,\n number: extractedNumber // Add number for CLI symlink cleanup\n }\n }\n }\n\n // Step 2: Display worktree details\n getLogger().info(`Preparing to cleanup worktree: ${identifier}`)\n\n // Step 3: Routine confirmation - worktree removal\n // Skip if --force (user explicitly bypasses) or --json (programmatic use can't interact)\n // Note: Safety checks (uncommitted changes, unmerged work) still require --force to bypass\n if (!force && !parsed.options.json) {\n const confirmWorktree = await promptConfirmation('Remove this worktree?', true)\n if (!confirmWorktree) {\n getLogger().info('Cleanup cancelled')\n return {\n identifier,\n success: false,\n dryRun: dryRun ?? false,\n operations: [],\n errors: [],\n rollbackRequired: false,\n }\n }\n }\n\n // Step 3.5: Read metadata BEFORE cleanup (cleanup deletes the worktree)\n let preCleanupMetadata: LoomMetadata | null = null\n try {\n // Find worktree path for metadata lookup\n const worktree = parsedInput.type === 'branch' && parsedInput.branchName\n ? await this.gitWorktreeManager.findWorktreeForBranch(parsedInput.branchName)\n : parsedInput.number !== undefined\n ? await this.gitWorktreeManager.findWorktreeForIssue(parsedInput.number)\n : null\n if (worktree) {\n const metadataManager = new MetadataManager()\n preCleanupMetadata = await metadataManager.readMetadata(worktree.path)\n }\n } catch (error: unknown) {\n getLogger().debug(`Failed to read metadata for telemetry: ${error instanceof Error ? error.message : String(error)}`)\n }\n\n // Step 4: Execute worktree cleanup (includes safety validation)\n // Issue #275 fix: Run 5-point safety check BEFORE any deletion\n // This prevents the scenario where worktree is deleted but branch deletion fails\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n const cleanupResult = await this.resourceCleanup.cleanupWorktree(parsedInput, {\n dryRun: dryRun ?? false,\n force: force ?? false,\n deleteBranch: true, // Always include branch deletion (safety checks run first)\n keepDatabase: false,\n checkMergeSafety: true, // Run 5-point safety check BEFORE any deletion\n archive: parsed.options.archive ?? false,\n })\n\n // Add dryRun flag to result\n cleanupResult.dryRun = dryRun ?? false\n\n // Step 5: Report cleanup results\n this.reportCleanupResults(cleanupResult)\n\n // Track loom.abandoned telemetry event (only for unfinished looms)\n if (cleanupResult.success && preCleanupMetadata && preCleanupMetadata.status !== 'finished') {\n trackLoomAbandoned(preCleanupMetadata)\n }\n\n // Final success message\n if (cleanupResult.success) {\n getLogger().success('Cleanup completed successfully')\n } else {\n getLogger().warn('Cleanup completed with errors - see details above')\n }\n\n return cleanupResult\n }\n\n /**\n * Report cleanup operation results to user\n */\n private reportCleanupResults(result: CleanupResult): void {\n getLogger().info('Cleanup operations:')\n\n result.operations.forEach(op => {\n const status = op.success ? '✓' : '✗'\n const message = op.error ? `${op.message}: ${op.error}` : op.message\n\n if (op.success) {\n getLogger().info(` ${status} ${message}`)\n } else {\n getLogger().error(` ${status} ${message}`)\n }\n })\n\n if (result.errors.length > 0) {\n getLogger().warn(`${result.errors.length} error(s) occurred during cleanup`)\n }\n }\n\n /**\n * Execute cleanup for all worktrees associated with an issue or PR number\n * Searches for worktrees by their path patterns (e.g., issue-25, pr-25, 25-feature, _pr_25)\n * Implements bash cleanup-worktree.sh remove_worktrees_by_issue() (lines 157-242)\n */\n private async executeIssueCleanup(parsed: ParsedCleanupInput): Promise<CleanupResult> {\n const issueNumber = parsed.issueNumber\n if (issueNumber === undefined) {\n throw new Error('No issue/PR number provided for cleanup')\n }\n\n const { force, dryRun } = parsed.options\n\n getLogger().info(`Finding worktrees related to issue/PR #${issueNumber}...`)\n\n // Step 1: Get all worktrees and filter by path pattern\n const worktrees = await this.gitWorktreeManager.listWorktrees()\n const matchingWorktrees = worktrees.filter(wt => {\n const path = wt.path.toLowerCase()\n // Lowercase for case-insensitive matching (Linear IDs are uppercase like MARK-1)\n const idStr = String(issueNumber).toLowerCase()\n\n // Check if path contains the identifier with proper word boundaries\n // Matches: issue-25, pr-25, 25-feature, _pr_25, issue-mark-1, etc.\n // Uses word boundary or common separators (-, _, /) for alphanumeric IDs\n const pattern = new RegExp(`(?:^|[/_-])${idStr}(?:[/_-]|$)`)\n return pattern.test(path)\n })\n\n if (matchingWorktrees.length === 0) {\n getLogger().warn(`No worktrees found for issue/PR #${issueNumber}`)\n getLogger().info(`Searched for worktree paths containing: ${issueNumber}, _pr_${issueNumber}, issue-${issueNumber}, etc.`)\n return {\n identifier: String(issueNumber),\n success: true,\n dryRun: dryRun ?? false,\n operations: [],\n errors: [],\n rollbackRequired: false,\n }\n }\n\n // Step 2: Build targets list from matching worktrees\n const targets: Array<{ branchName: string; hasWorktree: boolean; worktreePath?: string }> =\n matchingWorktrees.map(wt => ({\n branchName: wt.branch,\n hasWorktree: true,\n worktreePath: wt.path\n }))\n\n // Step 3: Display preview\n getLogger().info(`Found ${targets.length} worktree(s) related to issue/PR #${issueNumber}:`)\n for (const target of targets) {\n getLogger().info(` Branch: ${target.branchName} (${target.worktreePath})`)\n }\n\n // Step 4: Routine batch confirmation\n // Skip if --force (user explicitly bypasses) or --json (programmatic use can't interact)\n // Note: Safety checks per-worktree (uncommitted changes, unmerged work) still require --force to bypass\n if (!force && !parsed.options.json) {\n const confirmCleanup = await promptConfirmation(\n `Remove ${targets.length} worktree(s)?`,\n true\n )\n if (!confirmCleanup) {\n getLogger().info('Cleanup cancelled')\n return {\n identifier: String(issueNumber),\n success: false,\n dryRun: dryRun ?? false,\n operations: [],\n errors: [],\n rollbackRequired: false,\n }\n }\n }\n\n // Step 5: Process each target sequentially\n let worktreesRemoved = 0\n let branchesDeleted = 0\n const databaseBranchesDeletedList: string[] = []\n let failed = 0\n\n for (const target of targets) {\n getLogger().info(`Processing worktree: ${target.branchName}`)\n\n // Cleanup worktree using ResourceCleanup with ParsedInput\n // Now includes branch deletion with 5-point safety check BEFORE any deletion\n try {\n // Read metadata BEFORE cleanup for telemetry\n let targetMetadata: LoomMetadata | null = null\n if (target.worktreePath) {\n try {\n const metadataManager = new MetadataManager()\n targetMetadata = await metadataManager.readMetadata(target.worktreePath)\n } catch (error: unknown) {\n getLogger().debug(`Failed to read metadata for telemetry: ${error instanceof Error ? error.message : String(error)}`)\n }\n }\n\n // Use the known issue number directly instead of parsing from branch name\n // This ensures CLI symlinks (created with issue number) are properly cleaned up\n const parsedInput: ParsedInput = {\n type: 'issue',\n number: issueNumber, // Use the known issue number, not parsed from branch\n branchName: target.branchName,\n originalInput: String(issueNumber)\n }\n\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n // Issue #275 fix: Run safety checks BEFORE deleting worktree\n // This prevents the scenario where worktree is deleted but branch deletion fails\n const result = await this.resourceCleanup.cleanupWorktree(parsedInput, {\n dryRun: dryRun ?? false,\n force: force ?? false,\n deleteBranch: true, // Include branch deletion (with safety checks)\n keepDatabase: false,\n checkMergeSafety: true, // Run 5-point safety check BEFORE any deletion\n archive: parsed.options.archive ?? false,\n ...(target.worktreePath && { worktree: { path: target.worktreePath, branch: target.branchName } }),\n })\n\n if (result.success) {\n worktreesRemoved++\n getLogger().success(` Worktree removed: ${target.branchName}`)\n\n // Check if branch was deleted\n const branchOperation = result.operations.find(op => op.type === 'branch')\n if (branchOperation?.success) {\n branchesDeleted++\n getLogger().success(` Branch deleted: ${target.branchName}`)\n }\n\n // Check if database branch was actually deleted (use explicit deleted field)\n const dbOperation = result.operations.find(op => op.type === 'database')\n if (dbOperation?.deleted) {\n // Get branch name from result or use the target branch name\n const deletedBranchName = target.branchName\n databaseBranchesDeletedList.push(deletedBranchName)\n }\n\n // Track loom.abandoned telemetry (only for unfinished looms)\n if (targetMetadata && targetMetadata.status !== 'finished') {\n trackLoomAbandoned(targetMetadata)\n }\n } else {\n failed++\n getLogger().error(` Failed to remove worktree: ${target.branchName}`)\n for (const err of result.errors) {\n getLogger().error(` ${err.message}`)\n }\n }\n } catch (error) {\n failed++\n const errMsg = error instanceof Error ? error.message : 'Unknown error'\n getLogger().error(` Failed to cleanup: ${errMsg}`)\n continue // Continue with next worktree even if this one failed\n }\n }\n\n // Step 7: Report statistics\n getLogger().success(`Completed cleanup for issue/PR #${issueNumber}:`)\n getLogger().info(` Worktrees removed: ${worktreesRemoved}`)\n getLogger().info(` Branches deleted: ${branchesDeleted}`)\n if (databaseBranchesDeletedList.length > 0) {\n // Display branch names in the format requested\n getLogger().info(` Database branches deleted: ${databaseBranchesDeletedList.join(', ')}`)\n }\n if (failed > 0) {\n getLogger().warn(` Failed operations: ${failed}`)\n }\n\n // Return aggregated result\n return {\n identifier: String(issueNumber),\n success: failed === 0,\n dryRun: dryRun ?? false,\n operations: [\n { type: 'worktree' as const, success: true, message: `Removed ${worktreesRemoved} worktree(s)` },\n { type: 'branch' as const, success: true, message: `Deleted ${branchesDeleted} branch(es)` },\n ...(databaseBranchesDeletedList.length > 0 ? [{ type: 'database' as const, success: true, message: `Deleted ${databaseBranchesDeletedList.length} database branch(es)`, deleted: true }] : []),\n ],\n errors: [],\n rollbackRequired: false,\n }\n }\n}\n"],"mappings":"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","names":["numericPattern"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/cleanup.ts"],"sourcesContent":["import { getLogger } from '../utils/logger-context.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { ResourceCleanup } from '../lib/ResourceCleanup.js'\nimport { ProcessManager } from '../lib/process/ProcessManager.js'\nimport { DatabaseManager } from '../lib/DatabaseManager.js'\nimport { EnvironmentManager } from '../lib/EnvironmentManager.js'\nimport { CLIIsolationManager } from '../lib/CLIIsolationManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { promptConfirmation } from '../utils/prompt.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport { createNeonProviderFromSettings } from '../utils/neon-helpers.js'\nimport { LoomManager } from '../lib/LoomManager.js'\nimport { TelemetryService } from '../lib/TelemetryService.js'\nimport { MetadataManager } from '../lib/MetadataManager.js'\nimport type { LoomMetadata } from '../lib/MetadataManager.js'\n\nfunction trackLoomAbandoned(metadata: LoomMetadata): void {\n\ttry {\n\t\tconst durationMinutes = metadata.created_at\n\t\t\t? Math.round((Date.now() - new Date(metadata.created_at).getTime()) / 60000)\n\t\t\t: 0\n\t\tTelemetryService.getInstance().track('loom.abandoned', {\n\t\t\tduration_minutes: isNaN(durationMinutes) ? 0 : durationMinutes,\n\t\t\tphase_reached: metadata.state ?? 'unknown',\n\t\t})\n\t} catch (error: unknown) {\n\t\tgetLogger().debug(`Failed to track loom.abandoned telemetry: ${error instanceof Error ? error.message : String(error)}`)\n\t}\n}\nimport type { CleanupOptions } from '../types/index.js'\nimport type { CleanupResult } from '../types/cleanup.js'\nimport type { ParsedInput } from './start.js'\n\n/**\n * Input structure for CleanupCommand.execute()\n */\nexport interface CleanupCommandInput {\n identifier?: string\n options: CleanupOptions\n}\n\n/**\n * Parsed and validated cleanup command input\n * Mode determines which cleanup operation to perform\n */\nexport interface ParsedCleanupInput {\n mode: 'list' | 'single' | 'issue' | 'all'\n identifier?: string\n issueNumber?: string | number\n branchName?: string\n originalInput?: string\n options: CleanupOptions\n}\n\n/**\n * Manages cleanup command execution with option parsing and validation\n * Follows the command pattern established by StartCommand\n *\n * This implementation handles ONLY parsing, validation, and mode determination.\n * Actual cleanup operations are deferred to subsequent sub-issues.\n */\nexport class CleanupCommand {\n private readonly gitWorktreeManager: GitWorktreeManager\n private resourceCleanup?: ResourceCleanup\n private loomManager?: import('../lib/LoomManager.js').LoomManager\n private readonly identifierParser: IdentifierParser\n\n constructor(\n gitWorktreeManager?: GitWorktreeManager,\n resourceCleanup?: ResourceCleanup\n ) {\n // Load environment variables first\n const envResult = loadEnvIntoProcess()\n if (envResult.error) {\n getLogger().debug(`Environment loading warning: ${envResult.error.message}`)\n }\n if (envResult.parsed) {\n getLogger().debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`)\n }\n\n this.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager()\n\n // Initialize ResourceCleanup with DatabaseManager and CLIIsolationManager\n // ResourceCleanup will be initialized lazily with proper configuration\n if (resourceCleanup) {\n this.resourceCleanup = resourceCleanup\n }\n\n // Initialize IdentifierParser for pattern-based detection\n this.identifierParser = new IdentifierParser(this.gitWorktreeManager)\n }\n\n /**\n * Lazy initialization of ResourceCleanup and LoomManager with properly configured DatabaseManager\n */\n private async ensureResourceCleanup(): Promise<void> {\n if (this.resourceCleanup && this.loomManager) {\n return\n }\n\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const databaseUrlEnvVarName = settings.capabilities?.database?.databaseUrlEnvVarName ?? 'DATABASE_URL'\n\n const environmentManager = new EnvironmentManager()\n const neonProvider = createNeonProviderFromSettings(settings)\n const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName)\n const cliIsolationManager = new CLIIsolationManager()\n\n this.resourceCleanup ??= new ResourceCleanup(\n this.gitWorktreeManager,\n new ProcessManager(),\n databaseManager,\n cliIsolationManager\n )\n\n // Initialize LoomManager if not provided (for child loom detection)\n if (!this.loomManager) {\n const { IssueTrackerFactory } = await import('../lib/IssueTrackerFactory.js')\n const { ClaudeContextManager } = await import('../lib/ClaudeContextManager.js')\n const { ProjectCapabilityDetector } = await import('../lib/ProjectCapabilityDetector.js')\n const { DefaultBranchNamingService } = await import('../lib/BranchNamingService.js')\n\n this.loomManager = new LoomManager(\n this.gitWorktreeManager,\n IssueTrackerFactory.create(settings),\n new DefaultBranchNamingService({ useClaude: true }),\n environmentManager,\n new ClaudeContextManager(),\n new ProjectCapabilityDetector(),\n cliIsolationManager,\n settingsManager,\n databaseManager\n )\n }\n }\n\n /**\n * Check for child looms and exit gracefully if any exist\n * Always checks the TARGET loom (the one being cleaned up), not the current directory's loom\n *\n * @param parsed - The parsed input identifying the loom being cleaned up\n */\n private async checkForChildLooms(parsed: ParsedCleanupInput): Promise<void> {\n await this.ensureResourceCleanup()\n if (!this.loomManager) {\n throw new Error('Failed to initialize LoomManager')\n }\n\n // Determine which branch is being cleaned up based on parsed input\n let targetBranch: string | undefined\n\n if (parsed.branchName) {\n targetBranch = parsed.branchName\n } else if (parsed.mode === 'issue' && parsed.issueNumber !== undefined) {\n // For issues, try to find the worktree by issue number to get the branch name\n const worktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.issueNumber)\n targetBranch = worktree?.branch\n }\n\n // If we can't determine the target branch, skip the check\n if (!targetBranch) {\n getLogger().debug(`Cannot determine target branch for child loom check`)\n return\n }\n\n // Check if the TARGET loom has any child looms\n const hasChildLooms = await this.loomManager.checkAndWarnChildLooms(targetBranch)\n if (hasChildLooms) {\n throw new Error('Cannot cleanup loom while child looms exist. Please \\'finish\\' or \\'cleanup\\' child looms first.')\n }\n }\n\n /**\n * Main entry point for the cleanup command\n * Parses input, validates options, and determines operation mode\n */\n public async execute(input: CleanupCommandInput): Promise<CleanupResult | void> {\n // Step 1: Parse input and determine mode\n const parsed = this.parseInput(input)\n\n // Step 2: Validate option combinations (fail fast before any delay)\n this.validateInput(parsed)\n\n // Note: JSON mode auto-skips routine confirmations (programmatic use can't interact)\n // Safety checks still require --force to bypass (ResourceCleanup.validateWorktreeSafety throws errors)\n\n // Step 3: Check for child looms AFTER parsing input\n // This ensures we only block when cleaning the CURRENT loom (parent), not a child\n await this.checkForChildLooms(parsed)\n\n // Step 4: Handle deferred execution (after all validation passes)\n if (input.options.defer) {\n getLogger().info(`Waiting ${input.options.defer}ms before cleanup...`)\n await new Promise(resolve => globalThis.setTimeout(resolve, input.options.defer))\n }\n\n // Step 5: Execute based on mode\n getLogger().info(`Cleanup mode: ${parsed.mode}`)\n\n if (parsed.mode === 'single') {\n return await this.executeSingleCleanup(parsed)\n } else if (parsed.mode === 'list') {\n getLogger().info('Would list all worktrees') // TODO: Implement in Sub-issue #2\n getLogger().success('Command parsing and validation successful')\n return {\n identifier: 'list',\n success: true,\n dryRun: parsed.options.dryRun ?? false,\n operations: [],\n errors: [],\n rollbackRequired: false,\n }\n } else if (parsed.mode === 'all') {\n getLogger().info('Would remove all worktrees') // TODO: Implement in Sub-issue #5\n getLogger().success('Command parsing and validation successful')\n return {\n identifier: 'all',\n success: true,\n dryRun: parsed.options.dryRun ?? false,\n operations: [],\n errors: [],\n rollbackRequired: false,\n }\n } else if (parsed.mode === 'issue') {\n return await this.executeIssueCleanup(parsed)\n }\n }\n\n /**\n * Parse input to determine cleanup mode and extract relevant data\n * Implements auto-detection: numeric input = issue number, non-numeric = branch name\n *\n * @private\n */\n private parseInput(input: CleanupCommandInput): ParsedCleanupInput {\n const { identifier, options } = input\n\n // Trim identifier if present\n const trimmedIdentifier = identifier?.trim() ?? undefined\n\n // Mode: List (takes priority - it's informational only)\n if (options.list) {\n const result: ParsedCleanupInput = {\n mode: 'list',\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n return result\n }\n\n // Mode: All (remove everything)\n if (options.all) {\n const result: ParsedCleanupInput = {\n mode: 'all',\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n if (options.issue !== undefined) {\n result.issueNumber = options.issue\n }\n return result\n }\n\n // Mode: Explicit issue number via --issue flag\n if (options.issue !== undefined) {\n // Need to determine if identifier is branch or numeric to set branchName\n if (trimmedIdentifier) {\n const numericPattern = /^[0-9]+$/\n if (!numericPattern.test(trimmedIdentifier)) {\n // Identifier is a branch name with explicit --issue flag\n return {\n mode: 'issue',\n issueNumber: options.issue,\n branchName: trimmedIdentifier,\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n }\n }\n const result: ParsedCleanupInput = {\n mode: 'issue',\n issueNumber: options.issue,\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n return result\n }\n\n // Mode: Auto-detect from identifier\n if (!trimmedIdentifier) {\n throw new Error('Missing required argument: identifier. Use --all to remove all worktrees or --list to list them.')\n }\n\n // Auto-detection: Check if identifier is purely numeric\n // Pattern from bash script line 364: ^[0-9]+$\n const numericPattern = /^[0-9]+$/\n if (numericPattern.test(trimmedIdentifier)) {\n // Numeric input = issue number\n return {\n mode: 'issue',\n issueNumber: parseInt(trimmedIdentifier, 10),\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n } else {\n // Non-numeric = branch name\n return {\n mode: 'single',\n branchName: trimmedIdentifier,\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n }\n }\n\n /**\n * Validate parsed input for option conflicts\n * Throws descriptive errors for invalid option combinations\n *\n * @private\n */\n private validateInput(parsed: ParsedCleanupInput): void {\n const { mode, options, branchName } = parsed\n\n // Conflict: --list is informational only, incompatible with destructive operations\n if (mode === 'list') {\n if (options.all) {\n throw new Error('Cannot use --list with --all (list is informational only)')\n }\n if (options.issue !== undefined) {\n throw new Error('Cannot use --list with --issue (list is informational only)')\n }\n if (parsed.identifier) {\n throw new Error('Cannot use --list with a specific identifier (list shows all worktrees)')\n }\n }\n\n // Conflict: --all removes everything, can't combine with specific identifier or --issue\n if (mode === 'all') {\n if (parsed.identifier) {\n throw new Error('Cannot use --all with a specific identifier. Use one or the other.')\n }\n if (parsed.issueNumber !== undefined) {\n throw new Error('Cannot use --all with a specific identifier. Use one or the other.')\n }\n }\n\n // Conflict: explicit --issue flag with branch name identifier\n // (This prevents confusion when user provides both)\n if (options.issue !== undefined && branchName) {\n throw new Error('Cannot use --issue flag with branch name identifier. Use numeric identifier or --issue flag alone.')\n }\n\n // Note: --force and --dry-run are compatible with all modes (no conflicts)\n }\n\n /**\n * Execute cleanup for single worktree\n * Implements two-stage confirmation: worktree removal, then branch deletion\n * Uses IdentifierParser for pattern-based detection without GitHub API calls\n */\n private async executeSingleCleanup(parsed: ParsedCleanupInput): Promise<CleanupResult> {\n const identifier = parsed.branchName ?? parsed.identifier ?? ''\n if (!identifier) {\n throw new Error('No identifier found for cleanup')\n }\n const { force, dryRun } = parsed.options\n\n // Step 1: Parse identifier using pattern-based detection\n let parsedInput: ParsedInput = await this.identifierParser.parseForPatternDetection(identifier)\n\n // If type is 'branch', try to extract issue number for CLI symlink cleanup\n if (parsedInput.type === 'branch' && parsedInput.branchName) {\n const { extractIssueNumber } = await import('../utils/git.js')\n const extractedNumber = extractIssueNumber(parsedInput.branchName)\n if (extractedNumber !== null) {\n parsedInput = {\n ...parsedInput,\n number: extractedNumber // Add number for CLI symlink cleanup\n }\n }\n }\n\n // Step 2: Display worktree details\n getLogger().info(`Preparing to cleanup worktree: ${identifier}`)\n\n // Step 3: Routine confirmation - worktree removal\n // Skip if --force (user explicitly bypasses) or --json (programmatic use can't interact)\n // Note: Safety checks (uncommitted changes, unmerged work) still require --force to bypass\n if (!force && !parsed.options.json) {\n const confirmWorktree = await promptConfirmation('Remove this worktree?', true)\n if (!confirmWorktree) {\n getLogger().info('Cleanup cancelled')\n return {\n identifier,\n success: false,\n dryRun: dryRun ?? false,\n operations: [],\n errors: [],\n rollbackRequired: false,\n }\n }\n }\n\n // Step 3.5: Read metadata BEFORE cleanup (cleanup deletes the worktree)\n let preCleanupMetadata: LoomMetadata | null = null\n try {\n // Find worktree path for metadata lookup\n const worktree = parsedInput.type === 'branch' && parsedInput.branchName\n ? await this.gitWorktreeManager.findWorktreeForBranch(parsedInput.branchName)\n : parsedInput.number !== undefined\n ? await this.gitWorktreeManager.findWorktreeForIssue(parsedInput.number)\n : null\n if (worktree) {\n const metadataManager = new MetadataManager()\n preCleanupMetadata = await metadataManager.readMetadata(worktree.path)\n }\n } catch (error: unknown) {\n getLogger().debug(`Failed to read metadata for telemetry: ${error instanceof Error ? error.message : String(error)}`)\n }\n\n // Step 4: Execute worktree cleanup (includes safety validation)\n // Issue #275 fix: Run 5-point safety check BEFORE any deletion\n // This prevents the scenario where worktree is deleted but branch deletion fails\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n const cleanupResult = await this.resourceCleanup.cleanupWorktree(parsedInput, {\n dryRun: dryRun ?? false,\n force: force ?? false,\n deleteBranch: true, // Always include branch deletion (safety checks run first)\n keepDatabase: false,\n checkMergeSafety: true, // Run 5-point safety check BEFORE any deletion\n archive: parsed.options.archive ?? false,\n })\n\n // Add dryRun flag to result\n cleanupResult.dryRun = dryRun ?? false\n\n // Step 5: Report cleanup results\n this.reportCleanupResults(cleanupResult)\n\n // Track loom.abandoned telemetry event (only for unfinished looms)\n if (cleanupResult.success && preCleanupMetadata && preCleanupMetadata.status !== 'finished') {\n trackLoomAbandoned(preCleanupMetadata)\n }\n\n // Final success message\n if (cleanupResult.success) {\n getLogger().success('Cleanup completed successfully')\n } else {\n getLogger().warn('Cleanup completed with errors - see details above')\n }\n\n return cleanupResult\n }\n\n /**\n * Report cleanup operation results to user\n */\n private reportCleanupResults(result: CleanupResult): void {\n getLogger().info('Cleanup operations:')\n\n result.operations.forEach(op => {\n const status = op.success ? '✓' : '✗'\n const message = op.error ? `${op.message}: ${op.error}` : op.message\n\n if (op.success) {\n getLogger().info(` ${status} ${message}`)\n } else {\n getLogger().error(` ${status} ${message}`)\n }\n })\n\n if (result.errors.length > 0) {\n getLogger().warn(`${result.errors.length} error(s) occurred during cleanup`)\n }\n }\n\n /**\n * Execute cleanup for all worktrees associated with an issue or PR number\n * Searches for worktrees by their path patterns (e.g., issue-25, pr-25, 25-feature, _pr_25)\n * Implements bash cleanup-worktree.sh remove_worktrees_by_issue() (lines 157-242)\n */\n private async executeIssueCleanup(parsed: ParsedCleanupInput): Promise<CleanupResult> {\n const issueNumber = parsed.issueNumber\n if (issueNumber === undefined) {\n throw new Error('No issue/PR number provided for cleanup')\n }\n\n const { force, dryRun } = parsed.options\n\n getLogger().info(`Finding worktrees related to issue/PR #${issueNumber}...`)\n\n // Step 1: Get all worktrees and filter by path pattern\n const worktrees = await this.gitWorktreeManager.listWorktrees()\n const matchingWorktrees = worktrees.filter(wt => {\n const path = wt.path.toLowerCase()\n // Lowercase for case-insensitive matching (Linear IDs are uppercase like MARK-1)\n const idStr = String(issueNumber).toLowerCase()\n\n // Check if path contains the identifier with proper word boundaries\n // Matches: issue-25, pr-25, 25-feature, _pr_25, issue-mark-1, etc.\n // Uses word boundary or common separators (-, _, /) for alphanumeric IDs\n const pattern = new RegExp(`(?:^|[/_-])${idStr}(?:[/_-]|$)`)\n return pattern.test(path)\n })\n\n if (matchingWorktrees.length === 0) {\n getLogger().warn(`No worktrees found for issue/PR #${issueNumber}`)\n getLogger().info(`Searched for worktree paths containing: ${issueNumber}, _pr_${issueNumber}, issue-${issueNumber}, etc.`)\n return {\n identifier: String(issueNumber),\n success: true,\n dryRun: dryRun ?? false,\n operations: [],\n errors: [],\n rollbackRequired: false,\n }\n }\n\n // Step 2: Build targets list from matching worktrees\n const targets: Array<{ branchName: string; hasWorktree: boolean; worktreePath?: string }> =\n matchingWorktrees.map(wt => ({\n branchName: wt.branch,\n hasWorktree: true,\n worktreePath: wt.path\n }))\n\n // Step 3: Display preview\n getLogger().info(`Found ${targets.length} worktree(s) related to issue/PR #${issueNumber}:`)\n for (const target of targets) {\n getLogger().info(` Branch: ${target.branchName} (${target.worktreePath})`)\n }\n\n // Step 4: Routine batch confirmation\n // Skip if --force (user explicitly bypasses) or --json (programmatic use can't interact)\n // Note: Safety checks per-worktree (uncommitted changes, unmerged work) still require --force to bypass\n if (!force && !parsed.options.json) {\n const confirmCleanup = await promptConfirmation(\n `Remove ${targets.length} worktree(s)?`,\n true\n )\n if (!confirmCleanup) {\n getLogger().info('Cleanup cancelled')\n return {\n identifier: String(issueNumber),\n success: false,\n dryRun: dryRun ?? false,\n operations: [],\n errors: [],\n rollbackRequired: false,\n }\n }\n }\n\n // Step 5: Process each target sequentially\n let worktreesRemoved = 0\n let branchesDeleted = 0\n const databaseBranchesDeletedList: string[] = []\n let failed = 0\n\n for (const target of targets) {\n getLogger().info(`Processing worktree: ${target.branchName}`)\n\n // Cleanup worktree using ResourceCleanup with ParsedInput\n // Now includes branch deletion with 5-point safety check BEFORE any deletion\n try {\n // Read metadata BEFORE cleanup for telemetry\n let targetMetadata: LoomMetadata | null = null\n if (target.worktreePath) {\n try {\n const metadataManager = new MetadataManager()\n targetMetadata = await metadataManager.readMetadata(target.worktreePath)\n } catch (error: unknown) {\n getLogger().debug(`Failed to read metadata for telemetry: ${error instanceof Error ? error.message : String(error)}`)\n }\n }\n\n // Use the known issue number directly instead of parsing from branch name\n // This ensures CLI symlinks (created with issue number) are properly cleaned up\n const parsedInput: ParsedInput = {\n type: 'issue',\n number: issueNumber, // Use the known issue number, not parsed from branch\n branchName: target.branchName,\n originalInput: String(issueNumber)\n }\n\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n // Issue #275 fix: Run safety checks BEFORE deleting worktree\n // This prevents the scenario where worktree is deleted but branch deletion fails\n const result = await this.resourceCleanup.cleanupWorktree(parsedInput, {\n dryRun: dryRun ?? false,\n force: force ?? false,\n deleteBranch: true, // Include branch deletion (with safety checks)\n keepDatabase: false,\n checkMergeSafety: true, // Run 5-point safety check BEFORE any deletion\n archive: parsed.options.archive ?? false,\n ...(target.worktreePath && { worktree: { path: target.worktreePath, branch: target.branchName } }),\n })\n\n if (result.success) {\n worktreesRemoved++\n getLogger().success(` Worktree removed: ${target.branchName}`)\n\n // Check if branch was deleted\n const branchOperation = result.operations.find(op => op.type === 'branch')\n if (branchOperation?.success) {\n branchesDeleted++\n getLogger().success(` Branch deleted: ${target.branchName}`)\n }\n\n // Check if database branch was actually deleted (use explicit deleted field)\n const dbOperation = result.operations.find(op => op.type === 'database')\n if (dbOperation?.deleted) {\n // Get branch name from result or use the target branch name\n const deletedBranchName = target.branchName\n databaseBranchesDeletedList.push(deletedBranchName)\n }\n\n // Track loom.abandoned telemetry (only for unfinished looms)\n if (targetMetadata && targetMetadata.status !== 'finished') {\n trackLoomAbandoned(targetMetadata)\n }\n } else {\n failed++\n getLogger().error(` Failed to remove worktree: ${target.branchName}`)\n for (const err of result.errors) {\n getLogger().error(` ${err.message}`)\n }\n }\n } catch (error) {\n failed++\n const errMsg = error instanceof Error ? error.message : 'Unknown error'\n getLogger().error(` Failed to cleanup: ${errMsg}`)\n continue // Continue with next worktree even if this one failed\n }\n }\n\n // Step 7: Report statistics\n getLogger().success(`Completed cleanup for issue/PR #${issueNumber}:`)\n getLogger().info(` Worktrees removed: ${worktreesRemoved}`)\n getLogger().info(` Branches deleted: ${branchesDeleted}`)\n if (databaseBranchesDeletedList.length > 0) {\n // Display branch names in the format requested\n getLogger().info(` Database branches deleted: ${databaseBranchesDeletedList.join(', ')}`)\n }\n if (failed > 0) {\n getLogger().warn(` Failed operations: ${failed}`)\n }\n\n // Return aggregated result\n return {\n identifier: String(issueNumber),\n success: failed === 0,\n dryRun: dryRun ?? false,\n operations: [\n { type: 'worktree' as const, success: true, message: `Removed ${worktreesRemoved} worktree(s)` },\n { type: 'branch' as const, success: true, message: `Deleted ${branchesDeleted} branch(es)` },\n ...(databaseBranchesDeletedList.length > 0 ? [{ type: 'database' as const, success: true, message: `Deleted ${databaseBranchesDeletedList.length} database branch(es)`, deleted: true }] : []),\n ],\n errors: [],\n rollbackRequired: false,\n }\n }\n}\n"],"mappings":"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","names":["numericPattern"]}
|