claude-code-workflow 7.2.28 → 7.2.29
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/.codex/skills/brainstorm/SKILL.md +3 -3
- package/.codex/skills/clean/SKILL.md +3 -3
- package/.codex/skills/issue-discover/SKILL.md +13 -13
- package/.codex/skills/issue-discover/phases/02-discover.md +4 -4
- package/.codex/skills/issue-discover/phases/03-discover-by-prompt.md +3 -3
- package/.codex/skills/parallel-dev-cycle/SKILL.md +4 -4
- package/.codex/skills/parallel-dev-cycle/phases/02-agent-execution.md +6 -6
- package/.codex/skills/parallel-dev-cycle/phases/03-result-aggregation.md +10 -10
- package/.codex/skills/review-cycle/SKILL.md +10 -10
- package/.codex/skills/review-cycle/phases/02-parallel-review.md +6 -6
- package/.codex/skills/review-cycle/phases/04-iterative-deep-dive.md +4 -4
- package/.codex/skills/review-cycle/phases/07-fix-parallel-planning.md +4 -4
- package/.codex/skills/review-cycle/phases/08-fix-execution.md +2 -2
- package/.codex/skills/roadmap-with-file/SKILL.md +14 -14
- package/.codex/skills/spec-generator/README.md +1 -1
- package/.codex/skills/spec-generator/SKILL.md +184 -88
- package/.codex/skills/spec-generator/phases/01-5-requirement-clarification.md +4 -7
- package/.codex/skills/spec-generator/phases/01-discovery.md +30 -11
- package/.codex/skills/spec-generator/phases/02-product-brief.md +2 -5
- package/.codex/skills/spec-generator/phases/03-requirements.md +4 -6
- package/.codex/skills/spec-generator/phases/04-architecture.md +4 -6
- package/.codex/skills/spec-generator/phases/05-epics-stories.md +4 -6
- package/.codex/skills/spec-generator/phases/06-5-auto-fix.md +4 -5
- package/.codex/skills/spec-generator/phases/06-readiness-check.md +8 -8
- package/.codex/skills/spec-generator/phases/07-issue-export.md +2 -2
- package/.codex/skills/spec-setup/SKILL.md +4 -4
- package/.codex/skills/workflow-plan/SKILL.md +6 -6
- package/.codex/skills/workflow-tdd-plan/SKILL.md +5 -5
- package/.codex/skills/workflow-test-fix-cycle/SKILL.md +19 -19
- package/.codex/skills/workflow-test-fix-cycle/phases/01-test-fix-gen.md +5 -5
- package/.codex/skills/workflow-test-fix-cycle/phases/02-test-cycle-execute.md +5 -5
- package/ccw/frontend/dist/assets/{AlertDialog-BjP1ydDR.js → AlertDialog-exlTDW81.js} +3 -3
- package/ccw/frontend/dist/assets/{AlertDialog-BjP1ydDR.js.map → AlertDialog-exlTDW81.js.map} +1 -1
- package/ccw/frontend/dist/assets/{AnalysisPage-CAX3xqMf.js → AnalysisPage-cgV9LfAI.js} +2 -2
- package/ccw/frontend/dist/assets/{AnalysisPage-CAX3xqMf.js.map → AnalysisPage-cgV9LfAI.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ApiSettingsPage-CtWlmztq.js → ApiSettingsPage-Dk5jJdWt.js} +2 -2
- package/ccw/frontend/dist/assets/{ApiSettingsPage-CtWlmztq.js.map → ApiSettingsPage-Dk5jJdWt.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliModeToggle-hR4a-eLX.js → CliModeToggle-Be9xsPiv.js} +2 -2
- package/ccw/frontend/dist/assets/{CliModeToggle-hR4a-eLX.js.map → CliModeToggle-Be9xsPiv.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliSessionSharePage-DzNPkFN9.js → CliSessionSharePage-Bh9jBtPI.js} +2 -2
- package/ccw/frontend/dist/assets/{CliSessionSharePage-DzNPkFN9.js.map → CliSessionSharePage-Bh9jBtPI.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliViewerPage-BPEGN4TT.js → CliViewerPage-BrE-oyEq.js} +2 -2
- package/ccw/frontend/dist/assets/{CliViewerPage-BPEGN4TT.js.map → CliViewerPage-BrE-oyEq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CodexLensPage-Cf0r2RHY.js → CodexLensPage-Cd3nrC93.js} +2 -2
- package/ccw/frontend/dist/assets/{CodexLensPage-Cf0r2RHY.js.map → CodexLensPage-Cd3nrC93.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Collapsible-DEm1rJ4h.js → Collapsible-DXFl3VKF.js} +2 -2
- package/ccw/frontend/dist/assets/{Collapsible-DEm1rJ4h.js.map → Collapsible-DXFl3VKF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CommandsManagerPage-BpeWw8HO.js → CommandsManagerPage-IV8zpjgX.js} +2 -2
- package/ccw/frontend/dist/assets/{CommandsManagerPage-BpeWw8HO.js.map → CommandsManagerPage-IV8zpjgX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{DeepWikiPage-BEsmh2vF.js → DeepWikiPage-CpDxtmRX.js} +2 -2
- package/ccw/frontend/dist/assets/{DeepWikiPage-BEsmh2vF.js.map → DeepWikiPage-CpDxtmRX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{EndpointsPage-B30SFdtU.js → EndpointsPage-BchjWe7s.js} +2 -2
- package/ccw/frontend/dist/assets/{EndpointsPage-B30SFdtU.js.map → EndpointsPage-BchjWe7s.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ExplorerPage-BVvMpg1O.js → ExplorerPage-CbWvaJ0y.js} +2 -2
- package/ccw/frontend/dist/assets/{ExplorerPage-BVvMpg1O.js.map → ExplorerPage-CbWvaJ0y.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FixSessionPage-CL73dHbh.js → FixSessionPage-YMjVRiCk.js} +2 -2
- package/ccw/frontend/dist/assets/{FixSessionPage-CL73dHbh.js.map → FixSessionPage-YMjVRiCk.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-BL-28lMZ.js → FloatingFileBrowser-JW2ehYY_.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-BL-28lMZ.js.map → FloatingFileBrowser-JW2ehYY_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingPanel-BzZDciHZ.js → FloatingPanel-BtqzqDVq.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingPanel-BzZDciHZ.js.map → FloatingPanel-BtqzqDVq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{GraphExplorerPage-CDp6-d8P.js → GraphExplorerPage-BsJL_W4d.js} +3 -3
- package/ccw/frontend/dist/assets/{GraphExplorerPage-CDp6-d8P.js.map → GraphExplorerPage-BsJL_W4d.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HistoryPage-fZY_7O9n.js → HistoryPage-BuWpQ7k5.js} +2 -2
- package/ccw/frontend/dist/assets/{HistoryPage-fZY_7O9n.js.map → HistoryPage-BuWpQ7k5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HookManagerPage-4LJeC9bq.js → HookManagerPage-D0BtMIWy.js} +2 -2
- package/ccw/frontend/dist/assets/{HookManagerPage-4LJeC9bq.js.map → HookManagerPage-D0BtMIWy.js.map} +1 -1
- package/ccw/frontend/dist/assets/{InstallationsPage-Bpigrbhw.js → InstallationsPage-C7dwsAKG.js} +2 -2
- package/ccw/frontend/dist/assets/{InstallationsPage-Bpigrbhw.js.map → InstallationsPage-C7dwsAKG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{IssueHubPage-BP0zJc1R.js → IssueHubPage-D0nCNaeB.js} +2 -2
- package/ccw/frontend/dist/assets/{IssueHubPage-BP0zJc1R.js.map → IssueHubPage-D0nCNaeB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{LiteTasksPage-CSt2oVKQ.js → LiteTasksPage-B5c2Kb9r.js} +3 -3
- package/ccw/frontend/dist/assets/{LiteTasksPage-CSt2oVKQ.js.map → LiteTasksPage-B5c2Kb9r.js.map} +1 -1
- package/ccw/frontend/dist/assets/{McpManagerPage-B-xaMA0w.js → McpManagerPage-C-S5CehM.js} +2 -2
- package/ccw/frontend/dist/assets/{McpManagerPage-B-xaMA0w.js.map → McpManagerPage-C-S5CehM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{MemoryPage-CJqo_7DY.js → MemoryPage-P_B0JVUQ.js} +2 -2
- package/ccw/frontend/dist/assets/{MemoryPage-CJqo_7DY.js.map → MemoryPage-P_B0JVUQ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{NotFoundPage-ibZeQA-Y.js → NotFoundPage-S4Jn9LUE.js} +2 -2
- package/ccw/frontend/dist/assets/{NotFoundPage-ibZeQA-Y.js.map → NotFoundPage-S4Jn9LUE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{OrchestratorPage-DgJ4ctPQ.js → OrchestratorPage-C2Zlr7AC.js} +2 -2
- package/ccw/frontend/dist/assets/{OrchestratorPage-DgJ4ctPQ.js.map → OrchestratorPage-C2Zlr7AC.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-Cit0Yq0D.js → ProjectOverviewPage-CMVfz8s5.js} +2 -2
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-Cit0Yq0D.js.map → ProjectOverviewPage-CMVfz8s5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{PromptHistoryPage-Ce1HDIK0.js → PromptHistoryPage-YEMjFARX.js} +3 -3
- package/ccw/frontend/dist/assets/{PromptHistoryPage-Ce1HDIK0.js.map → PromptHistoryPage-YEMjFARX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ReviewSessionPage-J1KikNrk.js → ReviewSessionPage-DnTm55nG.js} +2 -2
- package/ccw/frontend/dist/assets/{ReviewSessionPage-J1KikNrk.js.map → ReviewSessionPage-DnTm55nG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{RulesManagerPage-CdBjTmth.js → RulesManagerPage-CUwebtO2.js} +2 -2
- package/ccw/frontend/dist/assets/{RulesManagerPage-CdBjTmth.js.map → RulesManagerPage-CUwebtO2.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionDetailPage-B9ZK7LvX.js → SessionDetailPage-0qyH1Z5P.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionDetailPage-B9ZK7LvX.js.map → SessionDetailPage-0qyH1Z5P.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionsPage-CW_nS5UR.js → SessionsPage-BpgP4087.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionsPage-CW_nS5UR.js.map → SessionsPage-BpgP4087.js.map} +1 -1
- package/ccw/frontend/dist/assets/SettingsPage-C3SJajeT.js +150 -0
- package/ccw/frontend/dist/assets/SettingsPage-C3SJajeT.js.map +1 -0
- package/ccw/frontend/dist/assets/SkillsManagerPage-vD9PTsmy.js +7 -0
- package/ccw/frontend/dist/assets/SkillsManagerPage-vD9PTsmy.js.map +1 -0
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-DJpi9XQL.js → SpecsSettingsPage-DT-yTVkD.js} +4 -4
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-DJpi9XQL.js.map → SpecsSettingsPage-DT-yTVkD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Switch-Ac6Ov7uy.js → Switch-CYSPdqWk.js} +2 -2
- package/ccw/frontend/dist/assets/{Switch-Ac6Ov7uy.js.map → Switch-CYSPdqWk.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TabsNavigation-DZAAspqR.js → TabsNavigation-CPh6Zor1.js} +2 -2
- package/ccw/frontend/dist/assets/{TabsNavigation-DZAAspqR.js.map → TabsNavigation-CPh6Zor1.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TaskDrawer-BJkwfhIZ.js → TaskDrawer-Ds-8830B.js} +2 -2
- package/ccw/frontend/dist/assets/{TaskDrawer-BJkwfhIZ.js.map → TaskDrawer-Ds-8830B.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TeamPage-BJgjxBgb.js → TeamPage-CJODUxBk.js} +2 -2
- package/ccw/frontend/dist/assets/{TeamPage-BJgjxBgb.js.map → TeamPage-CJODUxBk.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-D1WekoOy.js → TerminalDashboardPage-Cn3fGUuO.js} +3 -3
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-D1WekoOy.js.map → TerminalDashboardPage-Cn3fGUuO.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-DxemgIhF.js → archive-CjwVpw6k.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-DxemgIhF.js.map → archive-CjwVpw6k.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-restore-CjS83f1V.js → archive-restore-2vZa9Ic3.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-restore-CjS83f1V.js.map → archive-restore-2vZa9Ic3.js.map} +1 -1
- package/ccw/frontend/dist/assets/{arrow-right-B5PUcn8I.js → arrow-right-CUU5XDgT.js} +2 -2
- package/ccw/frontend/dist/assets/{arrow-right-B5PUcn8I.js.map → arrow-right-CUU5XDgT.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bookmark-plus-DCc9aPbb.js → bookmark-plus-Cc3nKRZ5.js} +2 -2
- package/ccw/frontend/dist/assets/{bookmark-plus-DCc9aPbb.js.map → bookmark-plus-Cc3nKRZ5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bot-DOwFtzak.js → bot-BwpSRDUa.js} +2 -2
- package/ccw/frontend/dist/assets/{bot-DOwFtzak.js.map → bot-BwpSRDUa.js.map} +1 -1
- package/ccw/frontend/dist/assets/{braces-96qH3aFh.js → braces-DBzUW1XC.js} +2 -2
- package/ccw/frontend/dist/assets/{braces-96qH3aFh.js.map → braces-DBzUW1XC.js.map} +1 -1
- package/ccw/frontend/dist/assets/{circle-stop-CCxSuil1.js → circle-stop-CGNNsjvE.js} +2 -2
- package/ccw/frontend/dist/assets/{circle-stop-CCxSuil1.js.map → circle-stop-CGNNsjvE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{cpu-CZNSJFdq.js → cpu-D27G86Ul.js} +2 -2
- package/ccw/frontend/dist/assets/{cpu-CZNSJFdq.js.map → cpu-D27G86Ul.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ellipsis-vertical-h8xtvw2_.js → ellipsis-vertical-C1Ij47Yz.js} +2 -2
- package/ccw/frontend/dist/assets/{ellipsis-vertical-h8xtvw2_.js.map → ellipsis-vertical-C1Ij47Yz.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-D3NY0bm6.js → eye-C6MOB7Au.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-D3NY0bm6.js.map → eye-C6MOB7Au.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-off-Cy2vkc8p.js → eye-off-BxfBlZ26.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-off-Cy2vkc8p.js.map → eye-off-BxfBlZ26.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-json-Bzq3U1Mx.js → file-json-NI237wA-.js} +2 -2
- package/ccw/frontend/dist/assets/{file-json-Bzq3U1Mx.js.map → file-json-NI237wA-.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-text-DwuwPDPi.js → file-text-Byn2_2v6.js} +2 -2
- package/ccw/frontend/dist/assets/{file-text-DwuwPDPi.js.map → file-text-Byn2_2v6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{filter-q9g-bknU.js → filter-D-7PhZjx.js} +2 -2
- package/ccw/frontend/dist/assets/{filter-q9g-bknU.js.map → filter-D-7PhZjx.js.map} +1 -1
- package/ccw/frontend/dist/assets/{folder-CL6vb42J.js → folder-BoAsK_FL.js} +2 -2
- package/ccw/frontend/dist/assets/{folder-CL6vb42J.js.map → folder-BoAsK_FL.js.map} +1 -1
- package/ccw/frontend/dist/assets/{gauge-BkrcQBly.js → gauge-DCSxJIS4.js} +2 -2
- package/ccw/frontend/dist/assets/{gauge-BkrcQBly.js.map → gauge-DCSxJIS4.js.map} +1 -1
- package/ccw/frontend/dist/assets/{globe-BQbwyNeV.js → globe-CHS3prza.js} +2 -2
- package/ccw/frontend/dist/assets/{globe-BQbwyNeV.js.map → globe-CHS3prza.js.map} +1 -1
- package/ccw/frontend/dist/assets/{grid-3x3-x5_7DrN7.js → grid-3x3-D7K35U7S.js} +2 -2
- package/ccw/frontend/dist/assets/{grid-3x3-x5_7DrN7.js.map → grid-3x3-D7K35U7S.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hard-drive-DTyWXwzf.js → hard-drive-eq9xE07G.js} +2 -2
- package/ccw/frontend/dist/assets/{hard-drive-DTyWXwzf.js.map → hard-drive-eq9xE07G.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hash-80O0kJO7.js → hash-C1DMpBua.js} +2 -2
- package/ccw/frontend/dist/assets/{hash-80O0kJO7.js.map → hash-C1DMpBua.js.map} +1 -1
- package/ccw/frontend/dist/assets/{history-DDlN2Bwa.js → history-Di5SBCY-.js} +2 -2
- package/ccw/frontend/dist/assets/{history-DDlN2Bwa.js.map → history-Di5SBCY-.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-mbeo62f8.js → index--_R7COnA.js} +2 -2
- package/ccw/frontend/dist/assets/{index-mbeo62f8.js.map → index--_R7COnA.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-rLgoBCfV.js → index-BUol9HDD.js} +3 -3
- package/ccw/frontend/dist/assets/{index-rLgoBCfV.js.map → index-BUol9HDD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-Bs80iCX0.js → index-CT9oykfw.js} +2 -2
- package/ccw/frontend/dist/assets/{index-Bs80iCX0.js.map → index-CT9oykfw.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-B9A3Hnrk.js → index-Ddwvf87H.js} +2 -2
- package/ccw/frontend/dist/assets/{index-B9A3Hnrk.js.map → index-Ddwvf87H.js.map} +1 -1
- package/ccw/frontend/dist/assets/{layout-grid-C1niOWJx.js → layout-grid-LiX0qZbN.js} +2 -2
- package/ccw/frontend/dist/assets/{layout-grid-C1niOWJx.js.map → layout-grid-LiX0qZbN.js.map} +1 -1
- package/ccw/frontend/dist/assets/{lightbulb-BTmI7SUg.js → lightbulb-CL3DVEwb.js} +2 -2
- package/ccw/frontend/dist/assets/{lightbulb-BTmI7SUg.js.map → lightbulb-CL3DVEwb.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-2-CB9HKeuZ.js → link-2-CC5cFeq6.js} +2 -2
- package/ccw/frontend/dist/assets/{link-2-CB9HKeuZ.js.map → link-2-CC5cFeq6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-koEYiemK.js → link-ngFQ9bs0.js} +2 -2
- package/ccw/frontend/dist/assets/{link-koEYiemK.js.map → link-ngFQ9bs0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{list-v2_GaLdC.js → list-BEU6I0KK.js} +2 -2
- package/ccw/frontend/dist/assets/{list-v2_GaLdC.js.map → list-BEU6I0KK.js.map} +1 -1
- package/ccw/frontend/dist/assets/{map-pin-BQNfAqG_.js → map-pin-BWZdLA6y.js} +2 -2
- package/ccw/frontend/dist/assets/{map-pin-BQNfAqG_.js.map → map-pin-BWZdLA6y.js.map} +1 -1
- package/ccw/frontend/dist/assets/{messages-square-Dzq5LGg9.js → messages-square-K6_Chm7n.js} +2 -2
- package/ccw/frontend/dist/assets/{messages-square-Dzq5LGg9.js.map → messages-square-K6_Chm7n.js.map} +1 -1
- package/ccw/frontend/dist/assets/{minimize-2-CtkoJXcz.js → minimize-2-CWkphauf.js} +2 -2
- package/ccw/frontend/dist/assets/{minimize-2-CtkoJXcz.js.map → minimize-2-CWkphauf.js.map} +1 -1
- package/ccw/frontend/dist/assets/{package-CH3smL37.js → package-DrNgkamn.js} +2 -2
- package/ccw/frontend/dist/assets/{package-CH3smL37.js.map → package-DrNgkamn.js.map} +1 -1
- package/ccw/frontend/dist/assets/{plug-CZ0aL_yF.js → plug-CMo3sw5_.js} +2 -2
- package/ccw/frontend/dist/assets/{plug-CZ0aL_yF.js.map → plug-CMo3sw5_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{power-F2A_J4l6.js → power-DppNTW5e.js} +2 -2
- package/ccw/frontend/dist/assets/{power-F2A_J4l6.js.map → power-DppNTW5e.js.map} +1 -1
- package/ccw/frontend/dist/assets/{save-Byxot0YU.js → save-CD8aPMbZ.js} +2 -2
- package/ccw/frontend/dist/assets/{save-Byxot0YU.js.map → save-CD8aPMbZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{send-JjqhUkpw.js → send-B4z90fQD.js} +2 -2
- package/ccw/frontend/dist/assets/{send-JjqhUkpw.js.map → send-B4z90fQD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{settings-2--SuN9rAt.js → settings-2-CAKRU_QC.js} +2 -2
- package/ccw/frontend/dist/assets/{settings-2--SuN9rAt.js.map → settings-2-CAKRU_QC.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-check-big-BbngGB2h.js → square-check-big-KhI3HrzX.js} +2 -2
- package/ccw/frontend/dist/assets/{square-check-big-BbngGB2h.js.map → square-check-big-KhI3HrzX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-pen-CgrHgZSl.js → square-pen-BtdGIpuq.js} +2 -2
- package/ccw/frontend/dist/assets/{square-pen-CgrHgZSl.js.map → square-pen-BtdGIpuq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{star-BU3TQr7Z.js → star-ZoBUkXoD.js} +2 -2
- package/ccw/frontend/dist/assets/{star-BU3TQr7Z.js.map → star-ZoBUkXoD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{style-CKs7nnn3.js → style-CltxQP-P.js} +2 -2
- package/ccw/frontend/dist/assets/{style-CKs7nnn3.js.map → style-CltxQP-P.js.map} +1 -1
- package/ccw/frontend/dist/assets/{target-DW5tsDW6.js → target-C32OUSGf.js} +2 -2
- package/ccw/frontend/dist/assets/{target-DW5tsDW6.js.map → target-C32OUSGf.js.map} +1 -1
- package/ccw/frontend/dist/assets/{test-tube-BHm7w3ON.js → test-tube-0IxoyAVZ.js} +2 -2
- package/ccw/frontend/dist/assets/{test-tube-BHm7w3ON.js.map → test-tube-0IxoyAVZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{upload-DYR7PWwt.js → upload-4eKCkyBn.js} +2 -2
- package/ccw/frontend/dist/assets/{upload-DYR7PWwt.js.map → upload-4eKCkyBn.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useApiSettings-D0TVgQD_.js → useApiSettings-zLTUWqhi.js} +2 -2
- package/ccw/frontend/dist/assets/{useApiSettings-D0TVgQD_.js.map → useApiSettings-zLTUWqhi.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCli-DfY8mAP8.js → useCli-BtN2vpOX.js} +2 -2
- package/ccw/frontend/dist/assets/{useCli-DfY8mAP8.js.map → useCli-BtN2vpOX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCommands-CGusDp0F.js → useCommands-_spj49qL.js} +2 -2
- package/ccw/frontend/dist/assets/{useCommands-CGusDp0F.js.map → useCommands-_spj49qL.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useDebounce-CIwh0fF1.js → useDebounce-Bm9KFZvd.js} +2 -2
- package/ccw/frontend/dist/assets/{useDebounce-CIwh0fF1.js.map → useDebounce-Bm9KFZvd.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useFileExplorer-FMyFv39K.js → useFileExplorer-DOmpm6v9.js} +2 -2
- package/ccw/frontend/dist/assets/{useFileExplorer-FMyFv39K.js.map → useFileExplorer-DOmpm6v9.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useLocale-B2qhsoTb.js → useLocale-D2rj4rea.js} +2 -2
- package/ccw/frontend/dist/assets/{useLocale-B2qhsoTb.js.map → useLocale-D2rj4rea.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSkills-cxKXMBm3.js → useSkills-OskEpomF.js} +3 -3
- package/ccw/frontend/dist/assets/{useSkills-cxKXMBm3.js.map → useSkills-OskEpomF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSystemSettings-B-xUT_z-.js → useSystemSettings-BjMgsNSF.js} +2 -2
- package/ccw/frontend/dist/assets/{useSystemSettings-B-xUT_z-.js.map → useSystemSettings-BjMgsNSF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{wand-sparkles-DZV_3lPr.js → wand-sparkles-CLhyYWa7.js} +2 -2
- package/ccw/frontend/dist/assets/{wand-sparkles-DZV_3lPr.js.map → wand-sparkles-CLhyYWa7.js.map} +1 -1
- package/ccw/frontend/dist/index.html +1 -1
- package/package.json +1 -1
- package/ccw/frontend/dist/assets/SettingsPage-B2PYzSoO.js +0 -150
- package/ccw/frontend/dist/assets/SettingsPage-B2PYzSoO.js.map +0 -1
- package/ccw/frontend/dist/assets/SkillsManagerPage-CTnWrrwp.js +0 -7
- package/ccw/frontend/dist/assets/SkillsManagerPage-CTnWrrwp.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpecsSettingsPage-DJpi9XQL.js","sources":["../../../../node_modules/lucide-react/dist/esm/icons/pen.js","../../src/components/specs/SpecCard.tsx","../../src/components/specs/SpecDialog.tsx","../../src/components/specs/SpecContentDialog.tsx","../../src/components/specs/InjectionControlTab.tsx","../../src/components/specs/GlobalSettingsTab.tsx","../../src/pages/SpecsSettingsPage.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Pen = createLucideIcon(\"Pen\", [\n [\n \"path\",\n {\n d: \"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\",\n key: \"1a8usu\"\n }\n ]\n]);\n\nexport { Pen as default };\n//# sourceMappingURL=pen.js.map\n","// ========================================\r\n// SpecCard Component\r\n// ========================================\r\n// Spec card with readMode badge, keywords, priority indicator and action menu\r\n\r\nimport * as React from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { cn } from '@/lib/utils';\r\nimport { Card, CardContent } from '@/components/ui/Card';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Switch } from '@/components/ui/Switch';\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuTrigger,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n DropdownMenuSeparator,\r\n} from '@/components/ui/DropdownMenu';\r\nimport {\r\n MoreVertical,\r\n Edit,\r\n Trash2,\r\n FileText,\r\n Tag,\r\n Eye,\r\n Globe,\r\n Folder,\r\n Layers,\r\n} from 'lucide-react';\r\n\r\n// ========== Types ==========\r\n\r\n/**\r\n * Spec dimension type\r\n */\r\nexport type SpecDimension = 'specs' | 'personal';\r\n\r\n/**\r\n * Spec scope type\r\n */\r\nexport type SpecScope = 'global' | 'project';\r\n\r\n/**\r\n * Spec read mode type\r\n */\r\nexport type SpecReadMode = 'required' | 'optional';\r\n\r\n/**\r\n * Spec priority type\r\n */\r\nexport type SpecPriority = 'critical' | 'high' | 'medium' | 'low';\r\n\r\n/**\r\n * Spec category type for workflow stage-based loading\r\n */\r\nexport type SpecCategory = 'general' | 'exploration' | 'planning' | 'execution';\r\n\r\n/**\r\n * Spec data structure\r\n */\r\nexport interface Spec {\r\n /** Unique spec identifier */\r\n id: string;\r\n /** Spec title (display name) */\r\n title: string;\r\n /** Spec file path */\r\n file: string;\r\n /** Spec dimension/category */\r\n dimension: SpecDimension;\r\n /** Scope: global (from ~/.ccw/) or project (from .ccw/) */\r\n scope: SpecScope;\r\n /** Workflow stage category for system-level loading */\r\n category?: SpecCategory;\r\n /** Read mode: required (always inject) or optional (keyword match) */\r\n readMode: SpecReadMode;\r\n /** Priority level */\r\n priority: SpecPriority;\r\n /** Keywords for matching (optional specs) */\r\n keywords: string[];\r\n /** Whether spec is enabled */\r\n enabled: boolean;\r\n /** Optional description */\r\n description?: string;\r\n}\r\n\r\n/**\r\n * SpecCard component props\r\n */\r\nexport interface SpecCardProps {\r\n /** Spec data */\r\n spec: Spec;\r\n /** Called when view content action is triggered */\r\n onView?: (spec: Spec) => void;\r\n /** Called when edit action is triggered */\r\n onEdit?: (spec: Spec) => void;\r\n /** Called when delete action is triggered */\r\n onDelete?: (specId: string) => void;\r\n /** Called when toggle enabled is triggered */\r\n onToggle?: (specId: string, enabled: boolean) => void;\r\n /** Optional className */\r\n className?: string;\r\n /** Show actions dropdown */\r\n showActions?: boolean;\r\n /** Disabled state for actions */\r\n actionsDisabled?: boolean;\r\n}\r\n\r\n// ========== Configuration ==========\r\n\r\n// Read mode badge configuration\r\nconst readModeConfig: Record<\r\n SpecReadMode,\r\n { variant: 'default' | 'secondary'; labelKey: string }\r\n> = {\r\n required: { variant: 'default', labelKey: 'specs.readMode.required' },\r\n optional: { variant: 'secondary', labelKey: 'specs.readMode.optional' },\r\n};\r\n\r\n// Priority badge configuration\r\nconst priorityConfig: Record<\r\n SpecPriority,\r\n { variant: 'destructive' | 'warning' | 'info' | 'secondary'; labelKey: string }\r\n> = {\r\n critical: { variant: 'destructive', labelKey: 'specs.priority.critical' },\r\n high: { variant: 'warning', labelKey: 'specs.priority.high' },\r\n medium: { variant: 'info', labelKey: 'specs.priority.medium' },\r\n low: { variant: 'secondary', labelKey: 'specs.priority.low' },\r\n};\r\n\r\n// Category badge configuration for workflow stage\r\nconst categoryConfig: Record<\r\n SpecCategory,\r\n { variant: 'default' | 'secondary' | 'outline'; labelKey: string }\r\n> = {\r\n general: { variant: 'secondary', labelKey: 'specs.category.general' },\r\n exploration: { variant: 'outline', labelKey: 'specs.category.exploration' },\r\n planning: { variant: 'outline', labelKey: 'specs.category.planning' },\r\n execution: { variant: 'outline', labelKey: 'specs.category.execution' },\r\n};\r\n\r\n// ========== Component ==========\r\n\r\n/**\r\n * SpecCard component for displaying spec information\r\n */\r\nexport function SpecCard({\r\n spec,\r\n onView,\r\n onEdit,\r\n onDelete,\r\n onToggle,\r\n className,\r\n showActions = true,\r\n actionsDisabled = false,\r\n}: SpecCardProps) {\r\n const { formatMessage } = useIntl();\r\n\r\n const readMode = readModeConfig[spec.readMode];\r\n const priority = priorityConfig[spec.priority];\r\n\r\n const handleToggle = (enabled: boolean) => {\r\n onToggle?.(spec.id, enabled);\r\n };\r\n\r\n const handleAction = (e: React.MouseEvent, action: 'edit' | 'delete') => {\r\n e.stopPropagation();\r\n switch (action) {\r\n case 'edit':\r\n onEdit?.(spec);\r\n break;\r\n case 'delete':\r\n onDelete?.(spec.id);\r\n break;\r\n }\r\n };\r\n\r\n return (\r\n <Card\r\n className={cn(\r\n 'group transition-all duration-200 hover:shadow-md hover:border-primary/30 hover-glow',\r\n !spec.enabled && 'opacity-60',\r\n className\r\n )}\r\n >\r\n <CardContent className=\"p-4\">\r\n {/* Header */}\r\n <div className=\"flex items-start justify-between gap-2\">\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <FileText className=\"h-4 w-4 text-muted-foreground shrink-0\" />\r\n <h3 className=\"font-medium text-card-foreground truncate\">\r\n {spec.title}\r\n </h3>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-0.5 truncate\">\r\n {spec.file}\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-2 flex-shrink-0\">\r\n {showActions && (\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity\"\r\n onClick={(e) => e.stopPropagation()}\r\n disabled={actionsDisabled}\r\n >\r\n <MoreVertical className=\"h-4 w-4\" />\r\n <span className=\"sr-only\">{formatMessage({ id: 'common.aria.actions' })}</span>\r\n </Button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\">\r\n <DropdownMenuItem onClick={(e) => { e.stopPropagation(); onView?.(spec); }}>\r\n <Eye className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'specs.actions.view', defaultMessage: 'View Content' })}\r\n </DropdownMenuItem>\r\n <DropdownMenuItem onClick={(e) => handleAction(e, 'edit')}>\r\n <Edit className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'specs.actions.edit' })}\r\n </DropdownMenuItem>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem\r\n onClick={(e) => handleAction(e, 'delete')}\r\n className=\"text-destructive focus:text-destructive\"\r\n >\r\n <Trash2 className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'specs.actions.delete' })}\r\n </DropdownMenuItem>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Badges */}\r\n <div className=\"mt-3 flex flex-wrap items-center gap-2\">\r\n {/* Category badge - workflow stage */}\r\n {spec.category && (\r\n <Badge variant={categoryConfig[spec.category].variant} className=\"text-xs gap-1\">\r\n <Layers className=\"h-3 w-3\" />\r\n {formatMessage({ id: categoryConfig[spec.category].labelKey, defaultMessage: spec.category })}\r\n </Badge>\r\n )}\r\n {/* Scope badge - only show for personal specs */}\r\n {spec.dimension === 'personal' && (\r\n <Badge variant=\"outline\" className=\"text-xs gap-1\">\r\n {spec.scope === 'global' ? (\r\n <>\r\n <Globe className=\"h-3 w-3\" />\r\n {formatMessage({ id: 'specs.scope.global', defaultMessage: 'Global' })}\r\n </>\r\n ) : (\r\n <>\r\n <Folder className=\"h-3 w-3\" />\r\n {formatMessage({ id: 'specs.scope.project', defaultMessage: 'Project' })}\r\n </>\r\n )}\r\n </Badge>\r\n )}\r\n <Badge variant={readMode.variant} className=\"text-xs\">\r\n {formatMessage({ id: readMode.labelKey })}\r\n </Badge>\r\n <Badge variant={priority.variant} className=\"text-xs\">\r\n {formatMessage({ id: priority.labelKey })}\r\n </Badge>\r\n </div>\r\n\r\n {/* Description */}\r\n {spec.description && (\r\n <p className=\"mt-3 text-sm text-muted-foreground line-clamp-2\">\r\n {spec.description}\r\n </p>\r\n )}\r\n\r\n {/* Keywords */}\r\n {spec.keywords.length > 0 && (\r\n <div className=\"mt-3 flex flex-wrap items-center gap-1.5\">\r\n <Tag className=\"h-3.5 w-3.5 text-muted-foreground\" />\r\n {spec.keywords.slice(0, 4).map((keyword) => (\r\n <Badge key={keyword} variant=\"outline\" className=\"text-xs px-1.5 py-0\">\r\n {keyword}\r\n </Badge>\r\n ))}\r\n {spec.keywords.length > 4 && (\r\n <span className=\"text-xs text-muted-foreground\">\r\n +{spec.keywords.length - 4}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Footer with toggle */}\r\n <div className=\"mt-3 pt-3 border-t border-border flex items-center justify-between\">\r\n <span className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: spec.enabled ? 'specs.status.enabled' : 'specs.status.disabled' })}\r\n </span>\r\n <Switch\r\n checked={spec.enabled}\r\n onCheckedChange={handleToggle}\r\n disabled={actionsDisabled}\r\n className=\"data-[state=checked]:bg-primary\"\r\n />\r\n </div>\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n\r\n/**\r\n * Skeleton loader for SpecCard\r\n */\r\nexport function SpecCardSkeleton({ className }: { className?: string }) {\r\n return (\r\n <Card className={cn('animate-pulse', className)}>\r\n <CardContent className=\"p-4\">\r\n <div className=\"flex items-start justify-between\">\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"h-4 w-4 rounded bg-muted\" />\r\n <div className=\"h-5 w-32 rounded bg-muted\" />\r\n </div>\r\n <div className=\"mt-1 h-3 w-24 rounded bg-muted\" />\r\n </div>\r\n <div className=\"h-8 w-8 rounded bg-muted\" />\r\n </div>\r\n <div className=\"mt-3 flex gap-2\">\r\n <div className=\"h-5 w-14 rounded-full bg-muted\" />\r\n <div className=\"h-5 w-12 rounded-full bg-muted\" />\r\n </div>\r\n <div className=\"mt-3 h-4 w-full rounded bg-muted\" />\r\n <div className=\"mt-2 flex gap-1.5\">\r\n <div className=\"h-5 w-16 rounded bg-muted\" />\r\n <div className=\"h-5 w-14 rounded bg-muted\" />\r\n <div className=\"h-5 w-12 rounded bg-muted\" />\r\n </div>\r\n <div className=\"mt-3 pt-3 border-t border-border flex items-center justify-between\">\r\n <div className=\"h-3 w-16 rounded bg-muted\" />\r\n <div className=\"h-5 w-9 rounded-full bg-muted\" />\r\n </div>\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n\r\nexport default SpecCard;\r\n","// ========================================\r\n// SpecDialog Component\r\n// ========================================\r\n// Dialog for editing spec frontmatter (title, readMode, priority, keywords)\r\n\r\nimport * as React from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n DialogDescription,\r\n DialogFooter,\r\n} from '@/components/ui/Dialog';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Label } from '@/components/ui/Label';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport {\r\n Select,\r\n SelectTrigger,\r\n SelectValue,\r\n SelectContent,\r\n SelectItem,\r\n} from '@/components/ui/Select';\r\nimport { Tag, X } from 'lucide-react';\r\nimport type { Spec, SpecReadMode, SpecPriority } from './SpecCard';\r\n\r\n// ========== Types ==========\r\n\r\n/**\r\n * Spec form data for editing\r\n */\r\nexport interface SpecFormData {\r\n title: string;\r\n readMode: SpecReadMode;\r\n priority: SpecPriority;\r\n keywords: string[];\r\n}\r\n\r\n/**\r\n * SpecDialog component props\r\n */\r\nexport interface SpecDialogProps {\r\n /** Whether dialog is open */\r\n open: boolean;\r\n /** Called when dialog open state changes */\r\n onOpenChange: (open: boolean) => void;\r\n /** Spec being edited */\r\n spec: Spec | null;\r\n /** Called when save is clicked */\r\n onSave: (specId: string, data: SpecFormData) => Promise<void> | void;\r\n /** Optional loading state */\r\n isLoading?: boolean;\r\n}\r\n\r\n// ========== Constants ==========\r\n\r\nconst READ_MODE_OPTIONS: { value: SpecReadMode; labelKey: string }[] = [\r\n { value: 'required', labelKey: 'specs.readMode.required' },\r\n { value: 'optional', labelKey: 'specs.readMode.optional' },\r\n];\r\n\r\nconst PRIORITY_OPTIONS: { value: SpecPriority; labelKey: string }[] = [\r\n { value: 'critical', labelKey: 'specs.priority.critical' },\r\n { value: 'high', labelKey: 'specs.priority.high' },\r\n { value: 'medium', labelKey: 'specs.priority.medium' },\r\n { value: 'low', labelKey: 'specs.priority.low' },\r\n];\r\n\r\n// ========== Component ==========\r\n\r\n/**\r\n * SpecDialog component for editing spec frontmatter\r\n */\r\nexport function SpecDialog({\r\n open,\r\n onOpenChange,\r\n spec,\r\n onSave,\r\n isLoading = false,\r\n}: SpecDialogProps) {\r\n const { formatMessage } = useIntl();\r\n const [formData, setFormData] = React.useState<SpecFormData>({\r\n title: '',\r\n readMode: 'optional',\r\n priority: 'medium',\r\n keywords: [],\r\n });\r\n const [keywordInput, setKeywordInput] = React.useState('');\r\n const [errors, setErrors] = React.useState<Partial<Record<keyof SpecFormData, string>>>({});\r\n\r\n // Reset form when spec changes\r\n React.useEffect(() => {\r\n if (spec) {\r\n setFormData({\r\n title: spec.title,\r\n readMode: spec.readMode,\r\n priority: spec.priority,\r\n keywords: [...spec.keywords],\r\n });\r\n setErrors({});\r\n setKeywordInput('');\r\n }\r\n }, [spec]);\r\n\r\n // Validate form\r\n const validateForm = (): boolean => {\r\n const newErrors: Partial<Record<keyof SpecFormData, string>> = {};\r\n\r\n if (!formData.title.trim()) {\r\n newErrors.title = formatMessage({ id: 'specs.validation.titleRequired' });\r\n }\r\n\r\n setErrors(newErrors);\r\n return Object.keys(newErrors).length === 0;\r\n };\r\n\r\n // Handle save\r\n const handleSave = async () => {\r\n if (!spec || !validateForm()) return;\r\n\r\n await onSave(spec.id, formData);\r\n };\r\n\r\n // Handle keyword input\r\n const handleKeywordKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\r\n if (e.key === 'Enter' || e.key === ',') {\r\n e.preventDefault();\r\n addKeyword();\r\n }\r\n };\r\n\r\n // Add keyword\r\n const addKeyword = () => {\r\n const keyword = keywordInput.trim().toLowerCase();\r\n if (keyword && !formData.keywords.includes(keyword)) {\r\n setFormData((prev) => ({\r\n ...prev,\r\n keywords: [...prev.keywords, keyword],\r\n }));\r\n }\r\n setKeywordInput('');\r\n };\r\n\r\n // Remove keyword\r\n const removeKeyword = (keyword: string) => {\r\n setFormData((prev) => ({\r\n ...prev,\r\n keywords: prev.keywords.filter((k) => k !== keyword),\r\n }));\r\n };\r\n\r\n if (!spec) return null;\r\n\r\n return (\r\n <Dialog open={open} onOpenChange={onOpenChange}>\r\n <DialogContent className=\"sm:max-w-[500px]\">\r\n <DialogHeader>\r\n <DialogTitle>\r\n {formatMessage({ id: 'specs.dialog.editTitle' }, { title: spec.title })}\r\n </DialogTitle>\r\n <DialogDescription>\r\n {formatMessage({ id: 'specs.dialog.editDescription' })}\r\n </DialogDescription>\r\n </DialogHeader>\r\n\r\n <div className=\"space-y-4 py-4\">\r\n {/* Title field */}\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"title\">\r\n {formatMessage({ id: 'specs.form.title' })}\r\n </Label>\r\n <Input\r\n id=\"title\"\r\n value={formData.title}\r\n onChange={(e) => setFormData((prev) => ({ ...prev, title: e.target.value }))}\r\n placeholder={formatMessage({ id: 'specs.form.titlePlaceholder' })}\r\n error={!!errors.title}\r\n disabled={isLoading}\r\n />\r\n {errors.title && (\r\n <p className=\"text-sm text-destructive\">{errors.title}</p>\r\n )}\r\n </div>\r\n\r\n {/* Read mode and Priority */}\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div className=\"space-y-2\">\r\n <Label>{formatMessage({ id: 'specs.form.readMode' })}</Label>\r\n <Select\r\n value={formData.readMode}\r\n onValueChange={(value: SpecReadMode) =>\r\n setFormData((prev) => ({ ...prev, readMode: value }))\r\n }\r\n disabled={isLoading}\r\n >\r\n <SelectTrigger>\r\n <SelectValue />\r\n </SelectTrigger>\r\n <SelectContent>\r\n {READ_MODE_OPTIONS.map((option) => (\r\n <SelectItem key={option.value} value={option.value}>\r\n {formatMessage({ id: option.labelKey })}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n\r\n <div className=\"space-y-2\">\r\n <Label>{formatMessage({ id: 'specs.form.priority' })}</Label>\r\n <Select\r\n value={formData.priority}\r\n onValueChange={(value: SpecPriority) =>\r\n setFormData((prev) => ({ ...prev, priority: value }))\r\n }\r\n disabled={isLoading}\r\n >\r\n <SelectTrigger>\r\n <SelectValue />\r\n </SelectTrigger>\r\n <SelectContent>\r\n {PRIORITY_OPTIONS.map((option) => (\r\n <SelectItem key={option.value} value={option.value}>\r\n {formatMessage({ id: option.labelKey })}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n </div>\r\n\r\n {/* Keywords */}\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"keywords\">\r\n {formatMessage({ id: 'specs.form.keywords' })}\r\n </Label>\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"relative flex-1\">\r\n <Input\r\n id=\"keywords\"\r\n value={keywordInput}\r\n onChange={(e) => setKeywordInput(e.target.value)}\r\n onKeyDown={handleKeywordKeyDown}\r\n onBlur={addKeyword}\r\n placeholder={formatMessage({ id: 'specs.form.keywordsPlaceholder' })}\r\n disabled={isLoading}\r\n />\r\n </div>\r\n <Button\r\n type=\"button\"\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={addKeyword}\r\n disabled={isLoading || !keywordInput.trim()}\r\n >\r\n {formatMessage({ id: 'specs.form.addKeyword' })}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'specs.form.keywordsHint' })}\r\n </p>\r\n\r\n {/* Keywords display */}\r\n {formData.keywords.length > 0 && (\r\n <div className=\"flex flex-wrap gap-1.5 mt-2\">\r\n <Tag className=\"h-3.5 w-3.5 text-muted-foreground mt-0.5\" />\r\n {formData.keywords.map((keyword) => (\r\n <Badge\r\n key={keyword}\r\n variant=\"secondary\"\r\n className=\"text-xs pl-2 pr-1 gap-1\"\r\n >\r\n {keyword}\r\n <button\r\n type=\"button\"\r\n onClick={() => removeKeyword(keyword)}\r\n className=\"ml-0.5 hover:text-destructive transition-colors\"\r\n disabled={isLoading}\r\n >\r\n <X className=\"h-3 w-3\" />\r\n </button>\r\n </Badge>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* File info */}\r\n <div className=\"pt-2 border-t border-border\">\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'specs.form.fileInfo' }, { file: spec.file })}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <DialogFooter>\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => onOpenChange(false)}\r\n disabled={isLoading}\r\n >\r\n {formatMessage({ id: 'common.cancel' })}\r\n </Button>\r\n <Button onClick={handleSave} disabled={isLoading}>\r\n {isLoading\r\n ? formatMessage({ id: 'specs.form.saving' })\r\n : formatMessage({ id: 'common.save' })}\r\n </Button>\r\n </DialogFooter>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}\r\n\r\nexport default SpecDialog;\r\n","// ========================================\r\n// SpecContentDialog Component\r\n// ========================================\r\n// Dialog for viewing and editing spec markdown content\r\n\r\nimport * as React from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { cn } from '@/lib/utils';\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n DialogDescription,\r\n DialogFooter,\r\n} from '@/components/ui/Dialog';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Textarea } from '@/components/ui/Textarea';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { Eye, Edit2, Save, FileText, Loader2 } from 'lucide-react';\r\nimport type { Spec } from './SpecCard';\r\n\r\n// ========== Types ==========\r\n\r\n/**\r\n * SpecContentDialog component props\r\n */\r\nexport interface SpecContentDialogProps {\r\n /** Whether dialog is open */\r\n open: boolean;\r\n /** Called when dialog open state changes */\r\n onOpenChange: (open: boolean) => void;\r\n /** Spec being viewed/edited */\r\n spec: Spec | null;\r\n /** Initial content of the spec */\r\n content?: string;\r\n /** Called when content is saved */\r\n onSave?: (specId: string, content: string) => Promise<void> | void;\r\n /** Whether in read-only mode */\r\n readOnly?: boolean;\r\n /** Optional loading state */\r\n isLoading?: boolean;\r\n}\r\n\r\n// ========== Helper Functions ==========\r\n\r\n/**\r\n * Extract frontmatter from markdown content\r\n */\r\nfunction parseFrontmatter(content: string): {\r\n frontmatter: Record<string, unknown>;\r\n body: string;\r\n} {\r\n const frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/;\r\n const match = content.match(frontmatterRegex);\r\n\r\n if (!match) {\r\n return { frontmatter: {}, body: content };\r\n }\r\n\r\n const frontmatterLines = match[1].split('\\n');\r\n const frontmatter: Record<string, unknown> = {};\r\n\r\n for (const line of frontmatterLines) {\r\n const colonIndex = line.indexOf(':');\r\n if (colonIndex > 0) {\r\n const key = line.slice(0, colonIndex).trim();\r\n const value = line.slice(colonIndex + 1).trim();\r\n\r\n // Parse arrays (keywords: [a, b, c])\r\n if (value.startsWith('[') && value.endsWith(']')) {\r\n frontmatter[key] = value\r\n .slice(1, -1)\r\n .split(',')\r\n .map(s => s.trim().replace(/^['\"]|['\"]$/g, ''))\r\n .filter(Boolean);\r\n } else {\r\n frontmatter[key] = value.replace(/^['\"]|['\"]$/g, '');\r\n }\r\n }\r\n }\r\n\r\n return { frontmatter, body: match[2] };\r\n}\r\n\r\n// ========== Component ==========\r\n\r\n/**\r\n * SpecContentDialog component for viewing and editing spec content\r\n */\r\nexport function SpecContentDialog({\r\n open,\r\n onOpenChange,\r\n spec,\r\n content: initialContent,\r\n onSave,\r\n readOnly = false,\r\n isLoading = false,\r\n}: SpecContentDialogProps) {\r\n const { formatMessage } = useIntl();\r\n const [mode, setMode] = React.useState<'view' | 'edit'>('view');\r\n const [content, setContent] = React.useState(initialContent || '');\r\n const [editedContent, setEditedContent] = React.useState('');\r\n\r\n // Parse frontmatter for display\r\n const { body } = React.useMemo(() => {\r\n return parseFrontmatter(content);\r\n }, [content]);\r\n\r\n // Reset when spec changes\r\n React.useEffect(() => {\r\n if (spec && open) {\r\n // Fetch spec content\r\n const fetchContent = async () => {\r\n try {\r\n const response = await fetch(`/api/specs/detail?file=${encodeURIComponent(spec.file)}`);\r\n if (response.ok) {\r\n const data = await response.json();\r\n setContent(data.content || '');\r\n setEditedContent(data.content || '');\r\n }\r\n } catch (error) {\r\n console.error('Failed to fetch spec content:', error);\r\n }\r\n };\r\n fetchContent();\r\n setMode('view');\r\n }\r\n }, [spec, open]);\r\n\r\n // Handle save\r\n const handleSave = async () => {\r\n if (!spec || !onSave) return;\r\n await onSave(spec.id, editedContent);\r\n setContent(editedContent);\r\n setMode('view');\r\n };\r\n\r\n // Handle cancel edit\r\n const handleCancelEdit = () => {\r\n setEditedContent(content);\r\n setMode('view');\r\n };\r\n\r\n if (!spec) return null;\r\n\r\n return (\r\n <Dialog open={open} onOpenChange={onOpenChange}>\r\n <DialogContent className={cn('sm:max-w-[800px] max-h-[80vh]', mode === 'edit' && 'flex flex-col')}>\r\n <DialogHeader>\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <FileText className=\"h-5 w-5\" />\r\n {spec.title}\r\n </DialogTitle>\r\n {!readOnly && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n onClick={() => mode === 'view' ? setMode('edit') : handleCancelEdit()}\r\n disabled={isLoading}\r\n >\r\n {mode === 'view' ? (\r\n <>\r\n <Edit2 className=\"h-4 w-4 mr-1\" />\r\n {formatMessage({ id: 'specs.content.edit', defaultMessage: 'Edit' })}\r\n </>\r\n ) : (\r\n <>\r\n <Eye className=\"h-4 w-4 mr-1\" />\r\n {formatMessage({ id: 'specs.content.view', defaultMessage: 'View' })}\r\n </>\r\n )}\r\n </Button>\r\n )}\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Badge variant={spec.readMode === 'required' ? 'default' : 'secondary'}>\r\n {formatMessage({ id: `specs.readMode.${spec.readMode}` })}\r\n </Badge>\r\n <Badge variant=\"outline\">\r\n {formatMessage({ id: `specs.priority.${spec.priority}` })}\r\n </Badge>\r\n </div>\r\n </div>\r\n <DialogDescription>\r\n {spec.file}\r\n </DialogDescription>\r\n </DialogHeader>\r\n\r\n <div className=\"flex-1 overflow-auto py-4\">\r\n {mode === 'view' ? (\r\n <div className=\"space-y-4\">\r\n {/* Frontmatter Info */}\r\n <div className=\"p-3 bg-muted/50 rounded-lg\">\r\n <div className=\"text-sm font-medium mb-2\">\r\n {formatMessage({ id: 'specs.content.metadata', defaultMessage: 'Metadata' })}\r\n </div>\r\n <div className=\"grid grid-cols-2 gap-2 text-sm\">\r\n <div>\r\n <span className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.form.readMode', defaultMessage: 'Read Mode' })}:\r\n </span>{' '}\r\n <Badge variant=\"secondary\" className=\"text-xs\">\r\n {formatMessage({ id: `specs.readMode.${spec.readMode}` })}\r\n </Badge>\r\n </div>\r\n <div>\r\n <span className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.form.priority', defaultMessage: 'Priority' })}:\r\n </span>{' '}\r\n <Badge variant=\"outline\" className=\"text-xs\">\r\n {formatMessage({ id: `specs.priority.${spec.priority}` })}\r\n </Badge>\r\n </div>\r\n </div>\r\n {spec.keywords.length > 0 && (\r\n <div className=\"mt-2 text-sm\">\r\n <span className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.form.keywords', defaultMessage: 'Keywords' })}:\r\n </span>{' '}\r\n {spec.keywords.map(k => (\r\n <Badge key={k} variant=\"outline\" className=\"text-xs mr-1\">{k}</Badge>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Markdown Content */}\r\n <div className=\"border rounded-lg\">\r\n <div className=\"bg-muted/30 px-3 py-2 border-b text-sm font-medium\">\r\n {formatMessage({ id: 'specs.content.markdownContent', defaultMessage: 'Markdown Content' })}\r\n </div>\r\n <pre className=\"p-4 text-sm overflow-auto max-h-[400px] whitespace-pre-wrap break-words\">\r\n {body || formatMessage({ id: 'specs.content.noContent', defaultMessage: 'No content available' })}\r\n </pre>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"space-y-4\">\r\n <div className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.content.editHint', defaultMessage: 'Edit the full markdown content including frontmatter. Changes to frontmatter will be reflected in the spec metadata.' })}\r\n </div>\r\n <Textarea\r\n value={editedContent}\r\n onChange={(e) => setEditedContent(e.target.value)}\r\n className=\"font-mono text-sm min-h-[400px] resize-none\"\r\n placeholder={formatMessage({ id: 'specs.content.placeholder', defaultMessage: '# Spec Title\\n\\nContent here...' })}\r\n disabled={isLoading}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n\r\n <DialogFooter>\r\n {mode === 'edit' ? (\r\n <>\r\n <Button variant=\"outline\" onClick={handleCancelEdit} disabled={isLoading}>\r\n {formatMessage({ id: 'specs.common.cancel', defaultMessage: 'Cancel' })}\r\n </Button>\r\n <Button onClick={handleSave} disabled={isLoading}>\r\n {isLoading ? (\r\n <>\r\n <Loader2 className=\"h-4 w-4 mr-2 animate-spin\" />\r\n {formatMessage({ id: 'specs.common.saving', defaultMessage: 'Saving...' })}\r\n </>\r\n ) : (\r\n <>\r\n <Save className=\"h-4 w-4 mr-2\" />\r\n {formatMessage({ id: 'specs.common.save', defaultMessage: 'Save' })}\r\n </>\r\n )}\r\n </Button>\r\n </>\r\n ) : (\r\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\r\n {formatMessage({ id: 'specs.common.close', defaultMessage: 'Close' })}\r\n </Button>\r\n )}\r\n </DialogFooter>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}\r\n\r\nexport default SpecContentDialog;\r\n","// ========================================\r\n// InjectionControlTab Component\r\n// ========================================\r\n// Tab for managing spec injection control settings\r\n\r\nimport { useState, useEffect, useCallback, useMemo } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { Link } from 'react-router-dom';\r\nimport { toast } from 'sonner';\r\nimport { cn } from '@/lib/utils';\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n} from '@/components/ui/Dialog';\r\nimport {\r\n Card,\r\n CardContent,\r\n CardDescription,\r\n CardHeader,\r\n CardTitle,\r\n} from '@/components/ui/Card';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Label } from '@/components/ui/Label';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Switch } from '@/components/ui/Switch';\r\nimport { Progress } from '@/components/ui/Progress';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport {\r\n AlertCircle,\r\n Info,\r\n Loader2,\r\n RefreshCw,\r\n AlertTriangle,\r\n Plug,\r\n Download,\r\n CheckCircle2,\r\n Settings,\r\n FileText,\r\n Eye,\r\n Globe,\r\n Folder,\r\n ChevronDown,\r\n ChevronRight,\r\n Layers,\r\n Filter,\r\n} from 'lucide-react';\r\nimport { useInstallRecommendedHooks, useSystemSettings } from '@/hooks/useSystemSettings';\r\nimport type { InjectionPreviewFile, InjectionPreviewResponse } from '@/lib/api';\r\nimport { getInjectionPreview, COMMAND_PREVIEWS, type CommandPreviewConfig } from '@/lib/api';\r\n\r\n// ========== Types ==========\r\n\r\nexport interface InjectionStats {\r\n requiredOnly: number;\r\n withKeywords: number;\r\n maxLength: number;\r\n percentage: number;\r\n}\r\n\r\nexport interface SpecStatsResponse {\r\n dimensions: {\r\n specs: { count: number; requiredCount: number };\r\n personal: { count: number; requiredCount: number };\r\n };\r\n injectionLength: InjectionStats;\r\n}\r\n\r\nexport interface InjectionSettings {\r\n maxLength: number;\r\n warnThreshold: number;\r\n truncateOnExceed: boolean;\r\n}\r\n\r\nexport interface SystemSettingsResponse {\r\n injectionControl: InjectionSettings;\r\n personalSpecDefaults: {\r\n defaultReadMode: 'required' | 'optional';\r\n autoEnable: boolean;\r\n };\r\n}\r\n\r\nexport interface InjectionControlTabProps {\r\n className?: string;\r\n}\r\n\r\n// ========== Category Configuration ==========\r\n\r\ntype SpecCategory = 'general' | 'exploration' | 'planning' | 'execution';\r\n\r\nconst SPEC_CATEGORIES: SpecCategory[] = ['general', 'exploration', 'planning', 'execution'];\r\n\r\nconst CATEGORY_CONFIG: Record<SpecCategory, { color: string; bgColor: string }> = {\r\n general: { color: 'text-gray-600', bgColor: 'bg-gray-100 dark:bg-gray-800' },\r\n exploration: { color: 'text-blue-600', bgColor: 'bg-blue-100 dark:bg-blue-900/30' },\r\n planning: { color: 'text-purple-600', bgColor: 'bg-purple-100 dark:bg-purple-900/30' },\r\n execution: { color: 'text-green-600', bgColor: 'bg-green-100 dark:bg-green-900/30' },\r\n};\r\n\r\n// ========== Recommended Hooks Configuration ==========\r\n\r\nconst RECOMMENDED_HOOKS = [\r\n {\r\n id: 'spec-injection-session',\r\n name: 'Spec Context Injection (Session)',\r\n event: 'SessionStart',\r\n command: 'ccw spec load --stdin',\r\n scope: 'global' as const,\r\n description: 'Automatically inject spec context when Claude session starts',\r\n },\r\n {\r\n id: 'spec-injection-prompt',\r\n name: 'Spec Context Injection (Prompt)',\r\n event: 'UserPromptSubmit',\r\n command: 'ccw spec load --stdin',\r\n scope: 'project' as const,\r\n description: 'Inject spec context when user submits a prompt, matching keywords',\r\n },\r\n];\r\n\r\n// ========== API Functions ==========\r\n\r\nasync function fetchSpecStats(): Promise<SpecStatsResponse> {\r\n const response = await fetch('/api/specs/stats');\r\n if (!response.ok) {\r\n throw new Error('Failed to fetch spec stats');\r\n }\r\n return response.json();\r\n}\r\n\r\nasync function fetchSystemSettings(): Promise<SystemSettingsResponse> {\r\n const response = await fetch('/api/system/settings');\r\n if (!response.ok) {\r\n throw new Error('Failed to fetch system settings');\r\n }\r\n return response.json();\r\n}\r\n\r\nasync function updateInjectionSettings(\r\n settings: Partial<InjectionSettings>\r\n): Promise<SystemSettingsResponse> {\r\n const currentSettings = await fetchSystemSettings();\r\n const response = await fetch('/api/system/settings', {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n injectionControl: {\r\n ...currentSettings.injectionControl,\r\n ...settings,\r\n },\r\n }),\r\n });\r\n if (!response.ok) {\r\n throw new Error('Failed to update settings');\r\n }\r\n return response.json();\r\n}\r\n\r\n// ========== Helper Functions ==========\r\n\r\nfunction formatNumber(num: number): string {\r\n return num.toLocaleString();\r\n}\r\n\r\nfunction calculatePercentage(current: number, max: number): number {\r\n if (max <= 0) return 0;\r\n return Math.min(100, (current / max) * 100);\r\n}\r\n\r\n// ========== Component ==========\r\n\r\nexport function InjectionControlTab({ className }: InjectionControlTabProps) {\r\n const { formatMessage } = useIntl();\r\n const installHooksMutation = useInstallRecommendedHooks();\r\n\r\n // State for stats\r\n const [stats, setStats] = useState<SpecStatsResponse | null>(null);\r\n const [statsLoading, setStatsLoading] = useState(true);\r\n const [statsError, setStatsError] = useState<Error | null>(null);\r\n\r\n // State for settings\r\n const [settings, setSettings] = useState<InjectionSettings>({\r\n maxLength: 8000,\r\n warnThreshold: 6000,\r\n truncateOnExceed: true,\r\n });\r\n const [settingsLoading, setSettingsLoading] = useState(true);\r\n\r\n // Form state (for local editing before save)\r\n const [formData, setFormData] = useState<InjectionSettings>(settings);\r\n const [hasChanges, setHasChanges] = useState(false);\r\n const [isSaving, setIsSaving] = useState(false);\r\n\r\n // State for hooks installation\r\n const [installingHookIds, setInstallingHookIds] = useState<string[]>([]);\r\n\r\n // Fetch system settings (for hooks installation status)\r\n const systemSettingsQuery = useSystemSettings();\r\n\r\n // State for injection preview\r\n const [previewMode, setPreviewMode] = useState<'required' | 'all'>('required');\r\n const [categoryFilter, setCategoryFilter] = useState<SpecCategory | 'all'>('all');\r\n const [previewData, setPreviewData] = useState<InjectionPreviewResponse | null>(null);\r\n const [previewLoading, setPreviewLoading] = useState(false);\r\n const [expandedDimensions, setExpandedDimensions] = useState<Record<string, boolean>>({\r\n specs: true,\r\n personal: true,\r\n });\r\n const [previewDialogOpen, setPreviewDialogOpen] = useState(false);\r\n const [previewFile, setPreviewFile] = useState<InjectionPreviewFile | null>(null);\r\n\r\n // State for command preview\r\n const [selectedCommand, setSelectedCommand] = useState<CommandPreviewConfig>(COMMAND_PREVIEWS[0]);\r\n const [commandPreviewData, setCommandPreviewData] = useState<InjectionPreviewResponse | null>(null);\r\n const [commandPreviewLoading, setCommandPreviewLoading] = useState(false);\r\n const [commandPreviewDialogOpen, setCommandPreviewDialogOpen] = useState(false);\r\n\r\n // Fetch stats\r\n const loadStats = useCallback(async () => {\r\n setStatsLoading(true);\r\n setStatsError(null);\r\n try {\r\n const data = await fetchSpecStats();\r\n setStats(data);\r\n } catch (err) {\r\n setStatsError(err instanceof Error ? err : new Error('Unknown error'));\r\n } finally {\r\n setStatsLoading(false);\r\n }\r\n }, []);\r\n\r\n // Fetch settings\r\n const loadSettings = useCallback(async () => {\r\n setSettingsLoading(true);\r\n try {\r\n const data = await fetchSystemSettings();\r\n setSettings(data.injectionControl);\r\n setFormData(data.injectionControl);\r\n } catch (err) {\r\n console.error('Failed to load settings:', err);\r\n } finally {\r\n setSettingsLoading(false);\r\n }\r\n }, []);\r\n\r\n // Load injection preview\r\n const loadPreview = useCallback(async () => {\r\n setPreviewLoading(true);\r\n try {\r\n const data = await getInjectionPreview(previewMode, false);\r\n setPreviewData(data);\r\n } catch (err) {\r\n console.error('Failed to load injection preview:', err);\r\n } finally {\r\n setPreviewLoading(false);\r\n }\r\n }, [previewMode]);\r\n\r\n // Load file content for preview\r\n const loadFilePreview = useCallback(async (file: InjectionPreviewFile) => {\r\n try {\r\n const data = await getInjectionPreview(previewMode, true);\r\n const fileWithData = data.files.find(f => f.file === file.file);\r\n if (fileWithData) {\r\n setPreviewFile(fileWithData);\r\n setPreviewDialogOpen(true);\r\n }\r\n } catch (err) {\r\n console.error('Failed to load file preview:', err);\r\n }\r\n }, [previewMode]);\r\n\r\n // Load command preview content\r\n const loadCommandPreview = useCallback(async (command: CommandPreviewConfig) => {\r\n setCommandPreviewLoading(true);\r\n try {\r\n const data = await getInjectionPreview(command.mode, true, undefined, command.category);\r\n setCommandPreviewData(data);\r\n setSelectedCommand(command);\r\n setCommandPreviewDialogOpen(true);\r\n } catch (err) {\r\n console.error('Failed to load command preview:', err);\r\n } finally {\r\n setCommandPreviewLoading(false);\r\n }\r\n }, []);\r\n\r\n // Initial load\r\n useEffect(() => {\r\n loadStats();\r\n loadSettings();\r\n }, [loadStats, loadSettings]);\r\n\r\n // Load preview when mode changes\r\n useEffect(() => {\r\n loadPreview();\r\n }, [loadPreview]);\r\n\r\n // Check for changes\r\n useEffect(() => {\r\n const changed =\r\n formData.maxLength !== settings.maxLength ||\r\n formData.warnThreshold !== settings.warnThreshold ||\r\n formData.truncateOnExceed !== settings.truncateOnExceed;\r\n setHasChanges(changed);\r\n }, [formData, settings]);\r\n\r\n // Handle form field changes\r\n const handleFieldChange = <K extends keyof InjectionSettings>(\r\n field: K,\r\n value: InjectionSettings[K]\r\n ) => {\r\n setFormData((prev) => ({ ...prev, [field]: value }));\r\n };\r\n\r\n // Save settings\r\n const handleSave = async () => {\r\n setIsSaving(true);\r\n try {\r\n const result = await updateInjectionSettings(formData);\r\n setSettings(result.injectionControl);\r\n setFormData(result.injectionControl);\r\n setHasChanges(false);\r\n toast.success(\r\n formatMessage({ id: 'specs.injection.saveSuccess' }, { default: 'Settings saved successfully' })\r\n );\r\n } catch (err) {\r\n toast.error(\r\n formatMessage({ id: 'specs.injection.saveError' }, { default: 'Failed to save settings' })\r\n );\r\n console.error('Failed to save settings:', err);\r\n } finally {\r\n setIsSaving(false);\r\n }\r\n };\r\n\r\n // Reset form\r\n const handleReset = () => {\r\n setFormData(settings);\r\n setHasChanges(false);\r\n };\r\n\r\n const maxLengthError =\r\n formData.maxLength < 1000 || formData.maxLength > 50000\r\n ? formatMessage({ id: 'specs.injection.maxLengthError', defaultMessage: 'Must be between 1000 and 50000' })\r\n : null;\r\n\r\n const warnThresholdError =\r\n formData.warnThreshold < 0 || formData.warnThreshold >= formData.maxLength\r\n ? formatMessage({ id: 'specs.injection.warnThresholdError', defaultMessage: 'Must be less than max length' })\r\n : null;\r\n\r\n // Toggle dimension expansion\r\n const toggleDimension = (dim: string) => {\r\n setExpandedDimensions(prev => ({ ...prev, [dim]: !prev[dim] }));\r\n };\r\n\r\n // ========== Hooks Installation ==========\r\n\r\n const installedHookIds = useMemo(() => {\r\n const installed = new Set<string>();\r\n const hooks = systemSettingsQuery.data?.recommendedHooks;\r\n if (hooks) {\r\n hooks.forEach(hook => {\r\n if (hook.installed) {\r\n installed.add(hook.id);\r\n }\r\n });\r\n }\r\n return installed;\r\n }, [systemSettingsQuery.data?.recommendedHooks]);\r\n\r\n const installedCount = installedHookIds.size;\r\n const allHooksInstalled = installedCount === RECOMMENDED_HOOKS.length;\r\n\r\n const handleInstallHook = useCallback(async (hookId: string) => {\r\n setInstallingHookIds(prev => [...prev, hookId]);\r\n try {\r\n await installHooksMutation.installHooks([hookId], 'global');\r\n toast.success(\r\n formatMessage({ id: 'specs.hooks.installSuccess', defaultMessage: 'Hook installed successfully' })\r\n );\r\n } catch (err) {\r\n toast.error(\r\n formatMessage({ id: 'specs.hooks.installError', defaultMessage: 'Failed to install hook' })\r\n );\r\n console.error('Failed to install hook:', err);\r\n } finally {\r\n setInstallingHookIds(prev => prev.filter(id => id !== hookId));\r\n }\r\n }, [installHooksMutation, formatMessage]);\r\n\r\n const handleInstallAllHooks = useCallback(async () => {\r\n const uninstalledHooks = RECOMMENDED_HOOKS.filter(h => !installedHookIds.has(h.id));\r\n if (uninstalledHooks.length === 0) return;\r\n\r\n setInstallingHookIds(uninstalledHooks.map(h => h.id));\r\n try {\r\n await installHooksMutation.installHooks(\r\n uninstalledHooks.map(h => h.id),\r\n 'global'\r\n );\r\n toast.success(\r\n formatMessage({ id: 'specs.hooks.installAllSuccess', defaultMessage: 'All hooks installed successfully' })\r\n );\r\n } catch (err) {\r\n toast.error(\r\n formatMessage({ id: 'specs.hooks.installError', defaultMessage: 'Failed to install hooks' })\r\n );\r\n console.error('Failed to install hooks:', err);\r\n } finally {\r\n setInstallingHookIds([]);\r\n }\r\n }, [installedHookIds, installHooksMutation, formatMessage]);\r\n\r\n // Group files by dimension and filter by category\r\n const filesByDimension = useMemo(() => {\r\n if (!previewData) return {};\r\n const grouped: Record<string, InjectionPreviewFile[]> = {};\r\n for (const file of previewData.files) {\r\n // Apply category filter\r\n if (categoryFilter !== 'all' && file.category !== categoryFilter) {\r\n continue;\r\n }\r\n if (!grouped[file.dimension]) {\r\n grouped[file.dimension] = [];\r\n }\r\n grouped[file.dimension].push(file);\r\n }\r\n return grouped;\r\n }, [previewData, categoryFilter]);\r\n\r\n // Calculate category statistics\r\n const categoryStats = useMemo(() => {\r\n if (!previewData) {\r\n return { general: 0, exploration: 0, planning: 0, execution: 0 };\r\n }\r\n const stats: Record<SpecCategory, number> = { general: 0, exploration: 0, planning: 0, execution: 0 };\r\n for (const file of previewData.files) {\r\n const cat = (file.category as SpecCategory) || 'general';\r\n if (stats[cat] !== undefined) {\r\n stats[cat]++;\r\n }\r\n }\r\n return stats;\r\n }, [previewData]);\r\n\r\n // Calculate progress and status - use API's maxLength for consistency\r\n const currentLength = stats?.injectionLength?.withKeywords || 0;\r\n const apiMaxLength = stats?.injectionLength?.maxLength || settings.maxLength;\r\n const maxLength = apiMaxLength; // Use API's maxLength for consistency\r\n const warnThreshold = settings.warnThreshold;\r\n const percentage = calculatePercentage(currentLength, maxLength);\r\n const isOverLimit = currentLength > maxLength;\r\n const isOverWarning = currentLength > warnThreshold;\r\n const remainingSpace = Math.max(0, maxLength - currentLength);\r\n\r\n // Calculate approximate line count (assuming ~80 chars per line)\r\n const estimatedLineCount = Math.ceil(currentLength / 80);\r\n const maxLineCount = Math.ceil(maxLength / 80);\r\n\r\n return (\r\n <div className={cn('space-y-6', className)}>\r\n {/* Recommended Hooks Section */}\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <Plug className=\"h-5 w-5\" />\r\n {formatMessage({ id: 'specs.recommendedHooks', defaultMessage: 'Recommended Hooks' })}\r\n </CardTitle>\r\n <CardDescription>\r\n {formatMessage({\r\n id: 'specs.recommendedHooksDesc',\r\n defaultMessage: 'One-click install spec injection hooks for automatic context loading',\r\n })}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n <Button\r\n onClick={handleInstallAllHooks}\r\n disabled={allHooksInstalled || installingHookIds.length > 0}\r\n >\r\n {allHooksInstalled ? (\r\n <>\r\n <CheckCircle2 className=\"h-4 w-4 mr-2\" />\r\n {formatMessage({ id: 'specs.allHooksInstalled', defaultMessage: 'All Hooks Installed' })}\r\n </>\r\n ) : (\r\n <>\r\n <Download className=\"h-4 w-4 mr-2\" />\r\n {formatMessage({ id: 'specs.installAllHooks', defaultMessage: 'Install All Hooks' })}\r\n </>\r\n )}\r\n </Button>\r\n <div className=\"text-sm text-muted-foreground\">\r\n {installedCount} / {RECOMMENDED_HOOKS.length}{' '}\r\n {formatMessage({ id: 'specs.hooksInstalled', defaultMessage: 'installed' })}\r\n </div>\r\n </div>\r\n <Button variant=\"ghost\" size=\"sm\" asChild>\r\n <Link to=\"/hooks\">\r\n <Settings className=\"h-4 w-4 mr-1\" />\r\n {formatMessage({ id: 'specs.manageHooks', defaultMessage: 'Manage Hooks' })}\r\n </Link>\r\n </Button>\r\n </div>\r\n\r\n <div className=\"grid gap-3\">\r\n {RECOMMENDED_HOOKS.map(hook => {\r\n const isInstalled = installedHookIds.has(hook.id);\r\n const isInstalling = installingHookIds.includes(hook.id);\r\n\r\n return (\r\n <div\r\n key={hook.id}\r\n className=\"flex items-center justify-between p-4 border rounded-lg\"\r\n >\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium\">{hook.name}</span>\r\n {isInstalled && <CheckCircle2 className=\"h-4 w-4 text-green-500\" />}\r\n </div>\r\n <div className=\"text-sm text-muted-foreground mt-1\">\r\n {hook.description}\r\n </div>\r\n <div className=\"flex items-center gap-4 mt-2 text-xs text-muted-foreground\">\r\n <span>\r\n {formatMessage({ id: 'specs.hookEvent', defaultMessage: 'Event' })}:{' '}\r\n <code className=\"bg-muted px-1 rounded\">{hook.event}</code>\r\n </span>\r\n <span>\r\n {formatMessage({ id: 'specs.hookScope', defaultMessage: 'Scope' })}:{' '}\r\n <code className=\"bg-muted px-1 rounded\">{hook.scope}</code>\r\n </span>\r\n </div>\r\n </div>\r\n <Button\r\n variant={isInstalled ? 'outline' : 'default'}\r\n size=\"sm\"\r\n disabled={isInstalled || isInstalling}\r\n onClick={() => handleInstallHook(hook.id)}\r\n >\r\n {isInstalling\r\n ? formatMessage({ id: 'specs.installing', defaultMessage: 'Installing...' })\r\n : isInstalled\r\n ? formatMessage({ id: 'specs.installed', defaultMessage: 'Installed' })\r\n : formatMessage({ id: 'specs.install', defaultMessage: 'Install' })}\r\n </Button>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Current Injection Status Card */}\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n {formatMessage(\r\n { id: 'specs.injection.statusTitle', defaultMessage: 'Current Injection Status' }\r\n )}\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-6 w-6\"\r\n onClick={() => { loadStats(); loadPreview(); }}\r\n disabled={statsLoading}\r\n >\r\n <RefreshCw className={cn('h-4 w-4', statsLoading && 'animate-spin')} />\r\n </Button>\r\n </CardTitle>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n {statsLoading ? (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\r\n </div>\r\n ) : statsError ? (\r\n <div className=\"text-sm text-destructive\">\r\n {formatMessage(\r\n { id: 'specs.injection.loadError', defaultMessage: 'Failed to load stats' }\r\n )}\r\n </div>\r\n ) : (\r\n <>\r\n {/* Current Length Display */}\r\n <div className=\"flex justify-between text-sm\">\r\n <span className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.currentLength', defaultMessage: 'Current Length' })}\r\n </span>\r\n <span\r\n className={cn(\r\n 'font-medium',\r\n isOverLimit && 'text-destructive',\r\n !isOverLimit && isOverWarning && 'text-yellow-600 dark:text-yellow-400'\r\n )}\r\n >\r\n {formatNumber(currentLength)} / {formatNumber(maxLength)}{' '}\r\n {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n <span className=\"text-muted-foreground ml-2\">\r\n (~{formatNumber(estimatedLineCount)} / {formatNumber(maxLineCount)} {formatMessage({ id: 'specs.injection.lines', defaultMessage: 'lines' })})\r\n </span>\r\n </span>\r\n </div>\r\n\r\n {/* Progress Bar */}\r\n <div className=\"space-y-2\">\r\n <div className=\"flex items-center justify-between text-xs text-muted-foreground mb-1\">\r\n <span>{percentage}%</span>\r\n <span>{formatMessage({ id: 'specs.injection.maxLimit', defaultMessage: 'Max' })}: {formatNumber(maxLength)}</span>\r\n </div>\r\n <div className=\"relative\">\r\n <Progress\r\n value={percentage}\r\n className={cn(\r\n 'h-3',\r\n isOverLimit && 'bg-destructive/20',\r\n !isOverLimit && isOverWarning && 'bg-yellow-100 dark:bg-yellow-900/30'\r\n )}\r\n indicatorClassName={cn(\r\n // Default: use a distinct blue color\r\n !isOverLimit && !isOverWarning && 'bg-sky-500 dark:bg-sky-400',\r\n isOverLimit && 'bg-destructive',\r\n !isOverLimit && isOverWarning && 'bg-yellow-500'\r\n )}\r\n />\r\n {/* Warning threshold marker */}\r\n <div\r\n className=\"absolute top-0 h-3 flex flex-col items-center\"\r\n style={{\r\n left: `${Math.min(100, (warnThreshold / maxLength) * 100)}%`,\r\n transform: 'translateX(-50%)',\r\n }}\r\n >\r\n <AlertTriangle className=\"h-3 w-3 text-yellow-500 -mt-4\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Warning Alert when over limit */}\r\n {isOverLimit && (\r\n <div className=\"flex items-start gap-3 p-4 rounded-lg bg-destructive/10 border border-destructive/20\">\r\n <AlertCircle className=\"h-5 w-5 text-destructive flex-shrink-0 mt-0.5\" />\r\n <div>\r\n <div className=\"font-medium text-destructive\">\r\n {formatMessage({ id: 'specs.injection.overLimit', defaultMessage: 'Over Limit' })}\r\n </div>\r\n <div className=\"text-sm text-muted-foreground mt-1\">\r\n {formatMessage(\r\n {\r\n id: 'specs.injection.overLimitDescription',\r\n defaultMessage: 'Current injection content exceeds maximum length of {max} characters. Excess content will be truncated.',\r\n },\r\n { max: formatNumber(maxLength) }\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Statistics Info */}\r\n <div className=\"p-4 rounded-lg bg-muted/50 space-y-2\">\r\n <div className=\"flex items-center gap-2 text-sm font-medium\">\r\n <Info className=\"h-4 w-4 text-muted-foreground\" />\r\n {formatMessage({ id: 'specs.injection.statsInfo', defaultMessage: 'Statistics' })}\r\n </div>\r\n <div className=\"grid grid-cols-2 gap-2 text-sm\">\r\n <div className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.requiredLength', defaultMessage: 'Required specs length:' })}\r\n </div>\r\n <div className=\"text-right\">\r\n {formatNumber(stats?.injectionLength?.requiredOnly || 0)} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </div>\r\n <div className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.matchedLength', defaultMessage: 'Keyword-matched length:' })}\r\n </div>\r\n <div className=\"text-right\">\r\n {formatNumber(stats?.injectionLength?.withKeywords || 0)} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </div>\r\n <div className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.remaining', defaultMessage: 'Remaining space:' })}\r\n </div>\r\n <div className={cn('text-right', remainingSpace === 0 && 'text-destructive')}>\r\n {formatNumber(remainingSpace)} ({Math.round(100 - percentage)}%)\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Injection Files List Card */}\r\n <Card>\r\n <CardHeader>\r\n <div className=\"flex items-center justify-between\">\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <FileText className=\"h-5 w-5\" />\r\n {formatMessage({ id: 'specs.injection.filesList', defaultMessage: 'Injection Files' })}\r\n </CardTitle>\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant={previewMode === 'required' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setPreviewMode('required')}\r\n >\r\n {formatMessage({ id: 'specs.readMode.required', defaultMessage: 'Required' })}\r\n </Button>\r\n <Button\r\n variant={previewMode === 'all' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setPreviewMode('all')}\r\n >\r\n {formatMessage({ id: 'specs.scope.all', defaultMessage: 'All' })}\r\n </Button>\r\n </div>\r\n </div>\r\n <CardDescription>\r\n {previewData && (\r\n <span>\r\n {previewData.stats.count} {formatMessage({ id: 'specs.injection.files', defaultMessage: 'files' })} • {formatNumber(previewData.stats.totalLength)} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </span>\r\n )}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n {/* Category Filter */}\r\n <div className=\"flex items-center gap-2 flex-wrap\">\r\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.filterByCategory', defaultMessage: 'Category:' })}\r\n </span>\r\n <div className=\"flex gap-2 flex-wrap\">\r\n <Button\r\n variant={categoryFilter === 'all' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setCategoryFilter('all')}\r\n >\r\n {formatMessage({ id: 'specs.category.all', defaultMessage: 'All' })}\r\n </Button>\r\n {SPEC_CATEGORIES.map(cat => (\r\n <Button\r\n key={cat}\r\n variant={categoryFilter === cat ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setCategoryFilter(cat)}\r\n className=\"gap-1\"\r\n >\r\n <Layers className=\"h-3 w-3\" />\r\n {formatMessage({ id: `specs.category.${cat}`, defaultMessage: cat })} ({categoryStats[cat]})\r\n </Button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Files List */}\r\n {previewLoading ? (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\r\n </div>\r\n ) : (\r\n <div className=\"h-[300px] overflow-auto\">\r\n <div className=\"space-y-2\">\r\n {Object.entries(filesByDimension).map(([dim, files]) => (\r\n <div key={dim} className=\"border rounded-lg\">\r\n <button\r\n className=\"w-full flex items-center justify-between p-3 hover:bg-muted/50 transition-colors\"\r\n onClick={() => toggleDimension(dim)}\r\n >\r\n <div className=\"flex items-center gap-2\">\r\n {expandedDimensions[dim] ? (\r\n <ChevronDown className=\"h-4 w-4\" />\r\n ) : (\r\n <ChevronRight className=\"h-4 w-4\" />\r\n )}\r\n <span className=\"font-medium capitalize\">\r\n {formatMessage({ id: `specs.dimension.${dim}`, defaultMessage: dim })}\r\n </span>\r\n <Badge variant=\"secondary\" className=\"text-xs\">\r\n {files.length}\r\n </Badge>\r\n </div>\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatNumber(files.reduce((sum, f) => sum + f.contentLength, 0))} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </span>\r\n </button>\r\n {expandedDimensions[dim] && (\r\n <div className=\"border-t\">\r\n {files.map((file) => {\r\n const fileCategory = (file.category as SpecCategory) || 'general';\r\n const categoryStyle = CATEGORY_CONFIG[fileCategory] || CATEGORY_CONFIG.general;\r\n return (\r\n <div\r\n key={file.file}\r\n className=\"flex items-center justify-between p-3 border-b last:border-b-0 hover:bg-muted/30\"\r\n >\r\n <div className=\"flex items-center gap-3 min-w-0\">\r\n {file.scope === 'global' ? (\r\n <Globe className=\"h-4 w-4 text-blue-500 flex-shrink-0\" />\r\n ) : (\r\n <Folder className=\"h-4 w-4 text-green-500 flex-shrink-0\" />\r\n )}\r\n <div className=\"min-w-0\">\r\n <div className=\"font-medium truncate\">{file.title}</div>\r\n <div className=\"text-xs text-muted-foreground truncate\">{file.file}</div>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Badge variant=\"outline\" className={cn('text-xs gap-1', categoryStyle.bgColor, categoryStyle.color)}>\r\n <Layers className=\"h-3 w-3\" />\r\n {formatMessage({ id: `specs.category.${fileCategory}`, defaultMessage: fileCategory })}\r\n </Badge>\r\n <Badge variant=\"outline\" className=\"text-xs\">\r\n {formatMessage({ id: `specs.priority.${file.priority}`, defaultMessage: file.priority })}\r\n </Badge>\r\n <span className=\"text-xs text-muted-foreground whitespace-nowrap\">\r\n {formatNumber(file.contentLength)}\r\n </span>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-7 w-7\"\r\n onClick={() => loadFilePreview(file)}\r\n >\r\n <Eye className=\"h-3.5 w-3.5\" />\r\n </Button>\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Command Preview Card */}\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <Eye className=\"h-5 w-5\" />\r\n {formatMessage({ id: 'specs.injection.commandPreview', defaultMessage: 'Command Injection Preview' })}\r\n </CardTitle>\r\n <CardDescription>\r\n {formatMessage({\r\n id: 'specs.injection.commandPreviewDesc',\r\n defaultMessage: 'Preview the content that would be injected by different CLI commands',\r\n })}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent>\r\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3\">\r\n {COMMAND_PREVIEWS.map((cmd) => (\r\n <Button\r\n key={cmd.command}\r\n variant=\"outline\"\r\n className=\"h-auto flex-col items-start py-3 px-4\"\r\n onClick={() => loadCommandPreview(cmd)}\r\n disabled={commandPreviewLoading}\r\n >\r\n <div className=\"font-medium text-sm\">\r\n {formatMessage({\r\n id: `specs.commandPreview.${cmd.labelKey}.label`,\r\n defaultMessage: cmd.labelKey\r\n })}\r\n </div>\r\n <div className=\"text-xs text-muted-foreground mt-1 line-clamp-2\">\r\n {formatMessage({\r\n id: `specs.commandPreview.${cmd.descriptionKey}.description`,\r\n defaultMessage: cmd.descriptionKey\r\n })}\r\n </div>\r\n <code className=\"text-xs bg-muted px-1.5 py-0.5 rounded mt-2 w-full text-center\">\r\n {cmd.command.replace('ccw spec load', '').trim() || 'default'}\r\n </code>\r\n </Button>\r\n ))}\r\n </div>\r\n {commandPreviewLoading && (\r\n <div className=\"flex items-center justify-center py-4 mt-4 border rounded-lg\">\r\n <Loader2 className=\"h-5 w-5 animate-spin text-muted-foreground mr-2\" />\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.loadingPreview', defaultMessage: 'Loading preview...' })}\r\n </span>\r\n </div>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Settings Card */}\r\n <Card>\r\n <CardHeader>\r\n <CardTitle>\r\n {formatMessage({ id: 'specs.injection.settingsTitle', defaultMessage: 'Injection Control Settings' })}\r\n </CardTitle>\r\n <CardDescription>\r\n {formatMessage({\r\n id: 'specs.injection.settingsDescription',\r\n defaultMessage: 'Configure how spec content is injected into AI context.',\r\n })}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-6\">\r\n {settingsLoading ? (\r\n <div className=\"flex items-center justify-center py-4\">\r\n <Loader2 className=\"h-5 w-5 animate-spin text-muted-foreground\" />\r\n </div>\r\n ) : (\r\n <>\r\n {/* Max Injection Length */}\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"maxLength\">\r\n {formatMessage({ id: 'specs.injection.maxLength', defaultMessage: 'Max Injection Length' })}\r\n </Label>\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"flex-1\">\r\n <Input\r\n id=\"maxLength\"\r\n type=\"number\"\r\n min={1000}\r\n max={50000}\r\n step={500}\r\n value={formData.maxLength}\r\n onChange={(e) => handleFieldChange('maxLength', Number(e.target.value))}\r\n className={cn(maxLengthError && 'border-destructive')}\r\n />\r\n </div>\r\n <span className=\"text-sm text-muted-foreground whitespace-nowrap\">\r\n (~{Math.ceil(formData.maxLength / 80)} {formatMessage({ id: 'specs.injection.lines', defaultMessage: 'lines' })})\r\n </span>\r\n </div>\r\n {maxLengthError && <p className=\"text-xs text-destructive mt-1\">{maxLengthError}</p>}\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({\r\n id: 'specs.injection.maxLengthHelp',\r\n defaultMessage: 'Recommended: 4000-10000 characters (50-125 lines). Too large may consume too much context.',\r\n })}\r\n </p>\r\n {/* Quick presets */}\r\n <div className=\"flex items-center gap-2 mt-2\">\r\n <span className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.quickPresets', defaultMessage: 'Quick presets:' })}\r\n </span>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"h-6 text-xs\"\r\n onClick={() => handleFieldChange('maxLength', 4000)}\r\n >\r\n 4000 (50 lines)\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"h-6 text-xs\"\r\n onClick={() => handleFieldChange('maxLength', 8000)}\r\n >\r\n 8000 (100 lines)\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"h-6 text-xs\"\r\n onClick={() => handleFieldChange('maxLength', 12000)}\r\n >\r\n 12000 (150 lines)\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n {/* Warning Threshold */}\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"warnThreshold\">\r\n {formatMessage({ id: 'specs.injection.warnThresholdLabel', defaultMessage: 'Warning Threshold' })}\r\n </Label>\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"flex-1\">\r\n <Input\r\n id=\"warnThreshold\"\r\n type=\"number\"\r\n min={500}\r\n max={formData.maxLength - 1}\r\n step={500}\r\n value={formData.warnThreshold}\r\n onChange={(e) => handleFieldChange('warnThreshold', Number(e.target.value))}\r\n className={cn(warnThresholdError && 'border-destructive')}\r\n />\r\n </div>\r\n <span className=\"text-sm text-muted-foreground whitespace-nowrap\">\r\n (~{Math.ceil(formData.warnThreshold / 80)} {formatMessage({ id: 'specs.injection.lines', defaultMessage: 'lines' })})\r\n </span>\r\n </div>\r\n {warnThresholdError && <p className=\"text-xs text-destructive mt-1\">{warnThresholdError}</p>}\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({\r\n id: 'specs.injection.warnThresholdHelp',\r\n defaultMessage: 'A warning will be displayed when injection length exceeds this value.',\r\n })}\r\n </p>\r\n </div>\r\n\r\n {/* Truncate on Exceed */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"space-y-0.5\">\r\n <Label htmlFor=\"truncate\">\r\n {formatMessage({ id: 'specs.injection.truncateOnExceed', defaultMessage: 'Truncate on Exceed' })}\r\n </Label>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({\r\n id: 'specs.injection.truncateHelp',\r\n defaultMessage: 'Automatically truncate content when it exceeds the maximum length.',\r\n })}\r\n </p>\r\n </div>\r\n <Switch\r\n id=\"truncate\"\r\n checked={formData.truncateOnExceed}\r\n onCheckedChange={(checked) => handleFieldChange('truncateOnExceed', checked)}\r\n />\r\n </div>\r\n\r\n {/* Action Buttons */}\r\n <div className=\"flex items-center justify-end gap-3 pt-4 border-t\">\r\n <Button\r\n variant=\"outline\"\r\n onClick={handleReset}\r\n disabled={!hasChanges || isSaving}\r\n >\r\n {formatMessage({ id: 'common.actions.reset', defaultMessage: 'Reset' })}\r\n </Button>\r\n <Button onClick={handleSave} disabled={!hasChanges || isSaving || !!maxLengthError || !!warnThresholdError}>\r\n {isSaving ? (\r\n <>\r\n <Loader2 className=\"h-4 w-4 mr-2 animate-spin\" />\r\n {formatMessage({ id: 'common.actions.saving', defaultMessage: 'Saving...' })}\r\n </>\r\n ) : (\r\n formatMessage({ id: 'common.actions.save', defaultMessage: 'Save' })\r\n )}\r\n </Button>\r\n </div>\r\n </>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* File Preview Dialog */}\r\n <Dialog open={previewDialogOpen} onOpenChange={setPreviewDialogOpen}>\r\n <DialogContent className=\"max-w-3xl max-h-[80vh]\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <FileText className=\"h-5 w-5\" />\r\n {previewFile?.title}\r\n </DialogTitle>\r\n </DialogHeader>\r\n <div className=\"flex-1 overflow-auto\">\r\n <pre className=\"text-sm whitespace-pre-wrap p-4 bg-muted rounded-lg\">\r\n {previewFile?.content || formatMessage({ id: 'specs.content.noContent', defaultMessage: 'No content available' })}\r\n </pre>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n\r\n {/* Command Preview Dialog */}\r\n <Dialog open={commandPreviewDialogOpen} onOpenChange={setCommandPreviewDialogOpen}>\r\n <DialogContent className=\"max-w-4xl max-h-[85vh]\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <Eye className=\"h-5 w-5\" />\r\n {formatMessage({ id: 'specs.injection.previewTitle', defaultMessage: 'Injection Preview' })}\r\n </DialogTitle>\r\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\r\n <code className=\"bg-muted px-2 py-1 rounded text-xs\">{selectedCommand.command}</code>\r\n <span>•</span>\r\n <span>\r\n {formatMessage({\r\n id: `specs.commandPreview.${selectedCommand.descriptionKey}.description`,\r\n defaultMessage: selectedCommand.descriptionKey\r\n })}\r\n </span>\r\n </div>\r\n </DialogHeader>\r\n <div className=\"space-y-4\">\r\n {/* Stats */}\r\n {commandPreviewData && (\r\n <div className=\"flex items-center gap-4 text-sm\">\r\n <Badge variant=\"secondary\">\r\n {commandPreviewData.stats.count} {formatMessage({ id: 'specs.injection.files', defaultMessage: 'files' })}\r\n </Badge>\r\n <Badge variant=\"secondary\">\r\n {formatNumber(commandPreviewData.stats.totalLength)} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </Badge>\r\n <Badge variant=\"secondary\">\r\n ~{Math.ceil(commandPreviewData.stats.totalLength / 80)} {formatMessage({ id: 'specs.injection.lines', defaultMessage: 'lines' })}\r\n </Badge>\r\n </div>\r\n )}\r\n {/* Preview Content */}\r\n <div className=\"flex-1 overflow-auto max-h-[60vh] border rounded-lg\">\r\n {commandPreviewData?.files.length ? (\r\n <div className=\"space-y-4 p-4\">\r\n {commandPreviewData.files.map((file, idx) => (\r\n <div key={file.file} className=\"space-y-2\">\r\n {/* File Header */}\r\n <div className=\"flex items-center justify-between text-sm\">\r\n <div className=\"flex items-center gap-2\">\r\n <Badge variant=\"outline\" className=\"text-xs\">\r\n {idx + 1}\r\n </Badge>\r\n <span className=\"font-medium\">{file.title}</span>\r\n {file.category && (\r\n <Badge variant=\"outline\" className={cn(\r\n 'text-xs',\r\n CATEGORY_CONFIG[file.category as SpecCategory]?.bgColor,\r\n CATEGORY_CONFIG[file.category as SpecCategory]?.color\r\n )}>\r\n {file.category}\r\n </Badge>\r\n )}\r\n </div>\r\n <span className=\"text-xs text-muted-foreground\">\r\n {formatNumber(file.contentLength)} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </span>\r\n </div>\r\n {/* File Content */}\r\n <pre className=\"text-xs whitespace-pre-wrap p-3 bg-muted rounded border-l-2 border-primary/30\">\r\n {file.content || formatMessage({ id: 'specs.content.noContent', defaultMessage: 'No content available' })}\r\n </pre>\r\n </div>\r\n ))}\r\n </div>\r\n ) : (\r\n <div className=\"flex items-center justify-center py-8 text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.noFiles', defaultMessage: 'No files match this command' })}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n </div>\r\n );\r\n}\r\n\r\nexport default InjectionControlTab;\r\n","// ========================================\r\n// GlobalSettingsTab Component\r\n// ========================================\r\n// Global settings for personal spec defaults and spec statistics\r\n\r\nimport { useState, useEffect } from 'react';\r\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\r\nimport { useIntl } from 'react-intl';\r\nimport { toast } from 'sonner';\r\nimport { Settings, RefreshCw, History } from 'lucide-react';\r\nimport {\r\n Card,\r\n CardHeader,\r\n CardTitle,\r\n CardDescription,\r\n CardContent,\r\n} from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Label } from '@/components/ui/Label';\r\nimport { Switch } from '@/components/ui/Switch';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport {\r\n Select,\r\n SelectTrigger,\r\n SelectValue,\r\n SelectContent,\r\n SelectItem,\r\n} from '@/components/ui/Select';\r\nimport { cn } from '@/lib/utils';\r\n\r\n// ========== Types ==========\r\n\r\ninterface PersonalSpecDefaults {\r\n defaultReadMode: 'required' | 'optional';\r\n autoEnable: boolean;\r\n}\r\n\r\ninterface DevProgressInjection {\r\n enabled: boolean;\r\n maxEntriesPerCategory: number;\r\n categories: ('feature' | 'enhancement' | 'bugfix' | 'refactor' | 'docs')[];\r\n}\r\n\r\ninterface SystemSettings {\r\n injectionControl: {\r\n maxLength: number;\r\n warnThreshold: number;\r\n truncateOnExceed: boolean;\r\n };\r\n personalSpecDefaults: PersonalSpecDefaults;\r\n devProgressInjection: DevProgressInjection;\r\n}\r\n\r\ninterface SpecDimensionStats {\r\n count: number;\r\n requiredCount: number;\r\n}\r\n\r\ninterface SpecStats {\r\n dimensions: {\r\n specs: SpecDimensionStats;\r\n personal: SpecDimensionStats;\r\n };\r\n injectionLength?: {\r\n requiredOnly: number;\r\n withKeywords: number;\r\n maxLength: number;\r\n percentage: number;\r\n };\r\n}\r\n\r\ninterface ProjectTechStats {\r\n total_features: number;\r\n total_sessions: number;\r\n last_updated: string | null;\r\n categories: {\r\n feature: number;\r\n enhancement: number;\r\n bugfix: number;\r\n refactor: number;\r\n docs: number;\r\n };\r\n}\r\n\r\n// ========== API Functions ==========\r\n\r\nconst API_BASE = '/api';\r\n\r\nasync function fetchSystemSettings(): Promise<SystemSettings> {\r\n const response = await fetch(`${API_BASE}/system/settings`, {\r\n credentials: 'same-origin',\r\n });\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch settings: ${response.statusText}`);\r\n }\r\n const data = await response.json();\r\n return data;\r\n}\r\n\r\nasync function updateSystemSettings(\r\n settings: Partial<SystemSettings>\r\n): Promise<{ success: boolean; settings: SystemSettings }> {\r\n const response = await fetch(`${API_BASE}/system/settings`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n credentials: 'same-origin',\r\n body: JSON.stringify(settings),\r\n });\r\n if (!response.ok) {\r\n throw new Error(`Failed to update settings: ${response.statusText}`);\r\n }\r\n return response.json();\r\n}\r\n\r\nasync function fetchSpecStats(): Promise<SpecStats> {\r\n const response = await fetch(`${API_BASE}/specs/stats`, {\r\n credentials: 'same-origin',\r\n });\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch spec stats: ${response.statusText}`);\r\n }\r\n return response.json();\r\n}\r\n\r\nasync function fetchProjectTechStats(): Promise<ProjectTechStats> {\r\n const response = await fetch(`${API_BASE}/project-tech/stats`, {\r\n credentials: 'same-origin',\r\n });\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch project-tech stats: ${response.statusText}`);\r\n }\r\n return response.json();\r\n}\r\n\r\n// ========== Query Keys ==========\r\n\r\nconst settingsKeys = {\r\n all: ['system-settings'] as const,\r\n settings: () => [...settingsKeys.all, 'settings'] as const,\r\n stats: () => [...settingsKeys.all, 'stats'] as const,\r\n projectTech: () => [...settingsKeys.all, 'project-tech'] as const,\r\n};\r\n\r\n// ========== Component ==========\r\n\r\nexport function GlobalSettingsTab() {\r\n const { formatMessage } = useIntl();\r\n const queryClient = useQueryClient();\r\n\r\n // Local state for immediate UI feedback\r\n const [localDefaults, setLocalDefaults] = useState<PersonalSpecDefaults>({\r\n defaultReadMode: 'optional',\r\n autoEnable: true,\r\n });\r\n\r\n // Local state for dev progress injection\r\n const [localDevProgress, setLocalDevProgress] = useState<DevProgressInjection>({\r\n enabled: true,\r\n maxEntriesPerCategory: 10,\r\n categories: ['feature', 'enhancement', 'bugfix', 'refactor', 'docs'],\r\n });\r\n\r\n // Fetch system settings\r\n const {\r\n data: settings,\r\n isLoading: isLoadingSettings,\r\n error: settingsError,\r\n } = useQuery({\r\n queryKey: settingsKeys.settings(),\r\n queryFn: fetchSystemSettings,\r\n staleTime: 60000, // 1 minute\r\n });\r\n\r\n // Fetch spec stats\r\n const {\r\n data: stats,\r\n isLoading: isLoadingStats,\r\n error: statsError,\r\n refetch: refetchStats,\r\n } = useQuery({\r\n queryKey: settingsKeys.stats(),\r\n queryFn: fetchSpecStats,\r\n staleTime: 30000, // 30 seconds\r\n });\r\n\r\n // Fetch project-tech stats\r\n const { data: projectTechStats } = useQuery({\r\n queryKey: settingsKeys.projectTech(),\r\n queryFn: fetchProjectTechStats,\r\n staleTime: 60000, // 1 minute\r\n });\r\n\r\n // Update settings mutation\r\n const updateMutation = useMutation({\r\n mutationFn: updateSystemSettings,\r\n onSuccess: (data) => {\r\n queryClient.setQueryData(settingsKeys.settings(), data.settings);\r\n toast.success(formatMessage({ id: 'specs.injection.saveSuccess', defaultMessage: 'Settings saved successfully' }));\r\n },\r\n onError: (error) => {\r\n toast.error(formatMessage(\r\n { id: 'specs.injection.saveError', defaultMessage: 'Failed to save settings: {error}' },\r\n { error: error.message }\r\n ));\r\n },\r\n });\r\n\r\n // Sync local state with server state\r\n useEffect(() => {\r\n if (settings?.personalSpecDefaults) {\r\n setLocalDefaults(settings.personalSpecDefaults);\r\n }\r\n if (settings?.devProgressInjection) {\r\n setLocalDevProgress(settings.devProgressInjection);\r\n }\r\n }, [settings]);\r\n\r\n // Handlers\r\n const handleReadModeChange = (value: 'required' | 'optional') => {\r\n const newDefaults = { ...localDefaults, defaultReadMode: value };\r\n setLocalDefaults(newDefaults);\r\n updateMutation.mutate({ personalSpecDefaults: newDefaults });\r\n };\r\n\r\n const handleAutoEnableChange = (checked: boolean) => {\r\n const newDefaults = { ...localDefaults, autoEnable: checked };\r\n setLocalDefaults(newDefaults);\r\n updateMutation.mutate({ personalSpecDefaults: newDefaults });\r\n };\r\n\r\n // Dev progress injection handlers\r\n const handleDevProgressToggle = (checked: boolean) => {\r\n const newDevProgress = { ...localDevProgress, enabled: checked };\r\n setLocalDevProgress(newDevProgress);\r\n updateMutation.mutate({ devProgressInjection: newDevProgress });\r\n };\r\n\r\n const handleMaxEntriesChange = (value: string) => {\r\n const numValue = parseInt(value, 10);\r\n if (!isNaN(numValue) && numValue >= 1 && numValue <= 50) {\r\n const newDevProgress = { ...localDevProgress, maxEntriesPerCategory: numValue };\r\n setLocalDevProgress(newDevProgress);\r\n updateMutation.mutate({ devProgressInjection: newDevProgress });\r\n }\r\n };\r\n\r\n const handleCategoryToggle = (category: 'feature' | 'enhancement' | 'bugfix' | 'refactor' | 'docs') => {\r\n const newCategories = localDevProgress.categories.includes(category)\r\n ? localDevProgress.categories.filter(c => c !== category)\r\n : [...localDevProgress.categories, category];\r\n const newDevProgress = { ...localDevProgress, categories: newCategories as DevProgressInjection['categories'] };\r\n setLocalDevProgress(newDevProgress);\r\n updateMutation.mutate({ devProgressInjection: newDevProgress });\r\n };\r\n\r\n // Calculate totals - Only include specs and personal dimensions\r\n const dimensions = stats?.dimensions || {};\r\n const dimensionEntries = Object.entries(dimensions)\r\n .filter(([dim]) => dim === 'specs' || dim === 'personal') as [\r\n keyof typeof dimensions,\r\n SpecDimensionStats\r\n ][];\r\n const totalCount = dimensionEntries.reduce(\r\n (sum, [, data]) => sum + data.count,\r\n 0\r\n );\r\n const totalRequired = dimensionEntries.reduce(\r\n (sum, [, data]) => sum + data.requiredCount,\r\n 0\r\n );\r\n\r\n const isLoading = isLoadingSettings || isLoadingStats;\r\n const hasError = settingsError || statsError;\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Personal Spec Defaults Card */}\r\n <Card>\r\n <CardHeader>\r\n <div className=\"flex items-center gap-2\">\r\n <Settings className=\"h-5 w-5 text-muted-foreground\" />\r\n <CardTitle>\r\n {formatMessage({ id: 'specs.settings.personalSpecDefaults', defaultMessage: 'Personal Spec Defaults' })}\r\n </CardTitle>\r\n </div>\r\n <CardDescription>\r\n {formatMessage({ id: 'specs.settings.personalSpecDefaultsDesc', defaultMessage: 'These settings will be applied when creating new personal specs' })}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-6\">\r\n {/* Default Read Mode */}\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"default-read-mode\">\r\n {formatMessage({ id: 'specs.settings.defaultReadMode', defaultMessage: 'Default Read Mode' })}\r\n </Label>\r\n <Select\r\n value={localDefaults.defaultReadMode}\r\n onValueChange={(value) =>\r\n handleReadModeChange(value as 'required' | 'optional')\r\n }\r\n >\r\n <SelectTrigger id=\"default-read-mode\" className=\"w-full\">\r\n <SelectValue placeholder={formatMessage({ id: 'specs.settings.selectReadMode', defaultMessage: 'Select read mode' })} />\r\n </SelectTrigger>\r\n <SelectContent>\r\n <SelectItem value=\"required\">\r\n {formatMessage({ id: 'specs.readMode.required', defaultMessage: 'Required' })}\r\n </SelectItem>\r\n <SelectItem value=\"optional\">\r\n {formatMessage({ id: 'specs.readMode.optional', defaultMessage: 'Optional' })}\r\n </SelectItem>\r\n </SelectContent>\r\n </Select>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.settings.defaultReadModeHelp', defaultMessage: 'The default read mode for newly created personal specs' })}\r\n </p>\r\n </div>\r\n\r\n {/* Auto Enable */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"space-y-0.5\">\r\n <Label htmlFor=\"auto-enable\">\r\n {formatMessage({ id: 'specs.settings.autoEnable', defaultMessage: 'Auto Enable New Specs' })}\r\n </Label>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.settings.autoEnableDescription', defaultMessage: 'Automatically enable newly created personal specs' })}\r\n </p>\r\n </div>\r\n <Switch\r\n id=\"auto-enable\"\r\n checked={localDefaults.autoEnable}\r\n onCheckedChange={handleAutoEnableChange}\r\n disabled={updateMutation.isPending}\r\n />\r\n </div>\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Spec Statistics Card */}\r\n <Card>\r\n <CardHeader>\r\n <div className=\"flex items-center justify-between\">\r\n <CardTitle>\r\n {formatMessage({ id: 'specs.settings.specStatistics', defaultMessage: 'Spec Statistics' })}\r\n </CardTitle>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n onClick={() => refetchStats()}\r\n disabled={isLoadingStats}\r\n >\r\n <RefreshCw\r\n className={cn(\r\n 'h-4 w-4',\r\n isLoadingStats && 'animate-spin'\r\n )}\r\n />\r\n </Button>\r\n </div>\r\n </CardHeader>\r\n <CardContent>\r\n {isLoading ? (\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\r\n {[1, 2, 3, 4].map((i) => (\r\n <div\r\n key={i}\r\n className=\"text-center p-4 rounded-lg bg-muted animate-pulse\"\r\n >\r\n <div className=\"h-8 w-12 mx-auto bg-muted-foreground/20 rounded mb-2\" />\r\n <div className=\"h-4 w-16 mx-auto bg-muted-foreground/20 rounded\" />\r\n </div>\r\n ))}\r\n </div>\r\n ) : hasError ? (\r\n <div className=\"text-center py-8 text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.loadError', defaultMessage: 'Failed to load statistics' })}\r\n </div>\r\n ) : (\r\n <>\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n {dimensionEntries\r\n .filter(([entry]) => entry[0] === 'specs' || entry[1] === 'personal')\r\n .map(([dim, data]) => (\r\n <div\r\n key={dim}\r\n className=\"text-center p-4 rounded-lg bg-muted/50 hover:bg-muted transition-colors\"\r\n >\r\n <div className=\"text-2xl font-bold text-foreground\">\r\n {data.count}\r\n </div>\r\n <div className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: `specs.dimension.${dim}`, defaultMessage: dim })}\r\n </div>\r\n <div className=\"text-xs text-muted-foreground mt-1\">\r\n {data.requiredCount} {formatMessage({ id: 'specs.required', defaultMessage: 'required' })}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {/* Summary */}\r\n <div className=\"mt-4 pt-4 border-t border-border\">\r\n <div className=\"flex justify-between text-sm text-muted-foreground\">\r\n <span>\r\n {formatMessage(\r\n { id: 'specs.settings.totalSpecs', defaultMessage: 'Total: {count} spec files' },\r\n { count: totalCount }\r\n )}\r\n </span>\r\n <span>\r\n {totalRequired} {formatMessage({ id: 'specs.readMode.required', defaultMessage: 'required' })} | {totalCount - totalRequired}{' '}\r\n {formatMessage({ id: 'specs.readMode.optional', defaultMessage: 'optional' })}\r\n </span>\r\n </div>\r\n </div>\r\n </>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Development Progress Injection Card */}\r\n <Card>\r\n <CardHeader>\r\n <div className=\"flex items-center gap-2\">\r\n <History className=\"h-5 w-5 text-muted-foreground\" />\r\n <CardTitle>\r\n {formatMessage({ id: 'specs.settings.devProgressInjection', defaultMessage: 'Development Progress Injection' })}\r\n </CardTitle>\r\n </div>\r\n <CardDescription>\r\n {formatMessage({ id: 'specs.settings.devProgressInjectionDesc', defaultMessage: 'Control how development progress from project-tech.json is injected into AI context' })}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-6\">\r\n {/* Enable Toggle */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"space-y-0.5\">\r\n <Label>\r\n {formatMessage({ id: 'specs.settings.enableDevProgress', defaultMessage: 'Enable Injection' })}\r\n </Label>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.settings.enableDevProgressDesc', defaultMessage: 'Include development history in AI context' })}\r\n </p>\r\n </div>\r\n <Switch\r\n checked={localDevProgress.enabled}\r\n onCheckedChange={handleDevProgressToggle}\r\n disabled={updateMutation.isPending}\r\n />\r\n </div>\r\n\r\n {/* Max Entries */}\r\n <div className=\"space-y-2\">\r\n <Label>\r\n {formatMessage({ id: 'specs.settings.maxEntries', defaultMessage: 'Max Entries per Category' })}\r\n </Label>\r\n <Input\r\n type=\"number\"\r\n min={1}\r\n max={50}\r\n value={localDevProgress.maxEntriesPerCategory}\r\n onChange={(e) => handleMaxEntriesChange(e.target.value)}\r\n disabled={updateMutation.isPending || !localDevProgress.enabled}\r\n className=\"w-24\"\r\n />\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.settings.maxEntriesDesc', defaultMessage: 'Maximum number of entries to include per category (1-50)' })}\r\n </p>\r\n </div>\r\n\r\n {/* Category Toggles */}\r\n <div className=\"space-y-2\">\r\n <Label>\r\n {formatMessage({ id: 'specs.settings.includeCategories', defaultMessage: 'Include Categories' })}\r\n </Label>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {(['feature', 'enhancement', 'bugfix', 'refactor', 'docs'] as const).map(cat => (\r\n <Badge\r\n key={cat}\r\n variant={localDevProgress.categories.includes(cat) ? 'default' : 'outline'}\r\n className={cn(\r\n 'cursor-pointer transition-colors',\r\n !localDevProgress.enabled && 'opacity-50 cursor-not-allowed'\r\n )}\r\n onClick={() => localDevProgress.enabled && handleCategoryToggle(cat)}\r\n >\r\n {formatMessage({ id: `specs.devCategory.${cat}`, defaultMessage: cat })} ({projectTechStats?.categories[cat] || 0})\r\n </Badge>\r\n ))}\r\n </div>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.settings.categoriesDesc', defaultMessage: 'Click to toggle category inclusion' })}\r\n </p>\r\n </div>\r\n\r\n {/* Stats Summary */}\r\n {projectTechStats && (\r\n <div className=\"text-sm text-muted-foreground pt-4 border-t border-border\">\r\n {projectTechStats.last_updated ? (\r\n formatMessage(\r\n { id: 'specs.settings.devProgressStats', defaultMessage: '{total} entries from {sessions} sessions, last updated: {date}' },\r\n {\r\n total: projectTechStats.total_features,\r\n sessions: projectTechStats.total_sessions,\r\n date: new Date(projectTechStats.last_updated).toLocaleDateString()\r\n }\r\n )\r\n ) : (\r\n formatMessage(\r\n { id: 'specs.settings.devProgressStatsNoDate', defaultMessage: '{total} entries from {sessions} sessions' },\r\n {\r\n total: projectTechStats.total_features,\r\n sessions: projectTechStats.total_sessions\r\n }\r\n )\r\n )}\r\n </div>\r\n )}\r\n </CardContent>\r\n </Card>\r\n </div>\r\n );\r\n}\r\n\r\nexport default GlobalSettingsTab;\r\n","/**\r\n * Specs Settings Page\r\n *\r\n * Main page for managing spec settings, injection control, and global settings.\r\n * Uses 4 tabs: Project Specs | Personal Specs | Injection | Settings\r\n * Supports category filtering (workflow stage) and scope filtering (personal only)\r\n */\r\nimport { useState, useMemo } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/Tabs';\r\nimport { Card, CardContent } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { ScrollText, User, Gauge, Settings, RefreshCw, Search, Globe, Folder, Filter, Layers } from 'lucide-react';\r\nimport { SpecCard, SpecDialog, SpecContentDialog, type Spec, type SpecFormData, type SpecCategory } from '@/components/specs';\r\nimport { InjectionControlTab } from '@/components/specs/InjectionControlTab';\r\nimport { GlobalSettingsTab } from '@/components/specs/GlobalSettingsTab';\r\nimport { useSpecStats, useSpecsList, useRebuildSpecIndex } from '@/hooks/useSystemSettings';\r\nimport { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore';\r\nimport type { SpecEntry } from '@/lib/api';\r\n\r\ntype SettingsTab = 'project-specs' | 'personal-specs' | 'injection' | 'settings';\r\ntype PersonalScopeFilter = 'all' | 'global' | 'project';\r\ntype CategoryFilter = 'all' | SpecCategory;\r\n\r\n// All available categories\r\nconst SPEC_CATEGORIES: SpecCategory[] = ['general', 'exploration', 'planning', 'execution'];\r\n\r\n// Convert SpecEntry to Spec for display\r\nfunction specEntryToSpec(entry: SpecEntry, dimension: string): Spec {\r\n return {\r\n id: entry.file,\r\n title: entry.title,\r\n dimension: dimension as Spec['dimension'],\r\n scope: entry.scope || 'project', // Default to project if not specified\r\n category: entry.category || 'general', // Default to general if not specified\r\n keywords: entry.keywords,\r\n readMode: entry.readMode as Spec['readMode'],\r\n priority: entry.priority as Spec['priority'],\r\n file: entry.file,\r\n enabled: true,\r\n };\r\n}\r\n\r\nexport function SpecsSettingsPage() {\r\n const { formatMessage } = useIntl();\r\n const projectPath = useWorkflowStore(selectProjectPath);\r\n const [activeTab, setActiveTab] = useState<SettingsTab>('project-specs');\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [personalScopeFilter, setPersonalScopeFilter] = useState<PersonalScopeFilter>('all');\r\n const [categoryFilter, setCategoryFilter] = useState<CategoryFilter>('all');\r\n const [editDialogOpen, setEditDialogOpen] = useState(false);\r\n const [contentDialogOpen, setContentDialogOpen] = useState(false);\r\n const [editingSpec, setEditingSpec] = useState<Spec | null>(null);\r\n const [viewingSpec, setViewingSpec] = useState<Spec | null>(null);\r\n\r\n // Fetch real data\r\n const { data: specsListData, isLoading: specsLoading, refetch: refetchSpecs } = useSpecsList({ projectPath });\r\n const { data: statsData } = useSpecStats({ projectPath });\r\n const rebuildMutation = useRebuildSpecIndex();\r\n\r\n // Convert specs data to display format\r\n const { projectSpecs, personalSpecs, globalPersonalSpecs, projectPersonalSpecs, categoryCounts } = useMemo(() => {\r\n if (!specsListData?.specs) {\r\n return {\r\n projectSpecs: [],\r\n personalSpecs: [],\r\n globalPersonalSpecs: [],\r\n projectPersonalSpecs: [],\r\n categoryCounts: { general: 0, exploration: 0, planning: 0, execution: 0 }\r\n };\r\n }\r\n\r\n const specs: Spec[] = [];\r\n const personal: Spec[] = [];\r\n const globalPersonal: Spec[] = [];\r\n const projectPersonal: Spec[] = [];\r\n const counts: Record<SpecCategory, number> = { general: 0, exploration: 0, planning: 0, execution: 0 };\r\n\r\n for (const [dimension, entries] of Object.entries(specsListData.specs)) {\r\n for (const entry of entries) {\r\n const spec = specEntryToSpec(entry, dimension);\r\n // Count by category\r\n if (spec.category) {\r\n counts[spec.category]++;\r\n }\r\n if (dimension === 'personal') {\r\n personal.push(spec);\r\n if (spec.scope === 'global') {\r\n globalPersonal.push(spec);\r\n } else {\r\n projectPersonal.push(spec);\r\n }\r\n } else {\r\n specs.push(spec);\r\n }\r\n }\r\n }\r\n\r\n return {\r\n projectSpecs: specs,\r\n personalSpecs: personal,\r\n globalPersonalSpecs: globalPersonal,\r\n projectPersonalSpecs: projectPersonal,\r\n categoryCounts: counts\r\n };\r\n }, [specsListData]);\r\n\r\n const isLoading = specsLoading;\r\n\r\n const handleSpecView = (spec: Spec) => {\r\n setViewingSpec(spec);\r\n setContentDialogOpen(true);\r\n };\r\n\r\n const handleSpecEdit = (spec: Spec) => {\r\n setEditingSpec(spec);\r\n setEditDialogOpen(true);\r\n };\r\n\r\n const handleSpecSave = async (specId: string, data: SpecFormData) => {\r\n console.log('Saving spec:', specId, data);\r\n // TODO: Implement save logic\r\n setEditDialogOpen(false);\r\n };\r\n\r\n const handleContentSave = async (specId: string, content: string) => {\r\n console.log('Saving spec content:', specId, content.length);\r\n // TODO: Implement content save logic\r\n };\r\n\r\n const handleSpecToggle = async (specId: string, enabled: boolean) => {\r\n console.log('Toggling spec:', specId, enabled);\r\n // TODO: Implement toggle logic\r\n };\r\n\r\n const handleSpecDelete = async (specId: string) => {\r\n console.log('Deleting spec:', specId);\r\n // TODO: Implement delete logic\r\n };\r\n\r\n const handleRebuildIndex = async () => {\r\n console.log('Rebuilding index...');\r\n rebuildMutation.mutate(undefined, {\r\n onSuccess: () => {\r\n refetchSpecs();\r\n }\r\n });\r\n };\r\n\r\n const filterSpecs = (specs: Spec[]) => {\r\n let result = specs;\r\n // Filter by category\r\n if (categoryFilter !== 'all') {\r\n result = result.filter(spec => spec.category === categoryFilter);\r\n }\r\n // Filter by search query\r\n if (searchQuery.trim()) {\r\n const query = searchQuery.toLowerCase();\r\n result = result.filter(spec =>\r\n spec.title.toLowerCase().includes(query) ||\r\n spec.keywords.some(k => k.toLowerCase().includes(query))\r\n );\r\n }\r\n return result;\r\n };\r\n\r\n const renderSpecsTab = (dimension: 'project' | 'personal') => {\r\n let specs = dimension === 'project' ? projectSpecs : personalSpecs;\r\n\r\n // Apply scope filter for personal specs\r\n if (dimension === 'personal') {\r\n if (personalScopeFilter === 'global') {\r\n specs = globalPersonalSpecs;\r\n } else if (personalScopeFilter === 'project') {\r\n specs = projectPersonalSpecs;\r\n }\r\n }\r\n\r\n const filteredSpecs = filterSpecs(specs);\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Search and Actions */}\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"relative flex-1\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n placeholder={formatMessage({ id: 'specs.searchPlaceholder', defaultMessage: 'Search specs...' })}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"pl-9\"\r\n />\r\n </div>\r\n <Button variant=\"outline\" onClick={handleRebuildIndex} disabled={rebuildMutation.isPending}>\r\n <RefreshCw className={`h-4 w-4 mr-2 ${rebuildMutation.isPending ? 'animate-spin' : ''}`} />\r\n {formatMessage({ id: 'specs.rebuildIndex', defaultMessage: 'Rebuild Index' })}\r\n </Button>\r\n </div>\r\n\r\n {/* Scope filter for personal specs */}\r\n {dimension === 'personal' && (\r\n <div className=\"flex items-center gap-2\">\r\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.filterByScope', defaultMessage: 'Filter by scope:' })}\r\n </span>\r\n <div className=\"flex gap-2\">\r\n <Button\r\n variant={personalScopeFilter === 'all' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setPersonalScopeFilter('all')}\r\n >\r\n {formatMessage({ id: 'specs.scope.all', defaultMessage: 'All' })} ({personalSpecs.length})\r\n </Button>\r\n <Button\r\n variant={personalScopeFilter === 'global' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setPersonalScopeFilter('global')}\r\n >\r\n <Globe className=\"h-3 w-3 mr-1\" />\r\n {formatMessage({ id: 'specs.scope.global', defaultMessage: 'Global' })} ({globalPersonalSpecs.length})\r\n </Button>\r\n <Button\r\n variant={personalScopeFilter === 'project' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setPersonalScopeFilter('project')}\r\n >\r\n <Folder className=\"h-3 w-3 mr-1\" />\r\n {formatMessage({ id: 'specs.scope.project', defaultMessage: 'Project' })} ({projectPersonalSpecs.length})\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Category filter for workflow stage */}\r\n <div className=\"flex items-center gap-2\">\r\n <Layers className=\"h-4 w-4 text-muted-foreground\" />\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.filterByCategory', defaultMessage: 'Workflow stage:' })}\r\n </span>\r\n <div className=\"flex gap-2 flex-wrap\">\r\n <Button\r\n variant={categoryFilter === 'all' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setCategoryFilter('all')}\r\n >\r\n {formatMessage({ id: 'specs.category.all', defaultMessage: 'All' })}\r\n </Button>\r\n {SPEC_CATEGORIES.map(cat => (\r\n <Button\r\n key={cat}\r\n variant={categoryFilter === cat ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setCategoryFilter(cat)}\r\n >\r\n {formatMessage({ id: `specs.category.${cat}`, defaultMessage: cat })} ({categoryCounts[cat]})\r\n </Button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Stats Summary - Only show specs and personal dimensions */}\r\n {statsData?.dimensions && (\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n {Object.entries(statsData.dimensions)\r\n .filter(([dim]) => dim === 'specs' || dim === 'personal')\r\n .map(([dim, data]) => (\r\n <Card key={dim}>\r\n <CardContent className=\"pt-4\">\r\n <div className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: `specs.dimension.${dim}`, defaultMessage: dim })}\r\n </div>\r\n <div className=\"text-2xl font-bold\">{(data as { count: number }).count}</div>\r\n <div className=\"text-xs text-muted-foreground\">\r\n {(data as { requiredCount: number }).requiredCount} {formatMessage({ id: 'specs.required', defaultMessage: 'required' })}\r\n </div>\r\n </CardContent>\r\n </Card>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Specs Grid */}\r\n {filteredSpecs.length === 0 ? (\r\n <Card>\r\n <CardContent className=\"py-8 text-center text-muted-foreground\">\r\n {isLoading\r\n ? formatMessage({ id: 'specs.loading', defaultMessage: 'Loading specs...' })\r\n : formatMessage({ id: 'specs.noSpecs', defaultMessage: 'No specs found. Create specs in .ccw/ directory.' })\r\n }\r\n </CardContent>\r\n </Card>\r\n ) : (\r\n <div className=\"grid gap-4\">\r\n {filteredSpecs.map(spec => (\r\n <SpecCard\r\n key={spec.id}\r\n spec={spec}\r\n onView={handleSpecView}\r\n onEdit={handleSpecEdit}\r\n onToggle={handleSpecToggle}\r\n onDelete={handleSpecDelete}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n };\r\n\r\n return (\r\n <div className=\"max-w-6xl mx-auto\">\r\n {/* Page Header */}\r\n <div className=\"mb-6\">\r\n <h1 className=\"text-2xl font-bold flex items-center gap-2\">\r\n <ScrollText className=\"h-6 w-6\" />\r\n {formatMessage({ id: 'specs.pageTitle', defaultMessage: 'Spec Settings' })}\r\n </h1>\r\n <p className=\"text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'specs.pageDescription', defaultMessage: 'Manage specification injection and system settings' })}\r\n </p>\r\n </div>\r\n\r\n {/* Main Tabs */}\r\n <Tabs value={activeTab} onValueChange={(v) => setActiveTab(v as SettingsTab)}>\r\n <TabsList className=\"grid grid-cols-4 mb-6\">\r\n <TabsTrigger value=\"project-specs\" className=\"flex items-center gap-2\">\r\n <ScrollText className=\"h-4 w-4\" />\r\n <span className=\"hidden sm:inline\">{formatMessage({ id: 'specs.tabProjectSpecs', defaultMessage: 'Project Specs' })}</span>\r\n </TabsTrigger>\r\n <TabsTrigger value=\"personal-specs\" className=\"flex items-center gap-2\">\r\n <User className=\"h-4 w-4\" />\r\n <span className=\"hidden sm:inline\">{formatMessage({ id: 'specs.tabPersonalSpecs', defaultMessage: 'Personal' })}</span>\r\n </TabsTrigger>\r\n <TabsTrigger value=\"injection\" className=\"flex items-center gap-2\">\r\n <Gauge className=\"h-4 w-4\" />\r\n <span className=\"hidden sm:inline\">{formatMessage({ id: 'specs.tabInjection', defaultMessage: 'Injection' })}</span>\r\n </TabsTrigger>\r\n <TabsTrigger value=\"settings\" className=\"flex items-center gap-2\">\r\n <Settings className=\"h-4 w-4\" />\r\n <span className=\"hidden sm:inline\">{formatMessage({ id: 'specs.tabSettings', defaultMessage: 'Settings' })}</span>\r\n </TabsTrigger>\r\n </TabsList>\r\n\r\n <TabsContent value=\"project-specs\">\r\n {renderSpecsTab('project')}\r\n </TabsContent>\r\n\r\n <TabsContent value=\"personal-specs\">\r\n {renderSpecsTab('personal')}\r\n </TabsContent>\r\n\r\n <TabsContent value=\"injection\">\r\n <InjectionControlTab />\r\n </TabsContent>\r\n\r\n <TabsContent value=\"settings\">\r\n <GlobalSettingsTab />\r\n </TabsContent>\r\n </Tabs>\r\n\r\n {/* Edit Spec Dialog */}\r\n <SpecDialog\r\n open={editDialogOpen}\r\n onOpenChange={setEditDialogOpen}\r\n spec={editingSpec}\r\n onSave={handleSpecSave}\r\n />\r\n\r\n {/* View/Edit Spec Content Dialog */}\r\n <SpecContentDialog\r\n open={contentDialogOpen}\r\n onOpenChange={setContentDialogOpen}\r\n spec={viewingSpec}\r\n onSave={handleContentSave}\r\n />\r\n </div>\r\n );\r\n}\r\n\r\nexport default SpecsSettingsPage;\r\n"],"names":["Pen","createLucideIcon","readModeConfig","priorityConfig","categoryConfig","SpecCard","spec","onView","onEdit","onDelete","onToggle","className","showActions","actionsDisabled","formatMessage","useIntl","readMode","priority","handleToggle","enabled","handleAction","e","action","jsx","Card","cn","jsxs","CardContent","FileText","DropdownMenu","DropdownMenuTrigger","Button","MoreVertical","DropdownMenuContent","DropdownMenuItem","Eye","Edit","DropdownMenuSeparator","Trash2","Badge","Layers","Fragment","Globe","Folder","Tag","keyword","Switch","READ_MODE_OPTIONS","PRIORITY_OPTIONS","SpecDialog","open","onOpenChange","onSave","isLoading","formData","setFormData","React.useState","keywordInput","setKeywordInput","errors","setErrors","React.useEffect","validateForm","newErrors","handleSave","handleKeywordKeyDown","addKeyword","prev","removeKeyword","k","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Label","Input","Select","value","SelectTrigger","SelectValue","SelectContent","option","SelectItem","X","DialogFooter","parseFrontmatter","content","frontmatterRegex","match","frontmatterLines","frontmatter","line","colonIndex","key","s","SpecContentDialog","initialContent","readOnly","mode","setMode","setContent","editedContent","setEditedContent","body","React.useMemo","response","data","error","handleCancelEdit","Edit2","Textarea","Loader2","Save","SPEC_CATEGORIES","CATEGORY_CONFIG","RECOMMENDED_HOOKS","fetchSpecStats","fetchSystemSettings","updateInjectionSettings","settings","currentSettings","formatNumber","num","calculatePercentage","current","max","InjectionControlTab","installHooksMutation","useInstallRecommendedHooks","stats","setStats","useState","statsLoading","setStatsLoading","statsError","setStatsError","setSettings","settingsLoading","setSettingsLoading","hasChanges","setHasChanges","isSaving","setIsSaving","installingHookIds","setInstallingHookIds","systemSettingsQuery","useSystemSettings","previewMode","setPreviewMode","categoryFilter","setCategoryFilter","previewData","setPreviewData","previewLoading","setPreviewLoading","expandedDimensions","setExpandedDimensions","previewDialogOpen","setPreviewDialogOpen","previewFile","setPreviewFile","selectedCommand","setSelectedCommand","COMMAND_PREVIEWS","commandPreviewData","setCommandPreviewData","commandPreviewLoading","setCommandPreviewLoading","commandPreviewDialogOpen","setCommandPreviewDialogOpen","loadStats","useCallback","err","loadSettings","loadPreview","getInjectionPreview","loadFilePreview","file","fileWithData","f","loadCommandPreview","command","useEffect","changed","handleFieldChange","field","result","toast","handleReset","maxLengthError","warnThresholdError","toggleDimension","dim","installedHookIds","useMemo","installed","hooks","_a","hook","installedCount","allHooksInstalled","handleInstallHook","hookId","id","handleInstallAllHooks","uninstalledHooks","h","filesByDimension","grouped","categoryStats","cat","currentLength","_b","maxLength","_c","warnThreshold","percentage","isOverLimit","isOverWarning","remainingSpace","estimatedLineCount","maxLineCount","CardHeader","CardTitle","Plug","CardDescription","CheckCircle2","Download","Link","Settings","isInstalled","isInstalling","RefreshCw","Progress","AlertTriangle","AlertCircle","Info","_d","_e","Filter","files","ChevronDown","ChevronRight","sum","fileCategory","categoryStyle","cmd","checked","idx","API_BASE","updateSystemSettings","fetchProjectTechStats","settingsKeys","GlobalSettingsTab","queryClient","useQueryClient","localDefaults","setLocalDefaults","localDevProgress","setLocalDevProgress","isLoadingSettings","settingsError","useQuery","isLoadingStats","refetchStats","projectTechStats","updateMutation","useMutation","handleReadModeChange","newDefaults","handleAutoEnableChange","handleDevProgressToggle","newDevProgress","handleMaxEntriesChange","numValue","handleCategoryToggle","category","newCategories","c","dimensions","dimensionEntries","totalCount","totalRequired","hasError","i","entry","History","specEntryToSpec","dimension","SpecsSettingsPage","projectPath","useWorkflowStore","selectProjectPath","activeTab","setActiveTab","searchQuery","setSearchQuery","personalScopeFilter","setPersonalScopeFilter","editDialogOpen","setEditDialogOpen","contentDialogOpen","setContentDialogOpen","editingSpec","setEditingSpec","viewingSpec","setViewingSpec","specsListData","specsLoading","refetchSpecs","useSpecsList","statsData","useSpecStats","rebuildMutation","useRebuildSpecIndex","projectSpecs","personalSpecs","globalPersonalSpecs","projectPersonalSpecs","categoryCounts","specs","personal","globalPersonal","projectPersonal","counts","entries","handleSpecView","handleSpecEdit","handleSpecSave","specId","handleContentSave","handleSpecToggle","handleSpecDelete","handleRebuildIndex","filterSpecs","query","renderSpecsTab","filteredSpecs","Search","ScrollText","Tabs","v","TabsList","TabsTrigger","User","Gauge","TabsContent"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"SpecsSettingsPage-DT-yTVkD.js","sources":["../../../../node_modules/lucide-react/dist/esm/icons/pen.js","../../src/components/specs/SpecCard.tsx","../../src/components/specs/SpecDialog.tsx","../../src/components/specs/SpecContentDialog.tsx","../../src/components/specs/InjectionControlTab.tsx","../../src/components/specs/GlobalSettingsTab.tsx","../../src/pages/SpecsSettingsPage.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Pen = createLucideIcon(\"Pen\", [\n [\n \"path\",\n {\n d: \"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\",\n key: \"1a8usu\"\n }\n ]\n]);\n\nexport { Pen as default };\n//# sourceMappingURL=pen.js.map\n","// ========================================\r\n// SpecCard Component\r\n// ========================================\r\n// Spec card with readMode badge, keywords, priority indicator and action menu\r\n\r\nimport * as React from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { cn } from '@/lib/utils';\r\nimport { Card, CardContent } from '@/components/ui/Card';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Switch } from '@/components/ui/Switch';\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuTrigger,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n DropdownMenuSeparator,\r\n} from '@/components/ui/DropdownMenu';\r\nimport {\r\n MoreVertical,\r\n Edit,\r\n Trash2,\r\n FileText,\r\n Tag,\r\n Eye,\r\n Globe,\r\n Folder,\r\n Layers,\r\n} from 'lucide-react';\r\n\r\n// ========== Types ==========\r\n\r\n/**\r\n * Spec dimension type\r\n */\r\nexport type SpecDimension = 'specs' | 'personal';\r\n\r\n/**\r\n * Spec scope type\r\n */\r\nexport type SpecScope = 'global' | 'project';\r\n\r\n/**\r\n * Spec read mode type\r\n */\r\nexport type SpecReadMode = 'required' | 'optional';\r\n\r\n/**\r\n * Spec priority type\r\n */\r\nexport type SpecPriority = 'critical' | 'high' | 'medium' | 'low';\r\n\r\n/**\r\n * Spec category type for workflow stage-based loading\r\n */\r\nexport type SpecCategory = 'general' | 'exploration' | 'planning' | 'execution';\r\n\r\n/**\r\n * Spec data structure\r\n */\r\nexport interface Spec {\r\n /** Unique spec identifier */\r\n id: string;\r\n /** Spec title (display name) */\r\n title: string;\r\n /** Spec file path */\r\n file: string;\r\n /** Spec dimension/category */\r\n dimension: SpecDimension;\r\n /** Scope: global (from ~/.ccw/) or project (from .ccw/) */\r\n scope: SpecScope;\r\n /** Workflow stage category for system-level loading */\r\n category?: SpecCategory;\r\n /** Read mode: required (always inject) or optional (keyword match) */\r\n readMode: SpecReadMode;\r\n /** Priority level */\r\n priority: SpecPriority;\r\n /** Keywords for matching (optional specs) */\r\n keywords: string[];\r\n /** Whether spec is enabled */\r\n enabled: boolean;\r\n /** Optional description */\r\n description?: string;\r\n}\r\n\r\n/**\r\n * SpecCard component props\r\n */\r\nexport interface SpecCardProps {\r\n /** Spec data */\r\n spec: Spec;\r\n /** Called when view content action is triggered */\r\n onView?: (spec: Spec) => void;\r\n /** Called when edit action is triggered */\r\n onEdit?: (spec: Spec) => void;\r\n /** Called when delete action is triggered */\r\n onDelete?: (specId: string) => void;\r\n /** Called when toggle enabled is triggered */\r\n onToggle?: (specId: string, enabled: boolean) => void;\r\n /** Optional className */\r\n className?: string;\r\n /** Show actions dropdown */\r\n showActions?: boolean;\r\n /** Disabled state for actions */\r\n actionsDisabled?: boolean;\r\n}\r\n\r\n// ========== Configuration ==========\r\n\r\n// Read mode badge configuration\r\nconst readModeConfig: Record<\r\n SpecReadMode,\r\n { variant: 'default' | 'secondary'; labelKey: string }\r\n> = {\r\n required: { variant: 'default', labelKey: 'specs.readMode.required' },\r\n optional: { variant: 'secondary', labelKey: 'specs.readMode.optional' },\r\n};\r\n\r\n// Priority badge configuration\r\nconst priorityConfig: Record<\r\n SpecPriority,\r\n { variant: 'destructive' | 'warning' | 'info' | 'secondary'; labelKey: string }\r\n> = {\r\n critical: { variant: 'destructive', labelKey: 'specs.priority.critical' },\r\n high: { variant: 'warning', labelKey: 'specs.priority.high' },\r\n medium: { variant: 'info', labelKey: 'specs.priority.medium' },\r\n low: { variant: 'secondary', labelKey: 'specs.priority.low' },\r\n};\r\n\r\n// Category badge configuration for workflow stage\r\nconst categoryConfig: Record<\r\n SpecCategory,\r\n { variant: 'default' | 'secondary' | 'outline'; labelKey: string }\r\n> = {\r\n general: { variant: 'secondary', labelKey: 'specs.category.general' },\r\n exploration: { variant: 'outline', labelKey: 'specs.category.exploration' },\r\n planning: { variant: 'outline', labelKey: 'specs.category.planning' },\r\n execution: { variant: 'outline', labelKey: 'specs.category.execution' },\r\n};\r\n\r\n// ========== Component ==========\r\n\r\n/**\r\n * SpecCard component for displaying spec information\r\n */\r\nexport function SpecCard({\r\n spec,\r\n onView,\r\n onEdit,\r\n onDelete,\r\n onToggle,\r\n className,\r\n showActions = true,\r\n actionsDisabled = false,\r\n}: SpecCardProps) {\r\n const { formatMessage } = useIntl();\r\n\r\n const readMode = readModeConfig[spec.readMode];\r\n const priority = priorityConfig[spec.priority];\r\n\r\n const handleToggle = (enabled: boolean) => {\r\n onToggle?.(spec.id, enabled);\r\n };\r\n\r\n const handleAction = (e: React.MouseEvent, action: 'edit' | 'delete') => {\r\n e.stopPropagation();\r\n switch (action) {\r\n case 'edit':\r\n onEdit?.(spec);\r\n break;\r\n case 'delete':\r\n onDelete?.(spec.id);\r\n break;\r\n }\r\n };\r\n\r\n return (\r\n <Card\r\n className={cn(\r\n 'group transition-all duration-200 hover:shadow-md hover:border-primary/30 hover-glow',\r\n !spec.enabled && 'opacity-60',\r\n className\r\n )}\r\n >\r\n <CardContent className=\"p-4\">\r\n {/* Header */}\r\n <div className=\"flex items-start justify-between gap-2\">\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <FileText className=\"h-4 w-4 text-muted-foreground shrink-0\" />\r\n <h3 className=\"font-medium text-card-foreground truncate\">\r\n {spec.title}\r\n </h3>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-0.5 truncate\">\r\n {spec.file}\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-2 flex-shrink-0\">\r\n {showActions && (\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity\"\r\n onClick={(e) => e.stopPropagation()}\r\n disabled={actionsDisabled}\r\n >\r\n <MoreVertical className=\"h-4 w-4\" />\r\n <span className=\"sr-only\">{formatMessage({ id: 'common.aria.actions' })}</span>\r\n </Button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\">\r\n <DropdownMenuItem onClick={(e) => { e.stopPropagation(); onView?.(spec); }}>\r\n <Eye className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'specs.actions.view', defaultMessage: 'View Content' })}\r\n </DropdownMenuItem>\r\n <DropdownMenuItem onClick={(e) => handleAction(e, 'edit')}>\r\n <Edit className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'specs.actions.edit' })}\r\n </DropdownMenuItem>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem\r\n onClick={(e) => handleAction(e, 'delete')}\r\n className=\"text-destructive focus:text-destructive\"\r\n >\r\n <Trash2 className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'specs.actions.delete' })}\r\n </DropdownMenuItem>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Badges */}\r\n <div className=\"mt-3 flex flex-wrap items-center gap-2\">\r\n {/* Category badge - workflow stage */}\r\n {spec.category && (\r\n <Badge variant={categoryConfig[spec.category].variant} className=\"text-xs gap-1\">\r\n <Layers className=\"h-3 w-3\" />\r\n {formatMessage({ id: categoryConfig[spec.category].labelKey, defaultMessage: spec.category })}\r\n </Badge>\r\n )}\r\n {/* Scope badge - only show for personal specs */}\r\n {spec.dimension === 'personal' && (\r\n <Badge variant=\"outline\" className=\"text-xs gap-1\">\r\n {spec.scope === 'global' ? (\r\n <>\r\n <Globe className=\"h-3 w-3\" />\r\n {formatMessage({ id: 'specs.scope.global', defaultMessage: 'Global' })}\r\n </>\r\n ) : (\r\n <>\r\n <Folder className=\"h-3 w-3\" />\r\n {formatMessage({ id: 'specs.scope.project', defaultMessage: 'Project' })}\r\n </>\r\n )}\r\n </Badge>\r\n )}\r\n <Badge variant={readMode.variant} className=\"text-xs\">\r\n {formatMessage({ id: readMode.labelKey })}\r\n </Badge>\r\n <Badge variant={priority.variant} className=\"text-xs\">\r\n {formatMessage({ id: priority.labelKey })}\r\n </Badge>\r\n </div>\r\n\r\n {/* Description */}\r\n {spec.description && (\r\n <p className=\"mt-3 text-sm text-muted-foreground line-clamp-2\">\r\n {spec.description}\r\n </p>\r\n )}\r\n\r\n {/* Keywords */}\r\n {spec.keywords.length > 0 && (\r\n <div className=\"mt-3 flex flex-wrap items-center gap-1.5\">\r\n <Tag className=\"h-3.5 w-3.5 text-muted-foreground\" />\r\n {spec.keywords.slice(0, 4).map((keyword) => (\r\n <Badge key={keyword} variant=\"outline\" className=\"text-xs px-1.5 py-0\">\r\n {keyword}\r\n </Badge>\r\n ))}\r\n {spec.keywords.length > 4 && (\r\n <span className=\"text-xs text-muted-foreground\">\r\n +{spec.keywords.length - 4}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Footer with toggle */}\r\n <div className=\"mt-3 pt-3 border-t border-border flex items-center justify-between\">\r\n <span className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: spec.enabled ? 'specs.status.enabled' : 'specs.status.disabled' })}\r\n </span>\r\n <Switch\r\n checked={spec.enabled}\r\n onCheckedChange={handleToggle}\r\n disabled={actionsDisabled}\r\n className=\"data-[state=checked]:bg-primary\"\r\n />\r\n </div>\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n\r\n/**\r\n * Skeleton loader for SpecCard\r\n */\r\nexport function SpecCardSkeleton({ className }: { className?: string }) {\r\n return (\r\n <Card className={cn('animate-pulse', className)}>\r\n <CardContent className=\"p-4\">\r\n <div className=\"flex items-start justify-between\">\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"h-4 w-4 rounded bg-muted\" />\r\n <div className=\"h-5 w-32 rounded bg-muted\" />\r\n </div>\r\n <div className=\"mt-1 h-3 w-24 rounded bg-muted\" />\r\n </div>\r\n <div className=\"h-8 w-8 rounded bg-muted\" />\r\n </div>\r\n <div className=\"mt-3 flex gap-2\">\r\n <div className=\"h-5 w-14 rounded-full bg-muted\" />\r\n <div className=\"h-5 w-12 rounded-full bg-muted\" />\r\n </div>\r\n <div className=\"mt-3 h-4 w-full rounded bg-muted\" />\r\n <div className=\"mt-2 flex gap-1.5\">\r\n <div className=\"h-5 w-16 rounded bg-muted\" />\r\n <div className=\"h-5 w-14 rounded bg-muted\" />\r\n <div className=\"h-5 w-12 rounded bg-muted\" />\r\n </div>\r\n <div className=\"mt-3 pt-3 border-t border-border flex items-center justify-between\">\r\n <div className=\"h-3 w-16 rounded bg-muted\" />\r\n <div className=\"h-5 w-9 rounded-full bg-muted\" />\r\n </div>\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n\r\nexport default SpecCard;\r\n","// ========================================\r\n// SpecDialog Component\r\n// ========================================\r\n// Dialog for editing spec frontmatter (title, readMode, priority, keywords)\r\n\r\nimport * as React from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n DialogDescription,\r\n DialogFooter,\r\n} from '@/components/ui/Dialog';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Label } from '@/components/ui/Label';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport {\r\n Select,\r\n SelectTrigger,\r\n SelectValue,\r\n SelectContent,\r\n SelectItem,\r\n} from '@/components/ui/Select';\r\nimport { Tag, X } from 'lucide-react';\r\nimport type { Spec, SpecReadMode, SpecPriority } from './SpecCard';\r\n\r\n// ========== Types ==========\r\n\r\n/**\r\n * Spec form data for editing\r\n */\r\nexport interface SpecFormData {\r\n title: string;\r\n readMode: SpecReadMode;\r\n priority: SpecPriority;\r\n keywords: string[];\r\n}\r\n\r\n/**\r\n * SpecDialog component props\r\n */\r\nexport interface SpecDialogProps {\r\n /** Whether dialog is open */\r\n open: boolean;\r\n /** Called when dialog open state changes */\r\n onOpenChange: (open: boolean) => void;\r\n /** Spec being edited */\r\n spec: Spec | null;\r\n /** Called when save is clicked */\r\n onSave: (specId: string, data: SpecFormData) => Promise<void> | void;\r\n /** Optional loading state */\r\n isLoading?: boolean;\r\n}\r\n\r\n// ========== Constants ==========\r\n\r\nconst READ_MODE_OPTIONS: { value: SpecReadMode; labelKey: string }[] = [\r\n { value: 'required', labelKey: 'specs.readMode.required' },\r\n { value: 'optional', labelKey: 'specs.readMode.optional' },\r\n];\r\n\r\nconst PRIORITY_OPTIONS: { value: SpecPriority; labelKey: string }[] = [\r\n { value: 'critical', labelKey: 'specs.priority.critical' },\r\n { value: 'high', labelKey: 'specs.priority.high' },\r\n { value: 'medium', labelKey: 'specs.priority.medium' },\r\n { value: 'low', labelKey: 'specs.priority.low' },\r\n];\r\n\r\n// ========== Component ==========\r\n\r\n/**\r\n * SpecDialog component for editing spec frontmatter\r\n */\r\nexport function SpecDialog({\r\n open,\r\n onOpenChange,\r\n spec,\r\n onSave,\r\n isLoading = false,\r\n}: SpecDialogProps) {\r\n const { formatMessage } = useIntl();\r\n const [formData, setFormData] = React.useState<SpecFormData>({\r\n title: '',\r\n readMode: 'optional',\r\n priority: 'medium',\r\n keywords: [],\r\n });\r\n const [keywordInput, setKeywordInput] = React.useState('');\r\n const [errors, setErrors] = React.useState<Partial<Record<keyof SpecFormData, string>>>({});\r\n\r\n // Reset form when spec changes\r\n React.useEffect(() => {\r\n if (spec) {\r\n setFormData({\r\n title: spec.title,\r\n readMode: spec.readMode,\r\n priority: spec.priority,\r\n keywords: [...spec.keywords],\r\n });\r\n setErrors({});\r\n setKeywordInput('');\r\n }\r\n }, [spec]);\r\n\r\n // Validate form\r\n const validateForm = (): boolean => {\r\n const newErrors: Partial<Record<keyof SpecFormData, string>> = {};\r\n\r\n if (!formData.title.trim()) {\r\n newErrors.title = formatMessage({ id: 'specs.validation.titleRequired' });\r\n }\r\n\r\n setErrors(newErrors);\r\n return Object.keys(newErrors).length === 0;\r\n };\r\n\r\n // Handle save\r\n const handleSave = async () => {\r\n if (!spec || !validateForm()) return;\r\n\r\n await onSave(spec.id, formData);\r\n };\r\n\r\n // Handle keyword input\r\n const handleKeywordKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\r\n if (e.key === 'Enter' || e.key === ',') {\r\n e.preventDefault();\r\n addKeyword();\r\n }\r\n };\r\n\r\n // Add keyword\r\n const addKeyword = () => {\r\n const keyword = keywordInput.trim().toLowerCase();\r\n if (keyword && !formData.keywords.includes(keyword)) {\r\n setFormData((prev) => ({\r\n ...prev,\r\n keywords: [...prev.keywords, keyword],\r\n }));\r\n }\r\n setKeywordInput('');\r\n };\r\n\r\n // Remove keyword\r\n const removeKeyword = (keyword: string) => {\r\n setFormData((prev) => ({\r\n ...prev,\r\n keywords: prev.keywords.filter((k) => k !== keyword),\r\n }));\r\n };\r\n\r\n if (!spec) return null;\r\n\r\n return (\r\n <Dialog open={open} onOpenChange={onOpenChange}>\r\n <DialogContent className=\"sm:max-w-[500px]\">\r\n <DialogHeader>\r\n <DialogTitle>\r\n {formatMessage({ id: 'specs.dialog.editTitle' }, { title: spec.title })}\r\n </DialogTitle>\r\n <DialogDescription>\r\n {formatMessage({ id: 'specs.dialog.editDescription' })}\r\n </DialogDescription>\r\n </DialogHeader>\r\n\r\n <div className=\"space-y-4 py-4\">\r\n {/* Title field */}\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"title\">\r\n {formatMessage({ id: 'specs.form.title' })}\r\n </Label>\r\n <Input\r\n id=\"title\"\r\n value={formData.title}\r\n onChange={(e) => setFormData((prev) => ({ ...prev, title: e.target.value }))}\r\n placeholder={formatMessage({ id: 'specs.form.titlePlaceholder' })}\r\n error={!!errors.title}\r\n disabled={isLoading}\r\n />\r\n {errors.title && (\r\n <p className=\"text-sm text-destructive\">{errors.title}</p>\r\n )}\r\n </div>\r\n\r\n {/* Read mode and Priority */}\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div className=\"space-y-2\">\r\n <Label>{formatMessage({ id: 'specs.form.readMode' })}</Label>\r\n <Select\r\n value={formData.readMode}\r\n onValueChange={(value: SpecReadMode) =>\r\n setFormData((prev) => ({ ...prev, readMode: value }))\r\n }\r\n disabled={isLoading}\r\n >\r\n <SelectTrigger>\r\n <SelectValue />\r\n </SelectTrigger>\r\n <SelectContent>\r\n {READ_MODE_OPTIONS.map((option) => (\r\n <SelectItem key={option.value} value={option.value}>\r\n {formatMessage({ id: option.labelKey })}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n\r\n <div className=\"space-y-2\">\r\n <Label>{formatMessage({ id: 'specs.form.priority' })}</Label>\r\n <Select\r\n value={formData.priority}\r\n onValueChange={(value: SpecPriority) =>\r\n setFormData((prev) => ({ ...prev, priority: value }))\r\n }\r\n disabled={isLoading}\r\n >\r\n <SelectTrigger>\r\n <SelectValue />\r\n </SelectTrigger>\r\n <SelectContent>\r\n {PRIORITY_OPTIONS.map((option) => (\r\n <SelectItem key={option.value} value={option.value}>\r\n {formatMessage({ id: option.labelKey })}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n </div>\r\n\r\n {/* Keywords */}\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"keywords\">\r\n {formatMessage({ id: 'specs.form.keywords' })}\r\n </Label>\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"relative flex-1\">\r\n <Input\r\n id=\"keywords\"\r\n value={keywordInput}\r\n onChange={(e) => setKeywordInput(e.target.value)}\r\n onKeyDown={handleKeywordKeyDown}\r\n onBlur={addKeyword}\r\n placeholder={formatMessage({ id: 'specs.form.keywordsPlaceholder' })}\r\n disabled={isLoading}\r\n />\r\n </div>\r\n <Button\r\n type=\"button\"\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={addKeyword}\r\n disabled={isLoading || !keywordInput.trim()}\r\n >\r\n {formatMessage({ id: 'specs.form.addKeyword' })}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'specs.form.keywordsHint' })}\r\n </p>\r\n\r\n {/* Keywords display */}\r\n {formData.keywords.length > 0 && (\r\n <div className=\"flex flex-wrap gap-1.5 mt-2\">\r\n <Tag className=\"h-3.5 w-3.5 text-muted-foreground mt-0.5\" />\r\n {formData.keywords.map((keyword) => (\r\n <Badge\r\n key={keyword}\r\n variant=\"secondary\"\r\n className=\"text-xs pl-2 pr-1 gap-1\"\r\n >\r\n {keyword}\r\n <button\r\n type=\"button\"\r\n onClick={() => removeKeyword(keyword)}\r\n className=\"ml-0.5 hover:text-destructive transition-colors\"\r\n disabled={isLoading}\r\n >\r\n <X className=\"h-3 w-3\" />\r\n </button>\r\n </Badge>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* File info */}\r\n <div className=\"pt-2 border-t border-border\">\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'specs.form.fileInfo' }, { file: spec.file })}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <DialogFooter>\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => onOpenChange(false)}\r\n disabled={isLoading}\r\n >\r\n {formatMessage({ id: 'common.cancel' })}\r\n </Button>\r\n <Button onClick={handleSave} disabled={isLoading}>\r\n {isLoading\r\n ? formatMessage({ id: 'specs.form.saving' })\r\n : formatMessage({ id: 'common.save' })}\r\n </Button>\r\n </DialogFooter>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}\r\n\r\nexport default SpecDialog;\r\n","// ========================================\r\n// SpecContentDialog Component\r\n// ========================================\r\n// Dialog for viewing and editing spec markdown content\r\n\r\nimport * as React from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { cn } from '@/lib/utils';\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n DialogDescription,\r\n DialogFooter,\r\n} from '@/components/ui/Dialog';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Textarea } from '@/components/ui/Textarea';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { Eye, Edit2, Save, FileText, Loader2 } from 'lucide-react';\r\nimport type { Spec } from './SpecCard';\r\n\r\n// ========== Types ==========\r\n\r\n/**\r\n * SpecContentDialog component props\r\n */\r\nexport interface SpecContentDialogProps {\r\n /** Whether dialog is open */\r\n open: boolean;\r\n /** Called when dialog open state changes */\r\n onOpenChange: (open: boolean) => void;\r\n /** Spec being viewed/edited */\r\n spec: Spec | null;\r\n /** Initial content of the spec */\r\n content?: string;\r\n /** Called when content is saved */\r\n onSave?: (specId: string, content: string) => Promise<void> | void;\r\n /** Whether in read-only mode */\r\n readOnly?: boolean;\r\n /** Optional loading state */\r\n isLoading?: boolean;\r\n}\r\n\r\n// ========== Helper Functions ==========\r\n\r\n/**\r\n * Extract frontmatter from markdown content\r\n */\r\nfunction parseFrontmatter(content: string): {\r\n frontmatter: Record<string, unknown>;\r\n body: string;\r\n} {\r\n const frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/;\r\n const match = content.match(frontmatterRegex);\r\n\r\n if (!match) {\r\n return { frontmatter: {}, body: content };\r\n }\r\n\r\n const frontmatterLines = match[1].split('\\n');\r\n const frontmatter: Record<string, unknown> = {};\r\n\r\n for (const line of frontmatterLines) {\r\n const colonIndex = line.indexOf(':');\r\n if (colonIndex > 0) {\r\n const key = line.slice(0, colonIndex).trim();\r\n const value = line.slice(colonIndex + 1).trim();\r\n\r\n // Parse arrays (keywords: [a, b, c])\r\n if (value.startsWith('[') && value.endsWith(']')) {\r\n frontmatter[key] = value\r\n .slice(1, -1)\r\n .split(',')\r\n .map(s => s.trim().replace(/^['\"]|['\"]$/g, ''))\r\n .filter(Boolean);\r\n } else {\r\n frontmatter[key] = value.replace(/^['\"]|['\"]$/g, '');\r\n }\r\n }\r\n }\r\n\r\n return { frontmatter, body: match[2] };\r\n}\r\n\r\n// ========== Component ==========\r\n\r\n/**\r\n * SpecContentDialog component for viewing and editing spec content\r\n */\r\nexport function SpecContentDialog({\r\n open,\r\n onOpenChange,\r\n spec,\r\n content: initialContent,\r\n onSave,\r\n readOnly = false,\r\n isLoading = false,\r\n}: SpecContentDialogProps) {\r\n const { formatMessage } = useIntl();\r\n const [mode, setMode] = React.useState<'view' | 'edit'>('view');\r\n const [content, setContent] = React.useState(initialContent || '');\r\n const [editedContent, setEditedContent] = React.useState('');\r\n\r\n // Parse frontmatter for display\r\n const { body } = React.useMemo(() => {\r\n return parseFrontmatter(content);\r\n }, [content]);\r\n\r\n // Reset when spec changes\r\n React.useEffect(() => {\r\n if (spec && open) {\r\n // Fetch spec content\r\n const fetchContent = async () => {\r\n try {\r\n const response = await fetch(`/api/specs/detail?file=${encodeURIComponent(spec.file)}`);\r\n if (response.ok) {\r\n const data = await response.json();\r\n setContent(data.content || '');\r\n setEditedContent(data.content || '');\r\n }\r\n } catch (error) {\r\n console.error('Failed to fetch spec content:', error);\r\n }\r\n };\r\n fetchContent();\r\n setMode('view');\r\n }\r\n }, [spec, open]);\r\n\r\n // Handle save\r\n const handleSave = async () => {\r\n if (!spec || !onSave) return;\r\n await onSave(spec.id, editedContent);\r\n setContent(editedContent);\r\n setMode('view');\r\n };\r\n\r\n // Handle cancel edit\r\n const handleCancelEdit = () => {\r\n setEditedContent(content);\r\n setMode('view');\r\n };\r\n\r\n if (!spec) return null;\r\n\r\n return (\r\n <Dialog open={open} onOpenChange={onOpenChange}>\r\n <DialogContent className={cn('sm:max-w-[800px] max-h-[80vh]', mode === 'edit' && 'flex flex-col')}>\r\n <DialogHeader>\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <FileText className=\"h-5 w-5\" />\r\n {spec.title}\r\n </DialogTitle>\r\n {!readOnly && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n onClick={() => mode === 'view' ? setMode('edit') : handleCancelEdit()}\r\n disabled={isLoading}\r\n >\r\n {mode === 'view' ? (\r\n <>\r\n <Edit2 className=\"h-4 w-4 mr-1\" />\r\n {formatMessage({ id: 'specs.content.edit', defaultMessage: 'Edit' })}\r\n </>\r\n ) : (\r\n <>\r\n <Eye className=\"h-4 w-4 mr-1\" />\r\n {formatMessage({ id: 'specs.content.view', defaultMessage: 'View' })}\r\n </>\r\n )}\r\n </Button>\r\n )}\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Badge variant={spec.readMode === 'required' ? 'default' : 'secondary'}>\r\n {formatMessage({ id: `specs.readMode.${spec.readMode}` })}\r\n </Badge>\r\n <Badge variant=\"outline\">\r\n {formatMessage({ id: `specs.priority.${spec.priority}` })}\r\n </Badge>\r\n </div>\r\n </div>\r\n <DialogDescription>\r\n {spec.file}\r\n </DialogDescription>\r\n </DialogHeader>\r\n\r\n <div className=\"flex-1 overflow-auto py-4\">\r\n {mode === 'view' ? (\r\n <div className=\"space-y-4\">\r\n {/* Frontmatter Info */}\r\n <div className=\"p-3 bg-muted/50 rounded-lg\">\r\n <div className=\"text-sm font-medium mb-2\">\r\n {formatMessage({ id: 'specs.content.metadata', defaultMessage: 'Metadata' })}\r\n </div>\r\n <div className=\"grid grid-cols-2 gap-2 text-sm\">\r\n <div>\r\n <span className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.form.readMode', defaultMessage: 'Read Mode' })}:\r\n </span>{' '}\r\n <Badge variant=\"secondary\" className=\"text-xs\">\r\n {formatMessage({ id: `specs.readMode.${spec.readMode}` })}\r\n </Badge>\r\n </div>\r\n <div>\r\n <span className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.form.priority', defaultMessage: 'Priority' })}:\r\n </span>{' '}\r\n <Badge variant=\"outline\" className=\"text-xs\">\r\n {formatMessage({ id: `specs.priority.${spec.priority}` })}\r\n </Badge>\r\n </div>\r\n </div>\r\n {spec.keywords.length > 0 && (\r\n <div className=\"mt-2 text-sm\">\r\n <span className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.form.keywords', defaultMessage: 'Keywords' })}:\r\n </span>{' '}\r\n {spec.keywords.map(k => (\r\n <Badge key={k} variant=\"outline\" className=\"text-xs mr-1\">{k}</Badge>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Markdown Content */}\r\n <div className=\"border rounded-lg\">\r\n <div className=\"bg-muted/30 px-3 py-2 border-b text-sm font-medium\">\r\n {formatMessage({ id: 'specs.content.markdownContent', defaultMessage: 'Markdown Content' })}\r\n </div>\r\n <pre className=\"p-4 text-sm overflow-auto max-h-[400px] whitespace-pre-wrap break-words\">\r\n {body || formatMessage({ id: 'specs.content.noContent', defaultMessage: 'No content available' })}\r\n </pre>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"space-y-4\">\r\n <div className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.content.editHint', defaultMessage: 'Edit the full markdown content including frontmatter. Changes to frontmatter will be reflected in the spec metadata.' })}\r\n </div>\r\n <Textarea\r\n value={editedContent}\r\n onChange={(e) => setEditedContent(e.target.value)}\r\n className=\"font-mono text-sm min-h-[400px] resize-none\"\r\n placeholder={formatMessage({ id: 'specs.content.placeholder', defaultMessage: '# Spec Title\\n\\nContent here...' })}\r\n disabled={isLoading}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n\r\n <DialogFooter>\r\n {mode === 'edit' ? (\r\n <>\r\n <Button variant=\"outline\" onClick={handleCancelEdit} disabled={isLoading}>\r\n {formatMessage({ id: 'specs.common.cancel', defaultMessage: 'Cancel' })}\r\n </Button>\r\n <Button onClick={handleSave} disabled={isLoading}>\r\n {isLoading ? (\r\n <>\r\n <Loader2 className=\"h-4 w-4 mr-2 animate-spin\" />\r\n {formatMessage({ id: 'specs.common.saving', defaultMessage: 'Saving...' })}\r\n </>\r\n ) : (\r\n <>\r\n <Save className=\"h-4 w-4 mr-2\" />\r\n {formatMessage({ id: 'specs.common.save', defaultMessage: 'Save' })}\r\n </>\r\n )}\r\n </Button>\r\n </>\r\n ) : (\r\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\r\n {formatMessage({ id: 'specs.common.close', defaultMessage: 'Close' })}\r\n </Button>\r\n )}\r\n </DialogFooter>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}\r\n\r\nexport default SpecContentDialog;\r\n","// ========================================\r\n// InjectionControlTab Component\r\n// ========================================\r\n// Tab for managing spec injection control settings\r\n\r\nimport { useState, useEffect, useCallback, useMemo } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { Link } from 'react-router-dom';\r\nimport { toast } from 'sonner';\r\nimport { cn } from '@/lib/utils';\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n} from '@/components/ui/Dialog';\r\nimport {\r\n Card,\r\n CardContent,\r\n CardDescription,\r\n CardHeader,\r\n CardTitle,\r\n} from '@/components/ui/Card';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Label } from '@/components/ui/Label';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Switch } from '@/components/ui/Switch';\r\nimport { Progress } from '@/components/ui/Progress';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport {\r\n AlertCircle,\r\n Info,\r\n Loader2,\r\n RefreshCw,\r\n AlertTriangle,\r\n Plug,\r\n Download,\r\n CheckCircle2,\r\n Settings,\r\n FileText,\r\n Eye,\r\n Globe,\r\n Folder,\r\n ChevronDown,\r\n ChevronRight,\r\n Layers,\r\n Filter,\r\n} from 'lucide-react';\r\nimport { useInstallRecommendedHooks, useSystemSettings } from '@/hooks/useSystemSettings';\r\nimport type { InjectionPreviewFile, InjectionPreviewResponse } from '@/lib/api';\r\nimport { getInjectionPreview, COMMAND_PREVIEWS, type CommandPreviewConfig } from '@/lib/api';\r\n\r\n// ========== Types ==========\r\n\r\nexport interface InjectionStats {\r\n requiredOnly: number;\r\n withKeywords: number;\r\n maxLength: number;\r\n percentage: number;\r\n}\r\n\r\nexport interface SpecStatsResponse {\r\n dimensions: {\r\n specs: { count: number; requiredCount: number };\r\n personal: { count: number; requiredCount: number };\r\n };\r\n injectionLength: InjectionStats;\r\n}\r\n\r\nexport interface InjectionSettings {\r\n maxLength: number;\r\n warnThreshold: number;\r\n truncateOnExceed: boolean;\r\n}\r\n\r\nexport interface SystemSettingsResponse {\r\n injectionControl: InjectionSettings;\r\n personalSpecDefaults: {\r\n defaultReadMode: 'required' | 'optional';\r\n autoEnable: boolean;\r\n };\r\n}\r\n\r\nexport interface InjectionControlTabProps {\r\n className?: string;\r\n}\r\n\r\n// ========== Category Configuration ==========\r\n\r\ntype SpecCategory = 'general' | 'exploration' | 'planning' | 'execution';\r\n\r\nconst SPEC_CATEGORIES: SpecCategory[] = ['general', 'exploration', 'planning', 'execution'];\r\n\r\nconst CATEGORY_CONFIG: Record<SpecCategory, { color: string; bgColor: string }> = {\r\n general: { color: 'text-gray-600', bgColor: 'bg-gray-100 dark:bg-gray-800' },\r\n exploration: { color: 'text-blue-600', bgColor: 'bg-blue-100 dark:bg-blue-900/30' },\r\n planning: { color: 'text-purple-600', bgColor: 'bg-purple-100 dark:bg-purple-900/30' },\r\n execution: { color: 'text-green-600', bgColor: 'bg-green-100 dark:bg-green-900/30' },\r\n};\r\n\r\n// ========== Recommended Hooks Configuration ==========\r\n\r\nconst RECOMMENDED_HOOKS = [\r\n {\r\n id: 'spec-injection-session',\r\n name: 'Spec Context Injection (Session)',\r\n event: 'SessionStart',\r\n command: 'ccw spec load --stdin',\r\n scope: 'global' as const,\r\n description: 'Automatically inject spec context when Claude session starts',\r\n },\r\n {\r\n id: 'spec-injection-prompt',\r\n name: 'Spec Context Injection (Prompt)',\r\n event: 'UserPromptSubmit',\r\n command: 'ccw spec load --stdin',\r\n scope: 'project' as const,\r\n description: 'Inject spec context when user submits a prompt, matching keywords',\r\n },\r\n];\r\n\r\n// ========== API Functions ==========\r\n\r\nasync function fetchSpecStats(): Promise<SpecStatsResponse> {\r\n const response = await fetch('/api/specs/stats');\r\n if (!response.ok) {\r\n throw new Error('Failed to fetch spec stats');\r\n }\r\n return response.json();\r\n}\r\n\r\nasync function fetchSystemSettings(): Promise<SystemSettingsResponse> {\r\n const response = await fetch('/api/system/settings');\r\n if (!response.ok) {\r\n throw new Error('Failed to fetch system settings');\r\n }\r\n return response.json();\r\n}\r\n\r\nasync function updateInjectionSettings(\r\n settings: Partial<InjectionSettings>\r\n): Promise<SystemSettingsResponse> {\r\n const currentSettings = await fetchSystemSettings();\r\n const response = await fetch('/api/system/settings', {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n injectionControl: {\r\n ...currentSettings.injectionControl,\r\n ...settings,\r\n },\r\n }),\r\n });\r\n if (!response.ok) {\r\n throw new Error('Failed to update settings');\r\n }\r\n return response.json();\r\n}\r\n\r\n// ========== Helper Functions ==========\r\n\r\nfunction formatNumber(num: number): string {\r\n return num.toLocaleString();\r\n}\r\n\r\nfunction calculatePercentage(current: number, max: number): number {\r\n if (max <= 0) return 0;\r\n return Math.min(100, (current / max) * 100);\r\n}\r\n\r\n// ========== Component ==========\r\n\r\nexport function InjectionControlTab({ className }: InjectionControlTabProps) {\r\n const { formatMessage } = useIntl();\r\n const installHooksMutation = useInstallRecommendedHooks();\r\n\r\n // State for stats\r\n const [stats, setStats] = useState<SpecStatsResponse | null>(null);\r\n const [statsLoading, setStatsLoading] = useState(true);\r\n const [statsError, setStatsError] = useState<Error | null>(null);\r\n\r\n // State for settings\r\n const [settings, setSettings] = useState<InjectionSettings>({\r\n maxLength: 8000,\r\n warnThreshold: 6000,\r\n truncateOnExceed: true,\r\n });\r\n const [settingsLoading, setSettingsLoading] = useState(true);\r\n\r\n // Form state (for local editing before save)\r\n const [formData, setFormData] = useState<InjectionSettings>(settings);\r\n const [hasChanges, setHasChanges] = useState(false);\r\n const [isSaving, setIsSaving] = useState(false);\r\n\r\n // State for hooks installation\r\n const [installingHookIds, setInstallingHookIds] = useState<string[]>([]);\r\n\r\n // Fetch system settings (for hooks installation status)\r\n const systemSettingsQuery = useSystemSettings();\r\n\r\n // State for injection preview\r\n const [previewMode, setPreviewMode] = useState<'required' | 'all'>('required');\r\n const [categoryFilter, setCategoryFilter] = useState<SpecCategory | 'all'>('all');\r\n const [previewData, setPreviewData] = useState<InjectionPreviewResponse | null>(null);\r\n const [previewLoading, setPreviewLoading] = useState(false);\r\n const [expandedDimensions, setExpandedDimensions] = useState<Record<string, boolean>>({\r\n specs: true,\r\n personal: true,\r\n });\r\n const [previewDialogOpen, setPreviewDialogOpen] = useState(false);\r\n const [previewFile, setPreviewFile] = useState<InjectionPreviewFile | null>(null);\r\n\r\n // State for command preview\r\n const [selectedCommand, setSelectedCommand] = useState<CommandPreviewConfig>(COMMAND_PREVIEWS[0]);\r\n const [commandPreviewData, setCommandPreviewData] = useState<InjectionPreviewResponse | null>(null);\r\n const [commandPreviewLoading, setCommandPreviewLoading] = useState(false);\r\n const [commandPreviewDialogOpen, setCommandPreviewDialogOpen] = useState(false);\r\n\r\n // Fetch stats\r\n const loadStats = useCallback(async () => {\r\n setStatsLoading(true);\r\n setStatsError(null);\r\n try {\r\n const data = await fetchSpecStats();\r\n setStats(data);\r\n } catch (err) {\r\n setStatsError(err instanceof Error ? err : new Error('Unknown error'));\r\n } finally {\r\n setStatsLoading(false);\r\n }\r\n }, []);\r\n\r\n // Fetch settings\r\n const loadSettings = useCallback(async () => {\r\n setSettingsLoading(true);\r\n try {\r\n const data = await fetchSystemSettings();\r\n setSettings(data.injectionControl);\r\n setFormData(data.injectionControl);\r\n } catch (err) {\r\n console.error('Failed to load settings:', err);\r\n } finally {\r\n setSettingsLoading(false);\r\n }\r\n }, []);\r\n\r\n // Load injection preview\r\n const loadPreview = useCallback(async () => {\r\n setPreviewLoading(true);\r\n try {\r\n const data = await getInjectionPreview(previewMode, false);\r\n setPreviewData(data);\r\n } catch (err) {\r\n console.error('Failed to load injection preview:', err);\r\n } finally {\r\n setPreviewLoading(false);\r\n }\r\n }, [previewMode]);\r\n\r\n // Load file content for preview\r\n const loadFilePreview = useCallback(async (file: InjectionPreviewFile) => {\r\n try {\r\n const data = await getInjectionPreview(previewMode, true);\r\n const fileWithData = data.files.find(f => f.file === file.file);\r\n if (fileWithData) {\r\n setPreviewFile(fileWithData);\r\n setPreviewDialogOpen(true);\r\n }\r\n } catch (err) {\r\n console.error('Failed to load file preview:', err);\r\n }\r\n }, [previewMode]);\r\n\r\n // Load command preview content\r\n const loadCommandPreview = useCallback(async (command: CommandPreviewConfig) => {\r\n setCommandPreviewLoading(true);\r\n try {\r\n const data = await getInjectionPreview(command.mode, true, undefined, command.category);\r\n setCommandPreviewData(data);\r\n setSelectedCommand(command);\r\n setCommandPreviewDialogOpen(true);\r\n } catch (err) {\r\n console.error('Failed to load command preview:', err);\r\n } finally {\r\n setCommandPreviewLoading(false);\r\n }\r\n }, []);\r\n\r\n // Initial load\r\n useEffect(() => {\r\n loadStats();\r\n loadSettings();\r\n }, [loadStats, loadSettings]);\r\n\r\n // Load preview when mode changes\r\n useEffect(() => {\r\n loadPreview();\r\n }, [loadPreview]);\r\n\r\n // Check for changes\r\n useEffect(() => {\r\n const changed =\r\n formData.maxLength !== settings.maxLength ||\r\n formData.warnThreshold !== settings.warnThreshold ||\r\n formData.truncateOnExceed !== settings.truncateOnExceed;\r\n setHasChanges(changed);\r\n }, [formData, settings]);\r\n\r\n // Handle form field changes\r\n const handleFieldChange = <K extends keyof InjectionSettings>(\r\n field: K,\r\n value: InjectionSettings[K]\r\n ) => {\r\n setFormData((prev) => ({ ...prev, [field]: value }));\r\n };\r\n\r\n // Save settings\r\n const handleSave = async () => {\r\n setIsSaving(true);\r\n try {\r\n const result = await updateInjectionSettings(formData);\r\n setSettings(result.injectionControl);\r\n setFormData(result.injectionControl);\r\n setHasChanges(false);\r\n toast.success(\r\n formatMessage({ id: 'specs.injection.saveSuccess' }, { default: 'Settings saved successfully' })\r\n );\r\n } catch (err) {\r\n toast.error(\r\n formatMessage({ id: 'specs.injection.saveError' }, { default: 'Failed to save settings' })\r\n );\r\n console.error('Failed to save settings:', err);\r\n } finally {\r\n setIsSaving(false);\r\n }\r\n };\r\n\r\n // Reset form\r\n const handleReset = () => {\r\n setFormData(settings);\r\n setHasChanges(false);\r\n };\r\n\r\n const maxLengthError =\r\n formData.maxLength < 1000 || formData.maxLength > 50000\r\n ? formatMessage({ id: 'specs.injection.maxLengthError', defaultMessage: 'Must be between 1000 and 50000' })\r\n : null;\r\n\r\n const warnThresholdError =\r\n formData.warnThreshold < 0 || formData.warnThreshold >= formData.maxLength\r\n ? formatMessage({ id: 'specs.injection.warnThresholdError', defaultMessage: 'Must be less than max length' })\r\n : null;\r\n\r\n // Toggle dimension expansion\r\n const toggleDimension = (dim: string) => {\r\n setExpandedDimensions(prev => ({ ...prev, [dim]: !prev[dim] }));\r\n };\r\n\r\n // ========== Hooks Installation ==========\r\n\r\n const installedHookIds = useMemo(() => {\r\n const installed = new Set<string>();\r\n const hooks = systemSettingsQuery.data?.recommendedHooks;\r\n if (hooks) {\r\n hooks.forEach(hook => {\r\n if (hook.installed) {\r\n installed.add(hook.id);\r\n }\r\n });\r\n }\r\n return installed;\r\n }, [systemSettingsQuery.data?.recommendedHooks]);\r\n\r\n const installedCount = installedHookIds.size;\r\n const allHooksInstalled = installedCount === RECOMMENDED_HOOKS.length;\r\n\r\n const handleInstallHook = useCallback(async (hookId: string) => {\r\n setInstallingHookIds(prev => [...prev, hookId]);\r\n try {\r\n await installHooksMutation.installHooks([hookId], 'global');\r\n toast.success(\r\n formatMessage({ id: 'specs.hooks.installSuccess', defaultMessage: 'Hook installed successfully' })\r\n );\r\n } catch (err) {\r\n toast.error(\r\n formatMessage({ id: 'specs.hooks.installError', defaultMessage: 'Failed to install hook' })\r\n );\r\n console.error('Failed to install hook:', err);\r\n } finally {\r\n setInstallingHookIds(prev => prev.filter(id => id !== hookId));\r\n }\r\n }, [installHooksMutation, formatMessage]);\r\n\r\n const handleInstallAllHooks = useCallback(async () => {\r\n const uninstalledHooks = RECOMMENDED_HOOKS.filter(h => !installedHookIds.has(h.id));\r\n if (uninstalledHooks.length === 0) return;\r\n\r\n setInstallingHookIds(uninstalledHooks.map(h => h.id));\r\n try {\r\n await installHooksMutation.installHooks(\r\n uninstalledHooks.map(h => h.id),\r\n 'global'\r\n );\r\n toast.success(\r\n formatMessage({ id: 'specs.hooks.installAllSuccess', defaultMessage: 'All hooks installed successfully' })\r\n );\r\n } catch (err) {\r\n toast.error(\r\n formatMessage({ id: 'specs.hooks.installError', defaultMessage: 'Failed to install hooks' })\r\n );\r\n console.error('Failed to install hooks:', err);\r\n } finally {\r\n setInstallingHookIds([]);\r\n }\r\n }, [installedHookIds, installHooksMutation, formatMessage]);\r\n\r\n // Group files by dimension and filter by category\r\n const filesByDimension = useMemo(() => {\r\n if (!previewData) return {};\r\n const grouped: Record<string, InjectionPreviewFile[]> = {};\r\n for (const file of previewData.files) {\r\n // Apply category filter\r\n if (categoryFilter !== 'all' && file.category !== categoryFilter) {\r\n continue;\r\n }\r\n if (!grouped[file.dimension]) {\r\n grouped[file.dimension] = [];\r\n }\r\n grouped[file.dimension].push(file);\r\n }\r\n return grouped;\r\n }, [previewData, categoryFilter]);\r\n\r\n // Calculate category statistics\r\n const categoryStats = useMemo(() => {\r\n if (!previewData) {\r\n return { general: 0, exploration: 0, planning: 0, execution: 0 };\r\n }\r\n const stats: Record<SpecCategory, number> = { general: 0, exploration: 0, planning: 0, execution: 0 };\r\n for (const file of previewData.files) {\r\n const cat = (file.category as SpecCategory) || 'general';\r\n if (stats[cat] !== undefined) {\r\n stats[cat]++;\r\n }\r\n }\r\n return stats;\r\n }, [previewData]);\r\n\r\n // Calculate progress and status - use API's maxLength for consistency\r\n const currentLength = stats?.injectionLength?.withKeywords || 0;\r\n const apiMaxLength = stats?.injectionLength?.maxLength || settings.maxLength;\r\n const maxLength = apiMaxLength; // Use API's maxLength for consistency\r\n const warnThreshold = settings.warnThreshold;\r\n const percentage = calculatePercentage(currentLength, maxLength);\r\n const isOverLimit = currentLength > maxLength;\r\n const isOverWarning = currentLength > warnThreshold;\r\n const remainingSpace = Math.max(0, maxLength - currentLength);\r\n\r\n // Calculate approximate line count (assuming ~80 chars per line)\r\n const estimatedLineCount = Math.ceil(currentLength / 80);\r\n const maxLineCount = Math.ceil(maxLength / 80);\r\n\r\n return (\r\n <div className={cn('space-y-6', className)}>\r\n {/* Recommended Hooks Section */}\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <Plug className=\"h-5 w-5\" />\r\n {formatMessage({ id: 'specs.recommendedHooks', defaultMessage: 'Recommended Hooks' })}\r\n </CardTitle>\r\n <CardDescription>\r\n {formatMessage({\r\n id: 'specs.recommendedHooksDesc',\r\n defaultMessage: 'One-click install spec injection hooks for automatic context loading',\r\n })}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n <Button\r\n onClick={handleInstallAllHooks}\r\n disabled={allHooksInstalled || installingHookIds.length > 0}\r\n >\r\n {allHooksInstalled ? (\r\n <>\r\n <CheckCircle2 className=\"h-4 w-4 mr-2\" />\r\n {formatMessage({ id: 'specs.allHooksInstalled', defaultMessage: 'All Hooks Installed' })}\r\n </>\r\n ) : (\r\n <>\r\n <Download className=\"h-4 w-4 mr-2\" />\r\n {formatMessage({ id: 'specs.installAllHooks', defaultMessage: 'Install All Hooks' })}\r\n </>\r\n )}\r\n </Button>\r\n <div className=\"text-sm text-muted-foreground\">\r\n {installedCount} / {RECOMMENDED_HOOKS.length}{' '}\r\n {formatMessage({ id: 'specs.hooksInstalled', defaultMessage: 'installed' })}\r\n </div>\r\n </div>\r\n <Button variant=\"ghost\" size=\"sm\" asChild>\r\n <Link to=\"/hooks\">\r\n <Settings className=\"h-4 w-4 mr-1\" />\r\n {formatMessage({ id: 'specs.manageHooks', defaultMessage: 'Manage Hooks' })}\r\n </Link>\r\n </Button>\r\n </div>\r\n\r\n <div className=\"grid gap-3\">\r\n {RECOMMENDED_HOOKS.map(hook => {\r\n const isInstalled = installedHookIds.has(hook.id);\r\n const isInstalling = installingHookIds.includes(hook.id);\r\n\r\n return (\r\n <div\r\n key={hook.id}\r\n className=\"flex items-center justify-between p-4 border rounded-lg\"\r\n >\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium\">{hook.name}</span>\r\n {isInstalled && <CheckCircle2 className=\"h-4 w-4 text-green-500\" />}\r\n </div>\r\n <div className=\"text-sm text-muted-foreground mt-1\">\r\n {hook.description}\r\n </div>\r\n <div className=\"flex items-center gap-4 mt-2 text-xs text-muted-foreground\">\r\n <span>\r\n {formatMessage({ id: 'specs.hookEvent', defaultMessage: 'Event' })}:{' '}\r\n <code className=\"bg-muted px-1 rounded\">{hook.event}</code>\r\n </span>\r\n <span>\r\n {formatMessage({ id: 'specs.hookScope', defaultMessage: 'Scope' })}:{' '}\r\n <code className=\"bg-muted px-1 rounded\">{hook.scope}</code>\r\n </span>\r\n </div>\r\n </div>\r\n <Button\r\n variant={isInstalled ? 'outline' : 'default'}\r\n size=\"sm\"\r\n disabled={isInstalled || isInstalling}\r\n onClick={() => handleInstallHook(hook.id)}\r\n >\r\n {isInstalling\r\n ? formatMessage({ id: 'specs.installing', defaultMessage: 'Installing...' })\r\n : isInstalled\r\n ? formatMessage({ id: 'specs.installed', defaultMessage: 'Installed' })\r\n : formatMessage({ id: 'specs.install', defaultMessage: 'Install' })}\r\n </Button>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Current Injection Status Card */}\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n {formatMessage(\r\n { id: 'specs.injection.statusTitle', defaultMessage: 'Current Injection Status' }\r\n )}\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-6 w-6\"\r\n onClick={() => { loadStats(); loadPreview(); }}\r\n disabled={statsLoading}\r\n >\r\n <RefreshCw className={cn('h-4 w-4', statsLoading && 'animate-spin')} />\r\n </Button>\r\n </CardTitle>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n {statsLoading ? (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\r\n </div>\r\n ) : statsError ? (\r\n <div className=\"text-sm text-destructive\">\r\n {formatMessage(\r\n { id: 'specs.injection.loadError', defaultMessage: 'Failed to load stats' }\r\n )}\r\n </div>\r\n ) : (\r\n <>\r\n {/* Current Length Display */}\r\n <div className=\"flex justify-between text-sm\">\r\n <span className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.currentLength', defaultMessage: 'Current Length' })}\r\n </span>\r\n <span\r\n className={cn(\r\n 'font-medium',\r\n isOverLimit && 'text-destructive',\r\n !isOverLimit && isOverWarning && 'text-yellow-600 dark:text-yellow-400'\r\n )}\r\n >\r\n {formatNumber(currentLength)} / {formatNumber(maxLength)}{' '}\r\n {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n <span className=\"text-muted-foreground ml-2\">\r\n (~{formatNumber(estimatedLineCount)} / {formatNumber(maxLineCount)} {formatMessage({ id: 'specs.injection.lines', defaultMessage: 'lines' })})\r\n </span>\r\n </span>\r\n </div>\r\n\r\n {/* Progress Bar */}\r\n <div className=\"space-y-2\">\r\n <div className=\"flex items-center justify-between text-xs text-muted-foreground mb-1\">\r\n <span>{percentage}%</span>\r\n <span>{formatMessage({ id: 'specs.injection.maxLimit', defaultMessage: 'Max' })}: {formatNumber(maxLength)}</span>\r\n </div>\r\n <div className=\"relative\">\r\n <Progress\r\n value={percentage}\r\n className={cn(\r\n 'h-3',\r\n isOverLimit && 'bg-destructive/20',\r\n !isOverLimit && isOverWarning && 'bg-yellow-100 dark:bg-yellow-900/30'\r\n )}\r\n indicatorClassName={cn(\r\n // Default: use a distinct blue color\r\n !isOverLimit && !isOverWarning && 'bg-sky-500 dark:bg-sky-400',\r\n isOverLimit && 'bg-destructive',\r\n !isOverLimit && isOverWarning && 'bg-yellow-500'\r\n )}\r\n />\r\n {/* Warning threshold marker */}\r\n <div\r\n className=\"absolute top-0 h-3 flex flex-col items-center\"\r\n style={{\r\n left: `${Math.min(100, (warnThreshold / maxLength) * 100)}%`,\r\n transform: 'translateX(-50%)',\r\n }}\r\n >\r\n <AlertTriangle className=\"h-3 w-3 text-yellow-500 -mt-4\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Warning Alert when over limit */}\r\n {isOverLimit && (\r\n <div className=\"flex items-start gap-3 p-4 rounded-lg bg-destructive/10 border border-destructive/20\">\r\n <AlertCircle className=\"h-5 w-5 text-destructive flex-shrink-0 mt-0.5\" />\r\n <div>\r\n <div className=\"font-medium text-destructive\">\r\n {formatMessage({ id: 'specs.injection.overLimit', defaultMessage: 'Over Limit' })}\r\n </div>\r\n <div className=\"text-sm text-muted-foreground mt-1\">\r\n {formatMessage(\r\n {\r\n id: 'specs.injection.overLimitDescription',\r\n defaultMessage: 'Current injection content exceeds maximum length of {max} characters. Excess content will be truncated.',\r\n },\r\n { max: formatNumber(maxLength) }\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Statistics Info */}\r\n <div className=\"p-4 rounded-lg bg-muted/50 space-y-2\">\r\n <div className=\"flex items-center gap-2 text-sm font-medium\">\r\n <Info className=\"h-4 w-4 text-muted-foreground\" />\r\n {formatMessage({ id: 'specs.injection.statsInfo', defaultMessage: 'Statistics' })}\r\n </div>\r\n <div className=\"grid grid-cols-2 gap-2 text-sm\">\r\n <div className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.requiredLength', defaultMessage: 'Required specs length:' })}\r\n </div>\r\n <div className=\"text-right\">\r\n {formatNumber(stats?.injectionLength?.requiredOnly || 0)} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </div>\r\n <div className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.matchedLength', defaultMessage: 'Keyword-matched length:' })}\r\n </div>\r\n <div className=\"text-right\">\r\n {formatNumber(stats?.injectionLength?.withKeywords || 0)} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </div>\r\n <div className=\"text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.remaining', defaultMessage: 'Remaining space:' })}\r\n </div>\r\n <div className={cn('text-right', remainingSpace === 0 && 'text-destructive')}>\r\n {formatNumber(remainingSpace)} ({Math.round(100 - percentage)}%)\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Injection Files List Card */}\r\n <Card>\r\n <CardHeader>\r\n <div className=\"flex items-center justify-between\">\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <FileText className=\"h-5 w-5\" />\r\n {formatMessage({ id: 'specs.injection.filesList', defaultMessage: 'Injection Files' })}\r\n </CardTitle>\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant={previewMode === 'required' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setPreviewMode('required')}\r\n >\r\n {formatMessage({ id: 'specs.readMode.required', defaultMessage: 'Required' })}\r\n </Button>\r\n <Button\r\n variant={previewMode === 'all' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setPreviewMode('all')}\r\n >\r\n {formatMessage({ id: 'specs.scope.all', defaultMessage: 'All' })}\r\n </Button>\r\n </div>\r\n </div>\r\n <CardDescription>\r\n {previewData && (\r\n <span>\r\n {previewData.stats.count} {formatMessage({ id: 'specs.injection.files', defaultMessage: 'files' })} • {formatNumber(previewData.stats.totalLength)} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </span>\r\n )}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n {/* Category Filter */}\r\n <div className=\"flex items-center gap-2 flex-wrap\">\r\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.filterByCategory', defaultMessage: 'Category:' })}\r\n </span>\r\n <div className=\"flex gap-2 flex-wrap\">\r\n <Button\r\n variant={categoryFilter === 'all' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setCategoryFilter('all')}\r\n >\r\n {formatMessage({ id: 'specs.category.all', defaultMessage: 'All' })}\r\n </Button>\r\n {SPEC_CATEGORIES.map(cat => (\r\n <Button\r\n key={cat}\r\n variant={categoryFilter === cat ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setCategoryFilter(cat)}\r\n className=\"gap-1\"\r\n >\r\n <Layers className=\"h-3 w-3\" />\r\n {formatMessage({ id: `specs.category.${cat}`, defaultMessage: cat })} ({categoryStats[cat]})\r\n </Button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Files List */}\r\n {previewLoading ? (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <Loader2 className=\"h-6 w-6 animate-spin text-muted-foreground\" />\r\n </div>\r\n ) : (\r\n <div className=\"h-[300px] overflow-auto\">\r\n <div className=\"space-y-2\">\r\n {Object.entries(filesByDimension).map(([dim, files]) => (\r\n <div key={dim} className=\"border rounded-lg\">\r\n <button\r\n className=\"w-full flex items-center justify-between p-3 hover:bg-muted/50 transition-colors\"\r\n onClick={() => toggleDimension(dim)}\r\n >\r\n <div className=\"flex items-center gap-2\">\r\n {expandedDimensions[dim] ? (\r\n <ChevronDown className=\"h-4 w-4\" />\r\n ) : (\r\n <ChevronRight className=\"h-4 w-4\" />\r\n )}\r\n <span className=\"font-medium capitalize\">\r\n {formatMessage({ id: `specs.dimension.${dim}`, defaultMessage: dim })}\r\n </span>\r\n <Badge variant=\"secondary\" className=\"text-xs\">\r\n {files.length}\r\n </Badge>\r\n </div>\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatNumber(files.reduce((sum, f) => sum + f.contentLength, 0))} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </span>\r\n </button>\r\n {expandedDimensions[dim] && (\r\n <div className=\"border-t\">\r\n {files.map((file) => {\r\n const fileCategory = (file.category as SpecCategory) || 'general';\r\n const categoryStyle = CATEGORY_CONFIG[fileCategory] || CATEGORY_CONFIG.general;\r\n return (\r\n <div\r\n key={file.file}\r\n className=\"flex items-center justify-between p-3 border-b last:border-b-0 hover:bg-muted/30\"\r\n >\r\n <div className=\"flex items-center gap-3 min-w-0\">\r\n {file.scope === 'global' ? (\r\n <Globe className=\"h-4 w-4 text-blue-500 flex-shrink-0\" />\r\n ) : (\r\n <Folder className=\"h-4 w-4 text-green-500 flex-shrink-0\" />\r\n )}\r\n <div className=\"min-w-0\">\r\n <div className=\"font-medium truncate\">{file.title}</div>\r\n <div className=\"text-xs text-muted-foreground truncate\">{file.file}</div>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Badge variant=\"outline\" className={cn('text-xs gap-1', categoryStyle.bgColor, categoryStyle.color)}>\r\n <Layers className=\"h-3 w-3\" />\r\n {formatMessage({ id: `specs.category.${fileCategory}`, defaultMessage: fileCategory })}\r\n </Badge>\r\n <Badge variant=\"outline\" className=\"text-xs\">\r\n {formatMessage({ id: `specs.priority.${file.priority}`, defaultMessage: file.priority })}\r\n </Badge>\r\n <span className=\"text-xs text-muted-foreground whitespace-nowrap\">\r\n {formatNumber(file.contentLength)}\r\n </span>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-7 w-7\"\r\n onClick={() => loadFilePreview(file)}\r\n >\r\n <Eye className=\"h-3.5 w-3.5\" />\r\n </Button>\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Command Preview Card */}\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <Eye className=\"h-5 w-5\" />\r\n {formatMessage({ id: 'specs.injection.commandPreview', defaultMessage: 'Command Injection Preview' })}\r\n </CardTitle>\r\n <CardDescription>\r\n {formatMessage({\r\n id: 'specs.injection.commandPreviewDesc',\r\n defaultMessage: 'Preview the content that would be injected by different CLI commands',\r\n })}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent>\r\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3\">\r\n {COMMAND_PREVIEWS.map((cmd) => (\r\n <Button\r\n key={cmd.command}\r\n variant=\"outline\"\r\n className=\"h-auto flex-col items-start py-3 px-4\"\r\n onClick={() => loadCommandPreview(cmd)}\r\n disabled={commandPreviewLoading}\r\n >\r\n <div className=\"font-medium text-sm\">\r\n {formatMessage({\r\n id: `specs.commandPreview.${cmd.labelKey}.label`,\r\n defaultMessage: cmd.labelKey\r\n })}\r\n </div>\r\n <div className=\"text-xs text-muted-foreground mt-1 line-clamp-2\">\r\n {formatMessage({\r\n id: `specs.commandPreview.${cmd.descriptionKey}.description`,\r\n defaultMessage: cmd.descriptionKey\r\n })}\r\n </div>\r\n <code className=\"text-xs bg-muted px-1.5 py-0.5 rounded mt-2 w-full text-center\">\r\n {cmd.command.replace('ccw spec load', '').trim() || 'default'}\r\n </code>\r\n </Button>\r\n ))}\r\n </div>\r\n {commandPreviewLoading && (\r\n <div className=\"flex items-center justify-center py-4 mt-4 border rounded-lg\">\r\n <Loader2 className=\"h-5 w-5 animate-spin text-muted-foreground mr-2\" />\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.loadingPreview', defaultMessage: 'Loading preview...' })}\r\n </span>\r\n </div>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Settings Card */}\r\n <Card>\r\n <CardHeader>\r\n <CardTitle>\r\n {formatMessage({ id: 'specs.injection.settingsTitle', defaultMessage: 'Injection Control Settings' })}\r\n </CardTitle>\r\n <CardDescription>\r\n {formatMessage({\r\n id: 'specs.injection.settingsDescription',\r\n defaultMessage: 'Configure how spec content is injected into AI context.',\r\n })}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-6\">\r\n {settingsLoading ? (\r\n <div className=\"flex items-center justify-center py-4\">\r\n <Loader2 className=\"h-5 w-5 animate-spin text-muted-foreground\" />\r\n </div>\r\n ) : (\r\n <>\r\n {/* Max Injection Length */}\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"maxLength\">\r\n {formatMessage({ id: 'specs.injection.maxLength', defaultMessage: 'Max Injection Length' })}\r\n </Label>\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"flex-1\">\r\n <Input\r\n id=\"maxLength\"\r\n type=\"number\"\r\n min={1000}\r\n max={50000}\r\n step={500}\r\n value={formData.maxLength}\r\n onChange={(e) => handleFieldChange('maxLength', Number(e.target.value))}\r\n className={cn(maxLengthError && 'border-destructive')}\r\n />\r\n </div>\r\n <span className=\"text-sm text-muted-foreground whitespace-nowrap\">\r\n (~{Math.ceil(formData.maxLength / 80)} {formatMessage({ id: 'specs.injection.lines', defaultMessage: 'lines' })})\r\n </span>\r\n </div>\r\n {maxLengthError && <p className=\"text-xs text-destructive mt-1\">{maxLengthError}</p>}\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({\r\n id: 'specs.injection.maxLengthHelp',\r\n defaultMessage: 'Recommended: 4000-10000 characters (50-125 lines). Too large may consume too much context.',\r\n })}\r\n </p>\r\n {/* Quick presets */}\r\n <div className=\"flex items-center gap-2 mt-2\">\r\n <span className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.quickPresets', defaultMessage: 'Quick presets:' })}\r\n </span>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"h-6 text-xs\"\r\n onClick={() => handleFieldChange('maxLength', 4000)}\r\n >\r\n 4000 (50 lines)\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"h-6 text-xs\"\r\n onClick={() => handleFieldChange('maxLength', 8000)}\r\n >\r\n 8000 (100 lines)\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"h-6 text-xs\"\r\n onClick={() => handleFieldChange('maxLength', 12000)}\r\n >\r\n 12000 (150 lines)\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n {/* Warning Threshold */}\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"warnThreshold\">\r\n {formatMessage({ id: 'specs.injection.warnThresholdLabel', defaultMessage: 'Warning Threshold' })}\r\n </Label>\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"flex-1\">\r\n <Input\r\n id=\"warnThreshold\"\r\n type=\"number\"\r\n min={500}\r\n max={formData.maxLength - 1}\r\n step={500}\r\n value={formData.warnThreshold}\r\n onChange={(e) => handleFieldChange('warnThreshold', Number(e.target.value))}\r\n className={cn(warnThresholdError && 'border-destructive')}\r\n />\r\n </div>\r\n <span className=\"text-sm text-muted-foreground whitespace-nowrap\">\r\n (~{Math.ceil(formData.warnThreshold / 80)} {formatMessage({ id: 'specs.injection.lines', defaultMessage: 'lines' })})\r\n </span>\r\n </div>\r\n {warnThresholdError && <p className=\"text-xs text-destructive mt-1\">{warnThresholdError}</p>}\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({\r\n id: 'specs.injection.warnThresholdHelp',\r\n defaultMessage: 'A warning will be displayed when injection length exceeds this value.',\r\n })}\r\n </p>\r\n </div>\r\n\r\n {/* Truncate on Exceed */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"space-y-0.5\">\r\n <Label htmlFor=\"truncate\">\r\n {formatMessage({ id: 'specs.injection.truncateOnExceed', defaultMessage: 'Truncate on Exceed' })}\r\n </Label>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({\r\n id: 'specs.injection.truncateHelp',\r\n defaultMessage: 'Automatically truncate content when it exceeds the maximum length.',\r\n })}\r\n </p>\r\n </div>\r\n <Switch\r\n id=\"truncate\"\r\n checked={formData.truncateOnExceed}\r\n onCheckedChange={(checked) => handleFieldChange('truncateOnExceed', checked)}\r\n />\r\n </div>\r\n\r\n {/* Action Buttons */}\r\n <div className=\"flex items-center justify-end gap-3 pt-4 border-t\">\r\n <Button\r\n variant=\"outline\"\r\n onClick={handleReset}\r\n disabled={!hasChanges || isSaving}\r\n >\r\n {formatMessage({ id: 'common.actions.reset', defaultMessage: 'Reset' })}\r\n </Button>\r\n <Button onClick={handleSave} disabled={!hasChanges || isSaving || !!maxLengthError || !!warnThresholdError}>\r\n {isSaving ? (\r\n <>\r\n <Loader2 className=\"h-4 w-4 mr-2 animate-spin\" />\r\n {formatMessage({ id: 'common.actions.saving', defaultMessage: 'Saving...' })}\r\n </>\r\n ) : (\r\n formatMessage({ id: 'common.actions.save', defaultMessage: 'Save' })\r\n )}\r\n </Button>\r\n </div>\r\n </>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* File Preview Dialog */}\r\n <Dialog open={previewDialogOpen} onOpenChange={setPreviewDialogOpen}>\r\n <DialogContent className=\"max-w-3xl max-h-[80vh]\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <FileText className=\"h-5 w-5\" />\r\n {previewFile?.title}\r\n </DialogTitle>\r\n </DialogHeader>\r\n <div className=\"flex-1 overflow-auto\">\r\n <pre className=\"text-sm whitespace-pre-wrap p-4 bg-muted rounded-lg\">\r\n {previewFile?.content || formatMessage({ id: 'specs.content.noContent', defaultMessage: 'No content available' })}\r\n </pre>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n\r\n {/* Command Preview Dialog */}\r\n <Dialog open={commandPreviewDialogOpen} onOpenChange={setCommandPreviewDialogOpen}>\r\n <DialogContent className=\"max-w-4xl max-h-[85vh]\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <Eye className=\"h-5 w-5\" />\r\n {formatMessage({ id: 'specs.injection.previewTitle', defaultMessage: 'Injection Preview' })}\r\n </DialogTitle>\r\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\r\n <code className=\"bg-muted px-2 py-1 rounded text-xs\">{selectedCommand.command}</code>\r\n <span>•</span>\r\n <span>\r\n {formatMessage({\r\n id: `specs.commandPreview.${selectedCommand.descriptionKey}.description`,\r\n defaultMessage: selectedCommand.descriptionKey\r\n })}\r\n </span>\r\n </div>\r\n </DialogHeader>\r\n <div className=\"space-y-4\">\r\n {/* Stats */}\r\n {commandPreviewData && (\r\n <div className=\"flex items-center gap-4 text-sm\">\r\n <Badge variant=\"secondary\">\r\n {commandPreviewData.stats.count} {formatMessage({ id: 'specs.injection.files', defaultMessage: 'files' })}\r\n </Badge>\r\n <Badge variant=\"secondary\">\r\n {formatNumber(commandPreviewData.stats.totalLength)} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </Badge>\r\n <Badge variant=\"secondary\">\r\n ~{Math.ceil(commandPreviewData.stats.totalLength / 80)} {formatMessage({ id: 'specs.injection.lines', defaultMessage: 'lines' })}\r\n </Badge>\r\n </div>\r\n )}\r\n {/* Preview Content */}\r\n <div className=\"flex-1 overflow-auto max-h-[60vh] border rounded-lg\">\r\n {commandPreviewData?.files.length ? (\r\n <div className=\"space-y-4 p-4\">\r\n {commandPreviewData.files.map((file, idx) => (\r\n <div key={file.file} className=\"space-y-2\">\r\n {/* File Header */}\r\n <div className=\"flex items-center justify-between text-sm\">\r\n <div className=\"flex items-center gap-2\">\r\n <Badge variant=\"outline\" className=\"text-xs\">\r\n {idx + 1}\r\n </Badge>\r\n <span className=\"font-medium\">{file.title}</span>\r\n {file.category && (\r\n <Badge variant=\"outline\" className={cn(\r\n 'text-xs',\r\n CATEGORY_CONFIG[file.category as SpecCategory]?.bgColor,\r\n CATEGORY_CONFIG[file.category as SpecCategory]?.color\r\n )}>\r\n {file.category}\r\n </Badge>\r\n )}\r\n </div>\r\n <span className=\"text-xs text-muted-foreground\">\r\n {formatNumber(file.contentLength)} {formatMessage({ id: 'specs.injection.characters', defaultMessage: 'characters' })}\r\n </span>\r\n </div>\r\n {/* File Content */}\r\n <pre className=\"text-xs whitespace-pre-wrap p-3 bg-muted rounded border-l-2 border-primary/30\">\r\n {file.content || formatMessage({ id: 'specs.content.noContent', defaultMessage: 'No content available' })}\r\n </pre>\r\n </div>\r\n ))}\r\n </div>\r\n ) : (\r\n <div className=\"flex items-center justify-center py-8 text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.noFiles', defaultMessage: 'No files match this command' })}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n </div>\r\n );\r\n}\r\n\r\nexport default InjectionControlTab;\r\n","// ========================================\r\n// GlobalSettingsTab Component\r\n// ========================================\r\n// Global settings for personal spec defaults and spec statistics\r\n\r\nimport { useState, useEffect } from 'react';\r\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\r\nimport { useIntl } from 'react-intl';\r\nimport { toast } from 'sonner';\r\nimport { Settings, RefreshCw, History } from 'lucide-react';\r\nimport {\r\n Card,\r\n CardHeader,\r\n CardTitle,\r\n CardDescription,\r\n CardContent,\r\n} from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Label } from '@/components/ui/Label';\r\nimport { Switch } from '@/components/ui/Switch';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport {\r\n Select,\r\n SelectTrigger,\r\n SelectValue,\r\n SelectContent,\r\n SelectItem,\r\n} from '@/components/ui/Select';\r\nimport { cn } from '@/lib/utils';\r\n\r\n// ========== Types ==========\r\n\r\ninterface PersonalSpecDefaults {\r\n defaultReadMode: 'required' | 'optional';\r\n autoEnable: boolean;\r\n}\r\n\r\ninterface DevProgressInjection {\r\n enabled: boolean;\r\n maxEntriesPerCategory: number;\r\n categories: ('feature' | 'enhancement' | 'bugfix' | 'refactor' | 'docs')[];\r\n}\r\n\r\ninterface SystemSettings {\r\n injectionControl: {\r\n maxLength: number;\r\n warnThreshold: number;\r\n truncateOnExceed: boolean;\r\n };\r\n personalSpecDefaults: PersonalSpecDefaults;\r\n devProgressInjection: DevProgressInjection;\r\n}\r\n\r\ninterface SpecDimensionStats {\r\n count: number;\r\n requiredCount: number;\r\n}\r\n\r\ninterface SpecStats {\r\n dimensions: {\r\n specs: SpecDimensionStats;\r\n personal: SpecDimensionStats;\r\n };\r\n injectionLength?: {\r\n requiredOnly: number;\r\n withKeywords: number;\r\n maxLength: number;\r\n percentage: number;\r\n };\r\n}\r\n\r\ninterface ProjectTechStats {\r\n total_features: number;\r\n total_sessions: number;\r\n last_updated: string | null;\r\n categories: {\r\n feature: number;\r\n enhancement: number;\r\n bugfix: number;\r\n refactor: number;\r\n docs: number;\r\n };\r\n}\r\n\r\n// ========== API Functions ==========\r\n\r\nconst API_BASE = '/api';\r\n\r\nasync function fetchSystemSettings(): Promise<SystemSettings> {\r\n const response = await fetch(`${API_BASE}/system/settings`, {\r\n credentials: 'same-origin',\r\n });\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch settings: ${response.statusText}`);\r\n }\r\n const data = await response.json();\r\n return data;\r\n}\r\n\r\nasync function updateSystemSettings(\r\n settings: Partial<SystemSettings>\r\n): Promise<{ success: boolean; settings: SystemSettings }> {\r\n const response = await fetch(`${API_BASE}/system/settings`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n credentials: 'same-origin',\r\n body: JSON.stringify(settings),\r\n });\r\n if (!response.ok) {\r\n throw new Error(`Failed to update settings: ${response.statusText}`);\r\n }\r\n return response.json();\r\n}\r\n\r\nasync function fetchSpecStats(): Promise<SpecStats> {\r\n const response = await fetch(`${API_BASE}/specs/stats`, {\r\n credentials: 'same-origin',\r\n });\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch spec stats: ${response.statusText}`);\r\n }\r\n return response.json();\r\n}\r\n\r\nasync function fetchProjectTechStats(): Promise<ProjectTechStats> {\r\n const response = await fetch(`${API_BASE}/project-tech/stats`, {\r\n credentials: 'same-origin',\r\n });\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch project-tech stats: ${response.statusText}`);\r\n }\r\n return response.json();\r\n}\r\n\r\n// ========== Query Keys ==========\r\n\r\nconst settingsKeys = {\r\n all: ['system-settings'] as const,\r\n settings: () => [...settingsKeys.all, 'settings'] as const,\r\n stats: () => [...settingsKeys.all, 'stats'] as const,\r\n projectTech: () => [...settingsKeys.all, 'project-tech'] as const,\r\n};\r\n\r\n// ========== Component ==========\r\n\r\nexport function GlobalSettingsTab() {\r\n const { formatMessage } = useIntl();\r\n const queryClient = useQueryClient();\r\n\r\n // Local state for immediate UI feedback\r\n const [localDefaults, setLocalDefaults] = useState<PersonalSpecDefaults>({\r\n defaultReadMode: 'optional',\r\n autoEnable: true,\r\n });\r\n\r\n // Local state for dev progress injection\r\n const [localDevProgress, setLocalDevProgress] = useState<DevProgressInjection>({\r\n enabled: true,\r\n maxEntriesPerCategory: 10,\r\n categories: ['feature', 'enhancement', 'bugfix', 'refactor', 'docs'],\r\n });\r\n\r\n // Fetch system settings\r\n const {\r\n data: settings,\r\n isLoading: isLoadingSettings,\r\n error: settingsError,\r\n } = useQuery({\r\n queryKey: settingsKeys.settings(),\r\n queryFn: fetchSystemSettings,\r\n staleTime: 60000, // 1 minute\r\n });\r\n\r\n // Fetch spec stats\r\n const {\r\n data: stats,\r\n isLoading: isLoadingStats,\r\n error: statsError,\r\n refetch: refetchStats,\r\n } = useQuery({\r\n queryKey: settingsKeys.stats(),\r\n queryFn: fetchSpecStats,\r\n staleTime: 30000, // 30 seconds\r\n });\r\n\r\n // Fetch project-tech stats\r\n const { data: projectTechStats } = useQuery({\r\n queryKey: settingsKeys.projectTech(),\r\n queryFn: fetchProjectTechStats,\r\n staleTime: 60000, // 1 minute\r\n });\r\n\r\n // Update settings mutation\r\n const updateMutation = useMutation({\r\n mutationFn: updateSystemSettings,\r\n onSuccess: (data) => {\r\n queryClient.setQueryData(settingsKeys.settings(), data.settings);\r\n toast.success(formatMessage({ id: 'specs.injection.saveSuccess', defaultMessage: 'Settings saved successfully' }));\r\n },\r\n onError: (error) => {\r\n toast.error(formatMessage(\r\n { id: 'specs.injection.saveError', defaultMessage: 'Failed to save settings: {error}' },\r\n { error: error.message }\r\n ));\r\n },\r\n });\r\n\r\n // Sync local state with server state\r\n useEffect(() => {\r\n if (settings?.personalSpecDefaults) {\r\n setLocalDefaults(settings.personalSpecDefaults);\r\n }\r\n if (settings?.devProgressInjection) {\r\n setLocalDevProgress(settings.devProgressInjection);\r\n }\r\n }, [settings]);\r\n\r\n // Handlers\r\n const handleReadModeChange = (value: 'required' | 'optional') => {\r\n const newDefaults = { ...localDefaults, defaultReadMode: value };\r\n setLocalDefaults(newDefaults);\r\n updateMutation.mutate({ personalSpecDefaults: newDefaults });\r\n };\r\n\r\n const handleAutoEnableChange = (checked: boolean) => {\r\n const newDefaults = { ...localDefaults, autoEnable: checked };\r\n setLocalDefaults(newDefaults);\r\n updateMutation.mutate({ personalSpecDefaults: newDefaults });\r\n };\r\n\r\n // Dev progress injection handlers\r\n const handleDevProgressToggle = (checked: boolean) => {\r\n const newDevProgress = { ...localDevProgress, enabled: checked };\r\n setLocalDevProgress(newDevProgress);\r\n updateMutation.mutate({ devProgressInjection: newDevProgress });\r\n };\r\n\r\n const handleMaxEntriesChange = (value: string) => {\r\n const numValue = parseInt(value, 10);\r\n if (!isNaN(numValue) && numValue >= 1 && numValue <= 50) {\r\n const newDevProgress = { ...localDevProgress, maxEntriesPerCategory: numValue };\r\n setLocalDevProgress(newDevProgress);\r\n updateMutation.mutate({ devProgressInjection: newDevProgress });\r\n }\r\n };\r\n\r\n const handleCategoryToggle = (category: 'feature' | 'enhancement' | 'bugfix' | 'refactor' | 'docs') => {\r\n const newCategories = localDevProgress.categories.includes(category)\r\n ? localDevProgress.categories.filter(c => c !== category)\r\n : [...localDevProgress.categories, category];\r\n const newDevProgress = { ...localDevProgress, categories: newCategories as DevProgressInjection['categories'] };\r\n setLocalDevProgress(newDevProgress);\r\n updateMutation.mutate({ devProgressInjection: newDevProgress });\r\n };\r\n\r\n // Calculate totals - Only include specs and personal dimensions\r\n const dimensions = stats?.dimensions || {};\r\n const dimensionEntries = Object.entries(dimensions)\r\n .filter(([dim]) => dim === 'specs' || dim === 'personal') as [\r\n keyof typeof dimensions,\r\n SpecDimensionStats\r\n ][];\r\n const totalCount = dimensionEntries.reduce(\r\n (sum, [, data]) => sum + data.count,\r\n 0\r\n );\r\n const totalRequired = dimensionEntries.reduce(\r\n (sum, [, data]) => sum + data.requiredCount,\r\n 0\r\n );\r\n\r\n const isLoading = isLoadingSettings || isLoadingStats;\r\n const hasError = settingsError || statsError;\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Personal Spec Defaults Card */}\r\n <Card>\r\n <CardHeader>\r\n <div className=\"flex items-center gap-2\">\r\n <Settings className=\"h-5 w-5 text-muted-foreground\" />\r\n <CardTitle>\r\n {formatMessage({ id: 'specs.settings.personalSpecDefaults', defaultMessage: 'Personal Spec Defaults' })}\r\n </CardTitle>\r\n </div>\r\n <CardDescription>\r\n {formatMessage({ id: 'specs.settings.personalSpecDefaultsDesc', defaultMessage: 'These settings will be applied when creating new personal specs' })}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-6\">\r\n {/* Default Read Mode */}\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"default-read-mode\">\r\n {formatMessage({ id: 'specs.settings.defaultReadMode', defaultMessage: 'Default Read Mode' })}\r\n </Label>\r\n <Select\r\n value={localDefaults.defaultReadMode}\r\n onValueChange={(value) =>\r\n handleReadModeChange(value as 'required' | 'optional')\r\n }\r\n >\r\n <SelectTrigger id=\"default-read-mode\" className=\"w-full\">\r\n <SelectValue placeholder={formatMessage({ id: 'specs.settings.selectReadMode', defaultMessage: 'Select read mode' })} />\r\n </SelectTrigger>\r\n <SelectContent>\r\n <SelectItem value=\"required\">\r\n {formatMessage({ id: 'specs.readMode.required', defaultMessage: 'Required' })}\r\n </SelectItem>\r\n <SelectItem value=\"optional\">\r\n {formatMessage({ id: 'specs.readMode.optional', defaultMessage: 'Optional' })}\r\n </SelectItem>\r\n </SelectContent>\r\n </Select>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.settings.defaultReadModeHelp', defaultMessage: 'The default read mode for newly created personal specs' })}\r\n </p>\r\n </div>\r\n\r\n {/* Auto Enable */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"space-y-0.5\">\r\n <Label htmlFor=\"auto-enable\">\r\n {formatMessage({ id: 'specs.settings.autoEnable', defaultMessage: 'Auto Enable New Specs' })}\r\n </Label>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.settings.autoEnableDescription', defaultMessage: 'Automatically enable newly created personal specs' })}\r\n </p>\r\n </div>\r\n <Switch\r\n id=\"auto-enable\"\r\n checked={localDefaults.autoEnable}\r\n onCheckedChange={handleAutoEnableChange}\r\n disabled={updateMutation.isPending}\r\n />\r\n </div>\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Spec Statistics Card */}\r\n <Card>\r\n <CardHeader>\r\n <div className=\"flex items-center justify-between\">\r\n <CardTitle>\r\n {formatMessage({ id: 'specs.settings.specStatistics', defaultMessage: 'Spec Statistics' })}\r\n </CardTitle>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n onClick={() => refetchStats()}\r\n disabled={isLoadingStats}\r\n >\r\n <RefreshCw\r\n className={cn(\r\n 'h-4 w-4',\r\n isLoadingStats && 'animate-spin'\r\n )}\r\n />\r\n </Button>\r\n </div>\r\n </CardHeader>\r\n <CardContent>\r\n {isLoading ? (\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\r\n {[1, 2, 3, 4].map((i) => (\r\n <div\r\n key={i}\r\n className=\"text-center p-4 rounded-lg bg-muted animate-pulse\"\r\n >\r\n <div className=\"h-8 w-12 mx-auto bg-muted-foreground/20 rounded mb-2\" />\r\n <div className=\"h-4 w-16 mx-auto bg-muted-foreground/20 rounded\" />\r\n </div>\r\n ))}\r\n </div>\r\n ) : hasError ? (\r\n <div className=\"text-center py-8 text-muted-foreground\">\r\n {formatMessage({ id: 'specs.injection.loadError', defaultMessage: 'Failed to load statistics' })}\r\n </div>\r\n ) : (\r\n <>\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n {dimensionEntries\r\n .filter(([entry]) => entry[0] === 'specs' || entry[1] === 'personal')\r\n .map(([dim, data]) => (\r\n <div\r\n key={dim}\r\n className=\"text-center p-4 rounded-lg bg-muted/50 hover:bg-muted transition-colors\"\r\n >\r\n <div className=\"text-2xl font-bold text-foreground\">\r\n {data.count}\r\n </div>\r\n <div className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: `specs.dimension.${dim}`, defaultMessage: dim })}\r\n </div>\r\n <div className=\"text-xs text-muted-foreground mt-1\">\r\n {data.requiredCount} {formatMessage({ id: 'specs.required', defaultMessage: 'required' })}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {/* Summary */}\r\n <div className=\"mt-4 pt-4 border-t border-border\">\r\n <div className=\"flex justify-between text-sm text-muted-foreground\">\r\n <span>\r\n {formatMessage(\r\n { id: 'specs.settings.totalSpecs', defaultMessage: 'Total: {count} spec files' },\r\n { count: totalCount }\r\n )}\r\n </span>\r\n <span>\r\n {totalRequired} {formatMessage({ id: 'specs.readMode.required', defaultMessage: 'required' })} | {totalCount - totalRequired}{' '}\r\n {formatMessage({ id: 'specs.readMode.optional', defaultMessage: 'optional' })}\r\n </span>\r\n </div>\r\n </div>\r\n </>\r\n )}\r\n </CardContent>\r\n </Card>\r\n\r\n {/* Development Progress Injection Card */}\r\n <Card>\r\n <CardHeader>\r\n <div className=\"flex items-center gap-2\">\r\n <History className=\"h-5 w-5 text-muted-foreground\" />\r\n <CardTitle>\r\n {formatMessage({ id: 'specs.settings.devProgressInjection', defaultMessage: 'Development Progress Injection' })}\r\n </CardTitle>\r\n </div>\r\n <CardDescription>\r\n {formatMessage({ id: 'specs.settings.devProgressInjectionDesc', defaultMessage: 'Control how development progress from project-tech.json is injected into AI context' })}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-6\">\r\n {/* Enable Toggle */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"space-y-0.5\">\r\n <Label>\r\n {formatMessage({ id: 'specs.settings.enableDevProgress', defaultMessage: 'Enable Injection' })}\r\n </Label>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.settings.enableDevProgressDesc', defaultMessage: 'Include development history in AI context' })}\r\n </p>\r\n </div>\r\n <Switch\r\n checked={localDevProgress.enabled}\r\n onCheckedChange={handleDevProgressToggle}\r\n disabled={updateMutation.isPending}\r\n />\r\n </div>\r\n\r\n {/* Max Entries */}\r\n <div className=\"space-y-2\">\r\n <Label>\r\n {formatMessage({ id: 'specs.settings.maxEntries', defaultMessage: 'Max Entries per Category' })}\r\n </Label>\r\n <Input\r\n type=\"number\"\r\n min={1}\r\n max={50}\r\n value={localDevProgress.maxEntriesPerCategory}\r\n onChange={(e) => handleMaxEntriesChange(e.target.value)}\r\n disabled={updateMutation.isPending || !localDevProgress.enabled}\r\n className=\"w-24\"\r\n />\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.settings.maxEntriesDesc', defaultMessage: 'Maximum number of entries to include per category (1-50)' })}\r\n </p>\r\n </div>\r\n\r\n {/* Category Toggles */}\r\n <div className=\"space-y-2\">\r\n <Label>\r\n {formatMessage({ id: 'specs.settings.includeCategories', defaultMessage: 'Include Categories' })}\r\n </Label>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {(['feature', 'enhancement', 'bugfix', 'refactor', 'docs'] as const).map(cat => (\r\n <Badge\r\n key={cat}\r\n variant={localDevProgress.categories.includes(cat) ? 'default' : 'outline'}\r\n className={cn(\r\n 'cursor-pointer transition-colors',\r\n !localDevProgress.enabled && 'opacity-50 cursor-not-allowed'\r\n )}\r\n onClick={() => localDevProgress.enabled && handleCategoryToggle(cat)}\r\n >\r\n {formatMessage({ id: `specs.devCategory.${cat}`, defaultMessage: cat })} ({projectTechStats?.categories[cat] || 0})\r\n </Badge>\r\n ))}\r\n </div>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.settings.categoriesDesc', defaultMessage: 'Click to toggle category inclusion' })}\r\n </p>\r\n </div>\r\n\r\n {/* Stats Summary */}\r\n {projectTechStats && (\r\n <div className=\"text-sm text-muted-foreground pt-4 border-t border-border\">\r\n {projectTechStats.last_updated ? (\r\n formatMessage(\r\n { id: 'specs.settings.devProgressStats', defaultMessage: '{total} entries from {sessions} sessions, last updated: {date}' },\r\n {\r\n total: projectTechStats.total_features,\r\n sessions: projectTechStats.total_sessions,\r\n date: new Date(projectTechStats.last_updated).toLocaleDateString()\r\n }\r\n )\r\n ) : (\r\n formatMessage(\r\n { id: 'specs.settings.devProgressStatsNoDate', defaultMessage: '{total} entries from {sessions} sessions' },\r\n {\r\n total: projectTechStats.total_features,\r\n sessions: projectTechStats.total_sessions\r\n }\r\n )\r\n )}\r\n </div>\r\n )}\r\n </CardContent>\r\n </Card>\r\n </div>\r\n );\r\n}\r\n\r\nexport default GlobalSettingsTab;\r\n","/**\r\n * Specs Settings Page\r\n *\r\n * Main page for managing spec settings, injection control, and global settings.\r\n * Uses 4 tabs: Project Specs | Personal Specs | Injection | Settings\r\n * Supports category filtering (workflow stage) and scope filtering (personal only)\r\n */\r\nimport { useState, useMemo } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/Tabs';\r\nimport { Card, CardContent } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { ScrollText, User, Gauge, Settings, RefreshCw, Search, Globe, Folder, Filter, Layers } from 'lucide-react';\r\nimport { SpecCard, SpecDialog, SpecContentDialog, type Spec, type SpecFormData, type SpecCategory } from '@/components/specs';\r\nimport { InjectionControlTab } from '@/components/specs/InjectionControlTab';\r\nimport { GlobalSettingsTab } from '@/components/specs/GlobalSettingsTab';\r\nimport { useSpecStats, useSpecsList, useRebuildSpecIndex } from '@/hooks/useSystemSettings';\r\nimport { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore';\r\nimport type { SpecEntry } from '@/lib/api';\r\n\r\ntype SettingsTab = 'project-specs' | 'personal-specs' | 'injection' | 'settings';\r\ntype PersonalScopeFilter = 'all' | 'global' | 'project';\r\ntype CategoryFilter = 'all' | SpecCategory;\r\n\r\n// All available categories\r\nconst SPEC_CATEGORIES: SpecCategory[] = ['general', 'exploration', 'planning', 'execution'];\r\n\r\n// Convert SpecEntry to Spec for display\r\nfunction specEntryToSpec(entry: SpecEntry, dimension: string): Spec {\r\n return {\r\n id: entry.file,\r\n title: entry.title,\r\n dimension: dimension as Spec['dimension'],\r\n scope: entry.scope || 'project', // Default to project if not specified\r\n category: entry.category || 'general', // Default to general if not specified\r\n keywords: entry.keywords,\r\n readMode: entry.readMode as Spec['readMode'],\r\n priority: entry.priority as Spec['priority'],\r\n file: entry.file,\r\n enabled: true,\r\n };\r\n}\r\n\r\nexport function SpecsSettingsPage() {\r\n const { formatMessage } = useIntl();\r\n const projectPath = useWorkflowStore(selectProjectPath);\r\n const [activeTab, setActiveTab] = useState<SettingsTab>('project-specs');\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [personalScopeFilter, setPersonalScopeFilter] = useState<PersonalScopeFilter>('all');\r\n const [categoryFilter, setCategoryFilter] = useState<CategoryFilter>('all');\r\n const [editDialogOpen, setEditDialogOpen] = useState(false);\r\n const [contentDialogOpen, setContentDialogOpen] = useState(false);\r\n const [editingSpec, setEditingSpec] = useState<Spec | null>(null);\r\n const [viewingSpec, setViewingSpec] = useState<Spec | null>(null);\r\n\r\n // Fetch real data\r\n const { data: specsListData, isLoading: specsLoading, refetch: refetchSpecs } = useSpecsList({ projectPath });\r\n const { data: statsData } = useSpecStats({ projectPath });\r\n const rebuildMutation = useRebuildSpecIndex();\r\n\r\n // Convert specs data to display format\r\n const { projectSpecs, personalSpecs, globalPersonalSpecs, projectPersonalSpecs, categoryCounts } = useMemo(() => {\r\n if (!specsListData?.specs) {\r\n return {\r\n projectSpecs: [],\r\n personalSpecs: [],\r\n globalPersonalSpecs: [],\r\n projectPersonalSpecs: [],\r\n categoryCounts: { general: 0, exploration: 0, planning: 0, execution: 0 }\r\n };\r\n }\r\n\r\n const specs: Spec[] = [];\r\n const personal: Spec[] = [];\r\n const globalPersonal: Spec[] = [];\r\n const projectPersonal: Spec[] = [];\r\n const counts: Record<SpecCategory, number> = { general: 0, exploration: 0, planning: 0, execution: 0 };\r\n\r\n for (const [dimension, entries] of Object.entries(specsListData.specs)) {\r\n for (const entry of entries) {\r\n const spec = specEntryToSpec(entry, dimension);\r\n // Count by category\r\n if (spec.category) {\r\n counts[spec.category]++;\r\n }\r\n if (dimension === 'personal') {\r\n personal.push(spec);\r\n if (spec.scope === 'global') {\r\n globalPersonal.push(spec);\r\n } else {\r\n projectPersonal.push(spec);\r\n }\r\n } else {\r\n specs.push(spec);\r\n }\r\n }\r\n }\r\n\r\n return {\r\n projectSpecs: specs,\r\n personalSpecs: personal,\r\n globalPersonalSpecs: globalPersonal,\r\n projectPersonalSpecs: projectPersonal,\r\n categoryCounts: counts\r\n };\r\n }, [specsListData]);\r\n\r\n const isLoading = specsLoading;\r\n\r\n const handleSpecView = (spec: Spec) => {\r\n setViewingSpec(spec);\r\n setContentDialogOpen(true);\r\n };\r\n\r\n const handleSpecEdit = (spec: Spec) => {\r\n setEditingSpec(spec);\r\n setEditDialogOpen(true);\r\n };\r\n\r\n const handleSpecSave = async (specId: string, data: SpecFormData) => {\r\n console.log('Saving spec:', specId, data);\r\n // TODO: Implement save logic\r\n setEditDialogOpen(false);\r\n };\r\n\r\n const handleContentSave = async (specId: string, content: string) => {\r\n console.log('Saving spec content:', specId, content.length);\r\n // TODO: Implement content save logic\r\n };\r\n\r\n const handleSpecToggle = async (specId: string, enabled: boolean) => {\r\n console.log('Toggling spec:', specId, enabled);\r\n // TODO: Implement toggle logic\r\n };\r\n\r\n const handleSpecDelete = async (specId: string) => {\r\n console.log('Deleting spec:', specId);\r\n // TODO: Implement delete logic\r\n };\r\n\r\n const handleRebuildIndex = async () => {\r\n console.log('Rebuilding index...');\r\n rebuildMutation.mutate(undefined, {\r\n onSuccess: () => {\r\n refetchSpecs();\r\n }\r\n });\r\n };\r\n\r\n const filterSpecs = (specs: Spec[]) => {\r\n let result = specs;\r\n // Filter by category\r\n if (categoryFilter !== 'all') {\r\n result = result.filter(spec => spec.category === categoryFilter);\r\n }\r\n // Filter by search query\r\n if (searchQuery.trim()) {\r\n const query = searchQuery.toLowerCase();\r\n result = result.filter(spec =>\r\n spec.title.toLowerCase().includes(query) ||\r\n spec.keywords.some(k => k.toLowerCase().includes(query))\r\n );\r\n }\r\n return result;\r\n };\r\n\r\n const renderSpecsTab = (dimension: 'project' | 'personal') => {\r\n let specs = dimension === 'project' ? projectSpecs : personalSpecs;\r\n\r\n // Apply scope filter for personal specs\r\n if (dimension === 'personal') {\r\n if (personalScopeFilter === 'global') {\r\n specs = globalPersonalSpecs;\r\n } else if (personalScopeFilter === 'project') {\r\n specs = projectPersonalSpecs;\r\n }\r\n }\r\n\r\n const filteredSpecs = filterSpecs(specs);\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Search and Actions */}\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"relative flex-1\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n placeholder={formatMessage({ id: 'specs.searchPlaceholder', defaultMessage: 'Search specs...' })}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"pl-9\"\r\n />\r\n </div>\r\n <Button variant=\"outline\" onClick={handleRebuildIndex} disabled={rebuildMutation.isPending}>\r\n <RefreshCw className={`h-4 w-4 mr-2 ${rebuildMutation.isPending ? 'animate-spin' : ''}`} />\r\n {formatMessage({ id: 'specs.rebuildIndex', defaultMessage: 'Rebuild Index' })}\r\n </Button>\r\n </div>\r\n\r\n {/* Scope filter for personal specs */}\r\n {dimension === 'personal' && (\r\n <div className=\"flex items-center gap-2\">\r\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.filterByScope', defaultMessage: 'Filter by scope:' })}\r\n </span>\r\n <div className=\"flex gap-2\">\r\n <Button\r\n variant={personalScopeFilter === 'all' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setPersonalScopeFilter('all')}\r\n >\r\n {formatMessage({ id: 'specs.scope.all', defaultMessage: 'All' })} ({personalSpecs.length})\r\n </Button>\r\n <Button\r\n variant={personalScopeFilter === 'global' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setPersonalScopeFilter('global')}\r\n >\r\n <Globe className=\"h-3 w-3 mr-1\" />\r\n {formatMessage({ id: 'specs.scope.global', defaultMessage: 'Global' })} ({globalPersonalSpecs.length})\r\n </Button>\r\n <Button\r\n variant={personalScopeFilter === 'project' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setPersonalScopeFilter('project')}\r\n >\r\n <Folder className=\"h-3 w-3 mr-1\" />\r\n {formatMessage({ id: 'specs.scope.project', defaultMessage: 'Project' })} ({projectPersonalSpecs.length})\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Category filter for workflow stage */}\r\n <div className=\"flex items-center gap-2\">\r\n <Layers className=\"h-4 w-4 text-muted-foreground\" />\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'specs.filterByCategory', defaultMessage: 'Workflow stage:' })}\r\n </span>\r\n <div className=\"flex gap-2 flex-wrap\">\r\n <Button\r\n variant={categoryFilter === 'all' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setCategoryFilter('all')}\r\n >\r\n {formatMessage({ id: 'specs.category.all', defaultMessage: 'All' })}\r\n </Button>\r\n {SPEC_CATEGORIES.map(cat => (\r\n <Button\r\n key={cat}\r\n variant={categoryFilter === cat ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setCategoryFilter(cat)}\r\n >\r\n {formatMessage({ id: `specs.category.${cat}`, defaultMessage: cat })} ({categoryCounts[cat]})\r\n </Button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Stats Summary - Only show specs and personal dimensions */}\r\n {statsData?.dimensions && (\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n {Object.entries(statsData.dimensions)\r\n .filter(([dim]) => dim === 'specs' || dim === 'personal')\r\n .map(([dim, data]) => (\r\n <Card key={dim}>\r\n <CardContent className=\"pt-4\">\r\n <div className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: `specs.dimension.${dim}`, defaultMessage: dim })}\r\n </div>\r\n <div className=\"text-2xl font-bold\">{(data as { count: number }).count}</div>\r\n <div className=\"text-xs text-muted-foreground\">\r\n {(data as { requiredCount: number }).requiredCount} {formatMessage({ id: 'specs.required', defaultMessage: 'required' })}\r\n </div>\r\n </CardContent>\r\n </Card>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Specs Grid */}\r\n {filteredSpecs.length === 0 ? (\r\n <Card>\r\n <CardContent className=\"py-8 text-center text-muted-foreground\">\r\n {isLoading\r\n ? formatMessage({ id: 'specs.loading', defaultMessage: 'Loading specs...' })\r\n : formatMessage({ id: 'specs.noSpecs', defaultMessage: 'No specs found. Create specs in .ccw/ directory.' })\r\n }\r\n </CardContent>\r\n </Card>\r\n ) : (\r\n <div className=\"grid gap-4\">\r\n {filteredSpecs.map(spec => (\r\n <SpecCard\r\n key={spec.id}\r\n spec={spec}\r\n onView={handleSpecView}\r\n onEdit={handleSpecEdit}\r\n onToggle={handleSpecToggle}\r\n onDelete={handleSpecDelete}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n };\r\n\r\n return (\r\n <div className=\"max-w-6xl mx-auto\">\r\n {/* Page Header */}\r\n <div className=\"mb-6\">\r\n <h1 className=\"text-2xl font-bold flex items-center gap-2\">\r\n <ScrollText className=\"h-6 w-6\" />\r\n {formatMessage({ id: 'specs.pageTitle', defaultMessage: 'Spec Settings' })}\r\n </h1>\r\n <p className=\"text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'specs.pageDescription', defaultMessage: 'Manage specification injection and system settings' })}\r\n </p>\r\n </div>\r\n\r\n {/* Main Tabs */}\r\n <Tabs value={activeTab} onValueChange={(v) => setActiveTab(v as SettingsTab)}>\r\n <TabsList className=\"grid grid-cols-4 mb-6\">\r\n <TabsTrigger value=\"project-specs\" className=\"flex items-center gap-2\">\r\n <ScrollText className=\"h-4 w-4\" />\r\n <span className=\"hidden sm:inline\">{formatMessage({ id: 'specs.tabProjectSpecs', defaultMessage: 'Project Specs' })}</span>\r\n </TabsTrigger>\r\n <TabsTrigger value=\"personal-specs\" className=\"flex items-center gap-2\">\r\n <User className=\"h-4 w-4\" />\r\n <span className=\"hidden sm:inline\">{formatMessage({ id: 'specs.tabPersonalSpecs', defaultMessage: 'Personal' })}</span>\r\n </TabsTrigger>\r\n <TabsTrigger value=\"injection\" className=\"flex items-center gap-2\">\r\n <Gauge className=\"h-4 w-4\" />\r\n <span className=\"hidden sm:inline\">{formatMessage({ id: 'specs.tabInjection', defaultMessage: 'Injection' })}</span>\r\n </TabsTrigger>\r\n <TabsTrigger value=\"settings\" className=\"flex items-center gap-2\">\r\n <Settings className=\"h-4 w-4\" />\r\n <span className=\"hidden sm:inline\">{formatMessage({ id: 'specs.tabSettings', defaultMessage: 'Settings' })}</span>\r\n </TabsTrigger>\r\n </TabsList>\r\n\r\n <TabsContent value=\"project-specs\">\r\n {renderSpecsTab('project')}\r\n </TabsContent>\r\n\r\n <TabsContent value=\"personal-specs\">\r\n {renderSpecsTab('personal')}\r\n </TabsContent>\r\n\r\n <TabsContent value=\"injection\">\r\n <InjectionControlTab />\r\n </TabsContent>\r\n\r\n <TabsContent value=\"settings\">\r\n <GlobalSettingsTab />\r\n </TabsContent>\r\n </Tabs>\r\n\r\n {/* Edit Spec Dialog */}\r\n <SpecDialog\r\n open={editDialogOpen}\r\n onOpenChange={setEditDialogOpen}\r\n spec={editingSpec}\r\n onSave={handleSpecSave}\r\n />\r\n\r\n {/* View/Edit Spec Content Dialog */}\r\n <SpecContentDialog\r\n open={contentDialogOpen}\r\n onOpenChange={setContentDialogOpen}\r\n spec={viewingSpec}\r\n onSave={handleContentSave}\r\n />\r\n </div>\r\n );\r\n}\r\n\r\nexport default SpecsSettingsPage;\r\n"],"names":["Pen","createLucideIcon","readModeConfig","priorityConfig","categoryConfig","SpecCard","spec","onView","onEdit","onDelete","onToggle","className","showActions","actionsDisabled","formatMessage","useIntl","readMode","priority","handleToggle","enabled","handleAction","e","action","jsx","Card","cn","jsxs","CardContent","FileText","DropdownMenu","DropdownMenuTrigger","Button","MoreVertical","DropdownMenuContent","DropdownMenuItem","Eye","Edit","DropdownMenuSeparator","Trash2","Badge","Layers","Fragment","Globe","Folder","Tag","keyword","Switch","READ_MODE_OPTIONS","PRIORITY_OPTIONS","SpecDialog","open","onOpenChange","onSave","isLoading","formData","setFormData","React.useState","keywordInput","setKeywordInput","errors","setErrors","React.useEffect","validateForm","newErrors","handleSave","handleKeywordKeyDown","addKeyword","prev","removeKeyword","k","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Label","Input","Select","value","SelectTrigger","SelectValue","SelectContent","option","SelectItem","X","DialogFooter","parseFrontmatter","content","frontmatterRegex","match","frontmatterLines","frontmatter","line","colonIndex","key","s","SpecContentDialog","initialContent","readOnly","mode","setMode","setContent","editedContent","setEditedContent","body","React.useMemo","response","data","error","handleCancelEdit","Edit2","Textarea","Loader2","Save","SPEC_CATEGORIES","CATEGORY_CONFIG","RECOMMENDED_HOOKS","fetchSpecStats","fetchSystemSettings","updateInjectionSettings","settings","currentSettings","formatNumber","num","calculatePercentage","current","max","InjectionControlTab","installHooksMutation","useInstallRecommendedHooks","stats","setStats","useState","statsLoading","setStatsLoading","statsError","setStatsError","setSettings","settingsLoading","setSettingsLoading","hasChanges","setHasChanges","isSaving","setIsSaving","installingHookIds","setInstallingHookIds","systemSettingsQuery","useSystemSettings","previewMode","setPreviewMode","categoryFilter","setCategoryFilter","previewData","setPreviewData","previewLoading","setPreviewLoading","expandedDimensions","setExpandedDimensions","previewDialogOpen","setPreviewDialogOpen","previewFile","setPreviewFile","selectedCommand","setSelectedCommand","COMMAND_PREVIEWS","commandPreviewData","setCommandPreviewData","commandPreviewLoading","setCommandPreviewLoading","commandPreviewDialogOpen","setCommandPreviewDialogOpen","loadStats","useCallback","err","loadSettings","loadPreview","getInjectionPreview","loadFilePreview","file","fileWithData","f","loadCommandPreview","command","useEffect","changed","handleFieldChange","field","result","toast","handleReset","maxLengthError","warnThresholdError","toggleDimension","dim","installedHookIds","useMemo","installed","hooks","_a","hook","installedCount","allHooksInstalled","handleInstallHook","hookId","id","handleInstallAllHooks","uninstalledHooks","h","filesByDimension","grouped","categoryStats","cat","currentLength","_b","maxLength","_c","warnThreshold","percentage","isOverLimit","isOverWarning","remainingSpace","estimatedLineCount","maxLineCount","CardHeader","CardTitle","Plug","CardDescription","CheckCircle2","Download","Link","Settings","isInstalled","isInstalling","RefreshCw","Progress","AlertTriangle","AlertCircle","Info","_d","_e","Filter","files","ChevronDown","ChevronRight","sum","fileCategory","categoryStyle","cmd","checked","idx","API_BASE","updateSystemSettings","fetchProjectTechStats","settingsKeys","GlobalSettingsTab","queryClient","useQueryClient","localDefaults","setLocalDefaults","localDevProgress","setLocalDevProgress","isLoadingSettings","settingsError","useQuery","isLoadingStats","refetchStats","projectTechStats","updateMutation","useMutation","handleReadModeChange","newDefaults","handleAutoEnableChange","handleDevProgressToggle","newDevProgress","handleMaxEntriesChange","numValue","handleCategoryToggle","category","newCategories","c","dimensions","dimensionEntries","totalCount","totalRequired","hasError","i","entry","History","specEntryToSpec","dimension","SpecsSettingsPage","projectPath","useWorkflowStore","selectProjectPath","activeTab","setActiveTab","searchQuery","setSearchQuery","personalScopeFilter","setPersonalScopeFilter","editDialogOpen","setEditDialogOpen","contentDialogOpen","setContentDialogOpen","editingSpec","setEditingSpec","viewingSpec","setViewingSpec","specsListData","specsLoading","refetchSpecs","useSpecsList","statsData","useSpecStats","rebuildMutation","useRebuildSpecIndex","projectSpecs","personalSpecs","globalPersonalSpecs","projectPersonalSpecs","categoryCounts","specs","personal","globalPersonal","projectPersonal","counts","entries","handleSpecView","handleSpecEdit","handleSpecSave","specId","handleContentSave","handleSpecToggle","handleSpecDelete","handleRebuildIndex","filterSpecs","query","renderSpecsTab","filteredSpecs","Search","ScrollText","Tabs","v","TabsList","TabsTrigger","User","Gauge","TabsContent"],"mappings":"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","x_google_ignoreList":[0]}
|