claude-code-workflow 7.2.15 → 7.2.16
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/.ccw/workflows/cli-templates/schemas/team-tasks-schema.json +255 -0
- package/.codex/agents/team-supervisor.toml +39 -0
- package/.codex/agents/team-worker.toml +46 -0
- package/.codex/skills/team-arch-opt/SKILL.md +151 -698
- package/.codex/skills/team-arch-opt/roles/analyzer/role.md +78 -0
- package/.codex/skills/team-arch-opt/roles/coordinator/commands/analyze.md +57 -0
- package/.codex/skills/team-arch-opt/roles/coordinator/commands/dispatch.md +287 -0
- package/.codex/skills/team-arch-opt/roles/coordinator/commands/monitor.md +204 -0
- package/.codex/skills/team-arch-opt/roles/coordinator/role.md +162 -0
- package/.codex/skills/team-arch-opt/roles/designer/role.md +115 -0
- package/.codex/skills/team-arch-opt/roles/refactorer/role.md +102 -0
- package/.codex/skills/team-arch-opt/roles/reviewer/role.md +111 -0
- package/.codex/skills/team-arch-opt/roles/validator/role.md +115 -0
- package/.codex/skills/team-arch-opt/specs/pipelines.md +102 -0
- package/.codex/skills/team-arch-opt/specs/team-config.json +263 -0
- package/.codex/skills/team-brainstorm/SKILL.md +167 -724
- package/.codex/skills/team-brainstorm/roles/challenger/role.md +61 -0
- package/.codex/skills/team-brainstorm/roles/coordinator/commands/analyze.md +58 -0
- package/.codex/skills/team-brainstorm/roles/coordinator/commands/dispatch.md +162 -0
- package/.codex/skills/team-brainstorm/roles/coordinator/commands/monitor.md +171 -0
- package/.codex/skills/team-brainstorm/roles/coordinator/role.md +140 -0
- package/.codex/skills/team-brainstorm/roles/evaluator/role.md +56 -0
- package/.codex/skills/team-brainstorm/roles/ideator/role.md +69 -0
- package/.codex/skills/team-brainstorm/roles/synthesizer/role.md +57 -0
- package/.codex/skills/team-brainstorm/specs/pipelines.md +72 -0
- package/.codex/skills/team-brainstorm/specs/team-config.json +86 -0
- package/.codex/skills/team-coordinate/SKILL.md +267 -667
- package/.codex/skills/team-coordinate/roles/coordinator/commands/analyze-task.md +247 -0
- package/.codex/skills/team-coordinate/roles/coordinator/commands/dispatch.md +126 -0
- package/.codex/skills/team-coordinate/roles/coordinator/commands/monitor.md +327 -0
- package/.codex/skills/team-coordinate/roles/coordinator/role.md +361 -0
- package/.codex/skills/team-coordinate/specs/knowledge-transfer.md +111 -0
- package/.codex/skills/team-coordinate/specs/pipelines.md +97 -0
- package/.codex/skills/team-coordinate/specs/quality-gates.md +112 -0
- package/.codex/skills/team-coordinate/specs/role-spec-template.md +192 -0
- package/.codex/skills/team-designer/SKILL.md +153 -691
- package/.codex/skills/team-designer/phases/01-requirements-analysis.md +250 -0
- package/.codex/skills/team-designer/phases/02-scaffold-generation.md +228 -0
- package/.codex/skills/team-designer/phases/03-content-generation.md +330 -0
- package/.codex/skills/team-designer/phases/04-validation.md +320 -0
- package/.codex/skills/team-executor/SKILL.md +191 -515
- package/.codex/skills/team-executor/roles/executor/commands/monitor.md +280 -0
- package/.codex/skills/team-executor/roles/executor/role.md +170 -0
- package/.codex/skills/team-executor/specs/session-schema.md +264 -0
- package/.codex/skills/team-frontend/SKILL.md +129 -750
- package/.codex/skills/team-frontend/roles/analyst/role.md +92 -0
- package/.codex/skills/team-frontend/roles/architect/role.md +86 -0
- package/.codex/skills/team-frontend/roles/coordinator/commands/analyze.md +52 -0
- package/.codex/skills/team-frontend/roles/coordinator/commands/dispatch.md +151 -0
- package/.codex/skills/team-frontend/roles/coordinator/commands/monitor.md +188 -0
- package/.codex/skills/team-frontend/roles/coordinator/role.md +157 -0
- package/.codex/skills/team-frontend/roles/developer/role.md +93 -0
- package/.codex/skills/team-frontend/roles/qa/role.md +79 -0
- package/.codex/skills/team-frontend/specs/pipelines.md +76 -0
- package/.codex/skills/team-frontend/specs/team-config.json +84 -0
- package/.codex/skills/team-frontend-debug/SKILL.md +191 -821
- package/.codex/skills/team-frontend-debug/roles/analyzer/role.md +208 -0
- package/.codex/skills/team-frontend-debug/roles/coordinator/commands/analyze.md +174 -0
- package/.codex/skills/team-frontend-debug/roles/coordinator/commands/dispatch.md +198 -0
- package/.codex/skills/team-frontend-debug/roles/coordinator/commands/monitor.md +143 -0
- package/.codex/skills/team-frontend-debug/roles/coordinator/role.md +131 -0
- package/.codex/skills/team-frontend-debug/roles/fixer/role.md +147 -0
- package/.codex/skills/team-frontend-debug/roles/reproducer/role.md +147 -0
- package/.codex/skills/team-frontend-debug/roles/tester/role.md +231 -0
- package/.codex/skills/team-frontend-debug/roles/verifier/role.md +172 -0
- package/.codex/skills/team-frontend-debug/specs/debug-tools.md +215 -0
- package/.codex/skills/team-frontend-debug/specs/pipelines.md +94 -0
- package/.codex/skills/team-issue/SKILL.md +166 -751
- package/.codex/skills/team-issue/roles/coordinator/commands/analyze.md +64 -0
- package/.codex/skills/team-issue/roles/coordinator/commands/dispatch.md +273 -0
- package/.codex/skills/team-issue/roles/coordinator/commands/monitor.md +194 -0
- package/.codex/skills/team-issue/roles/coordinator/role.md +175 -0
- package/.codex/skills/team-issue/roles/explorer/role.md +94 -0
- package/.codex/skills/team-issue/roles/implementer/role.md +87 -0
- package/.codex/skills/team-issue/roles/integrator/role.md +84 -0
- package/.codex/skills/team-issue/roles/planner/role.md +81 -0
- package/.codex/skills/team-issue/roles/reviewer/role.md +86 -0
- package/.codex/skills/team-issue/specs/pipelines.md +124 -0
- package/.codex/skills/team-issue/specs/team-config.json +70 -0
- package/.codex/skills/team-iterdev/SKILL.md +134 -825
- package/.codex/skills/team-iterdev/roles/architect/role.md +65 -0
- package/.codex/skills/team-iterdev/roles/coordinator/commands/analyze.md +62 -0
- package/.codex/skills/team-iterdev/roles/coordinator/commands/dispatch.md +187 -0
- package/.codex/skills/team-iterdev/roles/coordinator/commands/monitor.md +186 -0
- package/.codex/skills/team-iterdev/roles/coordinator/role.md +161 -0
- package/.codex/skills/team-iterdev/roles/developer/role.md +74 -0
- package/.codex/skills/team-iterdev/roles/reviewer/role.md +66 -0
- package/.codex/skills/team-iterdev/roles/tester/role.md +88 -0
- package/.codex/skills/team-iterdev/specs/pipelines.md +94 -0
- package/.codex/skills/team-iterdev/specs/team-config.json +172 -0
- package/.codex/skills/team-lifecycle-v4/MIGRATION-PLAN.md +512 -0
- package/.codex/skills/team-lifecycle-v4/SKILL.md +166 -723
- package/.codex/skills/team-lifecycle-v4/roles/analyst/role.md +104 -0
- package/.codex/skills/team-lifecycle-v4/roles/coordinator/commands/analyze.md +56 -0
- package/.codex/skills/team-lifecycle-v4/roles/coordinator/commands/dispatch.md +61 -0
- package/.codex/skills/team-lifecycle-v4/roles/coordinator/commands/monitor.md +177 -0
- package/.codex/skills/team-lifecycle-v4/roles/coordinator/role.md +152 -0
- package/.codex/skills/team-lifecycle-v4/roles/executor/commands/fix.md +35 -0
- package/.codex/skills/team-lifecycle-v4/roles/executor/commands/implement.md +63 -0
- package/.codex/skills/team-lifecycle-v4/roles/executor/role.md +89 -0
- package/.codex/skills/team-lifecycle-v4/roles/planner/role.md +108 -0
- package/.codex/skills/team-lifecycle-v4/roles/reviewer/commands/review-code.md +57 -0
- package/.codex/skills/team-lifecycle-v4/roles/reviewer/commands/review-spec.md +44 -0
- package/.codex/skills/team-lifecycle-v4/roles/reviewer/role.md +98 -0
- package/.codex/skills/team-lifecycle-v4/roles/supervisor/role.md +210 -0
- package/.codex/skills/team-lifecycle-v4/roles/tester/role.md +126 -0
- package/.codex/skills/team-lifecycle-v4/roles/writer/role.md +125 -0
- package/.codex/skills/team-lifecycle-v4/schemas/tasks-schema.md +82 -160
- package/.codex/skills/team-lifecycle-v4/specs/knowledge-transfer.md +136 -0
- package/.codex/skills/team-lifecycle-v4/specs/pipelines.md +125 -0
- package/.codex/skills/team-lifecycle-v4/specs/quality-gates.md +130 -0
- package/.codex/skills/team-perf-opt/SKILL.md +169 -697
- package/.codex/skills/team-perf-opt/roles/benchmarker/role.md +89 -0
- package/.codex/skills/team-perf-opt/roles/coordinator/commands/analyze.md +61 -0
- package/.codex/skills/team-perf-opt/roles/coordinator/commands/dispatch.md +262 -0
- package/.codex/skills/team-perf-opt/roles/coordinator/commands/monitor.md +320 -0
- package/.codex/skills/team-perf-opt/roles/coordinator/role.md +147 -0
- package/.codex/skills/team-perf-opt/roles/optimizer/role.md +97 -0
- package/.codex/skills/team-perf-opt/roles/profiler/role.md +73 -0
- package/.codex/skills/team-perf-opt/roles/reviewer/role.md +75 -0
- package/.codex/skills/team-perf-opt/roles/strategist/role.md +94 -0
- package/.codex/skills/team-perf-opt/specs/pipelines.md +65 -0
- package/.codex/skills/team-perf-opt/specs/team-config.json +246 -0
- package/.codex/skills/team-planex/SKILL.md +103 -477
- package/.codex/skills/team-planex/roles/coordinator/commands/analyze.md +52 -0
- package/.codex/skills/team-planex/roles/coordinator/commands/dispatch.md +80 -0
- package/.codex/skills/team-planex/roles/coordinator/commands/monitor.md +164 -0
- package/.codex/skills/team-planex/roles/coordinator/role.md +140 -0
- package/.codex/skills/team-planex/roles/executor/role.md +91 -0
- package/.codex/skills/team-planex/roles/planner/role.md +112 -0
- package/.codex/skills/team-planex/specs/pipelines.md +93 -0
- package/.codex/skills/team-quality-assurance/SKILL.md +148 -813
- package/.codex/skills/team-quality-assurance/roles/analyst/role.md +80 -0
- package/.codex/skills/team-quality-assurance/roles/coordinator/commands/analyze.md +72 -0
- package/.codex/skills/team-quality-assurance/roles/coordinator/commands/dispatch.md +108 -0
- package/.codex/skills/team-quality-assurance/roles/coordinator/commands/monitor.md +209 -0
- package/.codex/skills/team-quality-assurance/roles/coordinator/role.md +143 -0
- package/.codex/skills/team-quality-assurance/roles/executor/role.md +66 -0
- package/.codex/skills/team-quality-assurance/roles/generator/role.md +68 -0
- package/.codex/skills/team-quality-assurance/roles/scout/role.md +67 -0
- package/.codex/skills/team-quality-assurance/roles/strategist/role.md +71 -0
- package/.codex/skills/team-quality-assurance/specs/pipelines.md +115 -0
- package/.codex/skills/team-quality-assurance/specs/team-config.json +131 -0
- package/.codex/skills/team-review/SKILL.md +148 -533
- package/.codex/skills/team-review/roles/coordinator/commands/analyze.md +71 -0
- package/.codex/skills/team-review/roles/coordinator/commands/dispatch.md +90 -0
- package/.codex/skills/team-review/roles/coordinator/commands/monitor.md +185 -0
- package/.codex/skills/team-review/roles/coordinator/role.md +142 -0
- package/.codex/skills/team-review/roles/fixer/role.md +76 -0
- package/.codex/skills/team-review/roles/reviewer/role.md +68 -0
- package/.codex/skills/team-review/roles/scanner/role.md +71 -0
- package/.codex/skills/team-review/specs/dimensions.md +82 -0
- package/.codex/skills/team-review/specs/finding-schema.json +82 -0
- package/.codex/skills/team-review/specs/pipelines.md +102 -0
- package/.codex/skills/team-review/specs/team-config.json +27 -0
- package/.codex/skills/team-roadmap-dev/SKILL.md +162 -683
- package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/analyze.md +61 -0
- package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/dispatch.md +241 -0
- package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/monitor.md +468 -0
- package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/pause.md +90 -0
- package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/resume.md +137 -0
- package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/roadmap-discuss.md +243 -0
- package/.codex/skills/team-roadmap-dev/roles/coordinator/role.md +303 -0
- package/.codex/skills/team-roadmap-dev/roles/executor/role.md +71 -0
- package/.codex/skills/team-roadmap-dev/roles/planner/role.md +76 -0
- package/.codex/skills/team-roadmap-dev/roles/verifier/role.md +74 -0
- package/.codex/skills/team-roadmap-dev/specs/pipelines.md +93 -0
- package/.codex/skills/team-roadmap-dev/specs/team-config.json +95 -0
- package/.codex/skills/team-tech-debt/SKILL.md +129 -708
- package/.codex/skills/team-tech-debt/roles/assessor/role.md +69 -0
- package/.codex/skills/team-tech-debt/roles/coordinator/commands/analyze.md +47 -0
- package/.codex/skills/team-tech-debt/roles/coordinator/commands/dispatch.md +163 -0
- package/.codex/skills/team-tech-debt/roles/coordinator/commands/monitor.md +231 -0
- package/.codex/skills/team-tech-debt/roles/coordinator/role.md +141 -0
- package/.codex/skills/team-tech-debt/roles/executor/role.md +76 -0
- package/.codex/skills/team-tech-debt/roles/planner/role.md +69 -0
- package/.codex/skills/team-tech-debt/roles/scanner/role.md +82 -0
- package/.codex/skills/team-tech-debt/roles/validator/role.md +75 -0
- package/.codex/skills/team-tech-debt/specs/pipelines.md +47 -0
- package/.codex/skills/team-tech-debt/specs/team-config.json +129 -0
- package/.codex/skills/team-testing/SKILL.md +144 -769
- package/.codex/skills/team-testing/roles/analyst/role.md +95 -0
- package/.codex/skills/team-testing/roles/coordinator/commands/analyze.md +70 -0
- package/.codex/skills/team-testing/roles/coordinator/commands/dispatch.md +106 -0
- package/.codex/skills/team-testing/roles/coordinator/commands/monitor.md +242 -0
- package/.codex/skills/team-testing/roles/coordinator/role.md +151 -0
- package/.codex/skills/team-testing/roles/executor/role.md +96 -0
- package/.codex/skills/team-testing/roles/generator/role.md +95 -0
- package/.codex/skills/team-testing/roles/strategist/role.md +83 -0
- package/.codex/skills/team-testing/specs/pipelines.md +101 -0
- package/.codex/skills/team-testing/specs/team-config.json +93 -0
- package/.codex/skills/team-uidesign/SKILL.md +133 -767
- package/.codex/skills/team-uidesign/roles/coordinator/commands/analyze.md +59 -0
- package/.codex/skills/team-uidesign/roles/coordinator/commands/dispatch.md +156 -0
- package/.codex/skills/team-uidesign/roles/coordinator/commands/monitor.md +194 -0
- package/.codex/skills/team-uidesign/roles/coordinator/role.md +179 -0
- package/.codex/skills/team-uidesign/roles/designer/role.md +69 -0
- package/.codex/skills/team-uidesign/roles/implementer/role.md +72 -0
- package/.codex/skills/team-uidesign/roles/researcher/role.md +82 -0
- package/.codex/skills/team-uidesign/roles/reviewer/role.md +67 -0
- package/.codex/skills/team-uidesign/specs/pipelines.md +76 -0
- package/.codex/skills/team-uidesign/specs/team-config.json +107 -0
- package/.codex/skills/team-ultra-analyze/SKILL.md +166 -786
- package/.codex/skills/team-ultra-analyze/roles/analyst/role.md +90 -0
- package/.codex/skills/team-ultra-analyze/roles/coordinator/commands/analyze.md +73 -0
- package/.codex/skills/team-ultra-analyze/roles/coordinator/commands/dispatch.md +225 -0
- package/.codex/skills/team-ultra-analyze/roles/coordinator/commands/monitor.md +327 -0
- package/.codex/skills/team-ultra-analyze/roles/coordinator/role.md +223 -0
- package/.codex/skills/team-ultra-analyze/roles/discussant/role.md +104 -0
- package/.codex/skills/team-ultra-analyze/roles/explorer/role.md +74 -0
- package/.codex/skills/team-ultra-analyze/roles/synthesizer/role.md +78 -0
- package/.codex/skills/team-ultra-analyze/specs/pipelines.md +64 -0
- package/.codex/skills/team-ultra-analyze/specs/team-config.json +129 -0
- package/.codex/skills/team-ux-improve/SKILL.md +142 -638
- package/.codex/skills/team-ux-improve/roles/coordinator/commands/analyze.md +62 -0
- package/.codex/skills/team-ux-improve/roles/coordinator/commands/dispatch.md +233 -0
- package/.codex/skills/team-ux-improve/roles/coordinator/commands/monitor.md +160 -0
- package/.codex/skills/team-ux-improve/roles/coordinator/role.md +138 -0
- package/.codex/skills/team-ux-improve/roles/designer/role.md +122 -0
- package/.codex/skills/team-ux-improve/roles/diagnoser/role.md +93 -0
- package/.codex/skills/team-ux-improve/roles/explorer/role.md +77 -0
- package/.codex/skills/team-ux-improve/roles/implementer/role.md +102 -0
- package/.codex/skills/team-ux-improve/roles/scanner/role.md +93 -0
- package/.codex/skills/team-ux-improve/roles/tester/role.md +84 -0
- package/.codex/skills/team-ux-improve/specs/pipelines.md +54 -0
- package/.codex/skills/team-ux-improve/specs/team-config.json +181 -0
- package/.codex/skills/team-ux-improve/wisdom/anti-patterns/common-ux-pitfalls.md +17 -0
- package/.codex/skills/team-ux-improve/wisdom/contributions/.gitkeep +0 -0
- package/.codex/skills/team-ux-improve/wisdom/patterns/state-management.md +14 -0
- package/.codex/skills/team-ux-improve/wisdom/patterns/ui-feedback.md +16 -0
- package/.codex/skills/team-ux-improve/wisdom/principles/general-ux.md +16 -0
- package/ccw/dist/core/routes/cli-settings-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/cli-settings-routes.js +135 -133
- package/ccw/dist/core/routes/cli-settings-routes.js.map +1 -1
- package/ccw/frontend/dist/assets/{AlertDialog-BW9jiZ-p.js → AlertDialog-CnpjWAGm.js} +2 -2
- package/ccw/frontend/dist/assets/{AlertDialog-BW9jiZ-p.js.map → AlertDialog-CnpjWAGm.js.map} +1 -1
- package/ccw/frontend/dist/assets/{AnalysisPage-ds-w_nVO.js → AnalysisPage-BT2rDDUD.js} +2 -2
- package/ccw/frontend/dist/assets/{AnalysisPage-ds-w_nVO.js.map → AnalysisPage-BT2rDDUD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ApiSettingsPage-DlCbXxTz.js → ApiSettingsPage-DGpjiNVu.js} +2 -2
- package/ccw/frontend/dist/assets/{ApiSettingsPage-DlCbXxTz.js.map → ApiSettingsPage-DGpjiNVu.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliModeToggle-Dq3nL4fF.js → CliModeToggle-BqUadHn3.js} +2 -2
- package/ccw/frontend/dist/assets/{CliModeToggle-Dq3nL4fF.js.map → CliModeToggle-BqUadHn3.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliSessionSharePage-BNDkEE4u.js → CliSessionSharePage-C3AdsDkm.js} +2 -2
- package/ccw/frontend/dist/assets/{CliSessionSharePage-BNDkEE4u.js.map → CliSessionSharePage-C3AdsDkm.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliViewerPage-ChM-uNx_.js → CliViewerPage-BZXpgY0N.js} +2 -2
- package/ccw/frontend/dist/assets/{CliViewerPage-ChM-uNx_.js.map → CliViewerPage-BZXpgY0N.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CodexLensPage-DOcsYNQk.js → CodexLensPage-CePoJz-u.js} +2 -2
- package/ccw/frontend/dist/assets/{CodexLensPage-DOcsYNQk.js.map → CodexLensPage-CePoJz-u.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Collapsible-CRNbykXN.js → Collapsible-DXVzWwmb.js} +2 -2
- package/ccw/frontend/dist/assets/{Collapsible-CRNbykXN.js.map → Collapsible-DXVzWwmb.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CommandsManagerPage-C2JWcemF.js → CommandsManagerPage-B6wJYF0z.js} +2 -2
- package/ccw/frontend/dist/assets/{CommandsManagerPage-C2JWcemF.js.map → CommandsManagerPage-B6wJYF0z.js.map} +1 -1
- package/ccw/frontend/dist/assets/{DeepWikiPage-CvleOtJy.js → DeepWikiPage-D55fcvSk.js} +2 -2
- package/ccw/frontend/dist/assets/{DeepWikiPage-CvleOtJy.js.map → DeepWikiPage-D55fcvSk.js.map} +1 -1
- package/ccw/frontend/dist/assets/{EndpointsPage-CMOWQG64.js → EndpointsPage-DcGziJ5t.js} +2 -2
- package/ccw/frontend/dist/assets/{EndpointsPage-CMOWQG64.js.map → EndpointsPage-DcGziJ5t.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ExplorerPage-DaFPRlNo.js → ExplorerPage-C4eKzn7F.js} +2 -2
- package/ccw/frontend/dist/assets/{ExplorerPage-DaFPRlNo.js.map → ExplorerPage-C4eKzn7F.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FixSessionPage-CC4p04Az.js → FixSessionPage-BUHh954A.js} +2 -2
- package/ccw/frontend/dist/assets/{FixSessionPage-CC4p04Az.js.map → FixSessionPage-BUHh954A.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-DROn1xZ5.js → FloatingFileBrowser-C3GF_u1C.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-DROn1xZ5.js.map → FloatingFileBrowser-C3GF_u1C.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingPanel-CmL_yhDv.js → FloatingPanel-Cn-q9PyJ.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingPanel-CmL_yhDv.js.map → FloatingPanel-Cn-q9PyJ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{GraphExplorerPage-DCV5ybKE.js → GraphExplorerPage-DIpqgvoU.js} +2 -2
- package/ccw/frontend/dist/assets/{GraphExplorerPage-DCV5ybKE.js.map → GraphExplorerPage-DIpqgvoU.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HistoryPage-D0fYQZgc.js → HistoryPage-DzSvEAFe.js} +2 -2
- package/ccw/frontend/dist/assets/{HistoryPage-D0fYQZgc.js.map → HistoryPage-DzSvEAFe.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HookManagerPage-D2FuJfsM.js → HookManagerPage-C6LDhWrH.js} +2 -2
- package/ccw/frontend/dist/assets/{HookManagerPage-D2FuJfsM.js.map → HookManagerPage-C6LDhWrH.js.map} +1 -1
- package/ccw/frontend/dist/assets/{InstallationsPage-tjklillZ.js → InstallationsPage-D9ct9xFV.js} +2 -2
- package/ccw/frontend/dist/assets/{InstallationsPage-tjklillZ.js.map → InstallationsPage-D9ct9xFV.js.map} +1 -1
- package/ccw/frontend/dist/assets/{IssueHubPage-E4JVrhO1.js → IssueHubPage-CXgDC8pS.js} +2 -2
- package/ccw/frontend/dist/assets/{IssueHubPage-E4JVrhO1.js.map → IssueHubPage-CXgDC8pS.js.map} +1 -1
- package/ccw/frontend/dist/assets/{LiteTasksPage-aJuRoyLt.js → LiteTasksPage-DMkauCwG.js} +2 -2
- package/ccw/frontend/dist/assets/{LiteTasksPage-aJuRoyLt.js.map → LiteTasksPage-DMkauCwG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{McpManagerPage-BJeuWJv1.js → McpManagerPage-DhLDydgc.js} +2 -2
- package/ccw/frontend/dist/assets/{McpManagerPage-BJeuWJv1.js.map → McpManagerPage-DhLDydgc.js.map} +1 -1
- package/ccw/frontend/dist/assets/{MemoryPage-BI4FAXhs.js → MemoryPage-Be3nhq40.js} +2 -2
- package/ccw/frontend/dist/assets/{MemoryPage-BI4FAXhs.js.map → MemoryPage-Be3nhq40.js.map} +1 -1
- package/ccw/frontend/dist/assets/{NotFoundPage-DD2svchp.js → NotFoundPage-0yGnCePd.js} +2 -2
- package/ccw/frontend/dist/assets/{NotFoundPage-DD2svchp.js.map → NotFoundPage-0yGnCePd.js.map} +1 -1
- package/ccw/frontend/dist/assets/{OrchestratorPage-FC__7yYa.js → OrchestratorPage-_SmXZcGl.js} +2 -2
- package/ccw/frontend/dist/assets/{OrchestratorPage-FC__7yYa.js.map → OrchestratorPage-_SmXZcGl.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-DBB_-FzV.js → ProjectOverviewPage-BeXTMsdo.js} +2 -2
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-DBB_-FzV.js.map → ProjectOverviewPage-BeXTMsdo.js.map} +1 -1
- package/ccw/frontend/dist/assets/{PromptHistoryPage-BwOAvCH8.js → PromptHistoryPage-DS6ycuAv.js} +2 -2
- package/ccw/frontend/dist/assets/{PromptHistoryPage-BwOAvCH8.js.map → PromptHistoryPage-DS6ycuAv.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ReviewSessionPage-Dd1-g_gp.js → ReviewSessionPage-BoqyjhPo.js} +2 -2
- package/ccw/frontend/dist/assets/{ReviewSessionPage-Dd1-g_gp.js.map → ReviewSessionPage-BoqyjhPo.js.map} +1 -1
- package/ccw/frontend/dist/assets/{RulesManagerPage-B3RGdsKD.js → RulesManagerPage-DMAwkKlc.js} +2 -2
- package/ccw/frontend/dist/assets/{RulesManagerPage-B3RGdsKD.js.map → RulesManagerPage-DMAwkKlc.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionDetailPage-DM-W5R8K.js → SessionDetailPage-BgJRHIF4.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionDetailPage-DM-W5R8K.js.map → SessionDetailPage-BgJRHIF4.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionsPage-BVz1KCc7.js → SessionsPage-DBPdWlji.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionsPage-BVz1KCc7.js.map → SessionsPage-DBPdWlji.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SettingsPage-ComW7EZS.js → SettingsPage-BY3QiJhm.js} +4 -4
- package/ccw/frontend/dist/assets/{SettingsPage-ComW7EZS.js.map → SettingsPage-BY3QiJhm.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SkillsManagerPage-CKom9XwV.js → SkillsManagerPage-DS101Adm.js} +2 -2
- package/ccw/frontend/dist/assets/{SkillsManagerPage-CKom9XwV.js.map → SkillsManagerPage-DS101Adm.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-DQz7WP2s.js → SpecsSettingsPage-BcsLu1qq.js} +2 -2
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-DQz7WP2s.js.map → SpecsSettingsPage-BcsLu1qq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Switch-BPMdND9H.js → Switch-BL9AmNPC.js} +2 -2
- package/ccw/frontend/dist/assets/{Switch-BPMdND9H.js.map → Switch-BL9AmNPC.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TabsNavigation-qqt70VYL.js → TabsNavigation-BUcjsLeE.js} +2 -2
- package/ccw/frontend/dist/assets/{TabsNavigation-qqt70VYL.js.map → TabsNavigation-BUcjsLeE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TaskDrawer-BqK_qiHX.js → TaskDrawer-BNvfS6dq.js} +2 -2
- package/ccw/frontend/dist/assets/{TaskDrawer-BqK_qiHX.js.map → TaskDrawer-BNvfS6dq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TeamPage-u5_i0Rgh.js → TeamPage-CT-zNCrF.js} +2 -2
- package/ccw/frontend/dist/assets/{TeamPage-u5_i0Rgh.js.map → TeamPage-CT-zNCrF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-rUtC9e40.js → TerminalDashboardPage-DfZFGs8g.js} +2 -2
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-rUtC9e40.js.map → TerminalDashboardPage-DfZFGs8g.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-C3u8YNQF.js → archive-Cev1SaQq.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-C3u8YNQF.js.map → archive-Cev1SaQq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-restore-DfQ998g5.js → archive-restore-BIVluaHZ.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-restore-DfQ998g5.js.map → archive-restore-BIVluaHZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{arrow-right-BshJM9Po.js → arrow-right-DrivbS5j.js} +2 -2
- package/ccw/frontend/dist/assets/{arrow-right-BshJM9Po.js.map → arrow-right-DrivbS5j.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bookmark-plus-D03qJyOZ.js → bookmark-plus-DKyzL0Xg.js} +2 -2
- package/ccw/frontend/dist/assets/{bookmark-plus-D03qJyOZ.js.map → bookmark-plus-DKyzL0Xg.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bot-CyzWuwq0.js → bot-GBUkPAe3.js} +2 -2
- package/ccw/frontend/dist/assets/{bot-CyzWuwq0.js.map → bot-GBUkPAe3.js.map} +1 -1
- package/ccw/frontend/dist/assets/{braces-BPgtyjsG.js → braces-BWhm2c4g.js} +2 -2
- package/ccw/frontend/dist/assets/{braces-BPgtyjsG.js.map → braces-BWhm2c4g.js.map} +1 -1
- package/ccw/frontend/dist/assets/{circle-stop-Dix1AOmw.js → circle-stop-CBcZSKNp.js} +2 -2
- package/ccw/frontend/dist/assets/{circle-stop-Dix1AOmw.js.map → circle-stop-CBcZSKNp.js.map} +1 -1
- package/ccw/frontend/dist/assets/{cpu-CCQ4Q0Zh.js → cpu-CzNmuTZD.js} +2 -2
- package/ccw/frontend/dist/assets/{cpu-CCQ4Q0Zh.js.map → cpu-CzNmuTZD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ellipsis-vertical-BpTysg-Y.js → ellipsis-vertical-BoIyQKaI.js} +2 -2
- package/ccw/frontend/dist/assets/{ellipsis-vertical-BpTysg-Y.js.map → ellipsis-vertical-BoIyQKaI.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-DGY1rAZs.js → eye-BqxyhxQq.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-DGY1rAZs.js.map → eye-BqxyhxQq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-off-D8t3JfWG.js → eye-off-D9dTZP1A.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-off-D8t3JfWG.js.map → eye-off-D9dTZP1A.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-json-BAdJb0n8.js → file-json-CLYEUI6e.js} +2 -2
- package/ccw/frontend/dist/assets/{file-json-BAdJb0n8.js.map → file-json-CLYEUI6e.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-text-DrJFiOUB.js → file-text-D5j9C5XC.js} +2 -2
- package/ccw/frontend/dist/assets/{file-text-DrJFiOUB.js.map → file-text-D5j9C5XC.js.map} +1 -1
- package/ccw/frontend/dist/assets/{filter-CKqzYbz7.js → filter-CEUK5jsA.js} +2 -2
- package/ccw/frontend/dist/assets/{filter-CKqzYbz7.js.map → filter-CEUK5jsA.js.map} +1 -1
- package/ccw/frontend/dist/assets/{folder-CV8511y9.js → folder-BEOY8txM.js} +2 -2
- package/ccw/frontend/dist/assets/{folder-CV8511y9.js.map → folder-BEOY8txM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{gauge-XKvmu_uU.js → gauge-CbumHmVn.js} +2 -2
- package/ccw/frontend/dist/assets/{gauge-XKvmu_uU.js.map → gauge-CbumHmVn.js.map} +1 -1
- package/ccw/frontend/dist/assets/{globe-C56cDUzX.js → globe-D8_IB9gV.js} +2 -2
- package/ccw/frontend/dist/assets/{globe-C56cDUzX.js.map → globe-D8_IB9gV.js.map} +1 -1
- package/ccw/frontend/dist/assets/{grid-3x3-Bya-suFW.js → grid-3x3-BpzWmYF5.js} +2 -2
- package/ccw/frontend/dist/assets/{grid-3x3-Bya-suFW.js.map → grid-3x3-BpzWmYF5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hard-drive-CmuTZpsB.js → hard-drive-QIHpGln7.js} +2 -2
- package/ccw/frontend/dist/assets/{hard-drive-CmuTZpsB.js.map → hard-drive-QIHpGln7.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hash-CRPT_tJQ.js → hash-CP0YRHVs.js} +2 -2
- package/ccw/frontend/dist/assets/{hash-CRPT_tJQ.js.map → hash-CP0YRHVs.js.map} +1 -1
- package/ccw/frontend/dist/assets/{history-C1pJZQCL.js → history-hOjgVKax.js} +2 -2
- package/ccw/frontend/dist/assets/{history-C1pJZQCL.js.map → history-hOjgVKax.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-Dmt9OiEf.js → index-B_ysvdnP.js} +2 -2
- package/ccw/frontend/dist/assets/{index-Dmt9OiEf.js.map → index-B_ysvdnP.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-dWT2M6Ef.js → index-C5Oqx2xI.js} +3 -3
- package/ccw/frontend/dist/assets/{index-dWT2M6Ef.js.map → index-C5Oqx2xI.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-CI8-rBff.js → index-CJi0bWL-.js} +2 -2
- package/ccw/frontend/dist/assets/{index-CI8-rBff.js.map → index-CJi0bWL-.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-anSMmEF8.js → index-CdQpo1x0.js} +2 -2
- package/ccw/frontend/dist/assets/{index-anSMmEF8.js.map → index-CdQpo1x0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{layout-grid-TSO0BFQE.js → layout-grid-C38fQyLs.js} +2 -2
- package/ccw/frontend/dist/assets/{layout-grid-TSO0BFQE.js.map → layout-grid-C38fQyLs.js.map} +1 -1
- package/ccw/frontend/dist/assets/{lightbulb-Caj6fIQD.js → lightbulb-CClbCUzu.js} +2 -2
- package/ccw/frontend/dist/assets/{lightbulb-Caj6fIQD.js.map → lightbulb-CClbCUzu.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-2-DE9lMxa-.js → link-2-CB-LKbI0.js} +2 -2
- package/ccw/frontend/dist/assets/{link-2-DE9lMxa-.js.map → link-2-CB-LKbI0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-BZtPgLW0.js → link-BK6SBzHS.js} +2 -2
- package/ccw/frontend/dist/assets/{link-BZtPgLW0.js.map → link-BK6SBzHS.js.map} +1 -1
- package/ccw/frontend/dist/assets/{list-DubWyY-U.js → list-BME_WOA_.js} +2 -2
- package/ccw/frontend/dist/assets/{list-DubWyY-U.js.map → list-BME_WOA_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{map-pin-DwN_48AF.js → map-pin-ADsnCyjJ.js} +2 -2
- package/ccw/frontend/dist/assets/{map-pin-DwN_48AF.js.map → map-pin-ADsnCyjJ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{messages-square-bjxvaiM9.js → messages-square-CLflB1Cq.js} +2 -2
- package/ccw/frontend/dist/assets/{messages-square-bjxvaiM9.js.map → messages-square-CLflB1Cq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{minimize-2-CGfBKD_V.js → minimize-2-B3ZNzfGr.js} +2 -2
- package/ccw/frontend/dist/assets/{minimize-2-CGfBKD_V.js.map → minimize-2-B3ZNzfGr.js.map} +1 -1
- package/ccw/frontend/dist/assets/{package-nzWY6ilt.js → package-CByPhtMG.js} +2 -2
- package/ccw/frontend/dist/assets/{package-nzWY6ilt.js.map → package-CByPhtMG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{plug-CiLce49C.js → plug-BggRzPX9.js} +2 -2
- package/ccw/frontend/dist/assets/{plug-CiLce49C.js.map → plug-BggRzPX9.js.map} +1 -1
- package/ccw/frontend/dist/assets/{power-CFLmB-U9.js → power-CWuxQSJK.js} +2 -2
- package/ccw/frontend/dist/assets/{power-CFLmB-U9.js.map → power-CWuxQSJK.js.map} +1 -1
- package/ccw/frontend/dist/assets/{save-DuO6OF0C.js → save-BdJ6EX4Q.js} +2 -2
- package/ccw/frontend/dist/assets/{save-DuO6OF0C.js.map → save-BdJ6EX4Q.js.map} +1 -1
- package/ccw/frontend/dist/assets/{send-CZk9p0mM.js → send-Ce9wuY7Q.js} +2 -2
- package/ccw/frontend/dist/assets/{send-CZk9p0mM.js.map → send-Ce9wuY7Q.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-check-big-BY_1YQQg.js → square-check-big-D6jItkfw.js} +2 -2
- package/ccw/frontend/dist/assets/{square-check-big-BY_1YQQg.js.map → square-check-big-D6jItkfw.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-pen-CnZgm6g-.js → square-pen-Byxq21zp.js} +2 -2
- package/ccw/frontend/dist/assets/{square-pen-CnZgm6g-.js.map → square-pen-Byxq21zp.js.map} +1 -1
- package/ccw/frontend/dist/assets/{star-Cn1F0qy7.js → star-Codj9dvK.js} +2 -2
- package/ccw/frontend/dist/assets/{star-Cn1F0qy7.js.map → star-Codj9dvK.js.map} +1 -1
- package/ccw/frontend/dist/assets/{style-Dxs1iXCV.js → style-4bYpUGcc.js} +2 -2
- package/ccw/frontend/dist/assets/{style-Dxs1iXCV.js.map → style-4bYpUGcc.js.map} +1 -1
- package/ccw/frontend/dist/assets/{target-Bz1fLRKH.js → target-DKBoDNCn.js} +2 -2
- package/ccw/frontend/dist/assets/{target-Bz1fLRKH.js.map → target-DKBoDNCn.js.map} +1 -1
- package/ccw/frontend/dist/assets/{test-tube-C6qCYlDr.js → test-tube-DTqZcBtA.js} +2 -2
- package/ccw/frontend/dist/assets/{test-tube-C6qCYlDr.js.map → test-tube-DTqZcBtA.js.map} +1 -1
- package/ccw/frontend/dist/assets/{upload-C71kd4Qs.js → upload-DlUl-e6b.js} +2 -2
- package/ccw/frontend/dist/assets/{upload-C71kd4Qs.js.map → upload-DlUl-e6b.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useApiSettings-CqP2BAJ7.js → useApiSettings-D4zhKKT-.js} +2 -2
- package/ccw/frontend/dist/assets/{useApiSettings-CqP2BAJ7.js.map → useApiSettings-D4zhKKT-.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCli-PCoPoVeM.js → useCli-D-qDwsAH.js} +2 -2
- package/ccw/frontend/dist/assets/{useCli-PCoPoVeM.js.map → useCli-D-qDwsAH.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCommands-3OfPQPw4.js → useCommands-B0sidbbW.js} +2 -2
- package/ccw/frontend/dist/assets/{useCommands-3OfPQPw4.js.map → useCommands-B0sidbbW.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useDebounce-bXiFhQx9.js → useDebounce-eTtbKevt.js} +2 -2
- package/ccw/frontend/dist/assets/{useDebounce-bXiFhQx9.js.map → useDebounce-eTtbKevt.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useFileExplorer-DEyUm46_.js → useFileExplorer-MGSK0h33.js} +2 -2
- package/ccw/frontend/dist/assets/{useFileExplorer-DEyUm46_.js.map → useFileExplorer-MGSK0h33.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useLocale-sXTrdxcJ.js → useLocale-DDNxU7pJ.js} +2 -2
- package/ccw/frontend/dist/assets/{useLocale-sXTrdxcJ.js.map → useLocale-DDNxU7pJ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSkills-D0W0kXYm.js → useSkills-CZCRBtMY.js} +3 -3
- package/ccw/frontend/dist/assets/{useSkills-D0W0kXYm.js.map → useSkills-CZCRBtMY.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSystemSettings-DZ-8lZsG.js → useSystemSettings-DfQEFXSD.js} +2 -2
- package/ccw/frontend/dist/assets/{useSystemSettings-DZ-8lZsG.js.map → useSystemSettings-DfQEFXSD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{wand-sparkles-83GmAYuw.js → wand-sparkles-DCLvfgl1.js} +2 -2
- package/ccw/frontend/dist/assets/{wand-sparkles-83GmAYuw.js.map → wand-sparkles-DCLvfgl1.js.map} +1 -1
- package/ccw/frontend/dist/index.html +1 -1
- package/package.json +1 -1
- package/.codex/skills/team-arch-opt/agents/completion-handler.md +0 -138
- package/.codex/skills/team-arch-opt/agents/fix-cycle-handler.md +0 -146
- package/.codex/skills/team-arch-opt/agents/plan-reviewer.md +0 -150
- package/.codex/skills/team-arch-opt/instructions/agent-instruction.md +0 -114
- package/.codex/skills/team-arch-opt/schemas/tasks-schema.md +0 -174
- package/.codex/skills/team-brainstorm/agents/gc-controller.md +0 -122
- package/.codex/skills/team-brainstorm/agents/topic-clarifier.md +0 -126
- package/.codex/skills/team-brainstorm/instructions/agent-instruction.md +0 -105
- package/.codex/skills/team-brainstorm/schemas/tasks-schema.md +0 -171
- package/.codex/skills/team-coordinate/agents/completion-handler.md +0 -127
- package/.codex/skills/team-coordinate/agents/plan-reviewer.md +0 -145
- package/.codex/skills/team-coordinate/instructions/agent-instruction.md +0 -184
- package/.codex/skills/team-coordinate/schemas/tasks-schema.md +0 -165
- package/.codex/skills/team-designer/agents/requirement-clarifier.md +0 -247
- package/.codex/skills/team-designer/agents/validation-reporter.md +0 -186
- package/.codex/skills/team-designer/instructions/agent-instruction.md +0 -163
- package/.codex/skills/team-designer/schemas/tasks-schema.md +0 -180
- package/.codex/skills/team-executor/instructions/agent-instruction.md +0 -62
- package/.codex/skills/team-executor/schemas/tasks-schema.md +0 -141
- package/.codex/skills/team-frontend/agents/completion-handler.md +0 -131
- package/.codex/skills/team-frontend/agents/qa-gate-reviewer.md +0 -153
- package/.codex/skills/team-frontend/instructions/agent-instruction.md +0 -197
- package/.codex/skills/team-frontend/schemas/tasks-schema.md +0 -188
- package/.codex/skills/team-frontend-debug/agents/completion-handler.md +0 -142
- package/.codex/skills/team-frontend-debug/agents/conditional-skip-gate.md +0 -130
- package/.codex/skills/team-frontend-debug/agents/iteration-handler.md +0 -120
- package/.codex/skills/team-frontend-debug/instructions/agent-instruction.md +0 -272
- package/.codex/skills/team-frontend-debug/schemas/tasks-schema.md +0 -198
- package/.codex/skills/team-issue/agents/reviewer.md +0 -204
- package/.codex/skills/team-issue/instructions/agent-instruction.md +0 -198
- package/.codex/skills/team-issue/schemas/tasks-schema.md +0 -198
- package/.codex/skills/team-iterdev/agents/gc-controller.md +0 -193
- package/.codex/skills/team-iterdev/agents/task-analyzer.md +0 -206
- package/.codex/skills/team-iterdev/instructions/agent-instruction.md +0 -118
- package/.codex/skills/team-iterdev/schemas/tasks-schema.md +0 -174
- package/.codex/skills/team-lifecycle/SKILL.md +0 -906
- package/.codex/skills/team-lifecycle/agents/analyst.md +0 -424
- package/.codex/skills/team-lifecycle/agents/architect.md +0 -274
- package/.codex/skills/team-lifecycle/agents/discuss-agent.md +0 -422
- package/.codex/skills/team-lifecycle/agents/executor.md +0 -423
- package/.codex/skills/team-lifecycle/agents/explore-agent.md +0 -471
- package/.codex/skills/team-lifecycle/agents/fe-developer.md +0 -239
- package/.codex/skills/team-lifecycle/agents/fe-qa.md +0 -357
- package/.codex/skills/team-lifecycle/agents/planner.md +0 -437
- package/.codex/skills/team-lifecycle/agents/reviewer.md +0 -483
- package/.codex/skills/team-lifecycle/agents/tester.md +0 -423
- package/.codex/skills/team-lifecycle/agents/writer.md +0 -502
- package/.codex/skills/team-lifecycle/phases/01-requirement-clarification.md +0 -209
- package/.codex/skills/team-lifecycle/phases/02-team-initialization.md +0 -263
- package/.codex/skills/team-lifecycle/phases/03-task-chain-creation.md +0 -251
- package/.codex/skills/team-lifecycle/phases/04-pipeline-coordination.md +0 -831
- package/.codex/skills/team-lifecycle/phases/05-completion-report.md +0 -309
- package/.codex/skills/team-lifecycle/specs/document-standards.md +0 -192
- package/.codex/skills/team-lifecycle/specs/quality-gates.md +0 -207
- package/.codex/skills/team-lifecycle-v4/agents/quality-gate.md +0 -165
- package/.codex/skills/team-lifecycle-v4/agents/requirement-clarifier.md +0 -163
- package/.codex/skills/team-lifecycle-v4/agents/supervisor.md +0 -182
- package/.codex/skills/team-perf-opt/agents/completion-handler.md +0 -141
- package/.codex/skills/team-perf-opt/agents/fix-cycle-handler.md +0 -156
- package/.codex/skills/team-perf-opt/agents/plan-reviewer.md +0 -150
- package/.codex/skills/team-perf-opt/instructions/agent-instruction.md +0 -122
- package/.codex/skills/team-perf-opt/schemas/tasks-schema.md +0 -174
- package/.codex/skills/team-planex/instructions/agent-instruction.md +0 -301
- package/.codex/skills/team-planex/schemas/tasks-schema.md +0 -198
- package/.codex/skills/team-planex-v2/SKILL.md +0 -652
- package/.codex/skills/team-planex-v2/instructions/agent-instruction.md +0 -193
- package/.codex/skills/team-planex-v2/schemas/tasks-schema.md +0 -206
- package/.codex/skills/team-quality-assurance/agents/executor.md +0 -192
- package/.codex/skills/team-quality-assurance/agents/gc-loop-handler.md +0 -163
- package/.codex/skills/team-quality-assurance/instructions/agent-instruction.md +0 -185
- package/.codex/skills/team-quality-assurance/schemas/tasks-schema.md +0 -190
- package/.codex/skills/team-review/agents/fixer.md +0 -360
- package/.codex/skills/team-review/instructions/agent-instruction.md +0 -102
- package/.codex/skills/team-review/schemas/tasks-schema.md +0 -143
- package/.codex/skills/team-roadmap-dev/agents/roadmap-discusser.md +0 -176
- package/.codex/skills/team-roadmap-dev/agents/roadmap-planner.md +0 -194
- package/.codex/skills/team-roadmap-dev/agents/roadmap-verifier.md +0 -221
- package/.codex/skills/team-roadmap-dev/instructions/executor-instruction.md +0 -55
- package/.codex/skills/team-roadmap-dev/schemas/tasks-schema.md +0 -144
- package/.codex/skills/team-tech-debt/agents/gc-loop-manager.md +0 -130
- package/.codex/skills/team-tech-debt/agents/plan-approver.md +0 -151
- package/.codex/skills/team-tech-debt/instructions/agent-instruction.md +0 -390
- package/.codex/skills/team-tech-debt/schemas/tasks-schema.md +0 -196
- package/.codex/skills/team-testing/agents/executor.md +0 -195
- package/.codex/skills/team-testing/agents/gc-loop-handler.md +0 -155
- package/.codex/skills/team-testing/instructions/agent-instruction.md +0 -142
- package/.codex/skills/team-testing/schemas/tasks-schema.md +0 -172
- package/.codex/skills/team-uidesign/agents/completion-handler.md +0 -177
- package/.codex/skills/team-uidesign/agents/gc-loop-handler.md +0 -162
- package/.codex/skills/team-uidesign/instructions/agent-instruction.md +0 -509
- package/.codex/skills/team-uidesign/schemas/tasks-schema.md +0 -187
- package/.codex/skills/team-ultra-analyze/agents/discussion-feedback.md +0 -155
- package/.codex/skills/team-ultra-analyze/agents/topic-analyzer.md +0 -153
- package/.codex/skills/team-ultra-analyze/instructions/agent-instruction.md +0 -169
- package/.codex/skills/team-ultra-analyze/schemas/tasks-schema.md +0 -180
- package/.codex/skills/team-ux-improve/agents/ux-designer.md +0 -136
- package/.codex/skills/team-ux-improve/agents/ux-explorer.md +0 -158
- package/.codex/skills/team-ux-improve/agents/ux-tester.md +0 -174
- package/.codex/skills/team-ux-improve/instructions/ux-worker-instruction.md +0 -55
- package/.codex/skills/team-ux-improve/schemas/tasks-schema.md +0 -87
- /package/.codex/skills/{team-lifecycle/templates/architecture-doc.md → team-lifecycle-v4/templates/architecture.md} +0 -0
- /package/.codex/skills/{team-lifecycle/templates/epics-template.md → team-lifecycle-v4/templates/epics.md} +0 -0
- /package/.codex/skills/{team-lifecycle → team-lifecycle-v4}/templates/product-brief.md +0 -0
- /package/.codex/skills/{team-lifecycle/templates/requirements-prd.md → team-lifecycle-v4/templates/requirements.md} +0 -0
package/ccw/frontend/dist/assets/{ReviewSessionPage-Dd1-g_gp.js → ReviewSessionPage-BoqyjhPo.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ab as xe,aG as q,cT as ue,H as he,n as ge,u as pe,r as g,j as e,e as o,J as I,K as J,B as N,C,a as F,b as Q,an as ve,aw as H,ao as K,M as G,av as fe}from"./index-dWT2M6Ef.js";import{F as X}from"./file-text-DrJFiOUB.js";function je(p){const{data:v,isLoading:i,error:d,refetch:c}=xe({queryKey:["reviewSession",p],queryFn:()=>p?ue(p):Promise.resolve(null),enabled:!!p,staleTime:6e4}),j=q.useMemo(()=>{if(!(v!=null&&v.reviewDimensions))return[];const x=[];return v.reviewDimensions.forEach(b=>{(b.findings||[]).forEach(u=>{x.push({...u,dimension:b.name})})}),x},[v]),L=q.useMemo(()=>{const x={critical:0,high:0,medium:0,low:0};return j.forEach(b=>{const u=(b.severity||"medium").toLowerCase();x[u]!==void 0&&x[u]++}),x},[j]);return{reviewSession:v,flattenedFindings:j,severityCounts:L,isLoading:i,error:d,refetch:c}}function Ne(){var V;const{sessionId:p}=he(),v=ge(),{formatMessage:i}=pe(),{reviewSession:d,flattenedFindings:c,severityCounts:j,isLoading:L,error:x,refetch:b}=je(p),[u,D]=g.useState(new Set(["critical","high","medium","low"])),[y,R]=g.useState("all"),[z,_]=g.useState(""),[A,W]=g.useState("severity"),[E,Y]=g.useState("desc"),[h,S]=g.useState(new Set),[w,Z]=g.useState(null),T=()=>{v("/sessions")},ee=s=>{D(t=>{const r=new Set(t);return r.has(s)?r.delete(s):r.add(s),r})},se=()=>{D(new Set(["critical","high","medium","low"])),R("all"),_("")},$=s=>{S(t=>{const r=new Set(t);return r.has(s)?r.delete(s):r.add(s),r})},te=()=>{const s=m.map(t=>t.id).filter(t=>t!==void 0);S(new Set(s))},ie=()=>{const s=m.map(t=>t.id).filter(t=>t!==void 0);S(new Set(s))},re=s=>{const t=c.filter(r=>r.severity===s&&r.id!==void 0).map(r=>r.id);S(r=>{const n=new Set(r);return t.forEach(a=>n.add(a)),n})},ne=()=>{S(new Set)},B=s=>{Z(s)},ae=()=>{const s=c.filter(l=>l.id!==void 0&&h.has(l.id));if(s.length===0)return;const t={session_id:p,findings:s.map(l=>({id:l.id,title:l.title,description:l.description,severity:l.severity,dimension:l.dimension,file:l.file,line:l.line,recommendations:l.recommendations}))},r=new Blob([JSON.stringify(t,null,2)],{type:"application/json"}),n=URL.createObjectURL(r),a=document.createElement("a");a.href=n,a.download=`review-${p}-fix.json`,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(n)},M={critical:4,high:3,medium:2,low:1},le=g.useMemo(()=>{const s={all:c.length};return c.forEach(t=>{s[t.dimension]=(s[t.dimension]||0)+1}),s},[c]),m=g.useMemo(()=>{let s=c;if(y!=="all"&&(s=s.filter(t=>t.dimension===y)),u.size>0&&(s=s.filter(t=>u.has(t.severity))),z){const t=z.toLowerCase();s=s.filter(r=>{var n,a;return r.title.toLowerCase().includes(t)||((n=r.description)==null?void 0:n.toLowerCase().includes(t))||((a=r.file)==null?void 0:a.toLowerCase().includes(t))||r.dimension.toLowerCase().includes(t)})}return s=[...s].sort((t,r)=>{let n=0;switch(A){case"severity":n=M[t.severity]-M[r.severity];break;case"dimension":n=t.dimension.localeCompare(r.dimension);break;case"file":n=(t.file||"").localeCompare(r.file||"");break}return E==="asc"?n:-n}),s},[c,u,y,z,A,E]),O=s=>{switch(s){case"critical":return{variant:"destructive",icon:J,label:i({id:"reviewSession.severity.critical"})};case"high":return{variant:"warning",icon:H,label:i({id:"reviewSession.severity.high"})};case"medium":return{variant:"info",icon:fe,label:i({id:"reviewSession.severity.medium"})};case"low":return{variant:"secondary",icon:G,label:i({id:"reviewSession.severity.low"})}}};if(L)return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs(o,{variant:"ghost",size:"sm",disabled:!0,children:[e.jsx(I,{className:"h-4 w-4 mr-2"}),i({id:"common.actions.back"})]}),e.jsx("div",{className:"h-8 w-64 rounded bg-muted animate-pulse"})]}),e.jsx("div",{className:"h-64 rounded-lg bg-muted animate-pulse"})]});if(x)return e.jsxs("div",{className:"flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive",children:[e.jsx(J,{className:"h-5 w-5 flex-shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium",children:i({id:"common.errors.loadFailed"})}),e.jsx("p",{className:"text-xs mt-0.5",children:x.message})]}),e.jsx(o,{variant:"outline",size:"sm",onClick:()=>b(),children:i({id:"common.actions.retry"})})]});if(!d)return e.jsxs("div",{className:"flex flex-col items-center justify-center py-16 px-4",children:[e.jsx(X,{className:"h-12 w-12 text-muted-foreground mb-4"}),e.jsx("h3",{className:"text-lg font-medium text-foreground mb-2",children:i({id:"reviewSession.notFound.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground mb-4",children:i({id:"reviewSession.notFound.message"})}),e.jsxs(o,{onClick:T,children:[e.jsx(I,{className:"h-4 w-4 mr-2"}),i({id:"common.actions.back"})]})]});const P=d.reviewDimensions||[],de=c.length,U=d._isActive!==!1,oe=U?"ACTIVE":"ARCHIVED",ce=d.phase||"in-progress";return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center justify-between",children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs(o,{variant:"ghost",size:"sm",onClick:T,children:[e.jsx(I,{className:"h-4 w-4 mr-2"}),i({id:"common.actions.back"})]}),e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-semibold text-foreground flex items-center gap-2",children:["🔍 ",d.session_id]}),e.jsxs("div",{className:"flex items-center gap-2 mt-1",children:[e.jsx(N,{variant:"review",children:"Review"}),e.jsx(N,{variant:U?"success":"secondary",className:"text-xs",children:oe})]})]})]})}),e.jsx(C,{children:e.jsxs(F,{className:"p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-lg",children:"📊"}),e.jsx("span",{className:"font-semibold",children:i({id:"reviewSession.progress.title"})})]}),e.jsx(N,{variant:"secondary",children:ce.toUpperCase()})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3",children:[e.jsxs("div",{className:"flex items-center gap-3 p-3 bg-muted rounded-lg",children:[e.jsx("span",{className:"text-2xl",children:"📊"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-lg font-bold",children:de}),e.jsx("div",{className:"text-xs text-muted-foreground",children:i({id:"reviewSession.progress.totalFindings"})})]})]}),e.jsxs("div",{className:"flex items-center gap-3 p-3 bg-red-100 dark:bg-red-900/20 rounded-lg",children:[e.jsx("span",{className:"text-2xl",children:"🔴"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-lg font-bold text-red-600 dark:text-red-400",children:j.critical}),e.jsx("div",{className:"text-xs text-muted-foreground",children:i({id:"reviewSession.progress.critical"})})]})]}),e.jsxs("div",{className:"flex items-center gap-3 p-3 bg-orange-100 dark:bg-orange-900/20 rounded-lg",children:[e.jsx("span",{className:"text-2xl",children:"🟠"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-lg font-bold text-orange-600 dark:text-orange-400",children:j.high}),e.jsx("div",{className:"text-xs text-muted-foreground",children:i({id:"reviewSession.progress.high"})})]})]}),e.jsxs("div",{className:"flex items-center gap-3 p-3 bg-blue-100 dark:bg-blue-900/20 rounded-lg",children:[e.jsx("span",{className:"text-2xl",children:"🎯"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-lg font-bold text-blue-600 dark:text-blue-400",children:P.length}),e.jsx("div",{className:"text-xs text-muted-foreground",children:i({id:"reviewSession.stats.dimensions"})})]})]})]})]})}),e.jsx(C,{children:e.jsxs(F,{className:"p-4 space-y-4",children:[e.jsxs("div",{className:"flex flex-wrap gap-3 items-center",children:[e.jsxs("div",{className:"relative flex-1 min-w-[180px] max-w-md",children:[e.jsx(Q,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"}),e.jsx("input",{type:"text",placeholder:i({id:"reviewSession.search.placeholder"}),value:z,onChange:s=>_(s.target.value),className:"w-full pl-10 pr-4 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"})]}),e.jsxs("select",{value:A,onChange:s=>W(s.target.value),className:"px-3 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-primary",children:[e.jsx("option",{value:"severity",children:i({id:"reviewSession.sort.severity"})}),e.jsx("option",{value:"dimension",children:i({id:"reviewSession.sort.dimension"})}),e.jsx("option",{value:"file",children:i({id:"reviewSession.sort.file"})})]}),e.jsx(o,{variant:"outline",size:"sm",onClick:()=>Y(E==="asc"?"desc":"asc"),className:"w-9 p-0",children:E==="asc"?"↑":"↓"}),e.jsxs(o,{variant:"ghost",size:"sm",onClick:se,className:"text-muted-foreground hover:text-foreground",children:["✕ ",i({id:"reviewSession.filters.reset"})]})]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-4",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"text-xs font-medium text-muted-foreground mb-2",children:i({id:"reviewSession.filters.dimension"})}),e.jsxs("div",{className:"flex gap-1.5 overflow-x-auto pb-1 scrollbar-thin",children:[e.jsxs("button",{className:`px-3 py-1.5 rounded-md text-xs font-medium whitespace-nowrap transition-colors ${y==="all"?"bg-primary text-primary-foreground shadow-sm":"bg-muted/50 text-muted-foreground hover:bg-muted"}`,onClick:()=>R("all"),children:["All (",le.all||0,")"]}),P.map(s=>{var t;return e.jsxs("button",{className:`px-3 py-1.5 rounded-md text-xs font-medium whitespace-nowrap transition-colors ${y===s.name?"bg-primary text-primary-foreground shadow-sm":"bg-muted/50 text-muted-foreground hover:bg-muted"}`,onClick:()=>R(s.name),children:[s.name," (",((t=s.findings)==null?void 0:t.length)||0,")"]},s.name)})]})]}),e.jsxs("div",{className:"sm:w-auto",children:[e.jsx("div",{className:"text-xs font-medium text-muted-foreground mb-2",children:i({id:"reviewSession.filters.severity"})}),e.jsx("div",{className:"flex gap-1.5 flex-wrap",children:["critical","high","medium","low"].map(s=>{const t=u.has(s),r={critical:t?"bg-red-500 text-white border-red-500":"bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 border-red-200 dark:border-red-800",high:t?"bg-orange-500 text-white border-orange-500":"bg-orange-50 dark:bg-orange-900/20 text-orange-600 dark:text-orange-400 border-orange-200 dark:border-orange-800",medium:t?"bg-blue-500 text-white border-blue-500":"bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 border-blue-200 dark:border-blue-800",low:t?"bg-gray-500 text-white border-gray-500":"bg-gray-50 dark:bg-gray-900/20 text-gray-600 dark:text-gray-400 border-gray-200 dark:border-gray-800"};return e.jsxs("label",{className:`inline-flex items-center gap-1 px-2.5 py-1 rounded-md border text-xs font-medium cursor-pointer transition-all ${r[s]} ${t?"shadow-sm":"hover:opacity-80"}`,children:[e.jsx("input",{type:"checkbox",checked:t,onChange:()=>ee(s),className:"sr-only"}),e.jsx("span",{children:i({id:`reviewSession.severity.short.${s}`})}),e.jsxs("span",{className:"opacity-70",children:["(",c.filter(n=>n.severity===s).length,")"]})]},s)})})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 pt-3 border-t border-border",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"text-xs text-muted-foreground px-2 py-1 bg-muted rounded-md",children:h.size>0?i({id:"reviewSession.selection.countSelected"},{count:h.size}):i({id:"reviewSession.selection.total"},{count:m.length})}),h.size>0&&e.jsxs(e.Fragment,{children:[e.jsx(o,{variant:"outline",size:"sm",onClick:ne,className:"h-8 text-xs",children:i({id:"reviewSession.selection.clear"})}),e.jsxs(o,{variant:"outline",size:"sm",onClick:()=>re("critical"),className:"h-8 text-xs",children:["🔥 ",i({id:"reviewSession.selection.selectCritical"})]}),e.jsx(o,{variant:"outline",size:"sm",onClick:ie,className:"h-8 text-xs",children:i({id:"reviewSession.selection.selectVisible"})})]}),h.size===0&&e.jsx(o,{variant:"outline",size:"sm",onClick:te,className:"h-8 text-xs",children:i({id:"reviewSession.selection.selectAll"})})]}),e.jsxs(o,{variant:h.size>0?"default":"outline",size:"sm",onClick:ae,disabled:h.size===0,className:"h-8 gap-1.5 text-xs",children:[e.jsx(ve,{className:"h-3.5 w-3.5"}),"🔧 ",i({id:"reviewSession.export"})]})]})]})}),m.length===0?e.jsx(C,{children:e.jsx(F,{className:"p-12 text-center",children:((V=d==null?void 0:d.reviewSummary)==null?void 0:V.status)==="in_progress"&&(!(d!=null&&d.reviewDimensions)||d.reviewDimensions.length===0)?e.jsxs(e.Fragment,{children:[e.jsx(H,{className:"h-12 w-12 text-amber-500 mx-auto mb-4"}),e.jsx("h3",{className:"text-lg font-medium text-foreground mb-2",children:i({id:"reviewSession.notExecuted.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground mb-4",children:i({id:"reviewSession.notExecuted.message"})}),e.jsx("div",{className:"text-xs text-muted-foreground bg-muted p-3 rounded-lg inline-block",children:i({id:"reviewSession.notExecuted.hint"})})]}):e.jsxs(e.Fragment,{children:[e.jsx(X,{className:"h-12 w-12 text-muted-foreground mx-auto mb-4"}),e.jsx("h3",{className:"text-lg font-medium text-foreground mb-2",children:i({id:"reviewSession.empty.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground",children:i({id:"reviewSession.empty.message"})})]})})}):e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-[minmax(0,45fr)_minmax(0,55fr)] gap-4",children:[e.jsx(C,{children:e.jsxs(F,{className:"p-4",children:[e.jsx("div",{className:"flex items-center justify-between mb-3",children:e.jsx("span",{className:"text-sm font-medium",children:i({id:"reviewSession.findingsList.count"},{count:m.length})})}),e.jsx("div",{className:"space-y-2 max-h-[600px] overflow-y-auto",children:m.filter(s=>s.id!==void 0).map(s=>{const t=s.id,r=h.has(t),n=w===t,a=O(s.severity),l=a.icon;return e.jsx("div",{className:`p-3 rounded-lg border cursor-pointer transition-colors ${n?"bg-primary/10 border-primary":"bg-background border-border hover:bg-muted"}`,onClick:()=>B(t),children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx("input",{type:"checkbox",checked:r,onChange:k=>{k.stopPropagation(),$(t)},className:"mt-0.5 flex-shrink-0"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5 mb-1 flex-wrap",children:[e.jsxs(N,{variant:a.variant,className:"gap-1 text-xs",children:[e.jsx(l,{className:"h-2.5 w-2.5"}),a.label]}),e.jsx("span",{className:"text-xs text-muted-foreground",children:s.dimension})]}),e.jsx("p",{className:"text-sm font-medium text-foreground truncate",children:s.title}),s.file&&e.jsxs("p",{className:"text-xs text-muted-foreground font-mono truncate mt-0.5",children:[s.file,":",s.line||"?"]})]})]})},t)})})]})}),e.jsx(C,{className:"sticky top-4 self-start",children:e.jsx(F,{className:"p-0 h-full min-h-[500px]",children:w?(()=>{const s=c.find(f=>f.id===w);if(!s)return null;const t=O(s.severity),r=t.icon,n=h.has(w),a=m.findIndex(f=>f.id===w),l=a>0?m[a-1]:null,k=a<m.length-1?m[a+1]:null;return e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"sticky top-0 z-10 bg-background border-b border-border p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(o,{variant:"ghost",size:"sm",onClick:()=>l&&B(l.id),disabled:!l,className:"h-8 w-8 p-0",children:e.jsx(K,{className:"h-4 w-4 rotate-180"})}),e.jsxs("span",{className:"text-xs text-muted-foreground px-2",children:[a+1," / ",m.length]}),e.jsx(o,{variant:"ghost",size:"sm",onClick:()=>k&&B(k.id),disabled:!k,className:"h-8 w-8 p-0",children:e.jsx(K,{className:"h-4 w-4"})})]}),e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[e.jsxs(N,{variant:t.variant,className:"gap-1 text-xs",children:[e.jsx(r,{className:"h-3 w-3"}),t.label]}),e.jsx(N,{variant:"outline",className:"text-xs",children:s.dimension})]}),e.jsx(o,{variant:n?"default":"outline",size:"sm",onClick:f=>{f.stopPropagation(),$(w)},className:"h-8 text-xs",children:n?e.jsxs(e.Fragment,{children:[e.jsx(G,{className:"h-3.5 w-3.5 mr-1"}),i({id:"reviewSession.preview.selected"})]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"mr-1",children:"⊕"}),i({id:"reviewSession.preview.selectForFix"})]})})]}),e.jsx("h3",{className:"text-base font-semibold text-foreground line-clamp-2",children:s.title}),e.jsx("div",{className:"flex items-center gap-3 text-xs",children:s.file&&e.jsxs("div",{className:"flex items-center gap-1 text-muted-foreground flex-1 min-w-0",children:[e.jsx("span",{className:"flex-shrink-0",children:"📁"}),e.jsxs("code",{className:"truncate",children:[s.file,":",s.line||"?"]})]})})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-4 space-y-4",children:[s.description&&e.jsxs("div",{className:"bg-muted/30 rounded-lg p-3",children:[e.jsxs("div",{className:"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5",children:[e.jsx("span",{children:"📝"}),i({id:"reviewSession.preview.description"})]}),e.jsx("p",{className:"text-sm text-foreground leading-relaxed",children:s.description})]}),s.code_context&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5",children:[e.jsx("span",{children:"💻"}),i({id:"reviewSession.preview.codeContext"})]}),e.jsx("pre",{className:"text-xs bg-muted p-3 rounded-lg overflow-x-auto border border-border",children:e.jsx("code",{className:"text-foreground",children:s.code_context})})]}),s.root_cause&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5",children:[e.jsx("span",{children:"🎯"}),i({id:"reviewSession.preview.rootCause"})]}),e.jsx("p",{className:"text-sm text-foreground bg-muted/30 rounded-lg p-3 leading-relaxed",children:s.root_cause})]}),s.impact&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5",children:[e.jsx("span",{children:"⚠️"}),i({id:"reviewSession.preview.impact"})]}),e.jsx("p",{className:"text-sm text-foreground bg-orange-50 dark:bg-orange-900/20 rounded-lg p-3 leading-relaxed border border-orange-200 dark:border-orange-800",children:s.impact})]}),s.recommendations&&s.recommendations.length>0&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5",children:[e.jsx("span",{children:"✅"}),i({id:"reviewSession.preview.recommendations"})]}),e.jsx("ul",{className:"space-y-2",children:s.recommendations.map((f,me)=>e.jsxs("li",{className:"text-sm text-foreground flex items-start gap-2 bg-green-50 dark:bg-green-900/20 rounded-lg p-3 border border-green-200 dark:border-green-800",children:[e.jsx("span",{className:"text-green-600 dark:text-green-400 flex-shrink-0 mt-0.5",children:"✓"}),e.jsx("span",{className:"leading-relaxed",children:f})]},me))})]})]})]})})():e.jsxs("div",{className:"flex flex-col items-center justify-center h-full min-h-[400px] p-8 text-center bg-gradient-to-br from-muted/30 to-muted/10",children:[e.jsx("div",{className:"w-20 h-20 rounded-full bg-muted flex items-center justify-center mb-4",children:e.jsx(Q,{className:"h-10 w-10 text-muted-foreground"})}),e.jsx("h3",{className:"text-base font-semibold text-foreground mb-2",children:i({id:"reviewSession.preview.emptyTitle"})}),e.jsx("p",{className:"text-sm text-muted-foreground mb-4 max-w-[250px]",children:i({id:"reviewSession.preview.empty"})}),e.jsxs("div",{className:"flex flex-wrap gap-2 justify-center",children:[e.jsxs("div",{className:"flex items-center gap-1.5 px-3 py-1.5 bg-background rounded-lg border text-xs",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-destructive"}),i({id:"reviewSession.preview.emptyTipSeverity"})]}),e.jsxs("div",{className:"flex items-center gap-1.5 px-3 py-1.5 bg-background rounded-lg border text-xs",children:[e.jsx("span",{children:"📁"}),i({id:"reviewSession.preview.emptyTipFile"})]})]})]})})})]})]})}export{Ne as ReviewSessionPage,Ne as default};
|
|
2
|
-
//# sourceMappingURL=ReviewSessionPage-
|
|
1
|
+
import{ab as xe,aG as q,cT as ue,H as he,n as ge,u as pe,r as g,j as e,e as o,J as I,K as J,B as N,C,a as F,b as Q,an as ve,aw as H,ao as K,M as G,av as fe}from"./index-C5Oqx2xI.js";import{F as X}from"./file-text-D5j9C5XC.js";function je(p){const{data:v,isLoading:i,error:d,refetch:c}=xe({queryKey:["reviewSession",p],queryFn:()=>p?ue(p):Promise.resolve(null),enabled:!!p,staleTime:6e4}),j=q.useMemo(()=>{if(!(v!=null&&v.reviewDimensions))return[];const x=[];return v.reviewDimensions.forEach(b=>{(b.findings||[]).forEach(u=>{x.push({...u,dimension:b.name})})}),x},[v]),L=q.useMemo(()=>{const x={critical:0,high:0,medium:0,low:0};return j.forEach(b=>{const u=(b.severity||"medium").toLowerCase();x[u]!==void 0&&x[u]++}),x},[j]);return{reviewSession:v,flattenedFindings:j,severityCounts:L,isLoading:i,error:d,refetch:c}}function Ne(){var V;const{sessionId:p}=he(),v=ge(),{formatMessage:i}=pe(),{reviewSession:d,flattenedFindings:c,severityCounts:j,isLoading:L,error:x,refetch:b}=je(p),[u,D]=g.useState(new Set(["critical","high","medium","low"])),[y,R]=g.useState("all"),[z,_]=g.useState(""),[A,W]=g.useState("severity"),[E,Y]=g.useState("desc"),[h,S]=g.useState(new Set),[w,Z]=g.useState(null),T=()=>{v("/sessions")},ee=s=>{D(t=>{const r=new Set(t);return r.has(s)?r.delete(s):r.add(s),r})},se=()=>{D(new Set(["critical","high","medium","low"])),R("all"),_("")},$=s=>{S(t=>{const r=new Set(t);return r.has(s)?r.delete(s):r.add(s),r})},te=()=>{const s=m.map(t=>t.id).filter(t=>t!==void 0);S(new Set(s))},ie=()=>{const s=m.map(t=>t.id).filter(t=>t!==void 0);S(new Set(s))},re=s=>{const t=c.filter(r=>r.severity===s&&r.id!==void 0).map(r=>r.id);S(r=>{const n=new Set(r);return t.forEach(a=>n.add(a)),n})},ne=()=>{S(new Set)},B=s=>{Z(s)},ae=()=>{const s=c.filter(l=>l.id!==void 0&&h.has(l.id));if(s.length===0)return;const t={session_id:p,findings:s.map(l=>({id:l.id,title:l.title,description:l.description,severity:l.severity,dimension:l.dimension,file:l.file,line:l.line,recommendations:l.recommendations}))},r=new Blob([JSON.stringify(t,null,2)],{type:"application/json"}),n=URL.createObjectURL(r),a=document.createElement("a");a.href=n,a.download=`review-${p}-fix.json`,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(n)},M={critical:4,high:3,medium:2,low:1},le=g.useMemo(()=>{const s={all:c.length};return c.forEach(t=>{s[t.dimension]=(s[t.dimension]||0)+1}),s},[c]),m=g.useMemo(()=>{let s=c;if(y!=="all"&&(s=s.filter(t=>t.dimension===y)),u.size>0&&(s=s.filter(t=>u.has(t.severity))),z){const t=z.toLowerCase();s=s.filter(r=>{var n,a;return r.title.toLowerCase().includes(t)||((n=r.description)==null?void 0:n.toLowerCase().includes(t))||((a=r.file)==null?void 0:a.toLowerCase().includes(t))||r.dimension.toLowerCase().includes(t)})}return s=[...s].sort((t,r)=>{let n=0;switch(A){case"severity":n=M[t.severity]-M[r.severity];break;case"dimension":n=t.dimension.localeCompare(r.dimension);break;case"file":n=(t.file||"").localeCompare(r.file||"");break}return E==="asc"?n:-n}),s},[c,u,y,z,A,E]),O=s=>{switch(s){case"critical":return{variant:"destructive",icon:J,label:i({id:"reviewSession.severity.critical"})};case"high":return{variant:"warning",icon:H,label:i({id:"reviewSession.severity.high"})};case"medium":return{variant:"info",icon:fe,label:i({id:"reviewSession.severity.medium"})};case"low":return{variant:"secondary",icon:G,label:i({id:"reviewSession.severity.low"})}}};if(L)return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs(o,{variant:"ghost",size:"sm",disabled:!0,children:[e.jsx(I,{className:"h-4 w-4 mr-2"}),i({id:"common.actions.back"})]}),e.jsx("div",{className:"h-8 w-64 rounded bg-muted animate-pulse"})]}),e.jsx("div",{className:"h-64 rounded-lg bg-muted animate-pulse"})]});if(x)return e.jsxs("div",{className:"flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive",children:[e.jsx(J,{className:"h-5 w-5 flex-shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium",children:i({id:"common.errors.loadFailed"})}),e.jsx("p",{className:"text-xs mt-0.5",children:x.message})]}),e.jsx(o,{variant:"outline",size:"sm",onClick:()=>b(),children:i({id:"common.actions.retry"})})]});if(!d)return e.jsxs("div",{className:"flex flex-col items-center justify-center py-16 px-4",children:[e.jsx(X,{className:"h-12 w-12 text-muted-foreground mb-4"}),e.jsx("h3",{className:"text-lg font-medium text-foreground mb-2",children:i({id:"reviewSession.notFound.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground mb-4",children:i({id:"reviewSession.notFound.message"})}),e.jsxs(o,{onClick:T,children:[e.jsx(I,{className:"h-4 w-4 mr-2"}),i({id:"common.actions.back"})]})]});const P=d.reviewDimensions||[],de=c.length,U=d._isActive!==!1,oe=U?"ACTIVE":"ARCHIVED",ce=d.phase||"in-progress";return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center justify-between",children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs(o,{variant:"ghost",size:"sm",onClick:T,children:[e.jsx(I,{className:"h-4 w-4 mr-2"}),i({id:"common.actions.back"})]}),e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-semibold text-foreground flex items-center gap-2",children:["🔍 ",d.session_id]}),e.jsxs("div",{className:"flex items-center gap-2 mt-1",children:[e.jsx(N,{variant:"review",children:"Review"}),e.jsx(N,{variant:U?"success":"secondary",className:"text-xs",children:oe})]})]})]})}),e.jsx(C,{children:e.jsxs(F,{className:"p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-lg",children:"📊"}),e.jsx("span",{className:"font-semibold",children:i({id:"reviewSession.progress.title"})})]}),e.jsx(N,{variant:"secondary",children:ce.toUpperCase()})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3",children:[e.jsxs("div",{className:"flex items-center gap-3 p-3 bg-muted rounded-lg",children:[e.jsx("span",{className:"text-2xl",children:"📊"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-lg font-bold",children:de}),e.jsx("div",{className:"text-xs text-muted-foreground",children:i({id:"reviewSession.progress.totalFindings"})})]})]}),e.jsxs("div",{className:"flex items-center gap-3 p-3 bg-red-100 dark:bg-red-900/20 rounded-lg",children:[e.jsx("span",{className:"text-2xl",children:"🔴"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-lg font-bold text-red-600 dark:text-red-400",children:j.critical}),e.jsx("div",{className:"text-xs text-muted-foreground",children:i({id:"reviewSession.progress.critical"})})]})]}),e.jsxs("div",{className:"flex items-center gap-3 p-3 bg-orange-100 dark:bg-orange-900/20 rounded-lg",children:[e.jsx("span",{className:"text-2xl",children:"🟠"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-lg font-bold text-orange-600 dark:text-orange-400",children:j.high}),e.jsx("div",{className:"text-xs text-muted-foreground",children:i({id:"reviewSession.progress.high"})})]})]}),e.jsxs("div",{className:"flex items-center gap-3 p-3 bg-blue-100 dark:bg-blue-900/20 rounded-lg",children:[e.jsx("span",{className:"text-2xl",children:"🎯"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-lg font-bold text-blue-600 dark:text-blue-400",children:P.length}),e.jsx("div",{className:"text-xs text-muted-foreground",children:i({id:"reviewSession.stats.dimensions"})})]})]})]})]})}),e.jsx(C,{children:e.jsxs(F,{className:"p-4 space-y-4",children:[e.jsxs("div",{className:"flex flex-wrap gap-3 items-center",children:[e.jsxs("div",{className:"relative flex-1 min-w-[180px] max-w-md",children:[e.jsx(Q,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"}),e.jsx("input",{type:"text",placeholder:i({id:"reviewSession.search.placeholder"}),value:z,onChange:s=>_(s.target.value),className:"w-full pl-10 pr-4 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"})]}),e.jsxs("select",{value:A,onChange:s=>W(s.target.value),className:"px-3 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-primary",children:[e.jsx("option",{value:"severity",children:i({id:"reviewSession.sort.severity"})}),e.jsx("option",{value:"dimension",children:i({id:"reviewSession.sort.dimension"})}),e.jsx("option",{value:"file",children:i({id:"reviewSession.sort.file"})})]}),e.jsx(o,{variant:"outline",size:"sm",onClick:()=>Y(E==="asc"?"desc":"asc"),className:"w-9 p-0",children:E==="asc"?"↑":"↓"}),e.jsxs(o,{variant:"ghost",size:"sm",onClick:se,className:"text-muted-foreground hover:text-foreground",children:["✕ ",i({id:"reviewSession.filters.reset"})]})]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-4",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"text-xs font-medium text-muted-foreground mb-2",children:i({id:"reviewSession.filters.dimension"})}),e.jsxs("div",{className:"flex gap-1.5 overflow-x-auto pb-1 scrollbar-thin",children:[e.jsxs("button",{className:`px-3 py-1.5 rounded-md text-xs font-medium whitespace-nowrap transition-colors ${y==="all"?"bg-primary text-primary-foreground shadow-sm":"bg-muted/50 text-muted-foreground hover:bg-muted"}`,onClick:()=>R("all"),children:["All (",le.all||0,")"]}),P.map(s=>{var t;return e.jsxs("button",{className:`px-3 py-1.5 rounded-md text-xs font-medium whitespace-nowrap transition-colors ${y===s.name?"bg-primary text-primary-foreground shadow-sm":"bg-muted/50 text-muted-foreground hover:bg-muted"}`,onClick:()=>R(s.name),children:[s.name," (",((t=s.findings)==null?void 0:t.length)||0,")"]},s.name)})]})]}),e.jsxs("div",{className:"sm:w-auto",children:[e.jsx("div",{className:"text-xs font-medium text-muted-foreground mb-2",children:i({id:"reviewSession.filters.severity"})}),e.jsx("div",{className:"flex gap-1.5 flex-wrap",children:["critical","high","medium","low"].map(s=>{const t=u.has(s),r={critical:t?"bg-red-500 text-white border-red-500":"bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 border-red-200 dark:border-red-800",high:t?"bg-orange-500 text-white border-orange-500":"bg-orange-50 dark:bg-orange-900/20 text-orange-600 dark:text-orange-400 border-orange-200 dark:border-orange-800",medium:t?"bg-blue-500 text-white border-blue-500":"bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 border-blue-200 dark:border-blue-800",low:t?"bg-gray-500 text-white border-gray-500":"bg-gray-50 dark:bg-gray-900/20 text-gray-600 dark:text-gray-400 border-gray-200 dark:border-gray-800"};return e.jsxs("label",{className:`inline-flex items-center gap-1 px-2.5 py-1 rounded-md border text-xs font-medium cursor-pointer transition-all ${r[s]} ${t?"shadow-sm":"hover:opacity-80"}`,children:[e.jsx("input",{type:"checkbox",checked:t,onChange:()=>ee(s),className:"sr-only"}),e.jsx("span",{children:i({id:`reviewSession.severity.short.${s}`})}),e.jsxs("span",{className:"opacity-70",children:["(",c.filter(n=>n.severity===s).length,")"]})]},s)})})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 pt-3 border-t border-border",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"text-xs text-muted-foreground px-2 py-1 bg-muted rounded-md",children:h.size>0?i({id:"reviewSession.selection.countSelected"},{count:h.size}):i({id:"reviewSession.selection.total"},{count:m.length})}),h.size>0&&e.jsxs(e.Fragment,{children:[e.jsx(o,{variant:"outline",size:"sm",onClick:ne,className:"h-8 text-xs",children:i({id:"reviewSession.selection.clear"})}),e.jsxs(o,{variant:"outline",size:"sm",onClick:()=>re("critical"),className:"h-8 text-xs",children:["🔥 ",i({id:"reviewSession.selection.selectCritical"})]}),e.jsx(o,{variant:"outline",size:"sm",onClick:ie,className:"h-8 text-xs",children:i({id:"reviewSession.selection.selectVisible"})})]}),h.size===0&&e.jsx(o,{variant:"outline",size:"sm",onClick:te,className:"h-8 text-xs",children:i({id:"reviewSession.selection.selectAll"})})]}),e.jsxs(o,{variant:h.size>0?"default":"outline",size:"sm",onClick:ae,disabled:h.size===0,className:"h-8 gap-1.5 text-xs",children:[e.jsx(ve,{className:"h-3.5 w-3.5"}),"🔧 ",i({id:"reviewSession.export"})]})]})]})}),m.length===0?e.jsx(C,{children:e.jsx(F,{className:"p-12 text-center",children:((V=d==null?void 0:d.reviewSummary)==null?void 0:V.status)==="in_progress"&&(!(d!=null&&d.reviewDimensions)||d.reviewDimensions.length===0)?e.jsxs(e.Fragment,{children:[e.jsx(H,{className:"h-12 w-12 text-amber-500 mx-auto mb-4"}),e.jsx("h3",{className:"text-lg font-medium text-foreground mb-2",children:i({id:"reviewSession.notExecuted.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground mb-4",children:i({id:"reviewSession.notExecuted.message"})}),e.jsx("div",{className:"text-xs text-muted-foreground bg-muted p-3 rounded-lg inline-block",children:i({id:"reviewSession.notExecuted.hint"})})]}):e.jsxs(e.Fragment,{children:[e.jsx(X,{className:"h-12 w-12 text-muted-foreground mx-auto mb-4"}),e.jsx("h3",{className:"text-lg font-medium text-foreground mb-2",children:i({id:"reviewSession.empty.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground",children:i({id:"reviewSession.empty.message"})})]})})}):e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-[minmax(0,45fr)_minmax(0,55fr)] gap-4",children:[e.jsx(C,{children:e.jsxs(F,{className:"p-4",children:[e.jsx("div",{className:"flex items-center justify-between mb-3",children:e.jsx("span",{className:"text-sm font-medium",children:i({id:"reviewSession.findingsList.count"},{count:m.length})})}),e.jsx("div",{className:"space-y-2 max-h-[600px] overflow-y-auto",children:m.filter(s=>s.id!==void 0).map(s=>{const t=s.id,r=h.has(t),n=w===t,a=O(s.severity),l=a.icon;return e.jsx("div",{className:`p-3 rounded-lg border cursor-pointer transition-colors ${n?"bg-primary/10 border-primary":"bg-background border-border hover:bg-muted"}`,onClick:()=>B(t),children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx("input",{type:"checkbox",checked:r,onChange:k=>{k.stopPropagation(),$(t)},className:"mt-0.5 flex-shrink-0"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5 mb-1 flex-wrap",children:[e.jsxs(N,{variant:a.variant,className:"gap-1 text-xs",children:[e.jsx(l,{className:"h-2.5 w-2.5"}),a.label]}),e.jsx("span",{className:"text-xs text-muted-foreground",children:s.dimension})]}),e.jsx("p",{className:"text-sm font-medium text-foreground truncate",children:s.title}),s.file&&e.jsxs("p",{className:"text-xs text-muted-foreground font-mono truncate mt-0.5",children:[s.file,":",s.line||"?"]})]})]})},t)})})]})}),e.jsx(C,{className:"sticky top-4 self-start",children:e.jsx(F,{className:"p-0 h-full min-h-[500px]",children:w?(()=>{const s=c.find(f=>f.id===w);if(!s)return null;const t=O(s.severity),r=t.icon,n=h.has(w),a=m.findIndex(f=>f.id===w),l=a>0?m[a-1]:null,k=a<m.length-1?m[a+1]:null;return e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"sticky top-0 z-10 bg-background border-b border-border p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(o,{variant:"ghost",size:"sm",onClick:()=>l&&B(l.id),disabled:!l,className:"h-8 w-8 p-0",children:e.jsx(K,{className:"h-4 w-4 rotate-180"})}),e.jsxs("span",{className:"text-xs text-muted-foreground px-2",children:[a+1," / ",m.length]}),e.jsx(o,{variant:"ghost",size:"sm",onClick:()=>k&&B(k.id),disabled:!k,className:"h-8 w-8 p-0",children:e.jsx(K,{className:"h-4 w-4"})})]}),e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[e.jsxs(N,{variant:t.variant,className:"gap-1 text-xs",children:[e.jsx(r,{className:"h-3 w-3"}),t.label]}),e.jsx(N,{variant:"outline",className:"text-xs",children:s.dimension})]}),e.jsx(o,{variant:n?"default":"outline",size:"sm",onClick:f=>{f.stopPropagation(),$(w)},className:"h-8 text-xs",children:n?e.jsxs(e.Fragment,{children:[e.jsx(G,{className:"h-3.5 w-3.5 mr-1"}),i({id:"reviewSession.preview.selected"})]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"mr-1",children:"⊕"}),i({id:"reviewSession.preview.selectForFix"})]})})]}),e.jsx("h3",{className:"text-base font-semibold text-foreground line-clamp-2",children:s.title}),e.jsx("div",{className:"flex items-center gap-3 text-xs",children:s.file&&e.jsxs("div",{className:"flex items-center gap-1 text-muted-foreground flex-1 min-w-0",children:[e.jsx("span",{className:"flex-shrink-0",children:"📁"}),e.jsxs("code",{className:"truncate",children:[s.file,":",s.line||"?"]})]})})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-4 space-y-4",children:[s.description&&e.jsxs("div",{className:"bg-muted/30 rounded-lg p-3",children:[e.jsxs("div",{className:"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5",children:[e.jsx("span",{children:"📝"}),i({id:"reviewSession.preview.description"})]}),e.jsx("p",{className:"text-sm text-foreground leading-relaxed",children:s.description})]}),s.code_context&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5",children:[e.jsx("span",{children:"💻"}),i({id:"reviewSession.preview.codeContext"})]}),e.jsx("pre",{className:"text-xs bg-muted p-3 rounded-lg overflow-x-auto border border-border",children:e.jsx("code",{className:"text-foreground",children:s.code_context})})]}),s.root_cause&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5",children:[e.jsx("span",{children:"🎯"}),i({id:"reviewSession.preview.rootCause"})]}),e.jsx("p",{className:"text-sm text-foreground bg-muted/30 rounded-lg p-3 leading-relaxed",children:s.root_cause})]}),s.impact&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5",children:[e.jsx("span",{children:"⚠️"}),i({id:"reviewSession.preview.impact"})]}),e.jsx("p",{className:"text-sm text-foreground bg-orange-50 dark:bg-orange-900/20 rounded-lg p-3 leading-relaxed border border-orange-200 dark:border-orange-800",children:s.impact})]}),s.recommendations&&s.recommendations.length>0&&e.jsxs("div",{children:[e.jsxs("div",{className:"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5",children:[e.jsx("span",{children:"✅"}),i({id:"reviewSession.preview.recommendations"})]}),e.jsx("ul",{className:"space-y-2",children:s.recommendations.map((f,me)=>e.jsxs("li",{className:"text-sm text-foreground flex items-start gap-2 bg-green-50 dark:bg-green-900/20 rounded-lg p-3 border border-green-200 dark:border-green-800",children:[e.jsx("span",{className:"text-green-600 dark:text-green-400 flex-shrink-0 mt-0.5",children:"✓"}),e.jsx("span",{className:"leading-relaxed",children:f})]},me))})]})]})]})})():e.jsxs("div",{className:"flex flex-col items-center justify-center h-full min-h-[400px] p-8 text-center bg-gradient-to-br from-muted/30 to-muted/10",children:[e.jsx("div",{className:"w-20 h-20 rounded-full bg-muted flex items-center justify-center mb-4",children:e.jsx(Q,{className:"h-10 w-10 text-muted-foreground"})}),e.jsx("h3",{className:"text-base font-semibold text-foreground mb-2",children:i({id:"reviewSession.preview.emptyTitle"})}),e.jsx("p",{className:"text-sm text-muted-foreground mb-4 max-w-[250px]",children:i({id:"reviewSession.preview.empty"})}),e.jsxs("div",{className:"flex flex-wrap gap-2 justify-center",children:[e.jsxs("div",{className:"flex items-center gap-1.5 px-3 py-1.5 bg-background rounded-lg border text-xs",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-destructive"}),i({id:"reviewSession.preview.emptyTipSeverity"})]}),e.jsxs("div",{className:"flex items-center gap-1.5 px-3 py-1.5 bg-background rounded-lg border text-xs",children:[e.jsx("span",{children:"📁"}),i({id:"reviewSession.preview.emptyTipFile"})]})]})]})})})]})]})}export{Ne as ReviewSessionPage,Ne as default};
|
|
2
|
+
//# sourceMappingURL=ReviewSessionPage-BoqyjhPo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReviewSessionPage-Dd1-g_gp.js","sources":["../../src/hooks/useReviewSession.ts","../../src/pages/ReviewSessionPage.tsx"],"sourcesContent":["// ========================================\r\n// useReviewSession Hook\r\n// ========================================\r\n// Custom hook for fetching and managing review session data\r\n\r\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\r\nimport { fetchReviewSessions, fetchReviewSession, type ReviewSession, type ReviewFinding } from '@/lib/api';\r\n\r\ninterface UseReviewSessionsOptions {\r\n enabled?: boolean;\r\n refetchInterval?: number;\r\n}\r\n\r\n/**\r\n * Hook for fetching all review sessions\r\n */\r\nexport function useReviewSessions(options: UseReviewSessionsOptions = {}) {\r\n const queryClient = useQueryClient();\r\n\r\n const {\r\n data = [],\r\n isLoading,\r\n error,\r\n refetch,\r\n } = useQuery<ReviewSession[]>({\r\n queryKey: ['reviewSessions'],\r\n queryFn: fetchReviewSessions,\r\n staleTime: 30000,\r\n refetchInterval: options.refetchInterval,\r\n enabled: options.enabled ?? true,\r\n });\r\n\r\n // Prefetch a specific session\r\n const prefetchSession = (sessionId: string) => {\r\n queryClient.prefetchQuery({\r\n queryKey: ['reviewSession', sessionId],\r\n queryFn: () => fetchReviewSession(sessionId),\r\n staleTime: 60000,\r\n });\r\n };\r\n\r\n return {\r\n reviewSessions: data,\r\n isLoading,\r\n error,\r\n refetch,\r\n prefetchSession,\r\n };\r\n}\r\n\r\n/**\r\n * Hook for fetching a single review session\r\n */\r\nexport function useReviewSession(sessionId: string | undefined) {\r\n const {\r\n data: reviewSession,\r\n isLoading,\r\n error,\r\n refetch,\r\n } = useQuery<ReviewSession | null>({\r\n queryKey: ['reviewSession', sessionId],\r\n queryFn: () => (sessionId ? fetchReviewSession(sessionId) : Promise.resolve(null)),\r\n enabled: !!sessionId,\r\n staleTime: 60000,\r\n });\r\n\r\n // Flatten findings with dimension info\r\n const flattenedFindings = React.useMemo(() => {\r\n if (!reviewSession?.reviewDimensions) return [];\r\n const findings: Array<ReviewFinding & { dimension: string }> = [];\r\n reviewSession.reviewDimensions.forEach(dim => {\r\n (dim.findings || []).forEach(f => {\r\n findings.push({ ...f, dimension: dim.name });\r\n });\r\n });\r\n return findings;\r\n }, [reviewSession]);\r\n\r\n // Get severity counts\r\n const severityCounts = React.useMemo(() => {\r\n const counts = { critical: 0, high: 0, medium: 0, low: 0 };\r\n flattenedFindings.forEach(f => {\r\n const sev = (f.severity || 'medium').toLowerCase() as keyof typeof counts;\r\n if (counts[sev] !== undefined) {\r\n counts[sev]++;\r\n }\r\n });\r\n return counts;\r\n }, [flattenedFindings]);\r\n\r\n return {\r\n reviewSession,\r\n flattenedFindings,\r\n severityCounts,\r\n isLoading,\r\n error,\r\n refetch,\r\n };\r\n}\r\n\r\nimport React from 'react';\r\n","// ========================================\n// ReviewSessionPage Component\n// ========================================\n// Review session detail page with findings display, multi-select, dimension tabs, and fix progress carousel\n\nimport * as React from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { useIntl } from 'react-intl';\nimport {\n ArrowLeft,\n Search,\n CheckCircle,\n XCircle,\n AlertTriangle,\n Info,\n FileText,\n Download,\n ChevronRight,\n ChevronLeft as ChevronLeftIcon,\n ChevronRight as ChevronRightIcon,\n} from 'lucide-react';\nimport { useReviewSession } from '@/hooks/useReviewSession';\nimport { Button } from '@/components/ui/Button';\nimport { Badge } from '@/components/ui/Badge';\nimport { Card, CardContent } from '@/components/ui/Card';\n\ntype SeverityFilter = 'all' | 'critical' | 'high' | 'medium' | 'low';\ntype SortField = 'severity' | 'dimension' | 'file';\ntype SortOrder = 'asc' | 'desc';\n\ninterface FindingWithSelection {\n id: string;\n title: string;\n description?: string;\n severity: 'critical' | 'high' | 'medium' | 'low';\n dimension: string;\n category?: string;\n file?: string;\n line?: string;\n code_context?: string;\n recommendations?: string[];\n root_cause?: string;\n impact?: string;\n}\n\n// Fix Progress Types\ninterface FixStage {\n stage: number;\n status: 'completed' | 'in-progress' | 'pending';\n groups: string[];\n}\n\ninterface FixProgressData {\n fix_session_id: string;\n phase: 'planning' | 'execution' | 'completion';\n total_findings: number;\n fixed_count: number;\n failed_count: number;\n in_progress_count: number;\n pending_count: number;\n percent_complete: number;\n current_stage: number;\n total_stages: number;\n stages: FixStage[];\n active_agents: Array<{\n agent_id: string;\n group_id: string;\n current_finding: { finding_title: string } | null;\n }>;\n}\n\n/**\n * Fix Progress Carousel Component\n * Displays fix progress with polling and carousel navigation\n */\n// @ts-expect-error Component is defined for future use when backend implements /api/fix-progress\nfunction FixProgressCarousel({ sessionId }: { sessionId: string }) {\n const { formatMessage } = useIntl();\n const [fixProgressData, setFixProgressData] = React.useState<FixProgressData | null>(null);\n const [currentSlide, setCurrentSlide] = React.useState(0);\n const [isLoading, setIsLoading] = React.useState(false);\n\n // Sequential polling with AbortController — no concurrent requests possible\n React.useEffect(() => {\n const abortController = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let stopped = false;\n let errorCount = 0;\n\n const poll = async () => {\n if (stopped) return;\n\n setIsLoading(true);\n try {\n const response = await fetch(\n `/api/fix-progress?sessionId=${encodeURIComponent(sessionId)}`,\n { signal: abortController.signal }\n );\n if (!response.ok) {\n errorCount += 1;\n if (response.status === 404 || errorCount >= 3) {\n stopped = true;\n setFixProgressData(null);\n return;\n }\n } else {\n errorCount = 0;\n const data = await response.json();\n setFixProgressData(data);\n if (data?.phase === 'completion') {\n stopped = true;\n return;\n }\n }\n } catch {\n if (abortController.signal.aborted) return;\n errorCount += 1;\n if (errorCount >= 3) {\n stopped = true;\n return;\n }\n } finally {\n if (!abortController.signal.aborted) {\n setIsLoading(false);\n }\n }\n\n // Schedule next poll only after current request completes\n if (!stopped) {\n timeoutId = setTimeout(poll, 5000);\n }\n };\n\n poll();\n\n return () => {\n stopped = true;\n abortController.abort();\n if (timeoutId) clearTimeout(timeoutId);\n };\n }, [sessionId]);\n\n // Navigate carousel\n const navigateSlide = (direction: 'prev' | 'next' | number) => {\n if (!fixProgressData) return;\n\n const totalSlides = fixProgressData.active_agents.length > 0 ? 3 : 2;\n if (typeof direction === 'number') {\n setCurrentSlide(direction);\n } else if (direction === 'next') {\n setCurrentSlide((prev) => (prev + 1) % totalSlides);\n } else if (direction === 'prev') {\n setCurrentSlide((prev) => (prev - 1 + totalSlides) % totalSlides);\n }\n };\n\n if (isLoading && !fixProgressData) {\n return (\n <Card>\n <CardContent className=\"p-4\">\n <div className=\"h-32 bg-muted animate-pulse rounded\" />\n </CardContent>\n </Card>\n );\n }\n\n if (!fixProgressData) {\n return null;\n }\n\n const { phase, total_findings, fixed_count, failed_count, in_progress_count, pending_count, percent_complete, current_stage, total_stages, stages, active_agents } = fixProgressData;\n\n const phaseIcon = phase === 'planning' ? '📝' : phase === 'execution' ? '⚡' : '✅';\n const totalSlides = active_agents.length > 0 ? 3 : 2;\n\n return (\n <Card>\n <CardContent className=\"p-4 space-y-4\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg\">🔧</span>\n <span className=\"font-semibold text-sm\">{formatMessage({ id: 'reviewSession.fixProgress.title' })}</span>\n </div>\n {/* Stage Dots */}\n <div className=\"flex gap-1\">\n {stages.map((stage, i) => (\n <div\n key={i}\n className={`w-2 h-2 rounded-full ${\n stage.status === 'completed' ? 'bg-green-500' :\n stage.status === 'in-progress' ? 'bg-blue-500' :\n 'bg-gray-300 dark:bg-gray-600'\n }`}\n title={`Stage ${i + 1}: ${stage.status}`}\n />\n ))}\n </div>\n </div>\n\n {/* Carousel */}\n <div className=\"overflow-hidden\">\n <div\n className=\"flex transition-transform duration-300 ease-in-out\"\n style={{ transform: `translateX(-${currentSlide * 100}%)` }}\n >\n {/* Slide 1: Overview */}\n <div className=\"w-full flex-shrink-0\">\n <div className=\"flex items-center justify-between mb-3\">\n <Badge variant={phase === 'planning' ? 'secondary' : phase === 'execution' ? 'default' : 'success'}>\n {phaseIcon} {formatMessage({ id: `reviewSession.fixProgress.phase.${phase}` })}\n </Badge>\n <span className=\"text-xs text-muted-foreground\">{fixProgressData.fix_session_id}</span>\n </div>\n <div className=\"w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2 mb-2\">\n <div\n className=\"bg-primary h-2 rounded-full transition-all duration-300\"\n style={{ width: `${percent_complete}%` }}\n />\n </div>\n <div className=\"text-xs text-muted-foreground text-center\">\n {formatMessage({ id: 'reviewSession.fixProgress.complete' }, { percent: percent_complete.toFixed(0) })} · {formatMessage({ id: 'reviewSession.fixProgress.stage' })} {current_stage}/{total_stages}\n </div>\n </div>\n\n {/* Slide 2: Stats */}\n <div className=\"w-full flex-shrink-0\">\n <div className=\"grid grid-cols-4 gap-2\">\n <div className=\"text-center p-2 bg-muted rounded\">\n <div className=\"text-lg font-bold\">{total_findings}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.fixProgress.stats.total' })}</div>\n </div>\n <div className=\"text-center p-2 bg-green-100 dark:bg-green-900/20 rounded\">\n <div className=\"text-lg font-bold text-green-600 dark:text-green-400\">{fixed_count}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.fixProgress.stats.fixed' })}</div>\n </div>\n <div className=\"text-center p-2 bg-red-100 dark:bg-red-900/20 rounded\">\n <div className=\"text-lg font-bold text-red-600 dark:text-red-400\">{failed_count}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.fixProgress.stats.failed' })}</div>\n </div>\n <div className=\"text-center p-2 bg-yellow-100 dark:bg-yellow-900/20 rounded\">\n <div className=\"text-lg font-bold text-yellow-600 dark:text-yellow-400\">{pending_count + in_progress_count}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.fixProgress.stats.pending' })}</div>\n </div>\n </div>\n </div>\n\n {/* Slide 3: Active Agents (if any) */}\n {active_agents.length > 0 && (\n <div className=\"w-full flex-shrink-0\">\n <div className=\"text-sm font-semibold mb-2\">\n {active_agents.length} {active_agents.length === 1 ? formatMessage({ id: 'reviewSession.fixProgress.activeAgents' }) : formatMessage({ id: 'reviewSession.fixProgress.activeAgentsPlural' })}\n </div>\n <div className=\"space-y-2\">\n {active_agents.slice(0, 2).map((agent, i) => (\n <div key={i} className=\"flex items-center gap-2 p-2 bg-muted rounded\">\n <span>🤖</span>\n <span className=\"text-sm\">{agent.current_finding?.finding_title || formatMessage({ id: 'reviewSession.fixProgress.working' })}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Carousel Navigation */}\n {totalSlides > 1 && (\n <div className=\"flex items-center justify-between gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigateSlide('prev')}>\n <ChevronLeftIcon className=\"h-4 w-4\" />\n </Button>\n <div className=\"flex gap-1\">\n {Array.from({ length: totalSlides }).map((_, i) => (\n <button\n key={i}\n className={`w-2 h-2 rounded-full transition-colors ${\n currentSlide === i ? 'bg-primary' : 'bg-gray-300 dark:bg-gray-600'\n }`}\n onClick={() => navigateSlide(i)}\n />\n ))}\n </div>\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigateSlide('next')}>\n <ChevronRightIcon className=\"h-4 w-4\" />\n </Button>\n </div>\n )}\n </CardContent>\n </Card>\n );\n}\n\n/**\n * ReviewSessionPage component - Display review session findings\n */\nexport function ReviewSessionPage() {\n const { sessionId } = useParams<{ sessionId: string }>();\n const navigate = useNavigate();\n const { formatMessage } = useIntl();\n const {\n reviewSession,\n flattenedFindings,\n severityCounts,\n isLoading,\n error,\n refetch,\n } = useReviewSession(sessionId);\n\n const [severityFilter, setSeverityFilter] = React.useState<Set<SeverityFilter>>(\n new Set(['critical', 'high', 'medium', 'low'])\n );\n const [dimensionFilter, setDimensionFilter] = React.useState<string>('all');\n const [searchQuery, setSearchQuery] = React.useState('');\n const [sortField, setSortField] = React.useState<SortField>('severity');\n const [sortOrder, setSortOrder] = React.useState<SortOrder>('desc');\n const [selectedFindings, setSelectedFindings] = React.useState<Set<string>>(new Set());\n const [selectedFindingId, setSelectedFindingId] = React.useState<string | null>(null);\n\n const handleBack = () => {\n navigate('/sessions');\n };\n\n const toggleSeverity = (severity: SeverityFilter) => {\n setSeverityFilter(prev => {\n const next = new Set(prev);\n if (next.has(severity)) {\n next.delete(severity);\n } else {\n next.add(severity);\n }\n return next;\n });\n };\n\n const resetFilters = () => {\n setSeverityFilter(new Set(['critical', 'high', 'medium', 'low']));\n setDimensionFilter('all');\n setSearchQuery('');\n };\n\n const toggleSelectFinding = (findingId: string) => {\n setSelectedFindings(prev => {\n const next = new Set(prev);\n if (next.has(findingId)) {\n next.delete(findingId);\n } else {\n next.add(findingId);\n }\n return next;\n });\n };\n\n const selectAllFindings = () => {\n const validIds = filteredFindings.map(f => f.id).filter((id): id is string => id !== undefined);\n setSelectedFindings(new Set(validIds));\n };\n\n const selectVisibleFindings = () => {\n const validIds = filteredFindings.map(f => f.id).filter((id): id is string => id !== undefined);\n setSelectedFindings(new Set(validIds));\n };\n\n const selectBySeverity = (severity: FindingWithSelection['severity']) => {\n const severityIds = flattenedFindings\n .filter(f => f.severity === severity && f.id !== undefined)\n .map(f => f.id!);\n setSelectedFindings(prev => {\n const next = new Set(prev);\n severityIds.forEach(id => next.add(id));\n return next;\n });\n };\n\n const clearSelection = () => {\n setSelectedFindings(new Set());\n };\n\n const handleFindingClick = (findingId: string) => {\n setSelectedFindingId(findingId);\n };\n\n const exportSelectedAsJson = () => {\n const selected = flattenedFindings.filter(f => f.id !== undefined && selectedFindings.has(f.id));\n if (selected.length === 0) return;\n\n const exportData = {\n session_id: sessionId,\n findings: selected.map(f => ({\n id: f.id,\n title: f.title,\n description: f.description,\n severity: f.severity,\n dimension: f.dimension,\n file: f.file,\n line: f.line,\n recommendations: f.recommendations,\n })),\n };\n\n const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `review-${sessionId}-fix.json`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n };\n\n // Severity order for sorting\n const severityOrder = { critical: 4, high: 3, medium: 2, low: 1 };\n\n // Calculate dimension counts\n const dimensionCounts = React.useMemo(() => {\n const counts: Record<string, number> = { all: flattenedFindings.length };\n flattenedFindings.forEach(f => {\n counts[f.dimension] = (counts[f.dimension] || 0) + 1;\n });\n return counts;\n }, [flattenedFindings]);\n\n // Filter and sort findings\n const filteredFindings = React.useMemo(() => {\n let filtered = flattenedFindings;\n\n // Apply dimension filter\n if (dimensionFilter !== 'all') {\n filtered = filtered.filter(f => f.dimension === dimensionFilter);\n }\n\n // Apply severity filter\n if (severityFilter.size > 0) {\n filtered = filtered.filter(f => severityFilter.has(f.severity));\n }\n\n // Apply search filter\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n filtered = filtered.filter(f =>\n f.title.toLowerCase().includes(query) ||\n f.description?.toLowerCase().includes(query) ||\n f.file?.toLowerCase().includes(query) ||\n f.dimension.toLowerCase().includes(query)\n );\n }\n\n // Apply sorting\n filtered = [...filtered].sort((a, b) => {\n let comparison = 0;\n switch (sortField) {\n case 'severity':\n comparison = severityOrder[a.severity] - severityOrder[b.severity];\n break;\n case 'dimension':\n comparison = a.dimension.localeCompare(b.dimension);\n break;\n case 'file':\n comparison = (a.file || '').localeCompare(b.file || '');\n break;\n }\n return sortOrder === 'asc' ? comparison : -comparison;\n });\n\n return filtered;\n }, [flattenedFindings, severityFilter, dimensionFilter, searchQuery, sortField, sortOrder]);\n\n // Get severity badge props\n const getSeverityBadge = (severity: FindingWithSelection['severity']) => {\n switch (severity) {\n case 'critical':\n return { variant: 'destructive' as const, icon: XCircle, label: formatMessage({ id: 'reviewSession.severity.critical' }) };\n case 'high':\n return { variant: 'warning' as const, icon: AlertTriangle, label: formatMessage({ id: 'reviewSession.severity.high' }) };\n case 'medium':\n return { variant: 'info' as const, icon: Info, label: formatMessage({ id: 'reviewSession.severity.medium' }) };\n case 'low':\n return { variant: 'secondary' as const, icon: CheckCircle, label: formatMessage({ id: 'reviewSession.severity.low' }) };\n }\n };\n\n // Loading state\n if (isLoading) {\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center gap-4\">\n <Button variant=\"ghost\" size=\"sm\" disabled>\n <ArrowLeft className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'common.actions.back' })}\n </Button>\n <div className=\"h-8 w-64 rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"h-64 rounded-lg bg-muted animate-pulse\" />\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive\">\n <XCircle className=\"h-5 w-5 flex-shrink-0\" />\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium\">{formatMessage({ id: 'common.errors.loadFailed' })}</p>\n <p className=\"text-xs mt-0.5\">{error.message}</p>\n </div>\n <Button variant=\"outline\" size=\"sm\" onClick={() => refetch()}>\n {formatMessage({ id: 'common.actions.retry' })}\n </Button>\n </div>\n );\n }\n\n // Session not found\n if (!reviewSession) {\n return (\n <div className=\"flex flex-col items-center justify-center py-16 px-4\">\n <FileText className=\"h-12 w-12 text-muted-foreground mb-4\" />\n <h3 className=\"text-lg font-medium text-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.notFound.title' })}\n </h3>\n <p className=\"text-sm text-muted-foreground mb-4\">\n {formatMessage({ id: 'reviewSession.notFound.message' })}\n </p>\n <Button onClick={handleBack}>\n <ArrowLeft className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'common.actions.back' })}\n </Button>\n </div>\n );\n }\n\n const dimensions = reviewSession.reviewDimensions || [];\n const totalFindings = flattenedFindings.length;\n\n // Determine session status (ACTIVE or ARCHIVED)\n const isActive = reviewSession._isActive !== false;\n const sessionStatus = isActive ? 'ACTIVE' : 'ARCHIVED';\n const phase = reviewSession.phase || 'in-progress';\n\n return (\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-4\">\n <Button variant=\"ghost\" size=\"sm\" onClick={handleBack}>\n <ArrowLeft className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'common.actions.back' })}\n </Button>\n <div>\n <h1 className=\"text-2xl font-semibold text-foreground flex items-center gap-2\">\n 🔍 {reviewSession.session_id}\n </h1>\n <div className=\"flex items-center gap-2 mt-1\">\n <Badge variant=\"review\">Review</Badge>\n <Badge variant={isActive ? \"success\" : \"secondary\"} className=\"text-xs\">\n {sessionStatus}\n </Badge>\n </div>\n </div>\n </div>\n </div>\n\n {/* Review Progress Section */}\n <Card>\n <CardContent className=\"p-4 space-y-4\">\n {/* Review Progress Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg\">📊</span>\n <span className=\"font-semibold\">{formatMessage({ id: 'reviewSession.progress.title' })}</span>\n </div>\n <Badge variant=\"secondary\">{phase.toUpperCase()}</Badge>\n </div>\n\n {/* Summary Cards Grid */}\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-3\">\n <div className=\"flex items-center gap-3 p-3 bg-muted rounded-lg\">\n <span className=\"text-2xl\">📊</span>\n <div>\n <div className=\"text-lg font-bold\">{totalFindings}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.progress.totalFindings' })}</div>\n </div>\n </div>\n <div className=\"flex items-center gap-3 p-3 bg-red-100 dark:bg-red-900/20 rounded-lg\">\n <span className=\"text-2xl\">🔴</span>\n <div>\n <div className=\"text-lg font-bold text-red-600 dark:text-red-400\">{severityCounts.critical}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.progress.critical' })}</div>\n </div>\n </div>\n <div className=\"flex items-center gap-3 p-3 bg-orange-100 dark:bg-orange-900/20 rounded-lg\">\n <span className=\"text-2xl\">🟠</span>\n <div>\n <div className=\"text-lg font-bold text-orange-600 dark:text-orange-400\">{severityCounts.high}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.progress.high' })}</div>\n </div>\n </div>\n <div className=\"flex items-center gap-3 p-3 bg-blue-100 dark:bg-blue-900/20 rounded-lg\">\n <span className=\"text-2xl\">🎯</span>\n <div>\n <div className=\"text-lg font-bold text-blue-600 dark:text-blue-400\">{dimensions.length}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.stats.dimensions' })}</div>\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n\n {/* Fix Progress Carousel — disabled: backend /api/fix-progress not implemented yet\n See FRONTEND_BACKEND_ALIGNMENT_AUDIT.md for details */}\n {/* {sessionId && <FixProgressCarousel sessionId={sessionId} />} */}\n\n {/* Unified Filter Card with Dimension Tabs */}\n <Card>\n <CardContent className=\"p-4 space-y-4\">\n {/* Top Bar: Search + Sort + Reset */}\n <div className=\"flex flex-wrap gap-3 items-center\">\n <div className=\"relative flex-1 min-w-[180px] max-w-md\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <input\n type=\"text\"\n placeholder={formatMessage({ id: 'reviewSession.search.placeholder' })}\n value={searchQuery}\n onChange={e => setSearchQuery(e.target.value)}\n className=\"w-full pl-10 pr-4 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\"\n />\n </div>\n <select\n value={sortField}\n onChange={e => setSortField(e.target.value as SortField)}\n className=\"px-3 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"severity\">{formatMessage({ id: 'reviewSession.sort.severity' })}</option>\n <option value=\"dimension\">{formatMessage({ id: 'reviewSession.sort.dimension' })}</option>\n <option value=\"file\">{formatMessage({ id: 'reviewSession.sort.file' })}</option>\n </select>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc')}\n className=\"w-9 p-0\"\n >\n {sortOrder === 'asc' ? '↑' : '↓'}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={resetFilters} className=\"text-muted-foreground hover:text-foreground\">\n ✕ {formatMessage({ id: 'reviewSession.filters.reset' })}\n </Button>\n </div>\n\n {/* Middle Row: Dimension Tabs + Severity Filters */}\n <div className=\"flex flex-col sm:flex-row gap-4\">\n {/* Dimension Tabs - Horizontal Scrollable */}\n <div className=\"flex-1\">\n <div className=\"text-xs font-medium text-muted-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.filters.dimension' })}\n </div>\n <div className=\"flex gap-1.5 overflow-x-auto pb-1 scrollbar-thin\">\n <button\n className={`px-3 py-1.5 rounded-md text-xs font-medium whitespace-nowrap transition-colors ${\n dimensionFilter === 'all'\n ? 'bg-primary text-primary-foreground shadow-sm'\n : 'bg-muted/50 text-muted-foreground hover:bg-muted'\n }`}\n onClick={() => setDimensionFilter('all')}\n >\n All ({dimensionCounts.all || 0})\n </button>\n {dimensions.map(dim => (\n <button\n key={dim.name}\n className={`px-3 py-1.5 rounded-md text-xs font-medium whitespace-nowrap transition-colors ${\n dimensionFilter === dim.name\n ? 'bg-primary text-primary-foreground shadow-sm'\n : 'bg-muted/50 text-muted-foreground hover:bg-muted'\n }`}\n onClick={() => setDimensionFilter(dim.name)}\n >\n {dim.name} ({dim.findings?.length || 0})\n </button>\n ))}\n </div>\n </div>\n\n {/* Severity Filters - Compact Pills */}\n <div className=\"sm:w-auto\">\n <div className=\"text-xs font-medium text-muted-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.filters.severity' })}\n </div>\n <div className=\"flex gap-1.5 flex-wrap\">\n {(['critical', 'high', 'medium', 'low'] as const).map(severity => {\n const isEnabled = severityFilter.has(severity);\n const colors = {\n critical: isEnabled ? 'bg-red-500 text-white border-red-500' : 'bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 border-red-200 dark:border-red-800',\n high: isEnabled ? 'bg-orange-500 text-white border-orange-500' : 'bg-orange-50 dark:bg-orange-900/20 text-orange-600 dark:text-orange-400 border-orange-200 dark:border-orange-800',\n medium: isEnabled ? 'bg-blue-500 text-white border-blue-500' : 'bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 border-blue-200 dark:border-blue-800',\n low: isEnabled ? 'bg-gray-500 text-white border-gray-500' : 'bg-gray-50 dark:bg-gray-900/20 text-gray-600 dark:text-gray-400 border-gray-200 dark:border-gray-800',\n };\n return (\n <label\n key={severity}\n className={`inline-flex items-center gap-1 px-2.5 py-1 rounded-md border text-xs font-medium cursor-pointer transition-all ${\n colors[severity]\n } ${isEnabled ? 'shadow-sm' : 'hover:opacity-80'}`}\n >\n <input\n type=\"checkbox\"\n checked={isEnabled}\n onChange={() => toggleSeverity(severity)}\n className=\"sr-only\"\n />\n <span>{formatMessage({ id: `reviewSession.severity.short.${severity}` })}</span>\n <span className=\"opacity-70\">({flattenedFindings.filter(f => f.severity === severity).length})</span>\n </label>\n );\n })}\n </div>\n </div>\n </div>\n\n {/* Bottom Bar: Selection Actions + Export */}\n <div className=\"flex flex-wrap items-center justify-between gap-3 pt-3 border-t border-border\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-xs text-muted-foreground px-2 py-1 bg-muted rounded-md\">\n {selectedFindings.size > 0\n ? formatMessage({ id: 'reviewSession.selection.countSelected' }, { count: selectedFindings.size })\n : formatMessage({ id: 'reviewSession.selection.total' }, { count: filteredFindings.length })\n }\n </span>\n {selectedFindings.size > 0 && (\n <>\n <Button variant=\"outline\" size=\"sm\" onClick={clearSelection} className=\"h-8 text-xs\">\n {formatMessage({ id: 'reviewSession.selection.clear' })}\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={() => selectBySeverity('critical')} className=\"h-8 text-xs\">\n 🔥 {formatMessage({ id: 'reviewSession.selection.selectCritical' })}\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={selectVisibleFindings} className=\"h-8 text-xs\">\n {formatMessage({ id: 'reviewSession.selection.selectVisible' })}\n </Button>\n </>\n )}\n {selectedFindings.size === 0 && (\n <Button variant=\"outline\" size=\"sm\" onClick={selectAllFindings} className=\"h-8 text-xs\">\n {formatMessage({ id: 'reviewSession.selection.selectAll' })}\n </Button>\n )}\n </div>\n <Button\n variant={selectedFindings.size > 0 ? 'default' : 'outline'}\n size=\"sm\"\n onClick={exportSelectedAsJson}\n disabled={selectedFindings.size === 0}\n className=\"h-8 gap-1.5 text-xs\"\n >\n <Download className=\"h-3.5 w-3.5\" />\n 🔧 {formatMessage({ id: 'reviewSession.export' })}\n </Button>\n </div>\n </CardContent>\n </Card>\n\n {/* Split Panel: Findings List + Preview */}\n {filteredFindings.length === 0 ? (\n <Card>\n <CardContent className=\"p-12 text-center\">\n {/* Check if review hasn't been executed yet */}\n {reviewSession?.reviewSummary?.status === 'in_progress' &&\n (!reviewSession?.reviewDimensions || reviewSession.reviewDimensions.length === 0) ? (\n <>\n <AlertTriangle className=\"h-12 w-12 text-amber-500 mx-auto mb-4\" />\n <h3 className=\"text-lg font-medium text-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.notExecuted.title' })}\n </h3>\n <p className=\"text-sm text-muted-foreground mb-4\">\n {formatMessage({ id: 'reviewSession.notExecuted.message' })}\n </p>\n <div className=\"text-xs text-muted-foreground bg-muted p-3 rounded-lg inline-block\">\n {formatMessage({ id: 'reviewSession.notExecuted.hint' })}\n </div>\n </>\n ) : (\n <>\n <FileText className=\"h-12 w-12 text-muted-foreground mx-auto mb-4\" />\n <h3 className=\"text-lg font-medium text-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.empty.title' })}\n </h3>\n <p className=\"text-sm text-muted-foreground\">\n {formatMessage({ id: 'reviewSession.empty.message' })}\n </p>\n </>\n )}\n </CardContent>\n </Card>\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-[minmax(0,45fr)_minmax(0,55fr)] gap-4\">\n {/* Left Panel: Findings List */}\n <Card>\n <CardContent className=\"p-4\">\n <div className=\"flex items-center justify-between mb-3\">\n <span className=\"text-sm font-medium\">\n {formatMessage({ id: 'reviewSession.findingsList.count' }, { count: filteredFindings.length })}\n </span>\n </div>\n <div className=\"space-y-2 max-h-[600px] overflow-y-auto\">\n {filteredFindings.filter(f => f.id !== undefined).map(finding => {\n const findingId = finding.id!;\n const isSelected = selectedFindings.has(findingId);\n const isPreviewing = selectedFindingId === findingId;\n const badge = getSeverityBadge(finding.severity);\n const BadgeIcon = badge.icon;\n\n return (\n <div\n key={findingId}\n className={`p-3 rounded-lg border cursor-pointer transition-colors ${\n isPreviewing\n ? 'bg-primary/10 border-primary'\n : 'bg-background border-border hover:bg-muted'\n }`}\n onClick={() => handleFindingClick(findingId)}\n >\n <div className=\"flex items-start gap-2\">\n {/* Checkbox */}\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={(e) => {\n e.stopPropagation();\n toggleSelectFinding(findingId);\n }}\n className=\"mt-0.5 flex-shrink-0\"\n />\n\n {/* Compact Finding Content */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 mb-1 flex-wrap\">\n <Badge variant={badge.variant} className=\"gap-1 text-xs\">\n <BadgeIcon className=\"h-2.5 w-2.5\" />\n {badge.label}\n </Badge>\n <span className=\"text-xs text-muted-foreground\">\n {finding.dimension}\n </span>\n </div>\n <p className=\"text-sm font-medium text-foreground truncate\">\n {finding.title}\n </p>\n {finding.file && (\n <p className=\"text-xs text-muted-foreground font-mono truncate mt-0.5\">\n {finding.file}:{finding.line || '?'}\n </p>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n\n {/* Right Panel: Enhanced Preview */}\n <Card className=\"sticky top-4 self-start\">\n <CardContent className=\"p-0 h-full min-h-[500px]\">\n {!selectedFindingId ? (\n // Enhanced Empty State\n <div className=\"flex flex-col items-center justify-center h-full min-h-[400px] p-8 text-center bg-gradient-to-br from-muted/30 to-muted/10\">\n <div className=\"w-20 h-20 rounded-full bg-muted flex items-center justify-center mb-4\">\n <Search className=\"h-10 w-10 text-muted-foreground\" />\n </div>\n <h3 className=\"text-base font-semibold text-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.preview.emptyTitle' })}\n </h3>\n <p className=\"text-sm text-muted-foreground mb-4 max-w-[250px]\">\n {formatMessage({ id: 'reviewSession.preview.empty' })}\n </p>\n <div className=\"flex flex-wrap gap-2 justify-center\">\n <div className=\"flex items-center gap-1.5 px-3 py-1.5 bg-background rounded-lg border text-xs\">\n <span className=\"w-2 h-2 rounded-full bg-destructive\"></span>\n {formatMessage({ id: 'reviewSession.preview.emptyTipSeverity' })}\n </div>\n <div className=\"flex items-center gap-1.5 px-3 py-1.5 bg-background rounded-lg border text-xs\">\n <span>📁</span>\n {formatMessage({ id: 'reviewSession.preview.emptyTipFile' })}\n </div>\n </div>\n </div>\n ) : (\n // Preview Content\n (() => {\n const finding = flattenedFindings.find(f => f.id === selectedFindingId);\n if (!finding) return null;\n\n const badge = getSeverityBadge(finding.severity);\n const BadgeIcon = badge.icon;\n const isSelected = selectedFindings.has(selectedFindingId);\n\n // Find adjacent findings for navigation\n const findingIndex = filteredFindings.findIndex(f => f.id === selectedFindingId);\n const prevFinding = findingIndex > 0 ? filteredFindings[findingIndex - 1] : null;\n const nextFinding = findingIndex < filteredFindings.length - 1 ? filteredFindings[findingIndex + 1] : null;\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Sticky Header */}\n <div className=\"sticky top-0 z-10 bg-background border-b border-border p-4 space-y-3\">\n {/* Navigation + Badges Row */}\n <div className=\"flex items-center justify-between gap-2\">\n {/* Navigation Buttons */}\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => prevFinding && handleFindingClick(prevFinding.id!)}\n disabled={!prevFinding}\n className=\"h-8 w-8 p-0\"\n >\n <ChevronRight className=\"h-4 w-4 rotate-180\" />\n </Button>\n <span className=\"text-xs text-muted-foreground px-2\">\n {findingIndex + 1} / {filteredFindings.length}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => nextFinding && handleFindingClick(nextFinding.id!)}\n disabled={!nextFinding}\n className=\"h-8 w-8 p-0\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n </div>\n\n {/* Badges */}\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n <Badge variant={badge.variant} className=\"gap-1 text-xs\">\n <BadgeIcon className=\"h-3 w-3\" />\n {badge.label}\n </Badge>\n <Badge variant=\"outline\" className=\"text-xs\">\n {finding.dimension}\n </Badge>\n </div>\n\n {/* Select Button */}\n <Button\n variant={isSelected ? 'default' : 'outline'}\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n toggleSelectFinding(selectedFindingId);\n }}\n className=\"h-8 text-xs\"\n >\n {isSelected ? (\n <>\n <CheckCircle className=\"h-3.5 w-3.5 mr-1\" />\n {formatMessage({ id: 'reviewSession.preview.selected' })}\n </>\n ) : (\n <>\n <span className=\"mr-1\">⊕</span>\n {formatMessage({ id: 'reviewSession.preview.selectForFix' })}\n </>\n )}\n </Button>\n </div>\n\n {/* Title */}\n <h3 className=\"text-base font-semibold text-foreground line-clamp-2\">\n {finding.title}\n </h3>\n\n {/* Quick Info Bar */}\n <div className=\"flex items-center gap-3 text-xs\">\n {finding.file && (\n <div className=\"flex items-center gap-1 text-muted-foreground flex-1 min-w-0\">\n <span className=\"flex-shrink-0\">📁</span>\n <code className=\"truncate\">{finding.file}:{finding.line || '?'}</code>\n </div>\n )}\n </div>\n </div>\n\n {/* Scrollable Content */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4\">\n {/* Description */}\n {finding.description && (\n <div className=\"bg-muted/30 rounded-lg p-3\">\n <div className=\"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5\">\n <span>📝</span>\n {formatMessage({ id: 'reviewSession.preview.description' })}\n </div>\n <p className=\"text-sm text-foreground leading-relaxed\">\n {finding.description}\n </p>\n </div>\n )}\n\n {/* Code Context */}\n {finding.code_context && (\n <div>\n <div className=\"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5\">\n <span>💻</span>\n {formatMessage({ id: 'reviewSession.preview.codeContext' })}\n </div>\n <pre className=\"text-xs bg-muted p-3 rounded-lg overflow-x-auto border border-border\">\n <code className=\"text-foreground\">{finding.code_context}</code>\n </pre>\n </div>\n )}\n\n {/* Root Cause */}\n {finding.root_cause && (\n <div>\n <div className=\"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5\">\n <span>🎯</span>\n {formatMessage({ id: 'reviewSession.preview.rootCause' })}\n </div>\n <p className=\"text-sm text-foreground bg-muted/30 rounded-lg p-3 leading-relaxed\">\n {finding.root_cause}\n </p>\n </div>\n )}\n\n {/* Impact */}\n {finding.impact && (\n <div>\n <div className=\"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5\">\n <span>⚠️</span>\n {formatMessage({ id: 'reviewSession.preview.impact' })}\n </div>\n <p className=\"text-sm text-foreground bg-orange-50 dark:bg-orange-900/20 rounded-lg p-3 leading-relaxed border border-orange-200 dark:border-orange-800\">\n {finding.impact}\n </p>\n </div>\n )}\n\n {/* Recommendations */}\n {finding.recommendations && finding.recommendations.length > 0 && (\n <div>\n <div className=\"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5\">\n <span>✅</span>\n {formatMessage({ id: 'reviewSession.preview.recommendations' })}\n </div>\n <ul className=\"space-y-2\">\n {finding.recommendations.map((rec, idx) => (\n <li key={idx} className=\"text-sm text-foreground flex items-start gap-2 bg-green-50 dark:bg-green-900/20 rounded-lg p-3 border border-green-200 dark:border-green-800\">\n <span className=\"text-green-600 dark:text-green-400 flex-shrink-0 mt-0.5\">✓</span>\n <span className=\"leading-relaxed\">{rec}</span>\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n </div>\n );\n })()\n )}\n </CardContent>\n </Card>\n </div>\n )}\n </div>\n );\n}\n\nexport default ReviewSessionPage;\n"],"names":["useReviewSession","sessionId","reviewSession","isLoading","error","refetch","useQuery","fetchReviewSession","flattenedFindings","React","findings","dim","f","severityCounts","counts","sev","ReviewSessionPage","useParams","navigate","useNavigate","formatMessage","useIntl","severityFilter","setSeverityFilter","React.useState","dimensionFilter","setDimensionFilter","searchQuery","setSearchQuery","sortField","setSortField","sortOrder","setSortOrder","selectedFindings","setSelectedFindings","selectedFindingId","setSelectedFindingId","handleBack","toggleSeverity","severity","prev","next","resetFilters","toggleSelectFinding","findingId","selectAllFindings","validIds","filteredFindings","id","selectVisibleFindings","selectBySeverity","severityIds","clearSelection","handleFindingClick","exportSelectedAsJson","selected","exportData","blob","url","severityOrder","dimensionCounts","React.useMemo","filtered","query","_a","_b","a","b","comparison","getSeverityBadge","XCircle","AlertTriangle","Info","CheckCircle","jsxs","Button","jsx","ArrowLeft","FileText","dimensions","totalFindings","isActive","sessionStatus","phase","Badge","Card","CardContent","Search","e","isEnabled","colors","Fragment","Download","finding","isSelected","isPreviewing","badge","BadgeIcon","findingIndex","prevFinding","nextFinding","ChevronRight","rec","idx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ReviewSessionPage-BoqyjhPo.js","sources":["../../src/hooks/useReviewSession.ts","../../src/pages/ReviewSessionPage.tsx"],"sourcesContent":["// ========================================\r\n// useReviewSession Hook\r\n// ========================================\r\n// Custom hook for fetching and managing review session data\r\n\r\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\r\nimport { fetchReviewSessions, fetchReviewSession, type ReviewSession, type ReviewFinding } from '@/lib/api';\r\n\r\ninterface UseReviewSessionsOptions {\r\n enabled?: boolean;\r\n refetchInterval?: number;\r\n}\r\n\r\n/**\r\n * Hook for fetching all review sessions\r\n */\r\nexport function useReviewSessions(options: UseReviewSessionsOptions = {}) {\r\n const queryClient = useQueryClient();\r\n\r\n const {\r\n data = [],\r\n isLoading,\r\n error,\r\n refetch,\r\n } = useQuery<ReviewSession[]>({\r\n queryKey: ['reviewSessions'],\r\n queryFn: fetchReviewSessions,\r\n staleTime: 30000,\r\n refetchInterval: options.refetchInterval,\r\n enabled: options.enabled ?? true,\r\n });\r\n\r\n // Prefetch a specific session\r\n const prefetchSession = (sessionId: string) => {\r\n queryClient.prefetchQuery({\r\n queryKey: ['reviewSession', sessionId],\r\n queryFn: () => fetchReviewSession(sessionId),\r\n staleTime: 60000,\r\n });\r\n };\r\n\r\n return {\r\n reviewSessions: data,\r\n isLoading,\r\n error,\r\n refetch,\r\n prefetchSession,\r\n };\r\n}\r\n\r\n/**\r\n * Hook for fetching a single review session\r\n */\r\nexport function useReviewSession(sessionId: string | undefined) {\r\n const {\r\n data: reviewSession,\r\n isLoading,\r\n error,\r\n refetch,\r\n } = useQuery<ReviewSession | null>({\r\n queryKey: ['reviewSession', sessionId],\r\n queryFn: () => (sessionId ? fetchReviewSession(sessionId) : Promise.resolve(null)),\r\n enabled: !!sessionId,\r\n staleTime: 60000,\r\n });\r\n\r\n // Flatten findings with dimension info\r\n const flattenedFindings = React.useMemo(() => {\r\n if (!reviewSession?.reviewDimensions) return [];\r\n const findings: Array<ReviewFinding & { dimension: string }> = [];\r\n reviewSession.reviewDimensions.forEach(dim => {\r\n (dim.findings || []).forEach(f => {\r\n findings.push({ ...f, dimension: dim.name });\r\n });\r\n });\r\n return findings;\r\n }, [reviewSession]);\r\n\r\n // Get severity counts\r\n const severityCounts = React.useMemo(() => {\r\n const counts = { critical: 0, high: 0, medium: 0, low: 0 };\r\n flattenedFindings.forEach(f => {\r\n const sev = (f.severity || 'medium').toLowerCase() as keyof typeof counts;\r\n if (counts[sev] !== undefined) {\r\n counts[sev]++;\r\n }\r\n });\r\n return counts;\r\n }, [flattenedFindings]);\r\n\r\n return {\r\n reviewSession,\r\n flattenedFindings,\r\n severityCounts,\r\n isLoading,\r\n error,\r\n refetch,\r\n };\r\n}\r\n\r\nimport React from 'react';\r\n","// ========================================\n// ReviewSessionPage Component\n// ========================================\n// Review session detail page with findings display, multi-select, dimension tabs, and fix progress carousel\n\nimport * as React from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { useIntl } from 'react-intl';\nimport {\n ArrowLeft,\n Search,\n CheckCircle,\n XCircle,\n AlertTriangle,\n Info,\n FileText,\n Download,\n ChevronRight,\n ChevronLeft as ChevronLeftIcon,\n ChevronRight as ChevronRightIcon,\n} from 'lucide-react';\nimport { useReviewSession } from '@/hooks/useReviewSession';\nimport { Button } from '@/components/ui/Button';\nimport { Badge } from '@/components/ui/Badge';\nimport { Card, CardContent } from '@/components/ui/Card';\n\ntype SeverityFilter = 'all' | 'critical' | 'high' | 'medium' | 'low';\ntype SortField = 'severity' | 'dimension' | 'file';\ntype SortOrder = 'asc' | 'desc';\n\ninterface FindingWithSelection {\n id: string;\n title: string;\n description?: string;\n severity: 'critical' | 'high' | 'medium' | 'low';\n dimension: string;\n category?: string;\n file?: string;\n line?: string;\n code_context?: string;\n recommendations?: string[];\n root_cause?: string;\n impact?: string;\n}\n\n// Fix Progress Types\ninterface FixStage {\n stage: number;\n status: 'completed' | 'in-progress' | 'pending';\n groups: string[];\n}\n\ninterface FixProgressData {\n fix_session_id: string;\n phase: 'planning' | 'execution' | 'completion';\n total_findings: number;\n fixed_count: number;\n failed_count: number;\n in_progress_count: number;\n pending_count: number;\n percent_complete: number;\n current_stage: number;\n total_stages: number;\n stages: FixStage[];\n active_agents: Array<{\n agent_id: string;\n group_id: string;\n current_finding: { finding_title: string } | null;\n }>;\n}\n\n/**\n * Fix Progress Carousel Component\n * Displays fix progress with polling and carousel navigation\n */\n// @ts-expect-error Component is defined for future use when backend implements /api/fix-progress\nfunction FixProgressCarousel({ sessionId }: { sessionId: string }) {\n const { formatMessage } = useIntl();\n const [fixProgressData, setFixProgressData] = React.useState<FixProgressData | null>(null);\n const [currentSlide, setCurrentSlide] = React.useState(0);\n const [isLoading, setIsLoading] = React.useState(false);\n\n // Sequential polling with AbortController — no concurrent requests possible\n React.useEffect(() => {\n const abortController = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let stopped = false;\n let errorCount = 0;\n\n const poll = async () => {\n if (stopped) return;\n\n setIsLoading(true);\n try {\n const response = await fetch(\n `/api/fix-progress?sessionId=${encodeURIComponent(sessionId)}`,\n { signal: abortController.signal }\n );\n if (!response.ok) {\n errorCount += 1;\n if (response.status === 404 || errorCount >= 3) {\n stopped = true;\n setFixProgressData(null);\n return;\n }\n } else {\n errorCount = 0;\n const data = await response.json();\n setFixProgressData(data);\n if (data?.phase === 'completion') {\n stopped = true;\n return;\n }\n }\n } catch {\n if (abortController.signal.aborted) return;\n errorCount += 1;\n if (errorCount >= 3) {\n stopped = true;\n return;\n }\n } finally {\n if (!abortController.signal.aborted) {\n setIsLoading(false);\n }\n }\n\n // Schedule next poll only after current request completes\n if (!stopped) {\n timeoutId = setTimeout(poll, 5000);\n }\n };\n\n poll();\n\n return () => {\n stopped = true;\n abortController.abort();\n if (timeoutId) clearTimeout(timeoutId);\n };\n }, [sessionId]);\n\n // Navigate carousel\n const navigateSlide = (direction: 'prev' | 'next' | number) => {\n if (!fixProgressData) return;\n\n const totalSlides = fixProgressData.active_agents.length > 0 ? 3 : 2;\n if (typeof direction === 'number') {\n setCurrentSlide(direction);\n } else if (direction === 'next') {\n setCurrentSlide((prev) => (prev + 1) % totalSlides);\n } else if (direction === 'prev') {\n setCurrentSlide((prev) => (prev - 1 + totalSlides) % totalSlides);\n }\n };\n\n if (isLoading && !fixProgressData) {\n return (\n <Card>\n <CardContent className=\"p-4\">\n <div className=\"h-32 bg-muted animate-pulse rounded\" />\n </CardContent>\n </Card>\n );\n }\n\n if (!fixProgressData) {\n return null;\n }\n\n const { phase, total_findings, fixed_count, failed_count, in_progress_count, pending_count, percent_complete, current_stage, total_stages, stages, active_agents } = fixProgressData;\n\n const phaseIcon = phase === 'planning' ? '📝' : phase === 'execution' ? '⚡' : '✅';\n const totalSlides = active_agents.length > 0 ? 3 : 2;\n\n return (\n <Card>\n <CardContent className=\"p-4 space-y-4\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg\">🔧</span>\n <span className=\"font-semibold text-sm\">{formatMessage({ id: 'reviewSession.fixProgress.title' })}</span>\n </div>\n {/* Stage Dots */}\n <div className=\"flex gap-1\">\n {stages.map((stage, i) => (\n <div\n key={i}\n className={`w-2 h-2 rounded-full ${\n stage.status === 'completed' ? 'bg-green-500' :\n stage.status === 'in-progress' ? 'bg-blue-500' :\n 'bg-gray-300 dark:bg-gray-600'\n }`}\n title={`Stage ${i + 1}: ${stage.status}`}\n />\n ))}\n </div>\n </div>\n\n {/* Carousel */}\n <div className=\"overflow-hidden\">\n <div\n className=\"flex transition-transform duration-300 ease-in-out\"\n style={{ transform: `translateX(-${currentSlide * 100}%)` }}\n >\n {/* Slide 1: Overview */}\n <div className=\"w-full flex-shrink-0\">\n <div className=\"flex items-center justify-between mb-3\">\n <Badge variant={phase === 'planning' ? 'secondary' : phase === 'execution' ? 'default' : 'success'}>\n {phaseIcon} {formatMessage({ id: `reviewSession.fixProgress.phase.${phase}` })}\n </Badge>\n <span className=\"text-xs text-muted-foreground\">{fixProgressData.fix_session_id}</span>\n </div>\n <div className=\"w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2 mb-2\">\n <div\n className=\"bg-primary h-2 rounded-full transition-all duration-300\"\n style={{ width: `${percent_complete}%` }}\n />\n </div>\n <div className=\"text-xs text-muted-foreground text-center\">\n {formatMessage({ id: 'reviewSession.fixProgress.complete' }, { percent: percent_complete.toFixed(0) })} · {formatMessage({ id: 'reviewSession.fixProgress.stage' })} {current_stage}/{total_stages}\n </div>\n </div>\n\n {/* Slide 2: Stats */}\n <div className=\"w-full flex-shrink-0\">\n <div className=\"grid grid-cols-4 gap-2\">\n <div className=\"text-center p-2 bg-muted rounded\">\n <div className=\"text-lg font-bold\">{total_findings}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.fixProgress.stats.total' })}</div>\n </div>\n <div className=\"text-center p-2 bg-green-100 dark:bg-green-900/20 rounded\">\n <div className=\"text-lg font-bold text-green-600 dark:text-green-400\">{fixed_count}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.fixProgress.stats.fixed' })}</div>\n </div>\n <div className=\"text-center p-2 bg-red-100 dark:bg-red-900/20 rounded\">\n <div className=\"text-lg font-bold text-red-600 dark:text-red-400\">{failed_count}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.fixProgress.stats.failed' })}</div>\n </div>\n <div className=\"text-center p-2 bg-yellow-100 dark:bg-yellow-900/20 rounded\">\n <div className=\"text-lg font-bold text-yellow-600 dark:text-yellow-400\">{pending_count + in_progress_count}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.fixProgress.stats.pending' })}</div>\n </div>\n </div>\n </div>\n\n {/* Slide 3: Active Agents (if any) */}\n {active_agents.length > 0 && (\n <div className=\"w-full flex-shrink-0\">\n <div className=\"text-sm font-semibold mb-2\">\n {active_agents.length} {active_agents.length === 1 ? formatMessage({ id: 'reviewSession.fixProgress.activeAgents' }) : formatMessage({ id: 'reviewSession.fixProgress.activeAgentsPlural' })}\n </div>\n <div className=\"space-y-2\">\n {active_agents.slice(0, 2).map((agent, i) => (\n <div key={i} className=\"flex items-center gap-2 p-2 bg-muted rounded\">\n <span>🤖</span>\n <span className=\"text-sm\">{agent.current_finding?.finding_title || formatMessage({ id: 'reviewSession.fixProgress.working' })}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Carousel Navigation */}\n {totalSlides > 1 && (\n <div className=\"flex items-center justify-between gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigateSlide('prev')}>\n <ChevronLeftIcon className=\"h-4 w-4\" />\n </Button>\n <div className=\"flex gap-1\">\n {Array.from({ length: totalSlides }).map((_, i) => (\n <button\n key={i}\n className={`w-2 h-2 rounded-full transition-colors ${\n currentSlide === i ? 'bg-primary' : 'bg-gray-300 dark:bg-gray-600'\n }`}\n onClick={() => navigateSlide(i)}\n />\n ))}\n </div>\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigateSlide('next')}>\n <ChevronRightIcon className=\"h-4 w-4\" />\n </Button>\n </div>\n )}\n </CardContent>\n </Card>\n );\n}\n\n/**\n * ReviewSessionPage component - Display review session findings\n */\nexport function ReviewSessionPage() {\n const { sessionId } = useParams<{ sessionId: string }>();\n const navigate = useNavigate();\n const { formatMessage } = useIntl();\n const {\n reviewSession,\n flattenedFindings,\n severityCounts,\n isLoading,\n error,\n refetch,\n } = useReviewSession(sessionId);\n\n const [severityFilter, setSeverityFilter] = React.useState<Set<SeverityFilter>>(\n new Set(['critical', 'high', 'medium', 'low'])\n );\n const [dimensionFilter, setDimensionFilter] = React.useState<string>('all');\n const [searchQuery, setSearchQuery] = React.useState('');\n const [sortField, setSortField] = React.useState<SortField>('severity');\n const [sortOrder, setSortOrder] = React.useState<SortOrder>('desc');\n const [selectedFindings, setSelectedFindings] = React.useState<Set<string>>(new Set());\n const [selectedFindingId, setSelectedFindingId] = React.useState<string | null>(null);\n\n const handleBack = () => {\n navigate('/sessions');\n };\n\n const toggleSeverity = (severity: SeverityFilter) => {\n setSeverityFilter(prev => {\n const next = new Set(prev);\n if (next.has(severity)) {\n next.delete(severity);\n } else {\n next.add(severity);\n }\n return next;\n });\n };\n\n const resetFilters = () => {\n setSeverityFilter(new Set(['critical', 'high', 'medium', 'low']));\n setDimensionFilter('all');\n setSearchQuery('');\n };\n\n const toggleSelectFinding = (findingId: string) => {\n setSelectedFindings(prev => {\n const next = new Set(prev);\n if (next.has(findingId)) {\n next.delete(findingId);\n } else {\n next.add(findingId);\n }\n return next;\n });\n };\n\n const selectAllFindings = () => {\n const validIds = filteredFindings.map(f => f.id).filter((id): id is string => id !== undefined);\n setSelectedFindings(new Set(validIds));\n };\n\n const selectVisibleFindings = () => {\n const validIds = filteredFindings.map(f => f.id).filter((id): id is string => id !== undefined);\n setSelectedFindings(new Set(validIds));\n };\n\n const selectBySeverity = (severity: FindingWithSelection['severity']) => {\n const severityIds = flattenedFindings\n .filter(f => f.severity === severity && f.id !== undefined)\n .map(f => f.id!);\n setSelectedFindings(prev => {\n const next = new Set(prev);\n severityIds.forEach(id => next.add(id));\n return next;\n });\n };\n\n const clearSelection = () => {\n setSelectedFindings(new Set());\n };\n\n const handleFindingClick = (findingId: string) => {\n setSelectedFindingId(findingId);\n };\n\n const exportSelectedAsJson = () => {\n const selected = flattenedFindings.filter(f => f.id !== undefined && selectedFindings.has(f.id));\n if (selected.length === 0) return;\n\n const exportData = {\n session_id: sessionId,\n findings: selected.map(f => ({\n id: f.id,\n title: f.title,\n description: f.description,\n severity: f.severity,\n dimension: f.dimension,\n file: f.file,\n line: f.line,\n recommendations: f.recommendations,\n })),\n };\n\n const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `review-${sessionId}-fix.json`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n };\n\n // Severity order for sorting\n const severityOrder = { critical: 4, high: 3, medium: 2, low: 1 };\n\n // Calculate dimension counts\n const dimensionCounts = React.useMemo(() => {\n const counts: Record<string, number> = { all: flattenedFindings.length };\n flattenedFindings.forEach(f => {\n counts[f.dimension] = (counts[f.dimension] || 0) + 1;\n });\n return counts;\n }, [flattenedFindings]);\n\n // Filter and sort findings\n const filteredFindings = React.useMemo(() => {\n let filtered = flattenedFindings;\n\n // Apply dimension filter\n if (dimensionFilter !== 'all') {\n filtered = filtered.filter(f => f.dimension === dimensionFilter);\n }\n\n // Apply severity filter\n if (severityFilter.size > 0) {\n filtered = filtered.filter(f => severityFilter.has(f.severity));\n }\n\n // Apply search filter\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n filtered = filtered.filter(f =>\n f.title.toLowerCase().includes(query) ||\n f.description?.toLowerCase().includes(query) ||\n f.file?.toLowerCase().includes(query) ||\n f.dimension.toLowerCase().includes(query)\n );\n }\n\n // Apply sorting\n filtered = [...filtered].sort((a, b) => {\n let comparison = 0;\n switch (sortField) {\n case 'severity':\n comparison = severityOrder[a.severity] - severityOrder[b.severity];\n break;\n case 'dimension':\n comparison = a.dimension.localeCompare(b.dimension);\n break;\n case 'file':\n comparison = (a.file || '').localeCompare(b.file || '');\n break;\n }\n return sortOrder === 'asc' ? comparison : -comparison;\n });\n\n return filtered;\n }, [flattenedFindings, severityFilter, dimensionFilter, searchQuery, sortField, sortOrder]);\n\n // Get severity badge props\n const getSeverityBadge = (severity: FindingWithSelection['severity']) => {\n switch (severity) {\n case 'critical':\n return { variant: 'destructive' as const, icon: XCircle, label: formatMessage({ id: 'reviewSession.severity.critical' }) };\n case 'high':\n return { variant: 'warning' as const, icon: AlertTriangle, label: formatMessage({ id: 'reviewSession.severity.high' }) };\n case 'medium':\n return { variant: 'info' as const, icon: Info, label: formatMessage({ id: 'reviewSession.severity.medium' }) };\n case 'low':\n return { variant: 'secondary' as const, icon: CheckCircle, label: formatMessage({ id: 'reviewSession.severity.low' }) };\n }\n };\n\n // Loading state\n if (isLoading) {\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center gap-4\">\n <Button variant=\"ghost\" size=\"sm\" disabled>\n <ArrowLeft className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'common.actions.back' })}\n </Button>\n <div className=\"h-8 w-64 rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"h-64 rounded-lg bg-muted animate-pulse\" />\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive\">\n <XCircle className=\"h-5 w-5 flex-shrink-0\" />\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium\">{formatMessage({ id: 'common.errors.loadFailed' })}</p>\n <p className=\"text-xs mt-0.5\">{error.message}</p>\n </div>\n <Button variant=\"outline\" size=\"sm\" onClick={() => refetch()}>\n {formatMessage({ id: 'common.actions.retry' })}\n </Button>\n </div>\n );\n }\n\n // Session not found\n if (!reviewSession) {\n return (\n <div className=\"flex flex-col items-center justify-center py-16 px-4\">\n <FileText className=\"h-12 w-12 text-muted-foreground mb-4\" />\n <h3 className=\"text-lg font-medium text-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.notFound.title' })}\n </h3>\n <p className=\"text-sm text-muted-foreground mb-4\">\n {formatMessage({ id: 'reviewSession.notFound.message' })}\n </p>\n <Button onClick={handleBack}>\n <ArrowLeft className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'common.actions.back' })}\n </Button>\n </div>\n );\n }\n\n const dimensions = reviewSession.reviewDimensions || [];\n const totalFindings = flattenedFindings.length;\n\n // Determine session status (ACTIVE or ARCHIVED)\n const isActive = reviewSession._isActive !== false;\n const sessionStatus = isActive ? 'ACTIVE' : 'ARCHIVED';\n const phase = reviewSession.phase || 'in-progress';\n\n return (\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-4\">\n <Button variant=\"ghost\" size=\"sm\" onClick={handleBack}>\n <ArrowLeft className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'common.actions.back' })}\n </Button>\n <div>\n <h1 className=\"text-2xl font-semibold text-foreground flex items-center gap-2\">\n 🔍 {reviewSession.session_id}\n </h1>\n <div className=\"flex items-center gap-2 mt-1\">\n <Badge variant=\"review\">Review</Badge>\n <Badge variant={isActive ? \"success\" : \"secondary\"} className=\"text-xs\">\n {sessionStatus}\n </Badge>\n </div>\n </div>\n </div>\n </div>\n\n {/* Review Progress Section */}\n <Card>\n <CardContent className=\"p-4 space-y-4\">\n {/* Review Progress Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg\">📊</span>\n <span className=\"font-semibold\">{formatMessage({ id: 'reviewSession.progress.title' })}</span>\n </div>\n <Badge variant=\"secondary\">{phase.toUpperCase()}</Badge>\n </div>\n\n {/* Summary Cards Grid */}\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-3\">\n <div className=\"flex items-center gap-3 p-3 bg-muted rounded-lg\">\n <span className=\"text-2xl\">📊</span>\n <div>\n <div className=\"text-lg font-bold\">{totalFindings}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.progress.totalFindings' })}</div>\n </div>\n </div>\n <div className=\"flex items-center gap-3 p-3 bg-red-100 dark:bg-red-900/20 rounded-lg\">\n <span className=\"text-2xl\">🔴</span>\n <div>\n <div className=\"text-lg font-bold text-red-600 dark:text-red-400\">{severityCounts.critical}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.progress.critical' })}</div>\n </div>\n </div>\n <div className=\"flex items-center gap-3 p-3 bg-orange-100 dark:bg-orange-900/20 rounded-lg\">\n <span className=\"text-2xl\">🟠</span>\n <div>\n <div className=\"text-lg font-bold text-orange-600 dark:text-orange-400\">{severityCounts.high}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.progress.high' })}</div>\n </div>\n </div>\n <div className=\"flex items-center gap-3 p-3 bg-blue-100 dark:bg-blue-900/20 rounded-lg\">\n <span className=\"text-2xl\">🎯</span>\n <div>\n <div className=\"text-lg font-bold text-blue-600 dark:text-blue-400\">{dimensions.length}</div>\n <div className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'reviewSession.stats.dimensions' })}</div>\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n\n {/* Fix Progress Carousel — disabled: backend /api/fix-progress not implemented yet\n See FRONTEND_BACKEND_ALIGNMENT_AUDIT.md for details */}\n {/* {sessionId && <FixProgressCarousel sessionId={sessionId} />} */}\n\n {/* Unified Filter Card with Dimension Tabs */}\n <Card>\n <CardContent className=\"p-4 space-y-4\">\n {/* Top Bar: Search + Sort + Reset */}\n <div className=\"flex flex-wrap gap-3 items-center\">\n <div className=\"relative flex-1 min-w-[180px] max-w-md\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <input\n type=\"text\"\n placeholder={formatMessage({ id: 'reviewSession.search.placeholder' })}\n value={searchQuery}\n onChange={e => setSearchQuery(e.target.value)}\n className=\"w-full pl-10 pr-4 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\"\n />\n </div>\n <select\n value={sortField}\n onChange={e => setSortField(e.target.value as SortField)}\n className=\"px-3 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"severity\">{formatMessage({ id: 'reviewSession.sort.severity' })}</option>\n <option value=\"dimension\">{formatMessage({ id: 'reviewSession.sort.dimension' })}</option>\n <option value=\"file\">{formatMessage({ id: 'reviewSession.sort.file' })}</option>\n </select>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc')}\n className=\"w-9 p-0\"\n >\n {sortOrder === 'asc' ? '↑' : '↓'}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={resetFilters} className=\"text-muted-foreground hover:text-foreground\">\n ✕ {formatMessage({ id: 'reviewSession.filters.reset' })}\n </Button>\n </div>\n\n {/* Middle Row: Dimension Tabs + Severity Filters */}\n <div className=\"flex flex-col sm:flex-row gap-4\">\n {/* Dimension Tabs - Horizontal Scrollable */}\n <div className=\"flex-1\">\n <div className=\"text-xs font-medium text-muted-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.filters.dimension' })}\n </div>\n <div className=\"flex gap-1.5 overflow-x-auto pb-1 scrollbar-thin\">\n <button\n className={`px-3 py-1.5 rounded-md text-xs font-medium whitespace-nowrap transition-colors ${\n dimensionFilter === 'all'\n ? 'bg-primary text-primary-foreground shadow-sm'\n : 'bg-muted/50 text-muted-foreground hover:bg-muted'\n }`}\n onClick={() => setDimensionFilter('all')}\n >\n All ({dimensionCounts.all || 0})\n </button>\n {dimensions.map(dim => (\n <button\n key={dim.name}\n className={`px-3 py-1.5 rounded-md text-xs font-medium whitespace-nowrap transition-colors ${\n dimensionFilter === dim.name\n ? 'bg-primary text-primary-foreground shadow-sm'\n : 'bg-muted/50 text-muted-foreground hover:bg-muted'\n }`}\n onClick={() => setDimensionFilter(dim.name)}\n >\n {dim.name} ({dim.findings?.length || 0})\n </button>\n ))}\n </div>\n </div>\n\n {/* Severity Filters - Compact Pills */}\n <div className=\"sm:w-auto\">\n <div className=\"text-xs font-medium text-muted-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.filters.severity' })}\n </div>\n <div className=\"flex gap-1.5 flex-wrap\">\n {(['critical', 'high', 'medium', 'low'] as const).map(severity => {\n const isEnabled = severityFilter.has(severity);\n const colors = {\n critical: isEnabled ? 'bg-red-500 text-white border-red-500' : 'bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 border-red-200 dark:border-red-800',\n high: isEnabled ? 'bg-orange-500 text-white border-orange-500' : 'bg-orange-50 dark:bg-orange-900/20 text-orange-600 dark:text-orange-400 border-orange-200 dark:border-orange-800',\n medium: isEnabled ? 'bg-blue-500 text-white border-blue-500' : 'bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 border-blue-200 dark:border-blue-800',\n low: isEnabled ? 'bg-gray-500 text-white border-gray-500' : 'bg-gray-50 dark:bg-gray-900/20 text-gray-600 dark:text-gray-400 border-gray-200 dark:border-gray-800',\n };\n return (\n <label\n key={severity}\n className={`inline-flex items-center gap-1 px-2.5 py-1 rounded-md border text-xs font-medium cursor-pointer transition-all ${\n colors[severity]\n } ${isEnabled ? 'shadow-sm' : 'hover:opacity-80'}`}\n >\n <input\n type=\"checkbox\"\n checked={isEnabled}\n onChange={() => toggleSeverity(severity)}\n className=\"sr-only\"\n />\n <span>{formatMessage({ id: `reviewSession.severity.short.${severity}` })}</span>\n <span className=\"opacity-70\">({flattenedFindings.filter(f => f.severity === severity).length})</span>\n </label>\n );\n })}\n </div>\n </div>\n </div>\n\n {/* Bottom Bar: Selection Actions + Export */}\n <div className=\"flex flex-wrap items-center justify-between gap-3 pt-3 border-t border-border\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-xs text-muted-foreground px-2 py-1 bg-muted rounded-md\">\n {selectedFindings.size > 0\n ? formatMessage({ id: 'reviewSession.selection.countSelected' }, { count: selectedFindings.size })\n : formatMessage({ id: 'reviewSession.selection.total' }, { count: filteredFindings.length })\n }\n </span>\n {selectedFindings.size > 0 && (\n <>\n <Button variant=\"outline\" size=\"sm\" onClick={clearSelection} className=\"h-8 text-xs\">\n {formatMessage({ id: 'reviewSession.selection.clear' })}\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={() => selectBySeverity('critical')} className=\"h-8 text-xs\">\n 🔥 {formatMessage({ id: 'reviewSession.selection.selectCritical' })}\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={selectVisibleFindings} className=\"h-8 text-xs\">\n {formatMessage({ id: 'reviewSession.selection.selectVisible' })}\n </Button>\n </>\n )}\n {selectedFindings.size === 0 && (\n <Button variant=\"outline\" size=\"sm\" onClick={selectAllFindings} className=\"h-8 text-xs\">\n {formatMessage({ id: 'reviewSession.selection.selectAll' })}\n </Button>\n )}\n </div>\n <Button\n variant={selectedFindings.size > 0 ? 'default' : 'outline'}\n size=\"sm\"\n onClick={exportSelectedAsJson}\n disabled={selectedFindings.size === 0}\n className=\"h-8 gap-1.5 text-xs\"\n >\n <Download className=\"h-3.5 w-3.5\" />\n 🔧 {formatMessage({ id: 'reviewSession.export' })}\n </Button>\n </div>\n </CardContent>\n </Card>\n\n {/* Split Panel: Findings List + Preview */}\n {filteredFindings.length === 0 ? (\n <Card>\n <CardContent className=\"p-12 text-center\">\n {/* Check if review hasn't been executed yet */}\n {reviewSession?.reviewSummary?.status === 'in_progress' &&\n (!reviewSession?.reviewDimensions || reviewSession.reviewDimensions.length === 0) ? (\n <>\n <AlertTriangle className=\"h-12 w-12 text-amber-500 mx-auto mb-4\" />\n <h3 className=\"text-lg font-medium text-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.notExecuted.title' })}\n </h3>\n <p className=\"text-sm text-muted-foreground mb-4\">\n {formatMessage({ id: 'reviewSession.notExecuted.message' })}\n </p>\n <div className=\"text-xs text-muted-foreground bg-muted p-3 rounded-lg inline-block\">\n {formatMessage({ id: 'reviewSession.notExecuted.hint' })}\n </div>\n </>\n ) : (\n <>\n <FileText className=\"h-12 w-12 text-muted-foreground mx-auto mb-4\" />\n <h3 className=\"text-lg font-medium text-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.empty.title' })}\n </h3>\n <p className=\"text-sm text-muted-foreground\">\n {formatMessage({ id: 'reviewSession.empty.message' })}\n </p>\n </>\n )}\n </CardContent>\n </Card>\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-[minmax(0,45fr)_minmax(0,55fr)] gap-4\">\n {/* Left Panel: Findings List */}\n <Card>\n <CardContent className=\"p-4\">\n <div className=\"flex items-center justify-between mb-3\">\n <span className=\"text-sm font-medium\">\n {formatMessage({ id: 'reviewSession.findingsList.count' }, { count: filteredFindings.length })}\n </span>\n </div>\n <div className=\"space-y-2 max-h-[600px] overflow-y-auto\">\n {filteredFindings.filter(f => f.id !== undefined).map(finding => {\n const findingId = finding.id!;\n const isSelected = selectedFindings.has(findingId);\n const isPreviewing = selectedFindingId === findingId;\n const badge = getSeverityBadge(finding.severity);\n const BadgeIcon = badge.icon;\n\n return (\n <div\n key={findingId}\n className={`p-3 rounded-lg border cursor-pointer transition-colors ${\n isPreviewing\n ? 'bg-primary/10 border-primary'\n : 'bg-background border-border hover:bg-muted'\n }`}\n onClick={() => handleFindingClick(findingId)}\n >\n <div className=\"flex items-start gap-2\">\n {/* Checkbox */}\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={(e) => {\n e.stopPropagation();\n toggleSelectFinding(findingId);\n }}\n className=\"mt-0.5 flex-shrink-0\"\n />\n\n {/* Compact Finding Content */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 mb-1 flex-wrap\">\n <Badge variant={badge.variant} className=\"gap-1 text-xs\">\n <BadgeIcon className=\"h-2.5 w-2.5\" />\n {badge.label}\n </Badge>\n <span className=\"text-xs text-muted-foreground\">\n {finding.dimension}\n </span>\n </div>\n <p className=\"text-sm font-medium text-foreground truncate\">\n {finding.title}\n </p>\n {finding.file && (\n <p className=\"text-xs text-muted-foreground font-mono truncate mt-0.5\">\n {finding.file}:{finding.line || '?'}\n </p>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n\n {/* Right Panel: Enhanced Preview */}\n <Card className=\"sticky top-4 self-start\">\n <CardContent className=\"p-0 h-full min-h-[500px]\">\n {!selectedFindingId ? (\n // Enhanced Empty State\n <div className=\"flex flex-col items-center justify-center h-full min-h-[400px] p-8 text-center bg-gradient-to-br from-muted/30 to-muted/10\">\n <div className=\"w-20 h-20 rounded-full bg-muted flex items-center justify-center mb-4\">\n <Search className=\"h-10 w-10 text-muted-foreground\" />\n </div>\n <h3 className=\"text-base font-semibold text-foreground mb-2\">\n {formatMessage({ id: 'reviewSession.preview.emptyTitle' })}\n </h3>\n <p className=\"text-sm text-muted-foreground mb-4 max-w-[250px]\">\n {formatMessage({ id: 'reviewSession.preview.empty' })}\n </p>\n <div className=\"flex flex-wrap gap-2 justify-center\">\n <div className=\"flex items-center gap-1.5 px-3 py-1.5 bg-background rounded-lg border text-xs\">\n <span className=\"w-2 h-2 rounded-full bg-destructive\"></span>\n {formatMessage({ id: 'reviewSession.preview.emptyTipSeverity' })}\n </div>\n <div className=\"flex items-center gap-1.5 px-3 py-1.5 bg-background rounded-lg border text-xs\">\n <span>📁</span>\n {formatMessage({ id: 'reviewSession.preview.emptyTipFile' })}\n </div>\n </div>\n </div>\n ) : (\n // Preview Content\n (() => {\n const finding = flattenedFindings.find(f => f.id === selectedFindingId);\n if (!finding) return null;\n\n const badge = getSeverityBadge(finding.severity);\n const BadgeIcon = badge.icon;\n const isSelected = selectedFindings.has(selectedFindingId);\n\n // Find adjacent findings for navigation\n const findingIndex = filteredFindings.findIndex(f => f.id === selectedFindingId);\n const prevFinding = findingIndex > 0 ? filteredFindings[findingIndex - 1] : null;\n const nextFinding = findingIndex < filteredFindings.length - 1 ? filteredFindings[findingIndex + 1] : null;\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Sticky Header */}\n <div className=\"sticky top-0 z-10 bg-background border-b border-border p-4 space-y-3\">\n {/* Navigation + Badges Row */}\n <div className=\"flex items-center justify-between gap-2\">\n {/* Navigation Buttons */}\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => prevFinding && handleFindingClick(prevFinding.id!)}\n disabled={!prevFinding}\n className=\"h-8 w-8 p-0\"\n >\n <ChevronRight className=\"h-4 w-4 rotate-180\" />\n </Button>\n <span className=\"text-xs text-muted-foreground px-2\">\n {findingIndex + 1} / {filteredFindings.length}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => nextFinding && handleFindingClick(nextFinding.id!)}\n disabled={!nextFinding}\n className=\"h-8 w-8 p-0\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n </div>\n\n {/* Badges */}\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n <Badge variant={badge.variant} className=\"gap-1 text-xs\">\n <BadgeIcon className=\"h-3 w-3\" />\n {badge.label}\n </Badge>\n <Badge variant=\"outline\" className=\"text-xs\">\n {finding.dimension}\n </Badge>\n </div>\n\n {/* Select Button */}\n <Button\n variant={isSelected ? 'default' : 'outline'}\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n toggleSelectFinding(selectedFindingId);\n }}\n className=\"h-8 text-xs\"\n >\n {isSelected ? (\n <>\n <CheckCircle className=\"h-3.5 w-3.5 mr-1\" />\n {formatMessage({ id: 'reviewSession.preview.selected' })}\n </>\n ) : (\n <>\n <span className=\"mr-1\">⊕</span>\n {formatMessage({ id: 'reviewSession.preview.selectForFix' })}\n </>\n )}\n </Button>\n </div>\n\n {/* Title */}\n <h3 className=\"text-base font-semibold text-foreground line-clamp-2\">\n {finding.title}\n </h3>\n\n {/* Quick Info Bar */}\n <div className=\"flex items-center gap-3 text-xs\">\n {finding.file && (\n <div className=\"flex items-center gap-1 text-muted-foreground flex-1 min-w-0\">\n <span className=\"flex-shrink-0\">📁</span>\n <code className=\"truncate\">{finding.file}:{finding.line || '?'}</code>\n </div>\n )}\n </div>\n </div>\n\n {/* Scrollable Content */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4\">\n {/* Description */}\n {finding.description && (\n <div className=\"bg-muted/30 rounded-lg p-3\">\n <div className=\"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5\">\n <span>📝</span>\n {formatMessage({ id: 'reviewSession.preview.description' })}\n </div>\n <p className=\"text-sm text-foreground leading-relaxed\">\n {finding.description}\n </p>\n </div>\n )}\n\n {/* Code Context */}\n {finding.code_context && (\n <div>\n <div className=\"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5\">\n <span>💻</span>\n {formatMessage({ id: 'reviewSession.preview.codeContext' })}\n </div>\n <pre className=\"text-xs bg-muted p-3 rounded-lg overflow-x-auto border border-border\">\n <code className=\"text-foreground\">{finding.code_context}</code>\n </pre>\n </div>\n )}\n\n {/* Root Cause */}\n {finding.root_cause && (\n <div>\n <div className=\"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5\">\n <span>🎯</span>\n {formatMessage({ id: 'reviewSession.preview.rootCause' })}\n </div>\n <p className=\"text-sm text-foreground bg-muted/30 rounded-lg p-3 leading-relaxed\">\n {finding.root_cause}\n </p>\n </div>\n )}\n\n {/* Impact */}\n {finding.impact && (\n <div>\n <div className=\"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5\">\n <span>⚠️</span>\n {formatMessage({ id: 'reviewSession.preview.impact' })}\n </div>\n <p className=\"text-sm text-foreground bg-orange-50 dark:bg-orange-900/20 rounded-lg p-3 leading-relaxed border border-orange-200 dark:border-orange-800\">\n {finding.impact}\n </p>\n </div>\n )}\n\n {/* Recommendations */}\n {finding.recommendations && finding.recommendations.length > 0 && (\n <div>\n <div className=\"text-xs font-semibold text-foreground mb-1.5 flex items-center gap-1.5\">\n <span>✅</span>\n {formatMessage({ id: 'reviewSession.preview.recommendations' })}\n </div>\n <ul className=\"space-y-2\">\n {finding.recommendations.map((rec, idx) => (\n <li key={idx} className=\"text-sm text-foreground flex items-start gap-2 bg-green-50 dark:bg-green-900/20 rounded-lg p-3 border border-green-200 dark:border-green-800\">\n <span className=\"text-green-600 dark:text-green-400 flex-shrink-0 mt-0.5\">✓</span>\n <span className=\"leading-relaxed\">{rec}</span>\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n </div>\n );\n })()\n )}\n </CardContent>\n </Card>\n </div>\n )}\n </div>\n );\n}\n\nexport default ReviewSessionPage;\n"],"names":["useReviewSession","sessionId","reviewSession","isLoading","error","refetch","useQuery","fetchReviewSession","flattenedFindings","React","findings","dim","f","severityCounts","counts","sev","ReviewSessionPage","useParams","navigate","useNavigate","formatMessage","useIntl","severityFilter","setSeverityFilter","React.useState","dimensionFilter","setDimensionFilter","searchQuery","setSearchQuery","sortField","setSortField","sortOrder","setSortOrder","selectedFindings","setSelectedFindings","selectedFindingId","setSelectedFindingId","handleBack","toggleSeverity","severity","prev","next","resetFilters","toggleSelectFinding","findingId","selectAllFindings","validIds","filteredFindings","id","selectVisibleFindings","selectBySeverity","severityIds","clearSelection","handleFindingClick","exportSelectedAsJson","selected","exportData","blob","url","severityOrder","dimensionCounts","React.useMemo","filtered","query","_a","_b","a","b","comparison","getSeverityBadge","XCircle","AlertTriangle","Info","CheckCircle","jsxs","Button","jsx","ArrowLeft","FileText","dimensions","totalFindings","isActive","sessionStatus","phase","Badge","Card","CardContent","Search","e","isEnabled","colors","Fragment","Download","finding","isSelected","isPreviewing","badge","BadgeIcon","findingIndex","prevFinding","nextFinding","ChevronRight","rec","idx"],"mappings":"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"}
|