@girardelli/architect 5.0.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/INDEX.md +197 -0
- package/.agent/agents/AGENT-ORCHESTRATOR.md +408 -0
- package/.agent/agents/QA-TEST-ENGINEER.md +152 -0
- package/.agent/agents/SECURITY-AUDITOR.md +87 -0
- package/.agent/agents/TECH-DEBT-CONTROLLER.md +154 -0
- package/.agent/agents/TYPESCRIPT-BACKEND-DEVELOPER.md +484 -0
- package/.agent/guards/CODE-REVIEW-CHECKLIST.md +94 -0
- package/.agent/guards/PREFLIGHT.md +200 -0
- package/.agent/guards/QUALITY-GATES.md +212 -0
- package/.agent/hooks/post-analysis.sh +64 -0
- package/.agent/hooks/pre-commit.sh +68 -0
- package/.agent/hooks/pre-push.sh +59 -0
- package/.agent/rules/00-general.md +229 -0
- package/.agent/rules/01-architecture.md +182 -0
- package/.agent/rules/02-security.md +388 -0
- package/.agent/skills/ARCHITECT-INTEGRATION.md +103 -0
- package/.agent/skills/CI-PIPELINE.md +113 -0
- package/.agent/skills/PROJECT-PATTERNS.md +62 -0
- package/.agent/templates/ADR.md +95 -0
- package/.agent/templates/BDD.md +57 -0
- package/.agent/templates/C4.md +67 -0
- package/.agent/templates/TDD.md +86 -0
- package/.agent/templates/THREAT-MODEL.md +63 -0
- package/.agent/workflows/fix-bug.md +228 -0
- package/.agent/workflows/new-feature.md +311 -0
- package/.agent/workflows/review.md +95 -0
- package/.github/workflows/ci.yml +43 -0
- package/.github/workflows/publish.yml +40 -0
- package/README.md +6 -2
- package/architect-report--girardelli-architect.json +5332 -0
- package/architect-run.sh +6 -10
- package/debug.js +6 -0
- package/dist/adapters/cli.d.ts +14 -0
- package/dist/adapters/cli.d.ts.map +1 -0
- package/dist/{cli.js → adapters/cli.js} +11 -8
- package/dist/adapters/cli.js.map +1 -0
- package/dist/adapters/html-reporter/scripts.d.ts +6 -0
- package/dist/adapters/html-reporter/scripts.d.ts.map +1 -0
- package/dist/adapters/html-reporter/scripts.js +400 -0
- package/dist/adapters/html-reporter/scripts.js.map +1 -0
- package/dist/adapters/html-reporter/sections/agents.d.ts +3 -0
- package/dist/adapters/html-reporter/sections/agents.d.ts.map +1 -0
- package/dist/adapters/html-reporter/sections/agents.js +259 -0
- package/dist/adapters/html-reporter/sections/agents.js.map +1 -0
- package/dist/adapters/html-reporter/sections/anti-patterns.d.ts +14 -0
- package/dist/adapters/html-reporter/sections/anti-patterns.d.ts.map +1 -0
- package/dist/adapters/html-reporter/sections/anti-patterns.js +64 -0
- package/dist/adapters/html-reporter/sections/anti-patterns.js.map +1 -0
- package/dist/adapters/html-reporter/sections/header.d.ts +4 -0
- package/dist/adapters/html-reporter/sections/header.d.ts.map +1 -0
- package/dist/adapters/html-reporter/sections/header.js +30 -0
- package/dist/adapters/html-reporter/sections/header.js.map +1 -0
- package/dist/adapters/html-reporter/sections/layers.d.ts +10 -0
- package/dist/adapters/html-reporter/sections/layers.d.ts.map +1 -0
- package/dist/adapters/html-reporter/sections/layers.js +143 -0
- package/dist/adapters/html-reporter/sections/layers.js.map +1 -0
- package/dist/adapters/html-reporter/sections/overview.d.ts +3 -0
- package/dist/adapters/html-reporter/sections/overview.d.ts.map +1 -0
- package/dist/adapters/html-reporter/sections/overview.js +58 -0
- package/dist/adapters/html-reporter/sections/overview.js.map +1 -0
- package/dist/adapters/html-reporter/sections/refactoring-plan.d.ts +4 -0
- package/dist/adapters/html-reporter/sections/refactoring-plan.d.ts.map +1 -0
- package/dist/adapters/html-reporter/sections/refactoring-plan.js +151 -0
- package/dist/adapters/html-reporter/sections/refactoring-plan.js.map +1 -0
- package/dist/adapters/html-reporter/sections/score.d.ts +8 -0
- package/dist/adapters/html-reporter/sections/score.d.ts.map +1 -0
- package/dist/adapters/html-reporter/sections/score.js +69 -0
- package/dist/adapters/html-reporter/sections/score.js.map +1 -0
- package/dist/adapters/html-reporter/sections/suggestions.d.ts +8 -0
- package/dist/adapters/html-reporter/sections/suggestions.d.ts.map +1 -0
- package/dist/adapters/html-reporter/sections/suggestions.js +34 -0
- package/dist/adapters/html-reporter/sections/suggestions.js.map +1 -0
- package/dist/adapters/html-reporter/styles.d.ts +2 -0
- package/dist/adapters/html-reporter/styles.d.ts.map +1 -0
- package/dist/adapters/html-reporter/styles.js +526 -0
- package/dist/adapters/html-reporter/styles.js.map +1 -0
- package/dist/adapters/html-reporter/utils.d.ts +27 -0
- package/dist/adapters/html-reporter/utils.d.ts.map +1 -0
- package/dist/adapters/html-reporter/utils.js +82 -0
- package/dist/adapters/html-reporter/utils.js.map +1 -0
- package/dist/adapters/html-reporter/utils_adapters.d.ts +21 -0
- package/dist/adapters/html-reporter/utils_adapters.d.ts.map +1 -0
- package/dist/adapters/html-reporter/utils_adapters.js +32 -0
- package/dist/adapters/html-reporter/utils_adapters.js.map +1 -0
- package/dist/adapters/html-reporter/utils_sections.d.ts +8 -0
- package/dist/adapters/html-reporter/utils_sections.d.ts.map +1 -0
- package/dist/adapters/html-reporter/utils_sections.js +58 -0
- package/dist/adapters/html-reporter/utils_sections.js.map +1 -0
- package/dist/adapters/html-reporter.d.ts +9 -0
- package/dist/adapters/html-reporter.d.ts.map +1 -0
- package/dist/adapters/html-reporter.js +87 -0
- package/dist/adapters/html-reporter.js.map +1 -0
- package/dist/adapters/html-reporter_deps.d.ts +15 -0
- package/dist/adapters/html-reporter_deps.d.ts.map +1 -0
- package/dist/adapters/html-reporter_deps.js +12 -0
- package/dist/adapters/html-reporter_deps.js.map +1 -0
- package/dist/adapters/refactor-reporter.d.ts +20 -0
- package/dist/adapters/refactor-reporter.d.ts.map +1 -0
- package/dist/adapters/refactor-reporter.js +389 -0
- package/dist/adapters/refactor-reporter.js.map +1 -0
- package/dist/adapters/reporter.d.ts +13 -0
- package/dist/adapters/reporter.d.ts.map +1 -0
- package/dist/adapters/reporter.js +135 -0
- package/dist/adapters/reporter.js.map +1 -0
- package/dist/agent-generator/context-enricher.d.ts +4 -47
- package/dist/agent-generator/context-enricher.d.ts.map +1 -1
- package/dist/agent-generator/context-enricher.js +13 -573
- package/dist/agent-generator/context-enricher.js.map +1 -1
- package/dist/agent-generator/detectors/base-detector.d.ts +9 -0
- package/dist/agent-generator/detectors/base-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/base-detector.js +12 -0
- package/dist/agent-generator/detectors/base-detector.js.map +1 -0
- package/dist/agent-generator/detectors/dart-detector.d.ts +6 -0
- package/dist/agent-generator/detectors/dart-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/dart-detector.js +15 -0
- package/dist/agent-generator/detectors/dart-detector.js.map +1 -0
- package/dist/agent-generator/detectors/framework-registry.d.ts +6 -0
- package/dist/agent-generator/detectors/framework-registry.d.ts.map +1 -0
- package/dist/agent-generator/detectors/framework-registry.js +81 -0
- package/dist/agent-generator/detectors/framework-registry.js.map +1 -0
- package/dist/agent-generator/detectors/go-detector.d.ts +6 -0
- package/dist/agent-generator/detectors/go-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/go-detector.js +25 -0
- package/dist/agent-generator/detectors/go-detector.js.map +1 -0
- package/dist/agent-generator/detectors/java-detector.d.ts +6 -0
- package/dist/agent-generator/detectors/java-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/java-detector.js +44 -0
- package/dist/agent-generator/detectors/java-detector.js.map +1 -0
- package/dist/agent-generator/detectors/node-detector.d.ts +6 -0
- package/dist/agent-generator/detectors/node-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/node-detector.js +28 -0
- package/dist/agent-generator/detectors/node-detector.js.map +1 -0
- package/dist/agent-generator/detectors/php-detector.d.ts +6 -0
- package/dist/agent-generator/detectors/php-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/php-detector.js +28 -0
- package/dist/agent-generator/detectors/php-detector.js.map +1 -0
- package/dist/agent-generator/detectors/python-detector.d.ts +8 -0
- package/dist/agent-generator/detectors/python-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/python-detector.js +116 -0
- package/dist/agent-generator/detectors/python-detector.js.map +1 -0
- package/dist/agent-generator/detectors/ruby-detector.d.ts +6 -0
- package/dist/agent-generator/detectors/ruby-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/ruby-detector.js +22 -0
- package/dist/agent-generator/detectors/ruby-detector.js.map +1 -0
- package/dist/agent-generator/detectors/rust-detector.d.ts +6 -0
- package/dist/agent-generator/detectors/rust-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/rust-detector.js +18 -0
- package/dist/agent-generator/detectors/rust-detector.js.map +1 -0
- package/dist/agent-generator/detectors/structure-detector.d.ts +5 -0
- package/dist/agent-generator/detectors/structure-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/structure-detector.js +35 -0
- package/dist/agent-generator/detectors/structure-detector.js.map +1 -0
- package/dist/agent-generator/detectors/toolchain-detector.d.ts +6 -0
- package/dist/agent-generator/detectors/toolchain-detector.d.ts.map +1 -0
- package/dist/agent-generator/detectors/toolchain-detector.js +163 -0
- package/dist/agent-generator/detectors/toolchain-detector.js.map +1 -0
- package/dist/agent-generator/engines/audit-engine.d.ts +7 -0
- package/dist/agent-generator/engines/audit-engine.d.ts.map +1 -0
- package/dist/agent-generator/engines/audit-engine.js +84 -0
- package/dist/agent-generator/engines/audit-engine.js.map +1 -0
- package/dist/agent-generator/engines/context-builder.d.ts +11 -0
- package/dist/agent-generator/engines/context-builder.d.ts.map +1 -0
- package/dist/agent-generator/engines/context-builder.js +86 -0
- package/dist/agent-generator/engines/context-builder.js.map +1 -0
- package/dist/agent-generator/engines/generation-engine.d.ts +9 -0
- package/dist/agent-generator/engines/generation-engine.d.ts.map +1 -0
- package/dist/agent-generator/engines/generation-engine.js +177 -0
- package/dist/agent-generator/engines/generation-engine.js.map +1 -0
- package/dist/agent-generator/engines/suggestion-engine.d.ts +15 -0
- package/dist/agent-generator/engines/suggestion-engine.d.ts.map +1 -0
- package/dist/agent-generator/engines/suggestion-engine.js +176 -0
- package/dist/agent-generator/engines/suggestion-engine.js.map +1 -0
- package/dist/agent-generator/enrichers/analysis-helpers.d.ts +9 -0
- package/dist/agent-generator/enrichers/analysis-helpers.d.ts.map +1 -0
- package/dist/agent-generator/enrichers/analysis-helpers.js +51 -0
- package/dist/agent-generator/enrichers/analysis-helpers.js.map +1 -0
- package/dist/agent-generator/enrichers/description-generator.d.ts +5 -0
- package/dist/agent-generator/enrichers/description-generator.d.ts.map +1 -0
- package/dist/agent-generator/enrichers/description-generator.js +81 -0
- package/dist/agent-generator/enrichers/description-generator.js.map +1 -0
- package/dist/agent-generator/enrichers/endpoint-extractor.d.ts +8 -0
- package/dist/agent-generator/enrichers/endpoint-extractor.d.ts.map +1 -0
- package/dist/agent-generator/enrichers/endpoint-extractor.js +91 -0
- package/dist/agent-generator/enrichers/endpoint-extractor.js.map +1 -0
- package/dist/agent-generator/enrichers/layer-classifier.d.ts +13 -0
- package/dist/agent-generator/enrichers/layer-classifier.d.ts.map +1 -0
- package/dist/agent-generator/enrichers/layer-classifier.js +150 -0
- package/dist/agent-generator/enrichers/layer-classifier.js.map +1 -0
- package/dist/agent-generator/enrichers/module-extractor.d.ts +11 -0
- package/dist/agent-generator/enrichers/module-extractor.d.ts.map +1 -0
- package/dist/agent-generator/enrichers/module-extractor.js +174 -0
- package/dist/agent-generator/enrichers/module-extractor.js.map +1 -0
- package/dist/agent-generator/framework-detector.d.ts +4 -26
- package/dist/agent-generator/framework-detector.d.ts.map +1 -1
- package/dist/agent-generator/framework-detector.js +31 -584
- package/dist/agent-generator/framework-detector.js.map +1 -1
- package/dist/agent-generator/index.d.ts +8 -33
- package/dist/agent-generator/index.d.ts.map +1 -1
- package/dist/agent-generator/index.js +18 -524
- package/dist/agent-generator/index.js.map +1 -1
- package/dist/agent-generator/templates/helpers/base-helpers.d.ts +11 -0
- package/dist/agent-generator/templates/helpers/base-helpers.d.ts.map +1 -0
- package/dist/agent-generator/templates/helpers/base-helpers.js +20 -0
- package/dist/agent-generator/templates/helpers/base-helpers.js.map +1 -0
- package/dist/agent-generator/templates/helpers/cross-ref-helpers.d.ts +3 -0
- package/dist/agent-generator/templates/helpers/cross-ref-helpers.d.ts.map +1 -0
- package/dist/agent-generator/templates/helpers/cross-ref-helpers.js +77 -0
- package/dist/agent-generator/templates/helpers/cross-ref-helpers.js.map +1 -0
- package/dist/agent-generator/templates/helpers/security-helpers.d.ts +3 -0
- package/dist/agent-generator/templates/helpers/security-helpers.d.ts.map +1 -0
- package/dist/agent-generator/templates/helpers/security-helpers.js +182 -0
- package/dist/agent-generator/templates/helpers/security-helpers.js.map +1 -0
- package/dist/agent-generator/templates/helpers/stack-helpers.d.ts +5 -0
- package/dist/agent-generator/templates/helpers/stack-helpers.d.ts.map +1 -0
- package/dist/agent-generator/templates/helpers/stack-helpers.js +69 -0
- package/dist/agent-generator/templates/helpers/stack-helpers.js.map +1 -0
- package/dist/agent-generator/templates/helpers/structure-helpers.d.ts +3 -0
- package/dist/agent-generator/templates/helpers/structure-helpers.d.ts.map +1 -0
- package/dist/agent-generator/templates/helpers/structure-helpers.js +275 -0
- package/dist/agent-generator/templates/helpers/structure-helpers.js.map +1 -0
- package/dist/agent-generator/templates/helpers/summary-helpers.d.ts +7 -0
- package/dist/agent-generator/templates/helpers/summary-helpers.d.ts.map +1 -0
- package/dist/agent-generator/templates/helpers/summary-helpers.js +56 -0
- package/dist/agent-generator/templates/helpers/summary-helpers.js.map +1 -0
- package/dist/agent-generator/templates/template-helpers.d.ts +9 -72
- package/dist/agent-generator/templates/template-helpers.d.ts.map +1 -1
- package/dist/agent-generator/templates/template-helpers.js +9 -723
- package/dist/agent-generator/templates/template-helpers.js.map +1 -1
- package/dist/analyzers/git-history.d.ts +1 -1
- package/dist/analyzers/git-history.d.ts.map +1 -1
- package/dist/analyzers/git-history.js +16 -10
- package/dist/analyzers/git-history.js.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-generator/context-enricher.d.ts +18 -0
- package/dist/core/agent-generator/context-enricher.d.ts.map +1 -0
- package/dist/core/agent-generator/context-enricher.js +53 -0
- package/dist/core/agent-generator/context-enricher.js.map +1 -0
- package/dist/core/agent-generator/detectors/base-detector.d.ts +9 -0
- package/dist/core/agent-generator/detectors/base-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/base-detector.js +12 -0
- package/dist/core/agent-generator/detectors/base-detector.js.map +1 -0
- package/dist/core/agent-generator/detectors/dart-detector.d.ts +6 -0
- package/dist/core/agent-generator/detectors/dart-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/dart-detector.js +15 -0
- package/dist/core/agent-generator/detectors/dart-detector.js.map +1 -0
- package/dist/core/agent-generator/detectors/framework-registry.d.ts +6 -0
- package/dist/core/agent-generator/detectors/framework-registry.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/framework-registry.js +81 -0
- package/dist/core/agent-generator/detectors/framework-registry.js.map +1 -0
- package/dist/core/agent-generator/detectors/go-detector.d.ts +6 -0
- package/dist/core/agent-generator/detectors/go-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/go-detector.js +25 -0
- package/dist/core/agent-generator/detectors/go-detector.js.map +1 -0
- package/dist/core/agent-generator/detectors/java-detector.d.ts +6 -0
- package/dist/core/agent-generator/detectors/java-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/java-detector.js +44 -0
- package/dist/core/agent-generator/detectors/java-detector.js.map +1 -0
- package/dist/core/agent-generator/detectors/node-detector.d.ts +6 -0
- package/dist/core/agent-generator/detectors/node-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/node-detector.js +28 -0
- package/dist/core/agent-generator/detectors/node-detector.js.map +1 -0
- package/dist/core/agent-generator/detectors/php-detector.d.ts +6 -0
- package/dist/core/agent-generator/detectors/php-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/php-detector.js +28 -0
- package/dist/core/agent-generator/detectors/php-detector.js.map +1 -0
- package/dist/core/agent-generator/detectors/python-detector.d.ts +8 -0
- package/dist/core/agent-generator/detectors/python-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/python-detector.js +116 -0
- package/dist/core/agent-generator/detectors/python-detector.js.map +1 -0
- package/dist/core/agent-generator/detectors/ruby-detector.d.ts +6 -0
- package/dist/core/agent-generator/detectors/ruby-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/ruby-detector.js +22 -0
- package/dist/core/agent-generator/detectors/ruby-detector.js.map +1 -0
- package/dist/core/agent-generator/detectors/rust-detector.d.ts +6 -0
- package/dist/core/agent-generator/detectors/rust-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/rust-detector.js +18 -0
- package/dist/core/agent-generator/detectors/rust-detector.js.map +1 -0
- package/dist/core/agent-generator/detectors/structure-detector.d.ts +5 -0
- package/dist/core/agent-generator/detectors/structure-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/structure-detector.js +35 -0
- package/dist/core/agent-generator/detectors/structure-detector.js.map +1 -0
- package/dist/core/agent-generator/detectors/toolchain-detector.d.ts +6 -0
- package/dist/core/agent-generator/detectors/toolchain-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/detectors/toolchain-detector.js +163 -0
- package/dist/core/agent-generator/detectors/toolchain-detector.js.map +1 -0
- package/dist/core/agent-generator/domain-inferrer.d.ts +52 -0
- package/dist/core/agent-generator/domain-inferrer.d.ts.map +1 -0
- package/dist/core/agent-generator/domain-inferrer.js +585 -0
- package/dist/core/agent-generator/domain-inferrer.js.map +1 -0
- package/dist/core/agent-generator/engines/audit-engine.d.ts +9 -0
- package/dist/core/agent-generator/engines/audit-engine.d.ts.map +1 -0
- package/dist/core/agent-generator/engines/audit-engine.js +84 -0
- package/dist/core/agent-generator/engines/audit-engine.js.map +1 -0
- package/dist/core/agent-generator/engines/context-builder.d.ts +13 -0
- package/dist/core/agent-generator/engines/context-builder.d.ts.map +1 -0
- package/dist/core/agent-generator/engines/context-builder.js +86 -0
- package/dist/core/agent-generator/engines/context-builder.js.map +1 -0
- package/dist/core/agent-generator/engines/generation-engine.d.ts +8 -0
- package/dist/core/agent-generator/engines/generation-engine.d.ts.map +1 -0
- package/dist/core/agent-generator/engines/generation-engine.js +162 -0
- package/dist/core/agent-generator/engines/generation-engine.js.map +1 -0
- package/dist/core/agent-generator/engines/generation-engine_deps.d.ts +22 -0
- package/dist/core/agent-generator/engines/generation-engine_deps.d.ts.map +1 -0
- package/dist/core/agent-generator/engines/generation-engine_deps.js +17 -0
- package/dist/core/agent-generator/engines/generation-engine_deps.js.map +1 -0
- package/dist/core/agent-generator/engines/suggestion-engine.d.ts +14 -0
- package/dist/core/agent-generator/engines/suggestion-engine.d.ts.map +1 -0
- package/dist/core/agent-generator/engines/suggestion-engine.js +173 -0
- package/dist/core/agent-generator/engines/suggestion-engine.js.map +1 -0
- package/dist/core/agent-generator/engines/suggestion-engine_deps.d.ts +9 -0
- package/dist/core/agent-generator/engines/suggestion-engine_deps.d.ts.map +1 -0
- package/dist/core/agent-generator/engines/suggestion-engine_deps.js +5 -0
- package/dist/core/agent-generator/engines/suggestion-engine_deps.js.map +1 -0
- package/dist/core/agent-generator/enrichers/analysis-helpers.d.ts +10 -0
- package/dist/core/agent-generator/enrichers/analysis-helpers.d.ts.map +1 -0
- package/dist/core/agent-generator/enrichers/analysis-helpers.js +51 -0
- package/dist/core/agent-generator/enrichers/analysis-helpers.js.map +1 -0
- package/dist/core/agent-generator/enrichers/description-generator.d.ts +5 -0
- package/dist/core/agent-generator/enrichers/description-generator.d.ts.map +1 -0
- package/dist/core/agent-generator/enrichers/description-generator.js +81 -0
- package/dist/core/agent-generator/enrichers/description-generator.js.map +1 -0
- package/dist/core/agent-generator/enrichers/endpoint-extractor.d.ts +8 -0
- package/dist/core/agent-generator/enrichers/endpoint-extractor.d.ts.map +1 -0
- package/dist/core/agent-generator/enrichers/endpoint-extractor.js +91 -0
- package/dist/core/agent-generator/enrichers/endpoint-extractor.js.map +1 -0
- package/dist/core/agent-generator/enrichers/layer-classifier.d.ts +13 -0
- package/dist/core/agent-generator/enrichers/layer-classifier.d.ts.map +1 -0
- package/dist/core/agent-generator/enrichers/layer-classifier.js +150 -0
- package/dist/core/agent-generator/enrichers/layer-classifier.js.map +1 -0
- package/dist/core/agent-generator/enrichers/module-extractor.d.ts +11 -0
- package/dist/core/agent-generator/enrichers/module-extractor.d.ts.map +1 -0
- package/dist/core/agent-generator/enrichers/module-extractor.js +174 -0
- package/dist/core/agent-generator/enrichers/module-extractor.js.map +1 -0
- package/dist/core/agent-generator/framework-detector.d.ts +18 -0
- package/dist/core/agent-generator/framework-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/framework-detector.js +58 -0
- package/dist/core/agent-generator/framework-detector.js.map +1 -0
- package/dist/core/agent-generator/index.d.ts +26 -0
- package/dist/core/agent-generator/index.d.ts.map +1 -0
- package/dist/core/agent-generator/index.js +39 -0
- package/dist/core/agent-generator/index.js.map +1 -0
- package/dist/core/agent-generator/stack-detector.d.ts +14 -0
- package/dist/core/agent-generator/stack-detector.d.ts.map +1 -0
- package/dist/core/agent-generator/stack-detector.js +124 -0
- package/dist/core/agent-generator/stack-detector.js.map +1 -0
- package/dist/core/agent-generator/templates/core/agents.d.ts +17 -0
- package/dist/core/agent-generator/templates/core/agents.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/agents.js +1256 -0
- package/dist/core/agent-generator/templates/core/agents.js.map +1 -0
- package/dist/core/agent-generator/templates/core/architecture-rules.d.ts +7 -0
- package/dist/core/agent-generator/templates/core/architecture-rules.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/architecture-rules.js +274 -0
- package/dist/core/agent-generator/templates/core/architecture-rules.js.map +1 -0
- package/dist/core/agent-generator/templates/core/general-rules.d.ts +8 -0
- package/dist/core/agent-generator/templates/core/general-rules.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/general-rules.js +301 -0
- package/dist/core/agent-generator/templates/core/general-rules.js.map +1 -0
- package/dist/core/agent-generator/templates/core/hooks-generator.d.ts +21 -0
- package/dist/core/agent-generator/templates/core/hooks-generator.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/hooks-generator.js +233 -0
- package/dist/core/agent-generator/templates/core/hooks-generator.js.map +1 -0
- package/dist/core/agent-generator/templates/core/index-md.d.ts +7 -0
- package/dist/core/agent-generator/templates/core/index-md.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/index-md.js +246 -0
- package/dist/core/agent-generator/templates/core/index-md.js.map +1 -0
- package/dist/core/agent-generator/templates/core/orchestrator.d.ts +8 -0
- package/dist/core/agent-generator/templates/core/orchestrator.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/orchestrator.js +422 -0
- package/dist/core/agent-generator/templates/core/orchestrator.js.map +1 -0
- package/dist/core/agent-generator/templates/core/preflight.d.ts +8 -0
- package/dist/core/agent-generator/templates/core/preflight.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/preflight.js +213 -0
- package/dist/core/agent-generator/templates/core/preflight.js.map +1 -0
- package/dist/core/agent-generator/templates/core/quality-gates.d.ts +11 -0
- package/dist/core/agent-generator/templates/core/quality-gates.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/quality-gates.js +254 -0
- package/dist/core/agent-generator/templates/core/quality-gates.js.map +1 -0
- package/dist/core/agent-generator/templates/core/security-rules.d.ts +7 -0
- package/dist/core/agent-generator/templates/core/security-rules.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/security-rules.js +528 -0
- package/dist/core/agent-generator/templates/core/security-rules.js.map +1 -0
- package/dist/core/agent-generator/templates/core/skills-generator.d.ts +19 -0
- package/dist/core/agent-generator/templates/core/skills-generator.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/skills-generator.js +546 -0
- package/dist/core/agent-generator/templates/core/skills-generator.js.map +1 -0
- package/dist/core/agent-generator/templates/core/workflow-fix-bug.d.ts +7 -0
- package/dist/core/agent-generator/templates/core/workflow-fix-bug.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/workflow-fix-bug.js +237 -0
- package/dist/core/agent-generator/templates/core/workflow-fix-bug.js.map +1 -0
- package/dist/core/agent-generator/templates/core/workflow-new-feature.d.ts +8 -0
- package/dist/core/agent-generator/templates/core/workflow-new-feature.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/workflow-new-feature.js +321 -0
- package/dist/core/agent-generator/templates/core/workflow-new-feature.js.map +1 -0
- package/dist/core/agent-generator/templates/core/workflow-review.d.ts +7 -0
- package/dist/core/agent-generator/templates/core/workflow-review.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/core/workflow-review.js +104 -0
- package/dist/core/agent-generator/templates/core/workflow-review.js.map +1 -0
- package/dist/core/agent-generator/templates/domain/index.d.ts +22 -0
- package/dist/core/agent-generator/templates/domain/index.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/domain/index.js +1176 -0
- package/dist/core/agent-generator/templates/domain/index.js.map +1 -0
- package/dist/core/agent-generator/templates/helpers/base-helpers.d.ts +11 -0
- package/dist/core/agent-generator/templates/helpers/base-helpers.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/helpers/base-helpers.js +20 -0
- package/dist/core/agent-generator/templates/helpers/base-helpers.js.map +1 -0
- package/dist/core/agent-generator/templates/helpers/cross-ref-helpers.d.ts +3 -0
- package/dist/core/agent-generator/templates/helpers/cross-ref-helpers.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/helpers/cross-ref-helpers.js +77 -0
- package/dist/core/agent-generator/templates/helpers/cross-ref-helpers.js.map +1 -0
- package/dist/core/agent-generator/templates/helpers/security-helpers.d.ts +3 -0
- package/dist/core/agent-generator/templates/helpers/security-helpers.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/helpers/security-helpers.js +182 -0
- package/dist/core/agent-generator/templates/helpers/security-helpers.js.map +1 -0
- package/dist/core/agent-generator/templates/helpers/stack-helpers.d.ts +5 -0
- package/dist/core/agent-generator/templates/helpers/stack-helpers.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/helpers/stack-helpers.js +69 -0
- package/dist/core/agent-generator/templates/helpers/stack-helpers.js.map +1 -0
- package/dist/core/agent-generator/templates/helpers/structure-helpers.d.ts +3 -0
- package/dist/core/agent-generator/templates/helpers/structure-helpers.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/helpers/structure-helpers.js +275 -0
- package/dist/core/agent-generator/templates/helpers/structure-helpers.js.map +1 -0
- package/dist/core/agent-generator/templates/helpers/summary-helpers.d.ts +7 -0
- package/dist/core/agent-generator/templates/helpers/summary-helpers.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/helpers/summary-helpers.js +56 -0
- package/dist/core/agent-generator/templates/helpers/summary-helpers.js.map +1 -0
- package/dist/core/agent-generator/templates/stack/index.d.ts +8 -0
- package/dist/core/agent-generator/templates/stack/index.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/stack/index.js +695 -0
- package/dist/core/agent-generator/templates/stack/index.js.map +1 -0
- package/dist/core/agent-generator/templates/template-helpers.d.ts +12 -0
- package/dist/core/agent-generator/templates/template-helpers.d.ts.map +1 -0
- package/dist/core/agent-generator/templates/template-helpers.js +12 -0
- package/dist/core/agent-generator/templates/template-helpers.js.map +1 -0
- package/dist/core/agent-generator/types/agent.d.ts +40 -0
- package/dist/core/agent-generator/types/agent.d.ts.map +1 -0
- package/dist/core/agent-generator/types/agent.js +27 -0
- package/dist/core/agent-generator/types/agent.js.map +1 -0
- package/dist/core/agent-generator/types/domain.d.ts +59 -0
- package/dist/core/agent-generator/types/domain.d.ts.map +1 -0
- package/dist/core/agent-generator/types/domain.js +2 -0
- package/dist/core/agent-generator/types/domain.js.map +1 -0
- package/dist/core/agent-generator/types/stack.d.ts +37 -0
- package/dist/core/agent-generator/types/stack.d.ts.map +1 -0
- package/dist/core/agent-generator/types/stack.js +2 -0
- package/dist/core/agent-generator/types/stack.js.map +1 -0
- package/dist/core/agent-generator/types/template.d.ts +30 -0
- package/dist/core/agent-generator/types/template.d.ts.map +1 -0
- package/dist/core/agent-generator/types/template.js +2 -0
- package/dist/core/agent-generator/types/template.js.map +1 -0
- package/dist/core/agent-generator/types.d.ts +197 -0
- package/dist/core/agent-generator/types.d.ts.map +1 -0
- package/dist/core/agent-generator/types.js +27 -0
- package/dist/core/agent-generator/types.js.map +1 -0
- package/dist/core/analyzer.d.ts +39 -0
- package/dist/core/analyzer.d.ts.map +1 -0
- package/dist/core/analyzer.js +383 -0
- package/dist/core/analyzer.js.map +1 -0
- package/dist/core/analyzers/forecast.d.ts +85 -0
- package/dist/core/analyzers/forecast.d.ts.map +1 -0
- package/dist/core/analyzers/forecast.js +337 -0
- package/dist/core/analyzers/forecast.js.map +1 -0
- package/dist/core/analyzers/index.d.ts +10 -0
- package/dist/core/analyzers/index.d.ts.map +1 -0
- package/dist/core/analyzers/index.js +7 -0
- package/dist/core/analyzers/index.js.map +1 -0
- package/dist/core/analyzers/temporal-scorer.d.ts +72 -0
- package/dist/core/analyzers/temporal-scorer.d.ts.map +1 -0
- package/dist/core/analyzers/temporal-scorer.js +140 -0
- package/dist/core/analyzers/temporal-scorer.js.map +1 -0
- package/dist/core/anti-patterns.d.ts +25 -0
- package/dist/core/anti-patterns.d.ts.map +1 -0
- package/dist/core/anti-patterns.js +239 -0
- package/dist/core/anti-patterns.js.map +1 -0
- package/dist/core/architect.d.ts +70 -0
- package/dist/core/architect.d.ts.map +1 -0
- package/dist/core/architect.js +273 -0
- package/dist/core/architect.js.map +1 -0
- package/dist/core/architect_deps.d.ts +14 -0
- package/dist/core/architect_deps.d.ts.map +1 -0
- package/dist/core/architect_deps.js +12 -0
- package/dist/core/architect_deps.js.map +1 -0
- package/dist/core/config.d.ts +12 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +110 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/diagram.d.ts +10 -0
- package/dist/core/diagram.d.ts.map +1 -0
- package/dist/core/diagram.js +101 -0
- package/dist/core/diagram.js.map +1 -0
- package/dist/core/project-summarizer.d.ts +17 -0
- package/dist/core/project-summarizer.d.ts.map +1 -0
- package/dist/core/project-summarizer.js +39 -0
- package/dist/core/project-summarizer.js.map +1 -0
- package/dist/core/refactor-engine.d.ts +19 -0
- package/dist/core/refactor-engine.d.ts.map +1 -0
- package/dist/core/refactor-engine.js +86 -0
- package/dist/core/refactor-engine.js.map +1 -0
- package/dist/core/rules/barrel-optimizer.d.ts +14 -0
- package/dist/core/rules/barrel-optimizer.d.ts.map +1 -0
- package/dist/core/rules/barrel-optimizer.js +78 -0
- package/dist/core/rules/barrel-optimizer.js.map +1 -0
- package/dist/core/rules/dead-code-detector.d.ts +22 -0
- package/dist/core/rules/dead-code-detector.d.ts.map +1 -0
- package/dist/core/rules/dead-code-detector.js +118 -0
- package/dist/core/rules/dead-code-detector.js.map +1 -0
- package/dist/core/rules/hub-splitter.d.ts +14 -0
- package/dist/core/rules/hub-splitter.d.ts.map +1 -0
- package/dist/core/rules/hub-splitter.js +119 -0
- package/dist/core/rules/hub-splitter.js.map +1 -0
- package/dist/core/rules/import-organizer.d.ts +14 -0
- package/dist/core/rules/import-organizer.d.ts.map +1 -0
- package/dist/core/rules/import-organizer.js +86 -0
- package/dist/core/rules/import-organizer.js.map +1 -0
- package/dist/core/rules/module-grouper.d.ts +14 -0
- package/dist/core/rules/module-grouper.d.ts.map +1 -0
- package/dist/core/rules/module-grouper.js +118 -0
- package/dist/core/rules/module-grouper.js.map +1 -0
- package/dist/core/scorer.d.ts +27 -0
- package/dist/core/scorer.d.ts.map +1 -0
- package/dist/core/scorer.js +229 -0
- package/dist/core/scorer.js.map +1 -0
- package/dist/core/summarizer/keyword-extractor.d.ts +7 -0
- package/dist/core/summarizer/keyword-extractor.d.ts.map +1 -0
- package/dist/core/summarizer/keyword-extractor.js +37 -0
- package/dist/core/summarizer/keyword-extractor.js.map +1 -0
- package/dist/core/summarizer/module-inferrer.d.ts +12 -0
- package/dist/core/summarizer/module-inferrer.d.ts.map +1 -0
- package/dist/core/summarizer/module-inferrer.js +171 -0
- package/dist/core/summarizer/module-inferrer.js.map +1 -0
- package/dist/core/summarizer/package-reader.d.ts +4 -0
- package/dist/core/summarizer/package-reader.d.ts.map +1 -0
- package/dist/core/summarizer/package-reader.js +30 -0
- package/dist/core/summarizer/package-reader.js.map +1 -0
- package/dist/core/summarizer/purpose-inferrer.d.ts +9 -0
- package/dist/core/summarizer/purpose-inferrer.d.ts.map +1 -0
- package/dist/core/summarizer/purpose-inferrer.js +178 -0
- package/dist/core/summarizer/purpose-inferrer.js.map +1 -0
- package/dist/core/summarizer/readme-reader.d.ts +4 -0
- package/dist/core/summarizer/readme-reader.d.ts.map +1 -0
- package/dist/core/summarizer/readme-reader.js +21 -0
- package/dist/core/summarizer/readme-reader.js.map +1 -0
- package/dist/core/types/core.d.ts +87 -0
- package/dist/core/types/core.d.ts.map +1 -0
- package/dist/core/types/core.js +2 -0
- package/dist/core/types/core.js.map +1 -0
- package/dist/core/types/infrastructure.d.ts +39 -0
- package/dist/core/types/infrastructure.d.ts.map +1 -0
- package/dist/core/types/infrastructure.js +2 -0
- package/dist/core/types/infrastructure.js.map +1 -0
- package/dist/core/types/rules.d.ts +54 -0
- package/dist/core/types/rules.d.ts.map +1 -0
- package/dist/core/types/rules.js +2 -0
- package/dist/core/types/rules.js.map +1 -0
- package/dist/core/types/summarizer.d.ts +13 -0
- package/dist/core/types/summarizer.d.ts.map +1 -0
- package/dist/core/types/summarizer.js +2 -0
- package/dist/core/types/summarizer.js.map +1 -0
- package/dist/core/types.d.ts +187 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/diagram.d.ts +1 -0
- package/dist/diagram.d.ts.map +1 -1
- package/dist/diagram.js +24 -39
- package/dist/diagram.js.map +1 -1
- package/dist/html-reporter/scripts.d.ts +6 -0
- package/dist/html-reporter/scripts.d.ts.map +1 -0
- package/dist/html-reporter/scripts.js +316 -0
- package/dist/html-reporter/scripts.js.map +1 -0
- package/dist/html-reporter/sections/agents.d.ts +3 -0
- package/dist/html-reporter/sections/agents.d.ts.map +1 -0
- package/dist/html-reporter/sections/agents.js +259 -0
- package/dist/html-reporter/sections/agents.js.map +1 -0
- package/dist/html-reporter/sections/anti-patterns.d.ts +14 -0
- package/dist/html-reporter/sections/anti-patterns.d.ts.map +1 -0
- package/dist/html-reporter/sections/anti-patterns.js +64 -0
- package/dist/html-reporter/sections/anti-patterns.js.map +1 -0
- package/dist/html-reporter/sections/header.d.ts +4 -0
- package/dist/html-reporter/sections/header.d.ts.map +1 -0
- package/dist/html-reporter/sections/header.js +30 -0
- package/dist/html-reporter/sections/header.js.map +1 -0
- package/dist/html-reporter/sections/layers.d.ts +10 -0
- package/dist/html-reporter/sections/layers.d.ts.map +1 -0
- package/dist/html-reporter/sections/layers.js +143 -0
- package/dist/html-reporter/sections/layers.js.map +1 -0
- package/dist/html-reporter/sections/overview.d.ts +3 -0
- package/dist/html-reporter/sections/overview.d.ts.map +1 -0
- package/dist/html-reporter/sections/overview.js +58 -0
- package/dist/html-reporter/sections/overview.js.map +1 -0
- package/dist/html-reporter/sections/refactoring-plan.d.ts +4 -0
- package/dist/html-reporter/sections/refactoring-plan.d.ts.map +1 -0
- package/dist/html-reporter/sections/refactoring-plan.js +120 -0
- package/dist/html-reporter/sections/refactoring-plan.js.map +1 -0
- package/dist/html-reporter/sections/score.d.ts +8 -0
- package/dist/html-reporter/sections/score.d.ts.map +1 -0
- package/dist/html-reporter/sections/score.js +69 -0
- package/dist/html-reporter/sections/score.js.map +1 -0
- package/dist/html-reporter/sections/suggestions.d.ts +8 -0
- package/dist/html-reporter/sections/suggestions.d.ts.map +1 -0
- package/dist/html-reporter/sections/suggestions.js +34 -0
- package/dist/html-reporter/sections/suggestions.js.map +1 -0
- package/dist/html-reporter/styles.d.ts +2 -0
- package/dist/html-reporter/styles.d.ts.map +1 -0
- package/dist/html-reporter/styles.js +504 -0
- package/dist/html-reporter/styles.js.map +1 -0
- package/dist/html-reporter/utils.d.ts +27 -0
- package/dist/html-reporter/utils.d.ts.map +1 -0
- package/dist/html-reporter/utils.js +82 -0
- package/dist/html-reporter/utils.js.map +1 -0
- package/dist/html-reporter.d.ts +0 -37
- package/dist/html-reporter.d.ts.map +1 -1
- package/dist/html-reporter.js +29 -1679
- package/dist/html-reporter.js.map +1 -1
- package/dist/index.d.ts +16 -84
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -285
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/git-cache.d.ts +7 -0
- package/dist/infrastructure/git-cache.d.ts.map +1 -0
- package/dist/infrastructure/git-cache.js +41 -0
- package/dist/infrastructure/git-cache.js.map +1 -0
- package/dist/infrastructure/git-history.d.ts +113 -0
- package/dist/infrastructure/git-history.d.ts.map +1 -0
- package/dist/infrastructure/git-history.js +339 -0
- package/dist/infrastructure/git-history.js.map +1 -0
- package/dist/infrastructure/logger.d.ts +21 -0
- package/dist/infrastructure/logger.d.ts.map +1 -0
- package/dist/infrastructure/logger.js +59 -0
- package/dist/infrastructure/logger.js.map +1 -0
- package/dist/infrastructure/scanner.d.ts +32 -0
- package/dist/infrastructure/scanner.d.ts.map +1 -0
- package/dist/infrastructure/scanner.js +330 -0
- package/dist/infrastructure/scanner.js.map +1 -0
- package/dist/logger.d.ts +21 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +59 -0
- package/dist/logger.js.map +1 -0
- package/dist/project-summarizer.d.ts +6 -28
- package/dist/project-summarizer.d.ts.map +1 -1
- package/dist/project-summarizer.js +21 -445
- package/dist/project-summarizer.js.map +1 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +15 -13
- package/dist/scanner.js.map +1 -1
- package/dist/summarizer/keyword-extractor.d.ts +6 -0
- package/dist/summarizer/keyword-extractor.d.ts.map +1 -0
- package/dist/summarizer/keyword-extractor.js +37 -0
- package/dist/summarizer/keyword-extractor.js.map +1 -0
- package/dist/summarizer/module-inferrer.d.ts +10 -0
- package/dist/summarizer/module-inferrer.d.ts.map +1 -0
- package/dist/summarizer/module-inferrer.js +171 -0
- package/dist/summarizer/module-inferrer.js.map +1 -0
- package/dist/summarizer/package-reader.d.ts +4 -0
- package/dist/summarizer/package-reader.d.ts.map +1 -0
- package/dist/summarizer/package-reader.js +30 -0
- package/dist/summarizer/package-reader.js.map +1 -0
- package/dist/summarizer/purpose-inferrer.d.ts +8 -0
- package/dist/summarizer/purpose-inferrer.d.ts.map +1 -0
- package/dist/summarizer/purpose-inferrer.js +178 -0
- package/dist/summarizer/purpose-inferrer.js.map +1 -0
- package/dist/summarizer/readme-reader.d.ts +4 -0
- package/dist/summarizer/readme-reader.d.ts.map +1 -0
- package/dist/summarizer/readme-reader.js +21 -0
- package/dist/summarizer/readme-reader.js.map +1 -0
- package/fix-scorer.js +18 -0
- package/fix-tests.js +73 -0
- package/package.json +3 -3
- package/scripts/decompose-detectors.ts +183 -0
- package/scripts/decompose-detectors_deps.ts +16 -0
- package/scripts/decompose-enrichers.ts +191 -0
- package/scripts/decompose-enrichers_deps.ts +10 -0
- package/scripts/decompose-helpers.ts +92 -0
- package/scripts/decompose-summarizer.ts +127 -0
- package/setup-refactor.sh +21 -0
- package/src/{cli.ts → adapters/cli.ts} +14 -10
- package/src/adapters/html-reporter/scripts.ts +402 -0
- package/src/adapters/html-reporter/sections/agents.ts +267 -0
- package/src/adapters/html-reporter/sections/anti-patterns.ts +81 -0
- package/src/adapters/html-reporter/sections/header.ts +35 -0
- package/src/adapters/html-reporter/sections/layers.ts +165 -0
- package/src/adapters/html-reporter/sections/overview.ts +64 -0
- package/src/adapters/html-reporter/sections/refactoring-plan.ts +166 -0
- package/src/adapters/html-reporter/sections/score.ts +79 -0
- package/src/adapters/html-reporter/sections/suggestions.ts +39 -0
- package/src/adapters/html-reporter/styles.ts +525 -0
- package/src/adapters/html-reporter/utils_adapters.ts +39 -0
- package/src/adapters/html-reporter/utils_sections.ts +55 -0
- package/src/adapters/html-reporter.ts +89 -0
- package/src/adapters/html-reporter_deps.ts +14 -0
- package/src/{refactor-reporter.ts → adapters/refactor-reporter.ts} +1 -1
- package/src/{reporter.ts → adapters/reporter.ts} +1 -1
- package/src/core/agent-generator/context-enricher.ts +67 -0
- package/src/core/agent-generator/detectors/base-detector.ts +18 -0
- package/src/core/agent-generator/detectors/dart-detector.ts +17 -0
- package/src/core/agent-generator/detectors/framework-registry.ts +82 -0
- package/src/core/agent-generator/detectors/go-detector.ts +26 -0
- package/src/core/agent-generator/detectors/java-detector.ts +46 -0
- package/src/core/agent-generator/detectors/node-detector.ts +28 -0
- package/src/core/agent-generator/detectors/php-detector.ts +28 -0
- package/src/core/agent-generator/detectors/python-detector.ts +125 -0
- package/src/core/agent-generator/detectors/ruby-detector.ts +24 -0
- package/src/core/agent-generator/detectors/rust-detector.ts +19 -0
- package/src/core/agent-generator/detectors/structure-detector.ts +38 -0
- package/src/core/agent-generator/detectors/toolchain-detector.ts +180 -0
- package/src/{agent-generator → core/agent-generator}/domain-inferrer.ts +2 -7
- package/src/core/agent-generator/engines/audit-engine.ts +98 -0
- package/src/core/agent-generator/engines/context-builder.ts +96 -0
- package/src/core/agent-generator/engines/generation-engine.ts +184 -0
- package/src/core/agent-generator/engines/generation-engine_deps.ts +21 -0
- package/src/core/agent-generator/engines/suggestion-engine.ts +202 -0
- package/src/core/agent-generator/engines/suggestion-engine_deps.ts +8 -0
- package/src/core/agent-generator/enrichers/analysis-helpers.ts +58 -0
- package/src/core/agent-generator/enrichers/description-generator.ts +91 -0
- package/src/core/agent-generator/enrichers/endpoint-extractor.ts +114 -0
- package/src/core/agent-generator/enrichers/layer-classifier.ts +156 -0
- package/src/core/agent-generator/enrichers/module-extractor.ts +203 -0
- package/src/core/agent-generator/framework-detector.ts +66 -0
- package/src/core/agent-generator/index.ts +55 -0
- package/src/{agent-generator → core/agent-generator}/stack-detector.ts +2 -2
- package/src/{agent-generator → core/agent-generator}/templates/core/agents.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/architecture-rules.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/general-rules.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/hooks-generator.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/index-md.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/orchestrator.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/preflight.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/quality-gates.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/security-rules.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/skills-generator.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/workflow-fix-bug.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/workflow-new-feature.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/core/workflow-review.ts +1 -1
- package/src/{agent-generator → core/agent-generator}/templates/domain/index.ts +1 -1
- package/src/core/agent-generator/templates/helpers/base-helpers.ts +32 -0
- package/src/core/agent-generator/templates/helpers/cross-ref-helpers.ts +79 -0
- package/src/core/agent-generator/templates/helpers/security-helpers.ts +196 -0
- package/src/core/agent-generator/templates/helpers/stack-helpers.ts +78 -0
- package/src/core/agent-generator/templates/helpers/structure-helpers.ts +291 -0
- package/src/core/agent-generator/templates/helpers/summary-helpers.ts +65 -0
- package/src/{agent-generator → core/agent-generator}/templates/stack/index.ts +1 -1
- package/src/core/agent-generator/templates/template-helpers.ts +12 -0
- package/src/core/agent-generator/types/agent.ts +65 -0
- package/src/core/agent-generator/types/domain.ts +63 -0
- package/src/core/agent-generator/types/stack.ts +38 -0
- package/src/core/agent-generator/types/template.ts +31 -0
- package/src/{analyzer.ts → core/analyzer.ts} +2 -1
- package/src/{analyzers → core/analyzers}/forecast.ts +1 -1
- package/src/{analyzers → core/analyzers}/index.ts +2 -2
- package/src/{analyzers → core/analyzers}/temporal-scorer.ts +1 -1
- package/src/{anti-patterns.ts → core/anti-patterns.ts} +12 -2
- package/src/core/architect.ts +356 -0
- package/src/core/architect_deps.ts +13 -0
- package/src/{config.ts → core/config.ts} +1 -1
- package/src/{diagram.ts → core/diagram.ts} +27 -42
- package/src/core/project-summarizer.ts +42 -0
- package/src/{refactor-engine.ts → core/refactor-engine.ts} +2 -7
- package/src/{rules → core/rules}/barrel-optimizer.ts +3 -1
- package/src/{rules → core/rules}/dead-code-detector.ts +3 -1
- package/src/{rules → core/rules}/hub-splitter.ts +14 -2
- package/src/{rules → core/rules}/import-organizer.ts +5 -3
- package/src/{rules → core/rules}/module-grouper.ts +11 -2
- package/src/{scorer.ts → core/scorer.ts} +7 -7
- package/src/core/summarizer/keyword-extractor.ts +53 -0
- package/src/core/summarizer/module-inferrer.ts +194 -0
- package/src/core/summarizer/package-reader.ts +34 -0
- package/src/core/summarizer/purpose-inferrer.ts +197 -0
- package/src/core/summarizer/readme-reader.ts +24 -0
- package/src/core/types/core.ts +93 -0
- package/src/core/types/infrastructure.ts +41 -0
- package/src/core/types/rules.ts +51 -0
- package/src/core/types/summarizer.ts +8 -0
- package/src/index.ts +17 -384
- package/src/{analyzers → infrastructure}/git-history.ts +19 -10
- package/src/infrastructure/logger.ts +68 -0
- package/src/{scanner.ts → infrastructure/scanner.ts} +17 -14
- package/src/scripts/bundle-deps.js +123 -0
- package/src/scripts/fix-imports.mjs +106 -0
- package/src/scripts/refactor-imports.js +74 -0
- package/src/scripts/refactor-utils.js +23 -0
- package/test-shotgun.js +7 -0
- package/tests/agent-generator.test.ts +3 -2
- package/tests/analyzers-integration.test.ts +9 -9
- package/tests/anti-patterns.test.ts +3 -2
- package/tests/context-enricher.test.ts +3 -2
- package/tests/forecast.test.ts +4 -4
- package/tests/framework-detector.test.ts +2 -2
- package/tests/git-history.test.ts +20 -20
- package/tests/monorepo-scan.test.ts +4 -4
- package/tests/scanner.test.ts +2 -2
- package/tests/scorer.test.ts +17 -17
- package/tests/stack-detector.test.ts +2 -2
- package/tests/template-generation.test.ts +31 -30
- package/tests/template-helpers.test.ts +6 -28
- package/tests/temporal-scorer.test.ts +3 -3
- package/src/agent-generator/context-enricher.ts +0 -672
- package/src/agent-generator/framework-detector.ts +0 -669
- package/src/agent-generator/index.ts +0 -634
- package/src/agent-generator/templates/template-helpers.ts +0 -776
- package/src/agent-generator/types.ts +0 -232
- package/src/html-reporter.ts +0 -1830
- package/src/project-summarizer.ts +0 -521
- package/src/types.ts +0 -193
- /package/src/{analyzers → infrastructure}/git-cache.ts +0 -0
package/src/html-reporter.ts
DELETED
|
@@ -1,1830 +0,0 @@
|
|
|
1
|
-
import { AnalysisReport, AntiPattern, RefactoringPlan, RefactorStep } from './types.js';
|
|
2
|
-
import { AgentSuggestion } from './agent-generator/index.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Generates premium visual HTML reports from AnalysisReport.
|
|
6
|
-
* Features: D3.js force graph, bubble charts, radar chart, animated counters.
|
|
7
|
-
*/
|
|
8
|
-
export class HtmlReportGenerator {
|
|
9
|
-
generateHtml(report: AnalysisReport, plan?: RefactoringPlan, agentSuggestion?: AgentSuggestion): string {
|
|
10
|
-
const grouped = this.groupAntiPatterns(report.antiPatterns);
|
|
11
|
-
const sugGrouped = this.groupSuggestions(report.suggestions);
|
|
12
|
-
|
|
13
|
-
return `<!DOCTYPE html>
|
|
14
|
-
<html lang="en">
|
|
15
|
-
<head>
|
|
16
|
-
<meta charset="UTF-8">
|
|
17
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
18
|
-
<title>Architect Report — ${this.escapeHtml(report.projectInfo.name)}</title>
|
|
19
|
-
${this.getStyles()}
|
|
20
|
-
<script src="https://cdn.jsdelivr.net/npm/d3@7"><\/script>
|
|
21
|
-
</head>
|
|
22
|
-
<body>
|
|
23
|
-
${this.renderHeader(report)}
|
|
24
|
-
<div class="report-layout">
|
|
25
|
-
<nav class="sidebar" id="reportSidebar">
|
|
26
|
-
<div class="sidebar-title">Navigation</div>
|
|
27
|
-
<a href="#score" class="sidebar-link active" data-section="score">📊 Score</a>
|
|
28
|
-
${report.projectSummary ? `<a href="#overview" class="sidebar-link" data-section="overview">📋 Overview</a>` : ''}
|
|
29
|
-
<a href="#layers" class="sidebar-link" data-section="layers">📐 Layers & Graph</a>
|
|
30
|
-
<a href="#anti-patterns" class="sidebar-link" data-section="anti-patterns">⚠️ Anti-Patterns (${report.antiPatterns.length})</a>
|
|
31
|
-
<a href="#suggestions" class="sidebar-link" data-section="suggestions">💡 Suggestions (${report.suggestions.length})</a>
|
|
32
|
-
${plan ? `<a href="#refactoring" class="sidebar-link" data-section="refactoring">🔧 Refactoring (${plan.steps.length})</a>` : ''}
|
|
33
|
-
${agentSuggestion ? `<a href="#agents" class="sidebar-link" data-section="agents">🤖 Agents</a>` : ''}
|
|
34
|
-
</nav>
|
|
35
|
-
<button class="sidebar-toggle" onclick="document.getElementById('reportSidebar').classList.toggle('sidebar-open')">☰</button>
|
|
36
|
-
|
|
37
|
-
<div class="container">
|
|
38
|
-
<div id="score">
|
|
39
|
-
${this.renderScoreHero(report)}
|
|
40
|
-
${this.renderRadarChart(report)}
|
|
41
|
-
${this.renderStats(report)}
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
${this.renderProjectOverview(report)}
|
|
45
|
-
|
|
46
|
-
<details class="section-accordion" id="layers" open>
|
|
47
|
-
<summary class="section-accordion-header">📐 Layer Analysis & Dependencies</summary>
|
|
48
|
-
<div class="section-accordion-body">
|
|
49
|
-
${this.renderLayers(report)}
|
|
50
|
-
${this.renderDependencyGraph(report)}
|
|
51
|
-
</div>
|
|
52
|
-
</details>
|
|
53
|
-
|
|
54
|
-
<details class="section-accordion" id="anti-patterns" open>
|
|
55
|
-
<summary class="section-accordion-header">⚠️ Anti-Patterns (${report.antiPatterns.length})</summary>
|
|
56
|
-
<div class="section-accordion-body">
|
|
57
|
-
${this.renderAntiPatternBubbles(report, grouped)}
|
|
58
|
-
${this.renderAntiPatterns(report, grouped)}
|
|
59
|
-
</div>
|
|
60
|
-
</details>
|
|
61
|
-
|
|
62
|
-
<details class="section-accordion" id="suggestions">
|
|
63
|
-
<summary class="section-accordion-header">💡 Suggestions (${report.suggestions.length})</summary>
|
|
64
|
-
<div class="section-accordion-body">
|
|
65
|
-
${this.renderSuggestions(sugGrouped)}
|
|
66
|
-
</div>
|
|
67
|
-
</details>
|
|
68
|
-
|
|
69
|
-
${plan ? `<details class="section-accordion" id="refactoring" open>
|
|
70
|
-
<summary class="section-accordion-header">🔧 Refactoring Plan (${plan.steps.length} steps, ${plan.totalOperations} operations)</summary>
|
|
71
|
-
<div class="section-accordion-body">
|
|
72
|
-
${this.renderRefactoringPlan(plan)}
|
|
73
|
-
</div>
|
|
74
|
-
</details>` : ''}
|
|
75
|
-
|
|
76
|
-
${agentSuggestion ? `<details class="section-accordion" id="agents" open>
|
|
77
|
-
<summary class="section-accordion-header">🤖 Agent System</summary>
|
|
78
|
-
<div class="section-accordion-body">
|
|
79
|
-
${this.renderAgentSuggestions(agentSuggestion)}
|
|
80
|
-
</div>
|
|
81
|
-
</details>` : ''}
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
${this.renderFooter()}
|
|
85
|
-
${this.getScripts(report)}
|
|
86
|
-
</body>
|
|
87
|
-
</html>`;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
private scoreColor(score: number): string {
|
|
91
|
-
if (score >= 70) return '#22c55e';
|
|
92
|
-
if (score >= 50) return '#f59e0b';
|
|
93
|
-
return '#ef4444';
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
private scoreEmoji(score: number): string {
|
|
97
|
-
if (score >= 70) return '✅';
|
|
98
|
-
if (score >= 50) return '⚠️';
|
|
99
|
-
return '❌';
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
private scoreLabel(score: number): string {
|
|
103
|
-
if (score >= 90) return 'Excellent';
|
|
104
|
-
if (score >= 70) return 'Good';
|
|
105
|
-
if (score >= 50) return 'Needs Attention';
|
|
106
|
-
if (score >= 30) return 'Poor';
|
|
107
|
-
return 'Critical';
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
private escapeHtml(text: string): string {
|
|
111
|
-
return text
|
|
112
|
-
.replace(/&/g, '&')
|
|
113
|
-
.replace(/</g, '<')
|
|
114
|
-
.replace(/>/g, '>')
|
|
115
|
-
.replace(/"/g, '"');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
private groupAntiPatterns(
|
|
119
|
-
antiPatterns: AntiPattern[]
|
|
120
|
-
): Record<string, { count: number; severity: string; locations: string[]; suggestion: string }> {
|
|
121
|
-
const grouped: Record<string, { count: number; severity: string; locations: string[]; suggestion: string }> = {};
|
|
122
|
-
for (const p of antiPatterns) {
|
|
123
|
-
if (!grouped[p.name]) {
|
|
124
|
-
grouped[p.name] = { count: 0, severity: p.severity, locations: [], suggestion: p.suggestion };
|
|
125
|
-
}
|
|
126
|
-
grouped[p.name].count++;
|
|
127
|
-
if (grouped[p.name].locations.length < 10) {
|
|
128
|
-
grouped[p.name].locations.push(p.location);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return grouped;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
private groupSuggestions(
|
|
135
|
-
suggestions: Array<{ priority: string; title: string; description: string; impact: string }>
|
|
136
|
-
): Array<{ priority: string; title: string; description: string; impact: string; count: number }> {
|
|
137
|
-
const map = new Map<string, { priority: string; title: string; description: string; impact: string; count: number }>();
|
|
138
|
-
for (const s of suggestions) {
|
|
139
|
-
const key = `${s.title}|${s.priority}`;
|
|
140
|
-
if (!map.has(key)) {
|
|
141
|
-
map.set(key, { ...s, count: 0 });
|
|
142
|
-
}
|
|
143
|
-
map.get(key)!.count++;
|
|
144
|
-
}
|
|
145
|
-
return Array.from(map.values()).slice(0, 15);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
private renderHeader(report: AnalysisReport): string {
|
|
149
|
-
const date = new Date(report.timestamp).toLocaleDateString('en-US', {
|
|
150
|
-
year: 'numeric',
|
|
151
|
-
month: 'long',
|
|
152
|
-
day: 'numeric',
|
|
153
|
-
});
|
|
154
|
-
return `
|
|
155
|
-
<div class="header">
|
|
156
|
-
<h1>🏗️ Architect</h1>
|
|
157
|
-
<p class="subtitle">Architecture Analysis Report</p>
|
|
158
|
-
<div class="meta">
|
|
159
|
-
<span>📂 <strong>${this.escapeHtml(report.projectInfo.name)}</strong></span>
|
|
160
|
-
<span>📁 <strong>${report.projectInfo.totalFiles}</strong> files</span>
|
|
161
|
-
<span>📝 <strong>${report.projectInfo.totalLines.toLocaleString()}</strong> lines</span>
|
|
162
|
-
<span>💻 <strong>${report.projectInfo.primaryLanguages.join(', ')}</strong></span>
|
|
163
|
-
${report.projectInfo.frameworks.length > 0 ? `<span>🔧 <strong>${report.projectInfo.frameworks.join(', ')}</strong></span>` : ''}
|
|
164
|
-
<span>📅 <strong>${date}</strong></span>
|
|
165
|
-
</div>
|
|
166
|
-
</div>`;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
private renderProjectOverview(report: AnalysisReport): string {
|
|
170
|
-
const summary = report.projectSummary;
|
|
171
|
-
if (!summary) return '';
|
|
172
|
-
|
|
173
|
-
const modulesHtml = summary.modules.length > 0
|
|
174
|
-
? summary.modules.map(m => `
|
|
175
|
-
<div class="overview-module">
|
|
176
|
-
<div class="overview-module-name">${this.esc(m.name)}</div>
|
|
177
|
-
<div class="overview-module-desc">${this.esc(m.description)}</div>
|
|
178
|
-
<div class="overview-module-files">${m.files} file${m.files > 1 ? 's' : ''}</div>
|
|
179
|
-
</div>`).join('')
|
|
180
|
-
: '<div class="overview-empty">Nenhum módulo detectado</div>';
|
|
181
|
-
|
|
182
|
-
const techHtml = summary.techStack
|
|
183
|
-
.map(t => `<span class="overview-tag tech-tag">${this.esc(t)}</span>`)
|
|
184
|
-
.join('');
|
|
185
|
-
|
|
186
|
-
const keywordsHtml = summary.keywords
|
|
187
|
-
.map(k => `<span class="overview-tag keyword-tag">${this.esc(k)}</span>`)
|
|
188
|
-
.join('');
|
|
189
|
-
|
|
190
|
-
const entryHtml = summary.entryPoints.length > 0
|
|
191
|
-
? summary.entryPoints.map(e => `<code class="overview-entry">${this.esc(e)}</code>`).join(' ')
|
|
192
|
-
: '<span class="overview-empty">—</span>';
|
|
193
|
-
|
|
194
|
-
return `
|
|
195
|
-
<details class="section-accordion" id="overview" open>
|
|
196
|
-
<summary class="section-accordion-header">📋 Project Overview</summary>
|
|
197
|
-
<div class="section-accordion-body">
|
|
198
|
-
<div class="overview-grid">
|
|
199
|
-
<div class="overview-card overview-main">
|
|
200
|
-
<div class="overview-label">O que é</div>
|
|
201
|
-
<div class="overview-description">${this.esc(summary.description)}</div>
|
|
202
|
-
<div class="overview-purpose-row">
|
|
203
|
-
<span class="overview-purpose-label">Tipo:</span>
|
|
204
|
-
<span class="overview-purpose-value">${this.esc(summary.purpose)}</span>
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
<div class="overview-card">
|
|
208
|
-
<div class="overview-label">Tech Stack</div>
|
|
209
|
-
<div class="overview-tags">${techHtml || '<span class="overview-empty">—</span>'}</div>
|
|
210
|
-
</div>
|
|
211
|
-
<div class="overview-card">
|
|
212
|
-
<div class="overview-label">Keywords</div>
|
|
213
|
-
<div class="overview-tags">${keywordsHtml || '<span class="overview-empty">—</span>'}</div>
|
|
214
|
-
</div>
|
|
215
|
-
<div class="overview-card">
|
|
216
|
-
<div class="overview-label">Entry Points</div>
|
|
217
|
-
<div class="overview-entries">${entryHtml}</div>
|
|
218
|
-
</div>
|
|
219
|
-
</div>
|
|
220
|
-
<div class="overview-modules-section">
|
|
221
|
-
<div class="overview-label">Módulos Detectados (${summary.modules.length})</div>
|
|
222
|
-
<div class="overview-modules-grid">
|
|
223
|
-
${modulesHtml}
|
|
224
|
-
</div>
|
|
225
|
-
</div>
|
|
226
|
-
</div>
|
|
227
|
-
</details>`;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
private esc(text: string): string {
|
|
231
|
-
return text
|
|
232
|
-
.replace(/&/g, '&')
|
|
233
|
-
.replace(/</g, '<')
|
|
234
|
-
.replace(/>/g, '>')
|
|
235
|
-
.replace(/"/g, '"');
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
private renderScoreHero(report: AnalysisReport): string {
|
|
239
|
-
const overall = report.score.overall;
|
|
240
|
-
const circumference = 2 * Math.PI * 85;
|
|
241
|
-
const offset = circumference * (1 - overall / 100);
|
|
242
|
-
|
|
243
|
-
const breakdownItems = Object.entries(report.score.breakdown)
|
|
244
|
-
.map(
|
|
245
|
-
([name, score]) => `
|
|
246
|
-
<div class="score-item">
|
|
247
|
-
<div class="name">${name}</div>
|
|
248
|
-
<div class="val" style="color: ${this.scoreColor(score)}">${score} ${this.scoreEmoji(score)}</div>
|
|
249
|
-
<div class="bar-container">
|
|
250
|
-
<div class="bar" style="width: ${score}%; background: ${this.scoreColor(score)}"></div>
|
|
251
|
-
</div>
|
|
252
|
-
</div>`
|
|
253
|
-
)
|
|
254
|
-
.join('');
|
|
255
|
-
|
|
256
|
-
return `
|
|
257
|
-
<div class="score-hero">
|
|
258
|
-
<div class="score-circle">
|
|
259
|
-
<svg viewBox="0 0 200 200" width="180" height="180">
|
|
260
|
-
<circle class="bg" cx="100" cy="100" r="85" />
|
|
261
|
-
<circle class="fg" cx="100" cy="100" r="85"
|
|
262
|
-
stroke="${this.scoreColor(overall)}"
|
|
263
|
-
stroke-dasharray="${circumference}"
|
|
264
|
-
stroke-dashoffset="${offset}" />
|
|
265
|
-
</svg>
|
|
266
|
-
<div class="score-value">
|
|
267
|
-
<div class="number score-counter" data-target="${overall}" style="color: ${this.scoreColor(overall)}">0</div>
|
|
268
|
-
<div class="label">/ 100</div>
|
|
269
|
-
<div class="grade">${this.scoreLabel(overall)}</div>
|
|
270
|
-
</div>
|
|
271
|
-
</div>
|
|
272
|
-
<div class="score-breakdown">
|
|
273
|
-
${breakdownItems}
|
|
274
|
-
</div>
|
|
275
|
-
</div>`;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Radar chart for the 4 score components
|
|
280
|
-
*/
|
|
281
|
-
private renderRadarChart(report: AnalysisReport): string {
|
|
282
|
-
const entries = Object.entries(report.score.breakdown);
|
|
283
|
-
return `
|
|
284
|
-
<h2 class="section-title">🎯 Health Radar</h2>
|
|
285
|
-
<div class="card" style="display: flex; justify-content: center;">
|
|
286
|
-
<svg id="radar-chart" width="350" height="350" viewBox="0 0 350 350"></svg>
|
|
287
|
-
</div>`;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
private renderStats(report: AnalysisReport): string {
|
|
291
|
-
return `
|
|
292
|
-
<div class="stats-grid">
|
|
293
|
-
<div class="stat-card">
|
|
294
|
-
<div class="value stat-counter" data-target="${report.projectInfo.totalFiles}">0</div>
|
|
295
|
-
<div class="label">Files Scanned</div>
|
|
296
|
-
</div>
|
|
297
|
-
<div class="stat-card">
|
|
298
|
-
<div class="value stat-counter" data-target="${report.projectInfo.totalLines}">0</div>
|
|
299
|
-
<div class="label">Lines of Code</div>
|
|
300
|
-
</div>
|
|
301
|
-
<div class="stat-card">
|
|
302
|
-
<div class="value stat-counter" data-target="${report.antiPatterns.length}">0</div>
|
|
303
|
-
<div class="label">Anti-Patterns</div>
|
|
304
|
-
</div>
|
|
305
|
-
<div class="stat-card">
|
|
306
|
-
<div class="value stat-counter" data-target="${report.dependencyGraph.edges.length}">0</div>
|
|
307
|
-
<div class="label">Dependencies</div>
|
|
308
|
-
</div>
|
|
309
|
-
</div>`;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
private renderLayers(report: AnalysisReport): string {
|
|
313
|
-
if (report.layers.length === 0) return '';
|
|
314
|
-
|
|
315
|
-
const layerColors: Record<string, string> = {
|
|
316
|
-
API: '#ec4899',
|
|
317
|
-
Service: '#3b82f6',
|
|
318
|
-
Data: '#10b981',
|
|
319
|
-
UI: '#f59e0b',
|
|
320
|
-
Infrastructure: '#8b5cf6',
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
const cards = report.layers
|
|
324
|
-
.map((l) => {
|
|
325
|
-
const color = layerColors[l.name] || '#64748b';
|
|
326
|
-
return `
|
|
327
|
-
<div class="layer-card" style="--layer-color: ${color}">
|
|
328
|
-
<div class="count" style="color: ${color}">${l.files.length}</div>
|
|
329
|
-
<div class="name">${l.name}</div>
|
|
330
|
-
<div class="desc">${this.escapeHtml(l.description)}</div>
|
|
331
|
-
</div>`;
|
|
332
|
-
})
|
|
333
|
-
.join('');
|
|
334
|
-
|
|
335
|
-
return `
|
|
336
|
-
<h2 class="section-title">📐 Architectural Layers</h2>
|
|
337
|
-
<div class="layers-grid">${cards}</div>`;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Interactive D3.js force-directed dependency graph
|
|
342
|
-
*/
|
|
343
|
-
private renderDependencyGraph(report: AnalysisReport): string {
|
|
344
|
-
if (report.dependencyGraph.edges.length === 0) return '';
|
|
345
|
-
|
|
346
|
-
// Build real file set — only files that appear as SOURCE in edges (these are real scanned files)
|
|
347
|
-
const realFiles = new Set(report.dependencyGraph.edges.map(e => e.from));
|
|
348
|
-
|
|
349
|
-
// Count connections only for real files
|
|
350
|
-
const connectionCount: Record<string, number> = {};
|
|
351
|
-
for (const edge of report.dependencyGraph.edges) {
|
|
352
|
-
if (realFiles.has(edge.from)) {
|
|
353
|
-
connectionCount[edge.from] = (connectionCount[edge.from] || 0) + 1;
|
|
354
|
-
}
|
|
355
|
-
if (realFiles.has(edge.to)) {
|
|
356
|
-
connectionCount[edge.to] = (connectionCount[edge.to] || 0) + 1;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// Build layer map from report layers
|
|
361
|
-
const layerMap: Record<string, string> = {};
|
|
362
|
-
for (const layer of report.layers) {
|
|
363
|
-
for (const file of layer.files) {
|
|
364
|
-
layerMap[file] = layer.name;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// Create nodes only from real files
|
|
369
|
-
const allNodes = [...realFiles].map(n => ({
|
|
370
|
-
id: n,
|
|
371
|
-
name: n.split('/').pop() || n,
|
|
372
|
-
connections: connectionCount[n] || 0,
|
|
373
|
-
layer: layerMap[n] || 'Other',
|
|
374
|
-
}));
|
|
375
|
-
|
|
376
|
-
// ── Fallback: color by module/directory when layer detection is weak ──
|
|
377
|
-
const otherCount = allNodes.filter(n => n.layer === 'Other').length;
|
|
378
|
-
const useModuleColoring = allNodes.length > 0 && (otherCount / allNodes.length) > 0.7;
|
|
379
|
-
|
|
380
|
-
// Palette for module-based coloring (10 distinct, vibrant colors)
|
|
381
|
-
const modulePalette = [
|
|
382
|
-
'#3b82f6', '#ec4899', '#10b981', '#f59e0b', '#8b5cf6',
|
|
383
|
-
'#06b6d4', '#ef4444', '#84cc16', '#f97316', '#6366f1',
|
|
384
|
-
];
|
|
385
|
-
|
|
386
|
-
let moduleColorMap: Record<string, string> = {};
|
|
387
|
-
if (useModuleColoring) {
|
|
388
|
-
// Extract module (first meaningful directory) from each node path
|
|
389
|
-
const getModule = (filePath: string): string => {
|
|
390
|
-
const parts = filePath.split('/');
|
|
391
|
-
if (parts.length < 2) return 'root';
|
|
392
|
-
const first = parts[0];
|
|
393
|
-
// If first dir is common source dir, use second level
|
|
394
|
-
if (['src', 'lib', 'app', 'packages', 'modules', 'features', 'apps'].includes(first)) {
|
|
395
|
-
return parts.length > 2 ? parts[1] : first;
|
|
396
|
-
}
|
|
397
|
-
return first;
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
// Assign colors to modules
|
|
401
|
-
const moduleNames = [...new Set(allNodes.map(n => getModule(n.id)))];
|
|
402
|
-
moduleNames.forEach((mod, i) => {
|
|
403
|
-
moduleColorMap[mod] = modulePalette[i % modulePalette.length];
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
// Reassign layer field to module name for coloring
|
|
407
|
-
for (const node of allNodes) {
|
|
408
|
-
node.layer = getModule(node.id);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// Build links only between real files
|
|
413
|
-
const allLinks = report.dependencyGraph.edges
|
|
414
|
-
.filter(e => realFiles.has(e.from) && realFiles.has(e.to))
|
|
415
|
-
.map(e => ({ source: e.from, target: e.to }));
|
|
416
|
-
|
|
417
|
-
// Limit to top N most-connected nodes for large projects
|
|
418
|
-
const maxNodes = 60;
|
|
419
|
-
const sortedNodes = [...allNodes].sort((a, b) => b.connections - a.connections);
|
|
420
|
-
const limitedNodes = sortedNodes.slice(0, maxNodes);
|
|
421
|
-
const limitedNodeIds = new Set(limitedNodes.map(n => n.id));
|
|
422
|
-
const limitedLinks = allLinks.filter(l => limitedNodeIds.has(l.source) && limitedNodeIds.has(l.target));
|
|
423
|
-
const isLimited = allNodes.length > maxNodes;
|
|
424
|
-
|
|
425
|
-
// Collect unique layers/modules from limited nodes
|
|
426
|
-
const uniqueLayers = [...new Set(limitedNodes.map(n => n.layer))];
|
|
427
|
-
|
|
428
|
-
// Build dynamic color map for legend and D3
|
|
429
|
-
const colorMap: Record<string, string> = useModuleColoring
|
|
430
|
-
? moduleColorMap
|
|
431
|
-
: { API: '#ec4899', Service: '#3b82f6', Data: '#10b981', UI: '#f59e0b', Infrastructure: '#8b5cf6', Other: '#64748b' };
|
|
432
|
-
|
|
433
|
-
const legendLabel = useModuleColoring ? 'Colored by module' : 'Colored by layer';
|
|
434
|
-
|
|
435
|
-
const legendHtml = uniqueLayers.map(l => {
|
|
436
|
-
const color = colorMap[l] || '#64748b';
|
|
437
|
-
return `<span class="legend-item"><span class="legend-dot" style="background: ${color}"></span> ${l}</span>`;
|
|
438
|
-
}).join('');
|
|
439
|
-
|
|
440
|
-
const filterHtml = uniqueLayers.map(l => {
|
|
441
|
-
const color = colorMap[l] || '#64748b';
|
|
442
|
-
return `<label class="graph-filter-check"><input type="checkbox" checked data-layer="${l}" onchange="toggleGraphLayer('${l}', this.checked)"><span class="legend-dot" style="background: ${color}"></span> ${l}</label>`;
|
|
443
|
-
}).join('');
|
|
444
|
-
|
|
445
|
-
return `
|
|
446
|
-
<h2 class="section-title">🔗 Dependency Graph</h2>
|
|
447
|
-
<div class="card graph-card">
|
|
448
|
-
<div class="graph-controls">
|
|
449
|
-
<div class="graph-legend">
|
|
450
|
-
<span class="legend-label" style="color:#94a3b8;font-size:11px;margin-right:8px;">${legendLabel}:</span>
|
|
451
|
-
${legendHtml}
|
|
452
|
-
</div>
|
|
453
|
-
<div class="graph-filters">
|
|
454
|
-
<input type="text" id="graphSearch" class="graph-search" placeholder="🔍 Search node..." oninput="filterGraphNodes(this.value)">
|
|
455
|
-
<div class="graph-layer-filters">
|
|
456
|
-
${filterHtml}
|
|
457
|
-
</div>
|
|
458
|
-
</div>
|
|
459
|
-
${isLimited ? `<div class="graph-limit-notice">Showing top ${maxNodes} of ${allNodes.length} source files (most connected) · ${limitedLinks.length} links</div>` : ''}
|
|
460
|
-
</div>
|
|
461
|
-
<div id="dep-graph" style="width:100%; min-height:500px;"></div>
|
|
462
|
-
<div class="graph-hint">🖱️ Drag nodes • Scroll to zoom • Double-click to reset • Node size = connections</div>
|
|
463
|
-
</div>
|
|
464
|
-
<script type="application/json" id="graph-nodes">${JSON.stringify(limitedNodes)}${'</'+'script>'}
|
|
465
|
-
<script type="application/json" id="graph-links">${JSON.stringify(limitedLinks)}${'</'+'script>'}
|
|
466
|
-
<script type="application/json" id="graph-colors">${JSON.stringify(colorMap)}${'</'+'script>'}`;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
/**
|
|
470
|
-
* Bubble chart for anti-patterns — bigger = more severe
|
|
471
|
-
*/
|
|
472
|
-
private renderAntiPatternBubbles(
|
|
473
|
-
report: AnalysisReport,
|
|
474
|
-
grouped: Record<string, { count: number; severity: string; locations: string[]; suggestion: string }>
|
|
475
|
-
): string {
|
|
476
|
-
if (report.antiPatterns.length === 0) {
|
|
477
|
-
return `
|
|
478
|
-
<h2 class="section-title">✅ Anti-Patterns</h2>
|
|
479
|
-
<div class="card success-card">
|
|
480
|
-
<p>No significant anti-patterns detected. Excellent architecture!</p>
|
|
481
|
-
</div>`;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
const severityWeight: Record<string, number> = {
|
|
485
|
-
CRITICAL: 80, HIGH: 60, MEDIUM: 40, LOW: 25,
|
|
486
|
-
};
|
|
487
|
-
|
|
488
|
-
const severityColor: Record<string, string> = {
|
|
489
|
-
CRITICAL: '#ef4444', HIGH: '#f59e0b', MEDIUM: '#60a5fa', LOW: '#22c55e',
|
|
490
|
-
};
|
|
491
|
-
|
|
492
|
-
const bubbles = Object.entries(grouped).map(([name, data]) => ({
|
|
493
|
-
name,
|
|
494
|
-
count: data.count,
|
|
495
|
-
severity: data.severity,
|
|
496
|
-
radius: (severityWeight[data.severity] || 30) + data.count * 8,
|
|
497
|
-
color: severityColor[data.severity] || '#64748b',
|
|
498
|
-
}));
|
|
499
|
-
|
|
500
|
-
return `
|
|
501
|
-
<h2 class="section-title">🫧 Anti-Pattern Impact Map</h2>
|
|
502
|
-
<div class="card" style="display:flex; justify-content:center;">
|
|
503
|
-
<div id="bubble-chart" style="width:100%; min-height:300px;"></div>
|
|
504
|
-
</div>
|
|
505
|
-
<script type="application/json" id="bubble-data">${JSON.stringify(bubbles)}<\/script>`;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
private renderAntiPatterns(
|
|
509
|
-
report: AnalysisReport,
|
|
510
|
-
grouped: Record<string, { count: number; severity: string; locations: string[]; suggestion: string }>
|
|
511
|
-
): string {
|
|
512
|
-
if (report.antiPatterns.length === 0) return '';
|
|
513
|
-
|
|
514
|
-
const rows = Object.entries(grouped)
|
|
515
|
-
.sort((a, b) => b[1].count - a[1].count)
|
|
516
|
-
.map(
|
|
517
|
-
([name, data]) => `
|
|
518
|
-
<tr>
|
|
519
|
-
<td><strong>${this.escapeHtml(name)}</strong></td>
|
|
520
|
-
<td class="count-cell">${data.count}</td>
|
|
521
|
-
<td><span class="severity-badge severity-${data.severity}">${data.severity}</span></td>
|
|
522
|
-
<td><small class="suggestion">${this.escapeHtml(data.suggestion)}</small></td>
|
|
523
|
-
<td><div class="locations">${data.locations
|
|
524
|
-
.slice(0, 5)
|
|
525
|
-
.map((l) => `<code>${this.escapeHtml(l)}</code>`)
|
|
526
|
-
.join(' ')}${data.locations.length > 5 ? ` <em>+${data.count - 5} more</em>` : ''}</div></td>
|
|
527
|
-
</tr>`
|
|
528
|
-
)
|
|
529
|
-
.join('');
|
|
530
|
-
|
|
531
|
-
return `
|
|
532
|
-
<h2 class="section-title">⚠️ Anti-Pattern Details (${report.antiPatterns.length})</h2>
|
|
533
|
-
<div class="card">
|
|
534
|
-
<table>
|
|
535
|
-
<thead>
|
|
536
|
-
<tr>
|
|
537
|
-
<th>Pattern</th>
|
|
538
|
-
<th>Count</th>
|
|
539
|
-
<th>Severity</th>
|
|
540
|
-
<th>Suggestion</th>
|
|
541
|
-
<th>Locations</th>
|
|
542
|
-
</tr>
|
|
543
|
-
</thead>
|
|
544
|
-
<tbody>${rows}</tbody>
|
|
545
|
-
</table>
|
|
546
|
-
</div>`;
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
private renderSuggestions(
|
|
550
|
-
suggestions: Array<{ priority: string; title: string; description: string; impact: string; count: number }>
|
|
551
|
-
): string {
|
|
552
|
-
if (suggestions.length === 0) return '';
|
|
553
|
-
|
|
554
|
-
const rows = suggestions
|
|
555
|
-
.map(
|
|
556
|
-
(s, i) => `
|
|
557
|
-
<tr>
|
|
558
|
-
<td>${i + 1}</td>
|
|
559
|
-
<td><span class="severity-badge severity-${s.priority}">${s.priority}</span></td>
|
|
560
|
-
<td>
|
|
561
|
-
<strong>${this.escapeHtml(s.title)}</strong>
|
|
562
|
-
${s.count > 1 ? `<span class="count-badge">×${s.count}</span>` : ''}
|
|
563
|
-
<br/><small class="suggestion">${this.escapeHtml(s.description)}</small>
|
|
564
|
-
</td>
|
|
565
|
-
<td class="impact">${this.escapeHtml(s.impact)}</td>
|
|
566
|
-
</tr>`
|
|
567
|
-
)
|
|
568
|
-
.join('');
|
|
569
|
-
|
|
570
|
-
return `
|
|
571
|
-
<h2 class="section-title">💡 Refactoring Suggestions</h2>
|
|
572
|
-
<div class="card">
|
|
573
|
-
<table>
|
|
574
|
-
<thead>
|
|
575
|
-
<tr>
|
|
576
|
-
<th>#</th>
|
|
577
|
-
<th>Priority</th>
|
|
578
|
-
<th>Suggestion</th>
|
|
579
|
-
<th>Impact</th>
|
|
580
|
-
</tr>
|
|
581
|
-
</thead>
|
|
582
|
-
<tbody>${rows}</tbody>
|
|
583
|
-
</table>
|
|
584
|
-
</div>`;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
private renderFooter(): string {
|
|
588
|
-
return `
|
|
589
|
-
<div class="footer">
|
|
590
|
-
<p>Generated by <a href="https://github.com/camilooscargbaptista/architect">⚡ Architect v3.1</a> — Enterprise Architecture Intelligence</p>
|
|
591
|
-
<p>By <strong>Camilo Girardelli</strong> · <a href="https://www.girardellitecnologia.com">Girardelli Tecnologia</a></p>
|
|
592
|
-
</div>`;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// ── Refactoring Plan Section ──
|
|
596
|
-
|
|
597
|
-
private opColor(type: string): string {
|
|
598
|
-
switch (type) {
|
|
599
|
-
case 'CREATE': return '#22c55e';
|
|
600
|
-
case 'MOVE': return '#3b82f6';
|
|
601
|
-
case 'MODIFY': return '#f59e0b';
|
|
602
|
-
case 'DELETE': return '#ef4444';
|
|
603
|
-
default: return '#64748b';
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
private opIcon(type: string): string {
|
|
608
|
-
switch (type) {
|
|
609
|
-
case 'CREATE': return '➕';
|
|
610
|
-
case 'MOVE': return '📦';
|
|
611
|
-
case 'MODIFY': return '✏️';
|
|
612
|
-
case 'DELETE': return '🗑️';
|
|
613
|
-
default: return '📄';
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
private renderRefactoringPlan(plan: RefactoringPlan): string {
|
|
618
|
-
if (plan.steps.length === 0) {
|
|
619
|
-
return `
|
|
620
|
-
<h2 class="section-title">✅ Refactoring Plan</h2>
|
|
621
|
-
<div class="card success-card">
|
|
622
|
-
<p>No refactoring needed! Your architecture is already in great shape.</p>
|
|
623
|
-
</div>`;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
const improvement = plan.estimatedScoreAfter.overall - plan.currentScore.overall;
|
|
627
|
-
|
|
628
|
-
const metrics = Object.keys(plan.currentScore.breakdown) as Array<keyof typeof plan.currentScore.breakdown>;
|
|
629
|
-
const bars = metrics.map(metric => {
|
|
630
|
-
const before = plan.currentScore.breakdown[metric];
|
|
631
|
-
const after = plan.estimatedScoreAfter.breakdown[metric] ?? before;
|
|
632
|
-
const diff = after - before;
|
|
633
|
-
return `
|
|
634
|
-
<div class="comparison-row">
|
|
635
|
-
<div class="refactor-metric-name">${metric}</div>
|
|
636
|
-
<div class="refactor-metric-bars">
|
|
637
|
-
<div class="rbar-before" style="width: ${before}%; background: ${this.scoreColor(before)}40"><span>${before}</span></div>
|
|
638
|
-
<div class="rbar-after" style="width: ${after}%; background: ${this.scoreColor(after)}"><span>${after}</span></div>
|
|
639
|
-
</div>
|
|
640
|
-
<div class="refactor-metric-diff" style="color: ${diff > 0 ? '#22c55e' : '#64748b'}">
|
|
641
|
-
${diff > 0 ? `+${diff}` : diff === 0 ? '—' : String(diff)}
|
|
642
|
-
</div>
|
|
643
|
-
</div>`;
|
|
644
|
-
}).join('');
|
|
645
|
-
|
|
646
|
-
const stepsHtml = plan.steps.map(step => this.renderRefactorStep(step)).join('');
|
|
647
|
-
|
|
648
|
-
const criticalCount = plan.steps.filter(s => s.priority === 'CRITICAL').length;
|
|
649
|
-
const highCount = plan.steps.filter(s => s.priority === 'HIGH').length;
|
|
650
|
-
const mediumCount = plan.steps.filter(s => s.priority === 'MEDIUM').length;
|
|
651
|
-
const lowCount = plan.steps.filter(s => s.priority === 'LOW').length;
|
|
652
|
-
|
|
653
|
-
return `
|
|
654
|
-
<h2 class="section-title">🔧 Refactoring Plan</h2>
|
|
655
|
-
|
|
656
|
-
<div class="card refactor-score">
|
|
657
|
-
<div class="refactor-score-pair">
|
|
658
|
-
<div class="rscore-box">
|
|
659
|
-
<div class="rscore-num" style="color: ${this.scoreColor(plan.currentScore.overall)}">${plan.currentScore.overall}</div>
|
|
660
|
-
<div class="rscore-label">Current</div>
|
|
661
|
-
</div>
|
|
662
|
-
<div class="rscore-arrow">
|
|
663
|
-
<svg width="60" height="30" viewBox="0 0 60 30">
|
|
664
|
-
<path d="M5 15 L45 15 M40 8 L48 15 L40 22" stroke="#818cf8" stroke-width="2.5" fill="none"/>
|
|
665
|
-
</svg>
|
|
666
|
-
</div>
|
|
667
|
-
<div class="rscore-box">
|
|
668
|
-
<div class="rscore-num" style="color: ${this.scoreColor(plan.estimatedScoreAfter.overall)}">${plan.estimatedScoreAfter.overall}</div>
|
|
669
|
-
<div class="rscore-label">Estimated</div>
|
|
670
|
-
</div>
|
|
671
|
-
<div class="rscore-improvement" style="color: #22c55e">+${improvement} pts</div>
|
|
672
|
-
</div>
|
|
673
|
-
<div class="refactor-bars-section">
|
|
674
|
-
<div class="refactor-legend">
|
|
675
|
-
<span class="rlegend-tag rbefore">Before</span>
|
|
676
|
-
<span class="rlegend-tag rafter">After</span>
|
|
677
|
-
</div>
|
|
678
|
-
${bars}
|
|
679
|
-
</div>
|
|
680
|
-
</div>
|
|
681
|
-
|
|
682
|
-
<div class="refactor-stats-row">
|
|
683
|
-
<div class="rstat">${plan.steps.length} steps</div>
|
|
684
|
-
<div class="rstat">${plan.totalOperations} operations</div>
|
|
685
|
-
<div class="rstat">Tier 1: ${plan.tier1Steps}</div>
|
|
686
|
-
<div class="rstat">Tier 2: ${plan.tier2Steps}</div>
|
|
687
|
-
</div>
|
|
688
|
-
|
|
689
|
-
<div class="priority-bar">
|
|
690
|
-
${criticalCount ? `<div class="prio-seg prio-critical" style="flex: ${criticalCount}">🔴 ${criticalCount}</div>` : ''}
|
|
691
|
-
${highCount ? `<div class="prio-seg prio-high" style="flex: ${highCount}">🟠 ${highCount}</div>` : ''}
|
|
692
|
-
${mediumCount ? `<div class="prio-seg prio-medium" style="flex: ${mediumCount}">🔵 ${mediumCount}</div>` : ''}
|
|
693
|
-
${lowCount ? `<div class="prio-seg prio-low" style="flex: ${lowCount}">🟢 ${lowCount}</div>` : ''}
|
|
694
|
-
</div>
|
|
695
|
-
|
|
696
|
-
<div class="refactor-roadmap">
|
|
697
|
-
${stepsHtml}
|
|
698
|
-
</div>`;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
private renderRefactorStep(step: RefactorStep): string {
|
|
702
|
-
const operationsHtml = step.operations.map(op => `
|
|
703
|
-
<div class="rop">
|
|
704
|
-
<span class="rop-icon">${this.opIcon(op.type)}</span>
|
|
705
|
-
<span class="rop-badge" style="background: ${this.opColor(op.type)}20; color: ${this.opColor(op.type)}; border: 1px solid ${this.opColor(op.type)}40">${op.type}</span>
|
|
706
|
-
<code class="rop-path">${this.escapeHtml(op.path)}</code>
|
|
707
|
-
${op.newPath ? `<span class="rop-arrow">→</span> <code class="rop-path">${this.escapeHtml(op.newPath)}</code>` : ''}
|
|
708
|
-
<div class="rop-desc">${this.escapeHtml(op.description)}</div>
|
|
709
|
-
</div>
|
|
710
|
-
`).join('');
|
|
711
|
-
|
|
712
|
-
const impactHtml = step.scoreImpact.map(i =>
|
|
713
|
-
`<span class="rimpact-tag">${i.metric}: ${i.before}→${i.after} <strong>+${i.after - i.before}</strong></span>`
|
|
714
|
-
).join('');
|
|
715
|
-
|
|
716
|
-
return `
|
|
717
|
-
<div class="rstep-card">
|
|
718
|
-
<div class="rstep-header">
|
|
719
|
-
<div class="rstep-number">${step.id}</div>
|
|
720
|
-
<div class="rstep-info">
|
|
721
|
-
<div class="rstep-title-row">
|
|
722
|
-
<h3>${this.escapeHtml(step.title)}</h3>
|
|
723
|
-
<span class="severity-badge severity-${step.priority}">${step.priority}</span>
|
|
724
|
-
<span class="tier-badge">Tier ${step.tier}</span>
|
|
725
|
-
</div>
|
|
726
|
-
<p class="rstep-desc">${this.escapeHtml(step.description)}</p>
|
|
727
|
-
<details class="rstep-details">
|
|
728
|
-
<summary>📖 Why?</summary>
|
|
729
|
-
<p class="rstep-rationale">${this.escapeHtml(step.rationale)}</p>
|
|
730
|
-
</details>
|
|
731
|
-
</div>
|
|
732
|
-
</div>
|
|
733
|
-
<details class="rstep-ops-accordion">
|
|
734
|
-
<summary class="rstep-ops-toggle">📋 Operations (${step.operations.length})</summary>
|
|
735
|
-
<div class="rstep-ops">
|
|
736
|
-
${operationsHtml}
|
|
737
|
-
</div>
|
|
738
|
-
</details>
|
|
739
|
-
<div class="rstep-impact">
|
|
740
|
-
<h4>📈 Score Impact</h4>
|
|
741
|
-
<div class="rimpact-tags">${impactHtml}</div>
|
|
742
|
-
</div>
|
|
743
|
-
</div>`;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
/**
|
|
747
|
-
* All JavaScript for D3.js visualizations, animated counters, and radar chart
|
|
748
|
-
*/
|
|
749
|
-
private getScripts(report: AnalysisReport): string {
|
|
750
|
-
const breakdown = report.score.breakdown;
|
|
751
|
-
return `<script>
|
|
752
|
-
// ── Animated Counters ──
|
|
753
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
754
|
-
const counters = document.querySelectorAll('.score-counter, .stat-counter');
|
|
755
|
-
const observer = new IntersectionObserver((entries) => {
|
|
756
|
-
entries.forEach(entry => {
|
|
757
|
-
if (entry.isIntersecting) {
|
|
758
|
-
const el = entry.target;
|
|
759
|
-
const target = parseInt(el.dataset.target || '0');
|
|
760
|
-
animateCounter(el, target);
|
|
761
|
-
observer.unobserve(el);
|
|
762
|
-
}
|
|
763
|
-
});
|
|
764
|
-
}, { threshold: 0.5 });
|
|
765
|
-
|
|
766
|
-
counters.forEach(c => observer.observe(c));
|
|
767
|
-
|
|
768
|
-
// ── Sidebar Active Section Tracking ──
|
|
769
|
-
const sectionIds = ['score', 'layers', 'anti-patterns', 'suggestions', 'refactoring', 'agents'];
|
|
770
|
-
const sectionObserver = new IntersectionObserver((entries) => {
|
|
771
|
-
entries.forEach(entry => {
|
|
772
|
-
if (entry.isIntersecting) {
|
|
773
|
-
document.querySelectorAll('.sidebar-link').forEach(l => l.classList.remove('active'));
|
|
774
|
-
const link = document.querySelector('.sidebar-link[data-section="' + entry.target.id + '"]');
|
|
775
|
-
if (link) link.classList.add('active');
|
|
776
|
-
}
|
|
777
|
-
});
|
|
778
|
-
}, { threshold: 0.15, rootMargin: '-80px 0px -60% 0px' });
|
|
779
|
-
|
|
780
|
-
sectionIds.forEach(id => {
|
|
781
|
-
const el = document.getElementById(id);
|
|
782
|
-
if (el) sectionObserver.observe(el);
|
|
783
|
-
});
|
|
784
|
-
});
|
|
785
|
-
|
|
786
|
-
function animateCounter(el, target) {
|
|
787
|
-
const duration = 1500;
|
|
788
|
-
const start = performance.now();
|
|
789
|
-
const update = (now) => {
|
|
790
|
-
const elapsed = now - start;
|
|
791
|
-
const progress = Math.min(elapsed / duration, 1);
|
|
792
|
-
const ease = 1 - Math.pow(1 - progress, 3);
|
|
793
|
-
el.textContent = Math.round(target * ease).toLocaleString();
|
|
794
|
-
if (progress < 1) requestAnimationFrame(update);
|
|
795
|
-
};
|
|
796
|
-
requestAnimationFrame(update);
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
// ── Radar Chart ──
|
|
800
|
-
(function() {
|
|
801
|
-
const data = [
|
|
802
|
-
{ axis: 'Modularity', value: ${breakdown.modularity} },
|
|
803
|
-
{ axis: 'Coupling', value: ${breakdown.coupling} },
|
|
804
|
-
{ axis: 'Cohesion', value: ${breakdown.cohesion} },
|
|
805
|
-
{ axis: 'Layering', value: ${breakdown.layering} },
|
|
806
|
-
];
|
|
807
|
-
|
|
808
|
-
const svg = d3.select('#radar-chart');
|
|
809
|
-
const w = 350, h = 350, cx = w/2, cy = h/2, maxR = 120;
|
|
810
|
-
const levels = 5;
|
|
811
|
-
const total = data.length;
|
|
812
|
-
const angleSlice = (Math.PI * 2) / total;
|
|
813
|
-
|
|
814
|
-
// Grid circles
|
|
815
|
-
for (let i = 1; i <= levels; i++) {
|
|
816
|
-
const r = (maxR / levels) * i;
|
|
817
|
-
svg.append('circle')
|
|
818
|
-
.attr('cx', cx).attr('cy', cy).attr('r', r)
|
|
819
|
-
.attr('fill', 'none').attr('stroke', '#334155').attr('stroke-width', 0.5)
|
|
820
|
-
.attr('stroke-dasharray', '4,4');
|
|
821
|
-
|
|
822
|
-
svg.append('text')
|
|
823
|
-
.attr('x', cx + 4).attr('y', cy - r + 4)
|
|
824
|
-
.text(Math.round(100 / levels * i))
|
|
825
|
-
.attr('fill', '#475569').attr('font-size', '10px');
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
// Axis lines
|
|
829
|
-
data.forEach((d, i) => {
|
|
830
|
-
const angle = angleSlice * i - Math.PI/2;
|
|
831
|
-
const x = cx + Math.cos(angle) * (maxR + 20);
|
|
832
|
-
const y = cy + Math.sin(angle) * (maxR + 20);
|
|
833
|
-
|
|
834
|
-
svg.append('line')
|
|
835
|
-
.attr('x1', cx).attr('y1', cy).attr('x2', cx + Math.cos(angle) * maxR).attr('y2', cy + Math.sin(angle) * maxR)
|
|
836
|
-
.attr('stroke', '#334155').attr('stroke-width', 1);
|
|
837
|
-
|
|
838
|
-
svg.append('text')
|
|
839
|
-
.attr('x', x).attr('y', y)
|
|
840
|
-
.attr('text-anchor', 'middle').attr('dominant-baseline', 'middle')
|
|
841
|
-
.attr('fill', '#94a3b8').attr('font-size', '12px').attr('font-weight', '600')
|
|
842
|
-
.text(d.axis);
|
|
843
|
-
});
|
|
844
|
-
|
|
845
|
-
// Data polygon
|
|
846
|
-
const points = data.map((d, i) => {
|
|
847
|
-
const angle = angleSlice * i - Math.PI/2;
|
|
848
|
-
const r = (d.value / 100) * maxR;
|
|
849
|
-
return [cx + Math.cos(angle) * r, cy + Math.sin(angle) * r];
|
|
850
|
-
});
|
|
851
|
-
|
|
852
|
-
const pointsStr = points.map(p => p.join(',')).join(' ');
|
|
853
|
-
|
|
854
|
-
svg.append('polygon')
|
|
855
|
-
.attr('points', pointsStr)
|
|
856
|
-
.attr('fill', 'rgba(129, 140, 248, 0.15)')
|
|
857
|
-
.attr('stroke', '#818cf8').attr('stroke-width', 2);
|
|
858
|
-
|
|
859
|
-
// Data dots
|
|
860
|
-
points.forEach((p, i) => {
|
|
861
|
-
const color = data[i].value >= 70 ? '#22c55e' : data[i].value >= 50 ? '#f59e0b' : '#ef4444';
|
|
862
|
-
svg.append('circle')
|
|
863
|
-
.attr('cx', p[0]).attr('cy', p[1]).attr('r', 5)
|
|
864
|
-
.attr('fill', color).attr('stroke', '#0f172a').attr('stroke-width', 2);
|
|
865
|
-
|
|
866
|
-
svg.append('text')
|
|
867
|
-
.attr('x', p[0]).attr('y', p[1] - 12)
|
|
868
|
-
.attr('text-anchor', 'middle')
|
|
869
|
-
.attr('fill', color).attr('font-size', '12px').attr('font-weight', '700')
|
|
870
|
-
.text(data[i].value);
|
|
871
|
-
});
|
|
872
|
-
})();
|
|
873
|
-
|
|
874
|
-
// ── D3 Force Dependency Graph ──
|
|
875
|
-
(function() {
|
|
876
|
-
const nodesEl = document.getElementById('graph-nodes');
|
|
877
|
-
const linksEl = document.getElementById('graph-links');
|
|
878
|
-
if (!nodesEl || !linksEl) return;
|
|
879
|
-
|
|
880
|
-
const nodes = JSON.parse(nodesEl.textContent || '[]');
|
|
881
|
-
const links = JSON.parse(linksEl.textContent || '[]');
|
|
882
|
-
if (nodes.length === 0) return;
|
|
883
|
-
|
|
884
|
-
const container = document.getElementById('dep-graph');
|
|
885
|
-
const width = container.clientWidth || 800;
|
|
886
|
-
const height = 500;
|
|
887
|
-
container.style.height = height + 'px';
|
|
888
|
-
|
|
889
|
-
// Dynamic color map — loaded from JSON (supports both layer and module coloring)
|
|
890
|
-
const colorsEl = document.getElementById('graph-colors');
|
|
891
|
-
const layerColors = colorsEl ? JSON.parse(colorsEl.textContent || '{}') : {
|
|
892
|
-
API: '#ec4899', Service: '#3b82f6', Data: '#10b981',
|
|
893
|
-
UI: '#f59e0b', Infrastructure: '#8b5cf6', Other: '#64748b',
|
|
894
|
-
};
|
|
895
|
-
|
|
896
|
-
const svg = d3.select('#dep-graph').append('svg')
|
|
897
|
-
.attr('width', width).attr('height', height)
|
|
898
|
-
.attr('viewBox', [0, 0, width, height]);
|
|
899
|
-
|
|
900
|
-
// Zoom container
|
|
901
|
-
const g = svg.append('g');
|
|
902
|
-
|
|
903
|
-
// Zoom behavior
|
|
904
|
-
const zoom = d3.zoom()
|
|
905
|
-
.scaleExtent([0.2, 5])
|
|
906
|
-
.on('zoom', (event) => { g.attr('transform', event.transform); });
|
|
907
|
-
svg.call(zoom);
|
|
908
|
-
|
|
909
|
-
// Double-click to reset zoom
|
|
910
|
-
svg.on('dblclick.zoom', () => {
|
|
911
|
-
svg.transition().duration(500).call(zoom.transform, d3.zoomIdentity);
|
|
912
|
-
});
|
|
913
|
-
|
|
914
|
-
// Arrow marker
|
|
915
|
-
g.append('defs').append('marker')
|
|
916
|
-
.attr('id', 'arrowhead').attr('viewBox', '-0 -5 10 10')
|
|
917
|
-
.attr('refX', 20).attr('refY', 0).attr('orient', 'auto')
|
|
918
|
-
.attr('markerWidth', 6).attr('markerHeight', 6)
|
|
919
|
-
.append('path').attr('d', 'M 0,-5 L 10,0 L 0,5')
|
|
920
|
-
.attr('fill', '#475569');
|
|
921
|
-
|
|
922
|
-
// Tuned simulation for better spread
|
|
923
|
-
const simulation = d3.forceSimulation(nodes)
|
|
924
|
-
.force('link', d3.forceLink(links).id(d => d.id).distance(80))
|
|
925
|
-
.force('charge', d3.forceManyBody().strength(-250))
|
|
926
|
-
.force('center', d3.forceCenter(width / 2, height / 2))
|
|
927
|
-
.force('x', d3.forceX(width / 2).strength(0.05))
|
|
928
|
-
.force('y', d3.forceY(height / 2).strength(0.05))
|
|
929
|
-
.force('collision', d3.forceCollide().radius(d => Math.max(d.connections * 2 + 16, 20)));
|
|
930
|
-
|
|
931
|
-
const link = g.append('g')
|
|
932
|
-
.selectAll('line').data(links).join('line')
|
|
933
|
-
.attr('stroke', '#334155').attr('stroke-width', 1)
|
|
934
|
-
.attr('stroke-opacity', 0.4).attr('marker-end', 'url(#arrowhead)');
|
|
935
|
-
|
|
936
|
-
const node = g.append('g')
|
|
937
|
-
.selectAll('g').data(nodes).join('g')
|
|
938
|
-
.call(d3.drag()
|
|
939
|
-
.on('start', (e, d) => { if (!e.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; })
|
|
940
|
-
.on('drag', (e, d) => { d.fx = e.x; d.fy = e.y; })
|
|
941
|
-
.on('end', (e, d) => { if (!e.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; })
|
|
942
|
-
);
|
|
943
|
-
|
|
944
|
-
// Node circles — color by layer
|
|
945
|
-
node.append('circle')
|
|
946
|
-
.attr('r', d => Math.max(d.connections * 2.5 + 5, 6))
|
|
947
|
-
.attr('fill', d => layerColors[d.layer] || '#64748b')
|
|
948
|
-
.attr('stroke', '#0f172a').attr('stroke-width', 1.5)
|
|
949
|
-
.attr('opacity', 0.9);
|
|
950
|
-
|
|
951
|
-
// Node labels — only show for nodes with enough connections
|
|
952
|
-
node.filter(d => d.connections >= 2).append('text')
|
|
953
|
-
.text(d => d.name.replace(/\\.[^.]+$/, ''))
|
|
954
|
-
.attr('x', 0).attr('y', d => -(Math.max(d.connections * 2.5 + 5, 6) + 4))
|
|
955
|
-
.attr('text-anchor', 'middle')
|
|
956
|
-
.attr('fill', '#e2e8f0').attr('font-size', '9px').attr('font-weight', '500');
|
|
957
|
-
|
|
958
|
-
// Tooltip
|
|
959
|
-
node.append('title')
|
|
960
|
-
.text(d => d.id + '\\nConnections: ' + d.connections + '\\nLayer: ' + d.layer);
|
|
961
|
-
|
|
962
|
-
simulation.on('tick', () => {
|
|
963
|
-
link
|
|
964
|
-
.attr('x1', d => d.source.x).attr('y1', d => d.source.y)
|
|
965
|
-
.attr('x2', d => d.target.x).attr('y2', d => d.target.y);
|
|
966
|
-
node.attr('transform', d => 'translate(' + d.x + ',' + d.y + ')');
|
|
967
|
-
});
|
|
968
|
-
|
|
969
|
-
// Expose search and filter functions
|
|
970
|
-
window.filterGraphNodes = function(query) {
|
|
971
|
-
if (!query) {
|
|
972
|
-
node.attr('opacity', 1);
|
|
973
|
-
link.attr('opacity', 0.4);
|
|
974
|
-
return;
|
|
975
|
-
}
|
|
976
|
-
query = query.toLowerCase();
|
|
977
|
-
node.attr('opacity', d => d.id.toLowerCase().includes(query) || d.name.toLowerCase().includes(query) ? 1 : 0.1);
|
|
978
|
-
link.attr('opacity', d => {
|
|
979
|
-
const srcMatch = d.source.id.toLowerCase().includes(query);
|
|
980
|
-
const tgtMatch = d.target.id.toLowerCase().includes(query);
|
|
981
|
-
return (srcMatch || tgtMatch) ? 0.6 : 0.05;
|
|
982
|
-
});
|
|
983
|
-
};
|
|
984
|
-
|
|
985
|
-
window.toggleGraphLayer = function(layer, visible) {
|
|
986
|
-
node.filter(d => d.layer === layer)
|
|
987
|
-
.transition().duration(300)
|
|
988
|
-
.attr('opacity', visible ? 1 : 0.05);
|
|
989
|
-
link.filter(d => d.source.layer === layer || d.target.layer === layer)
|
|
990
|
-
.transition().duration(300)
|
|
991
|
-
.attr('opacity', visible ? 0.4 : 0.02);
|
|
992
|
-
};
|
|
993
|
-
})();
|
|
994
|
-
|
|
995
|
-
// ── Bubble Chart ──
|
|
996
|
-
(function() {
|
|
997
|
-
const dataEl = document.getElementById('bubble-data');
|
|
998
|
-
if (!dataEl) return;
|
|
999
|
-
|
|
1000
|
-
const bubbles = JSON.parse(dataEl.textContent || '[]');
|
|
1001
|
-
if (bubbles.length === 0) return;
|
|
1002
|
-
|
|
1003
|
-
const container = document.getElementById('bubble-chart');
|
|
1004
|
-
const width = container.clientWidth || 600;
|
|
1005
|
-
const height = 300;
|
|
1006
|
-
|
|
1007
|
-
const svg = d3.select('#bubble-chart').append('svg')
|
|
1008
|
-
.attr('width', width).attr('height', height)
|
|
1009
|
-
.attr('viewBox', [0, 0, width, height]);
|
|
1010
|
-
|
|
1011
|
-
const simulation = d3.forceSimulation(bubbles)
|
|
1012
|
-
.force('charge', d3.forceManyBody().strength(5))
|
|
1013
|
-
.force('center', d3.forceCenter(width / 2, height / 2))
|
|
1014
|
-
.force('collision', d3.forceCollide().radius(d => d.radius + 4))
|
|
1015
|
-
.stop();
|
|
1016
|
-
|
|
1017
|
-
for (let i = 0; i < 120; i++) simulation.tick();
|
|
1018
|
-
|
|
1019
|
-
const g = svg.selectAll('g').data(bubbles).join('g')
|
|
1020
|
-
.attr('transform', d => 'translate(' + d.x + ',' + d.y + ')');
|
|
1021
|
-
|
|
1022
|
-
// Glow effect
|
|
1023
|
-
g.append('circle')
|
|
1024
|
-
.attr('r', d => d.radius)
|
|
1025
|
-
.attr('fill', d => d.color + '20')
|
|
1026
|
-
.attr('stroke', d => d.color).attr('stroke-width', 2)
|
|
1027
|
-
.attr('opacity', 0)
|
|
1028
|
-
.transition().duration(800).delay((d, i) => i * 200)
|
|
1029
|
-
.attr('opacity', 1);
|
|
1030
|
-
|
|
1031
|
-
// Inner circle
|
|
1032
|
-
g.append('circle')
|
|
1033
|
-
.attr('r', d => d.radius * 0.7)
|
|
1034
|
-
.attr('fill', d => d.color + '30')
|
|
1035
|
-
.attr('opacity', 0)
|
|
1036
|
-
.transition().duration(800).delay((d, i) => i * 200)
|
|
1037
|
-
.attr('opacity', 1);
|
|
1038
|
-
|
|
1039
|
-
// Name
|
|
1040
|
-
g.append('text')
|
|
1041
|
-
.text(d => d.name)
|
|
1042
|
-
.attr('text-anchor', 'middle').attr('dy', '-0.3em')
|
|
1043
|
-
.attr('fill', '#e2e8f0').attr('font-size', d => Math.max(d.radius / 4, 10) + 'px')
|
|
1044
|
-
.attr('font-weight', '700');
|
|
1045
|
-
|
|
1046
|
-
// Count badge
|
|
1047
|
-
g.append('text')
|
|
1048
|
-
.text(d => '×' + d.count)
|
|
1049
|
-
.attr('text-anchor', 'middle').attr('dy', '1.2em')
|
|
1050
|
-
.attr('fill', d => d.color).attr('font-size', d => Math.max(d.radius / 5, 9) + 'px')
|
|
1051
|
-
.attr('font-weight', '600');
|
|
1052
|
-
|
|
1053
|
-
// Severity label
|
|
1054
|
-
g.append('text')
|
|
1055
|
-
.text(d => d.severity)
|
|
1056
|
-
.attr('text-anchor', 'middle').attr('dy', '2.5em')
|
|
1057
|
-
.attr('fill', '#64748b').attr('font-size', '9px').attr('text-transform', 'uppercase');
|
|
1058
|
-
})();
|
|
1059
|
-
<\/script>`;
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
private renderAgentSuggestions(s: AgentSuggestion): string {
|
|
1064
|
-
const roleIcon = (name: string): string => {
|
|
1065
|
-
if (name.includes('ORCHESTRATOR')) return '\u{1F3AD}';
|
|
1066
|
-
if (name.includes('BACKEND') || name.includes('FRONTEND') || name.includes('DATABASE') || name.includes('FLUTTER')) return '\u{1F4BB}';
|
|
1067
|
-
if (name.includes('SECURITY')) return '\u{1F6E1}\uFE0F';
|
|
1068
|
-
if (name.includes('QA')) return '\u{1F9EA}';
|
|
1069
|
-
if (name.includes('TECH-DEBT')) return '\u{1F4CA}';
|
|
1070
|
-
return '\u{1F916}';
|
|
1071
|
-
};
|
|
1072
|
-
|
|
1073
|
-
const roleLabel = (name: string): string => {
|
|
1074
|
-
if (name.includes('ORCHESTRATOR')) return 'coordination';
|
|
1075
|
-
if (name.includes('SECURITY')) return 'protection';
|
|
1076
|
-
if (name.includes('QA')) return 'quality';
|
|
1077
|
-
if (name.includes('TECH-DEBT')) return 'governance';
|
|
1078
|
-
return 'development';
|
|
1079
|
-
};
|
|
1080
|
-
|
|
1081
|
-
const roleColor = (name: string): string => {
|
|
1082
|
-
if (name.includes('ORCHESTRATOR')) return '#c084fc';
|
|
1083
|
-
if (name.includes('SECURITY')) return '#f87171';
|
|
1084
|
-
if (name.includes('QA')) return '#34d399';
|
|
1085
|
-
if (name.includes('TECH-DEBT')) return '#fbbf24';
|
|
1086
|
-
return '#60a5fa';
|
|
1087
|
-
};
|
|
1088
|
-
|
|
1089
|
-
// Status helpers
|
|
1090
|
-
const statusBadge = (status: string): string => {
|
|
1091
|
-
const map: Record<string, { icon: string; label: string; color: string }> = {
|
|
1092
|
-
'KEEP': { icon: '✅', label: 'KEEP', color: '#22c55e' },
|
|
1093
|
-
'MODIFY': { icon: '🔵', label: 'MODIFY', color: '#3b82f6' },
|
|
1094
|
-
'CREATE': { icon: '🟡', label: 'NEW', color: '#f59e0b' },
|
|
1095
|
-
'DELETE': { icon: '🔴', label: 'REMOVE', color: '#ef4444' },
|
|
1096
|
-
};
|
|
1097
|
-
const s = map[status] || map['CREATE'];
|
|
1098
|
-
return `<span class="agent-status-badge" style="background:${s.color}20;color:${s.color};border:1px solid ${s.color}40">${s.icon} ${s.label}</span>`;
|
|
1099
|
-
};
|
|
1100
|
-
|
|
1101
|
-
const statusBorder = (status: string): string => {
|
|
1102
|
-
const map: Record<string, string> = {
|
|
1103
|
-
'KEEP': '#22c55e', 'MODIFY': '#3b82f6', 'CREATE': '#f59e0b', 'DELETE': '#ef4444',
|
|
1104
|
-
};
|
|
1105
|
-
return map[status] || '#334155';
|
|
1106
|
-
};
|
|
1107
|
-
|
|
1108
|
-
const agentCards = s.suggestedAgents.map(a =>
|
|
1109
|
-
`<label class="agent-toggle-card" data-category="agents" data-name="${a.name}">
|
|
1110
|
-
<input type="checkbox" class="agent-check" ${a.status !== 'DELETE' ? 'checked' : ''} data-type="agents" data-item="${a.name}">
|
|
1111
|
-
<div class="agent-toggle-inner" style="border-color:${statusBorder(a.status)}">
|
|
1112
|
-
<div class="agent-toggle-icon">${roleIcon(a.name)}</div>
|
|
1113
|
-
<div class="agent-toggle-info">
|
|
1114
|
-
<span class="agent-toggle-name">${a.name}</span>
|
|
1115
|
-
<span class="agent-toggle-role" style="color:${roleColor(a.name)}">${roleLabel(a.name)}</span>
|
|
1116
|
-
${a.description ? `<span class="agent-toggle-desc">${a.description}</span>` : ''}
|
|
1117
|
-
</div>
|
|
1118
|
-
${statusBadge(a.status)}
|
|
1119
|
-
<div class="agent-toggle-check">\u2713</div>
|
|
1120
|
-
</div>
|
|
1121
|
-
</label>`
|
|
1122
|
-
).join('\n');
|
|
1123
|
-
|
|
1124
|
-
const miniCard = (item: { name: string; status: string; description?: string }, icon: string, type: string): string =>
|
|
1125
|
-
`<label class="agent-toggle-card mini" data-category="${type}">
|
|
1126
|
-
<input type="checkbox" class="agent-check" ${item.status !== 'DELETE' ? 'checked' : ''} data-type="${type}" data-item="${item.name}">
|
|
1127
|
-
<div class="agent-toggle-inner" style="border-color:${statusBorder(item.status)}">
|
|
1128
|
-
<span class="agent-toggle-icon">${icon}</span>
|
|
1129
|
-
<div class="agent-toggle-info">
|
|
1130
|
-
<span class="agent-toggle-name">${item.name}.md</span>
|
|
1131
|
-
${item.description ? `<span class="agent-toggle-desc">${item.description}</span>` : ''}
|
|
1132
|
-
</div>
|
|
1133
|
-
${statusBadge(item.status)}
|
|
1134
|
-
<div class="agent-toggle-check">\u2713</div>
|
|
1135
|
-
</div>
|
|
1136
|
-
</label>`;
|
|
1137
|
-
|
|
1138
|
-
const ruleCards = s.suggestedRules.map(r => miniCard(r, '\u{1F4CF}', 'rules')).join('\n');
|
|
1139
|
-
const guardCards = s.suggestedGuards.map(g => miniCard(g, '\u{1F6E1}\uFE0F', 'guards')).join('\n');
|
|
1140
|
-
const workflowCards = s.suggestedWorkflows.map(w => miniCard(w, '\u26A1', 'workflows')).join('\n');
|
|
1141
|
-
|
|
1142
|
-
const skillCards = s.suggestedSkills.map(sk =>
|
|
1143
|
-
`<label class="agent-toggle-card" data-category="skills">
|
|
1144
|
-
<input type="checkbox" class="agent-check" checked data-type="skills" data-item="${sk.source}">
|
|
1145
|
-
<div class="agent-toggle-inner" style="border-color:${statusBorder(sk.status)}">
|
|
1146
|
-
<span class="agent-toggle-icon">\u{1F9E0}</span>
|
|
1147
|
-
<div class="agent-toggle-info">
|
|
1148
|
-
<span class="agent-toggle-name">${sk.name}</span>
|
|
1149
|
-
<span class="agent-toggle-role" style="color:#34d399">${sk.description}</span>
|
|
1150
|
-
</div>
|
|
1151
|
-
${statusBadge(sk.status)}
|
|
1152
|
-
<div class="agent-toggle-check">\u2713</div>
|
|
1153
|
-
</div>
|
|
1154
|
-
</label>`
|
|
1155
|
-
).join('\n');
|
|
1156
|
-
|
|
1157
|
-
const auditSection = s.audit.filter(f => f.type !== 'OK').length > 0 ? `
|
|
1158
|
-
<div class="agent-audit-section">
|
|
1159
|
-
<h3 class="agent-section-subtitle">\u{1F50D} Audit Findings</h3>
|
|
1160
|
-
<div class="agent-audit-grid">
|
|
1161
|
-
${s.audit.filter(f => f.type !== 'OK').map(f => {
|
|
1162
|
-
const icon = f.type === 'MISSING' ? '\u274C' : f.type === 'IMPROVEMENT' ? '\u{1F4A1}' : '\u26A0\uFE0F';
|
|
1163
|
-
const cls = f.type === 'MISSING' ? 'audit-missing' : 'audit-improvement';
|
|
1164
|
-
return `<div class="agent-audit-item ${cls}">
|
|
1165
|
-
<span class="audit-icon">${icon}</span>
|
|
1166
|
-
<div class="audit-content">
|
|
1167
|
-
<span class="audit-desc">${f.description}</span>
|
|
1168
|
-
${f.suggestion ? `<span class="audit-suggestion">\u2192 ${f.suggestion}</span>` : ''}
|
|
1169
|
-
</div>
|
|
1170
|
-
</div>`;
|
|
1171
|
-
}).join('\n')}
|
|
1172
|
-
</div>
|
|
1173
|
-
</div>` : '';
|
|
1174
|
-
|
|
1175
|
-
const stackPills = [
|
|
1176
|
-
`\u{1F527} ${s.stack.primary}`,
|
|
1177
|
-
`\u{1F4E6} ${s.stack.frameworks.length > 0 ? s.stack.frameworks.join(', ') : 'No framework'}`,
|
|
1178
|
-
s.hasExistingAgents ? '\u{1F4C1} Existing .agent/' : '\u{1F4C1} New .agent/',
|
|
1179
|
-
...(s.stack.hasBackend ? ['\u{1F519} Backend'] : []),
|
|
1180
|
-
...(s.stack.hasFrontend ? ['\u{1F5A5}\uFE0F Frontend'] : []),
|
|
1181
|
-
...(s.stack.hasMobile ? ['\u{1F4F1} Mobile'] : []),
|
|
1182
|
-
...(s.stack.hasDatabase ? ['\u{1F5C4}\uFE0F Database'] : []),
|
|
1183
|
-
];
|
|
1184
|
-
|
|
1185
|
-
const totalItems = s.suggestedAgents.length + s.suggestedRules.length + s.suggestedGuards.length + s.suggestedWorkflows.length + s.suggestedSkills.length;
|
|
1186
|
-
|
|
1187
|
-
// Status summary counts
|
|
1188
|
-
const allItems = [...s.suggestedAgents, ...s.suggestedRules, ...s.suggestedGuards, ...s.suggestedWorkflows];
|
|
1189
|
-
const keepCount = allItems.filter(i => i.status === 'KEEP').length;
|
|
1190
|
-
const modifyCount = allItems.filter(i => i.status === 'MODIFY').length;
|
|
1191
|
-
const createCount = allItems.filter(i => i.status === 'CREATE').length;
|
|
1192
|
-
|
|
1193
|
-
return `
|
|
1194
|
-
<h2 class="section-title">\u{1F916} Agent System</h2>
|
|
1195
|
-
|
|
1196
|
-
<div class="card agent-system-card">
|
|
1197
|
-
<div class="agent-stack-banner">
|
|
1198
|
-
${stackPills.map(p => `<div class="stack-pill">${p}</div>`).join('\n ')}
|
|
1199
|
-
</div>
|
|
1200
|
-
|
|
1201
|
-
<div class="agent-status-legend">
|
|
1202
|
-
<span class="status-legend-item"><span class="legend-dot" style="background:#22c55e"></span> KEEP (${keepCount})</span>
|
|
1203
|
-
<span class="status-legend-item"><span class="legend-dot" style="background:#3b82f6"></span> MODIFY (${modifyCount})</span>
|
|
1204
|
-
<span class="status-legend-item"><span class="legend-dot" style="background:#f59e0b"></span> NEW (${createCount})</span>
|
|
1205
|
-
</div>
|
|
1206
|
-
|
|
1207
|
-
<div class="agent-controls">
|
|
1208
|
-
<button class="agent-ctrl-btn" onclick="toggleAll(true)">\u2705 Select All</button>
|
|
1209
|
-
<button class="agent-ctrl-btn" onclick="toggleAll(false)">\u2B1C Select None</button>
|
|
1210
|
-
<span class="agent-count-label"><span id="agentSelectedCount">${totalItems}</span> selected</span>
|
|
1211
|
-
</div>
|
|
1212
|
-
|
|
1213
|
-
<h3 class="agent-section-subtitle">\u{1F916} Agents</h3>
|
|
1214
|
-
<div class="agent-toggle-grid">
|
|
1215
|
-
${agentCards}
|
|
1216
|
-
</div>
|
|
1217
|
-
|
|
1218
|
-
<div class="agent-extras-grid">
|
|
1219
|
-
<div>
|
|
1220
|
-
<h3 class="agent-section-subtitle">\u{1F4CF} Rules</h3>
|
|
1221
|
-
<div class="agent-toggle-list">${ruleCards}</div>
|
|
1222
|
-
</div>
|
|
1223
|
-
<div>
|
|
1224
|
-
<h3 class="agent-section-subtitle">\u{1F6E1}\uFE0F Guards</h3>
|
|
1225
|
-
<div class="agent-toggle-list">${guardCards}</div>
|
|
1226
|
-
</div>
|
|
1227
|
-
<div>
|
|
1228
|
-
<h3 class="agent-section-subtitle">\u26A1 Workflows</h3>
|
|
1229
|
-
<div class="agent-toggle-list">${workflowCards}</div>
|
|
1230
|
-
</div>
|
|
1231
|
-
</div>
|
|
1232
|
-
|
|
1233
|
-
<h3 class="agent-section-subtitle">\u{1F9E0} Skills <span style="font-size:0.7rem;color:#94a3b8;font-weight:400">from skills.sh</span></h3>
|
|
1234
|
-
<div class="agent-toggle-grid">
|
|
1235
|
-
${skillCards}
|
|
1236
|
-
</div>
|
|
1237
|
-
|
|
1238
|
-
${auditSection}
|
|
1239
|
-
|
|
1240
|
-
<div class="agent-command-box">
|
|
1241
|
-
<div class="agent-command-header">
|
|
1242
|
-
<span>\u{1F4A1} Command to generate selected items:</span>
|
|
1243
|
-
<button class="agent-copy-btn" onclick="copyAgentCommand()">
|
|
1244
|
-
<span id="copyIcon">\u{1F4CB}</span> Copy
|
|
1245
|
-
</button>
|
|
1246
|
-
</div>
|
|
1247
|
-
<code id="agentCommandOutput" class="agent-command-code">${s.command}</code>
|
|
1248
|
-
</div>
|
|
1249
|
-
</div>
|
|
1250
|
-
|
|
1251
|
-
<style>
|
|
1252
|
-
.agent-system-card { padding: 1.5rem; }
|
|
1253
|
-
.agent-stack-banner { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
|
|
1254
|
-
.stack-pill { background: #1e293b; border: 1px solid #334155; border-radius: 99px; padding: 0.4rem 1rem; font-size: 0.8rem; color: #94a3b8; white-space: nowrap; }
|
|
1255
|
-
.agent-status-legend { display: flex; gap: 1.5rem; margin-bottom: 1rem; padding: 0.5rem 0; border-bottom: 1px solid #1e293b; }
|
|
1256
|
-
.status-legend-item { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; color: #94a3b8; }
|
|
1257
|
-
.agent-status-badge { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.15rem 0.5rem; border-radius: 99px; font-size: 0.65rem; font-weight: 700; flex-shrink: 0; letter-spacing: 0.03em; }
|
|
1258
|
-
.agent-toggle-desc { display: block; font-size: 0.65rem; color: #64748b; margin-top: 0.15rem; line-height: 1.3; }
|
|
1259
|
-
.agent-controls { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1.5rem; }
|
|
1260
|
-
.agent-ctrl-btn { background: #1e293b; border: 1px solid #334155; color: #e2e8f0; padding: 0.4rem 1rem; border-radius: 8px; font-size: 0.8rem; cursor: pointer; transition: all 0.2s; }
|
|
1261
|
-
.agent-ctrl-btn:hover { background: #334155; }
|
|
1262
|
-
.agent-count-label { color: #94a3b8; font-size: 0.85rem; margin-left: auto; }
|
|
1263
|
-
#agentSelectedCount { color: #c084fc; font-weight: 700; }
|
|
1264
|
-
.agent-section-subtitle { color: #e2e8f0; font-size: 1.05rem; font-weight: 700; margin: 1.25rem 0 0.75rem; }
|
|
1265
|
-
.agent-toggle-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 0.75rem; }
|
|
1266
|
-
.agent-toggle-card { cursor: pointer; transition: all 0.3s; }
|
|
1267
|
-
.agent-toggle-card input { display: none; }
|
|
1268
|
-
.agent-toggle-inner { display: flex; align-items: center; gap: 0.75rem; background: #1e293b; border: 2px solid #334155; border-radius: 12px; padding: 0.75rem 1rem; transition: all 0.3s; }
|
|
1269
|
-
.agent-toggle-card input:checked + .agent-toggle-inner { background: #1e1b4b; }
|
|
1270
|
-
.agent-toggle-icon { font-size: 1.3rem; flex-shrink: 0; }
|
|
1271
|
-
.agent-toggle-info { flex: 1; min-width: 0; }
|
|
1272
|
-
.agent-toggle-name { display: block; color: #e2e8f0; font-weight: 600; font-size: 0.85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
1273
|
-
.agent-toggle-role { display: block; font-size: 0.7rem; margin-top: 0.15rem; }
|
|
1274
|
-
.agent-toggle-check { color: #334155; font-size: 1rem; flex-shrink: 0; transition: color 0.3s; }
|
|
1275
|
-
.agent-toggle-card input:checked + .agent-toggle-inner .agent-toggle-check { color: #818cf8; }
|
|
1276
|
-
.agent-toggle-card.mini .agent-toggle-inner { padding: 0.5rem 0.75rem; border-radius: 8px; }
|
|
1277
|
-
.agent-extras-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-top: 0.5rem; }
|
|
1278
|
-
@media (max-width: 768px) { .agent-extras-grid { grid-template-columns: 1fr; } }
|
|
1279
|
-
.agent-toggle-list { display: flex; flex-direction: column; gap: 0.5rem; }
|
|
1280
|
-
.agent-audit-section { margin-top: 1.5rem; }
|
|
1281
|
-
.agent-audit-grid { display: flex; flex-direction: column; gap: 0.5rem; }
|
|
1282
|
-
.agent-audit-item { display: flex; gap: 0.75rem; align-items: flex-start; background: #1e293b; padding: 0.75rem 1rem; border-radius: 8px; }
|
|
1283
|
-
.agent-audit-item.audit-missing { border-left: 3px solid #ef4444; }
|
|
1284
|
-
.agent-audit-item.audit-improvement { border-left: 3px solid #fbbf24; }
|
|
1285
|
-
.audit-icon { font-size: 1rem; flex-shrink: 0; margin-top: 2px; }
|
|
1286
|
-
.audit-content { display: flex; flex-direction: column; gap: 0.25rem; }
|
|
1287
|
-
.audit-desc { color: #e2e8f0; font-size: 0.85rem; }
|
|
1288
|
-
.audit-suggestion { color: #94a3b8; font-size: 0.8rem; font-style: italic; }
|
|
1289
|
-
.agent-command-box { margin-top: 1.5rem; background: #0f172a; border-radius: 12px; border: 1px solid #334155; overflow: hidden; }
|
|
1290
|
-
.agent-command-header { display: flex; justify-content: space-between; align-items: center; padding: 0.75rem 1rem; background: #1e293b; font-size: 0.8rem; color: #94a3b8; }
|
|
1291
|
-
.agent-copy-btn { background: #c084fc; color: #0f172a; border: none; border-radius: 6px; padding: 0.4rem 0.8rem; cursor: pointer; font-size: 0.75rem; font-weight: 600; transition: all 0.2s; }
|
|
1292
|
-
.agent-copy-btn:hover { background: #a855f7; transform: scale(1.05); }
|
|
1293
|
-
.agent-command-code { display: block; padding: 1rem; color: #c084fc; font-size: 0.85rem; word-break: break-all; font-family: 'Fira Code', monospace; }
|
|
1294
|
-
</style>
|
|
1295
|
-
|
|
1296
|
-
<script>
|
|
1297
|
-
(function() {
|
|
1298
|
-
var basePath = ${JSON.stringify(s.command.replace('architect agents ', ''))};
|
|
1299
|
-
var totalItems = ${totalItems};
|
|
1300
|
-
function updateCommand() {
|
|
1301
|
-
var checks = document.querySelectorAll('.agent-check');
|
|
1302
|
-
var selected = { agents: [], rules: [], guards: [], workflows: [], skills: [] };
|
|
1303
|
-
var count = 0;
|
|
1304
|
-
checks.forEach(function(cb) { if (cb.checked) { selected[cb.dataset.type].push(cb.dataset.item); count++; } });
|
|
1305
|
-
document.getElementById('agentSelectedCount').textContent = count;
|
|
1306
|
-
var cmd;
|
|
1307
|
-
if (count === totalItems) { cmd = 'architect agents ' + basePath; }
|
|
1308
|
-
else if (count === 0) { cmd = '# No items selected'; }
|
|
1309
|
-
else {
|
|
1310
|
-
var parts = ['architect agents ' + basePath];
|
|
1311
|
-
if (selected.agents.length > 0) parts.push('--agents ' + selected.agents.join(','));
|
|
1312
|
-
if (selected.rules.length > 0) parts.push('--rules ' + selected.rules.join(','));
|
|
1313
|
-
if (selected.guards.length > 0) parts.push('--guards ' + selected.guards.join(','));
|
|
1314
|
-
if (selected.workflows.length > 0) parts.push('--workflows ' + selected.workflows.join(','));
|
|
1315
|
-
if (selected.skills.length > 0) parts.push('&& ' + selected.skills.map(function(sk){ return 'npx skills add ' + sk; }).join(' && '));
|
|
1316
|
-
cmd = parts.join(' ');
|
|
1317
|
-
}
|
|
1318
|
-
document.getElementById('agentCommandOutput').textContent = cmd;
|
|
1319
|
-
}
|
|
1320
|
-
document.querySelectorAll('.agent-check').forEach(function(cb) { cb.addEventListener('change', updateCommand); });
|
|
1321
|
-
window.toggleAll = function(state) { document.querySelectorAll('.agent-check').forEach(function(cb) { cb.checked = state; }); updateCommand(); };
|
|
1322
|
-
window.copyAgentCommand = function() { var cmd = document.getElementById('agentCommandOutput').textContent; navigator.clipboard.writeText(cmd).then(function() { var btn = document.getElementById('copyIcon'); btn.textContent = '\u2705'; setTimeout(function() { btn.textContent = '\ud83d\udccb'; }, 2000); }); };
|
|
1323
|
-
})();
|
|
1324
|
-
<\/script>`;
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1327
|
-
private getStyles(): string {
|
|
1328
|
-
return `<style>
|
|
1329
|
-
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');
|
|
1330
|
-
|
|
1331
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
1332
|
-
|
|
1333
|
-
body {
|
|
1334
|
-
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
1335
|
-
background: #0f172a;
|
|
1336
|
-
color: #e2e8f0;
|
|
1337
|
-
line-height: 1.6;
|
|
1338
|
-
min-height: 100vh;
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
html { scroll-behavior: smooth; }
|
|
1342
|
-
|
|
1343
|
-
/* ── Layout ── */
|
|
1344
|
-
.report-layout { display: flex; min-height: 100vh; }
|
|
1345
|
-
|
|
1346
|
-
.sidebar {
|
|
1347
|
-
position: sticky; top: 0; height: 100vh; width: 220px; min-width: 220px;
|
|
1348
|
-
background: linear-gradient(180deg, #0f172a 0%, #1e293b 100%);
|
|
1349
|
-
border-right: 1px solid #334155; padding: 1.5rem 0;
|
|
1350
|
-
display: flex; flex-direction: column; gap: 0.25rem;
|
|
1351
|
-
overflow-y: auto; z-index: 100;
|
|
1352
|
-
}
|
|
1353
|
-
.sidebar-title {
|
|
1354
|
-
font-size: 0.7rem; font-weight: 700; text-transform: uppercase;
|
|
1355
|
-
letter-spacing: 0.15em; color: #475569; padding: 0 1.25rem; margin-bottom: 0.75rem;
|
|
1356
|
-
}
|
|
1357
|
-
.sidebar-link {
|
|
1358
|
-
display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 1.25rem;
|
|
1359
|
-
color: #94a3b8; text-decoration: none; font-size: 0.8rem; font-weight: 500;
|
|
1360
|
-
border-left: 3px solid transparent; transition: all 0.2s;
|
|
1361
|
-
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
1362
|
-
}
|
|
1363
|
-
.sidebar-link:hover { color: #e2e8f0; background: #1e293b; border-left-color: #475569; }
|
|
1364
|
-
.sidebar-link.active { color: #c084fc; background: #c084fc10; border-left-color: #c084fc; font-weight: 700; }
|
|
1365
|
-
|
|
1366
|
-
.sidebar-toggle {
|
|
1367
|
-
display: none; position: fixed; bottom: 1.5rem; right: 1.5rem; z-index: 200;
|
|
1368
|
-
width: 48px; height: 48px; border-radius: 50%; border: none;
|
|
1369
|
-
background: #c084fc; color: #0f172a; font-size: 1.2rem; cursor: pointer;
|
|
1370
|
-
box-shadow: 0 4px 16px rgba(192,132,252,0.4); transition: all 0.2s;
|
|
1371
|
-
}
|
|
1372
|
-
.sidebar-toggle:hover { transform: scale(1.1); }
|
|
1373
|
-
|
|
1374
|
-
@media (max-width: 1024px) {
|
|
1375
|
-
.sidebar {
|
|
1376
|
-
position: fixed; left: -240px; top: 0; width: 240px; min-width: 240px;
|
|
1377
|
-
transition: left 0.3s ease; box-shadow: none;
|
|
1378
|
-
}
|
|
1379
|
-
.sidebar.sidebar-open { left: 0; box-shadow: 4px 0 24px rgba(0,0,0,0.5); }
|
|
1380
|
-
.sidebar-toggle { display: flex; align-items: center; justify-content: center; }
|
|
1381
|
-
.report-layout { flex-direction: column; }
|
|
1382
|
-
}
|
|
1383
|
-
|
|
1384
|
-
.container { max-width: 1200px; margin: 0 auto; padding: 2rem; flex: 1; min-width: 0; }
|
|
1385
|
-
|
|
1386
|
-
/* ── Header ── */
|
|
1387
|
-
.header {
|
|
1388
|
-
text-align: center;
|
|
1389
|
-
padding: 3rem 2rem;
|
|
1390
|
-
background: linear-gradient(135deg, #1e293b 0%, #0f172a 50%, #1e1b4b 100%);
|
|
1391
|
-
border-bottom: 1px solid #334155;
|
|
1392
|
-
margin-bottom: 2rem;
|
|
1393
|
-
}
|
|
1394
|
-
.header h1 {
|
|
1395
|
-
font-size: 2.5rem;
|
|
1396
|
-
font-weight: 900;
|
|
1397
|
-
background: linear-gradient(135deg, #818cf8, #c084fc, #f472b6);
|
|
1398
|
-
-webkit-background-clip: text;
|
|
1399
|
-
-webkit-text-fill-color: transparent;
|
|
1400
|
-
margin-bottom: 0.5rem;
|
|
1401
|
-
}
|
|
1402
|
-
.header .subtitle { color: #94a3b8; font-size: 1.1rem; font-weight: 300; }
|
|
1403
|
-
.header .meta {
|
|
1404
|
-
margin-top: 1rem;
|
|
1405
|
-
display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap;
|
|
1406
|
-
}
|
|
1407
|
-
.header .meta span {
|
|
1408
|
-
background: #1e293b; padding: 0.4rem 1rem; border-radius: 99px;
|
|
1409
|
-
font-size: 0.85rem; color: #94a3b8; border: 1px solid #334155;
|
|
1410
|
-
}
|
|
1411
|
-
.header .meta span strong { color: #e2e8f0; }
|
|
1412
|
-
|
|
1413
|
-
/* ── Score Hero ── */
|
|
1414
|
-
.score-hero {
|
|
1415
|
-
display: flex; align-items: center; justify-content: center; gap: 3rem;
|
|
1416
|
-
padding: 2.5rem;
|
|
1417
|
-
background: linear-gradient(135deg, #1e293b, #1e1b4b);
|
|
1418
|
-
border-radius: 24px; border: 1px solid #334155;
|
|
1419
|
-
margin-bottom: 2rem; flex-wrap: wrap;
|
|
1420
|
-
}
|
|
1421
|
-
.score-circle { position: relative; width: 180px; height: 180px; }
|
|
1422
|
-
.score-circle svg { transform: rotate(-90deg); }
|
|
1423
|
-
.score-circle circle { fill: none; stroke-width: 10; stroke-linecap: round; }
|
|
1424
|
-
.score-circle .bg { stroke: #334155; }
|
|
1425
|
-
.score-circle .fg { transition: stroke-dashoffset 1.5s cubic-bezier(0.4, 0, 0.2, 1); }
|
|
1426
|
-
.score-value {
|
|
1427
|
-
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
|
|
1428
|
-
text-align: center;
|
|
1429
|
-
}
|
|
1430
|
-
.score-value .number { font-size: 3rem; font-weight: 900; line-height: 1; }
|
|
1431
|
-
.score-value .label { font-size: 0.85rem; color: #94a3b8; text-transform: uppercase; letter-spacing: 2px; }
|
|
1432
|
-
.score-value .grade { font-size: 0.75rem; color: #64748b; margin-top: 4px; text-transform: uppercase; letter-spacing: 1px; }
|
|
1433
|
-
|
|
1434
|
-
.score-breakdown { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
|
|
1435
|
-
.score-item {
|
|
1436
|
-
padding: 1rem 1.5rem; background: rgba(255,255,255,0.03);
|
|
1437
|
-
border-radius: 12px; border: 1px solid #334155; min-width: 200px;
|
|
1438
|
-
}
|
|
1439
|
-
.score-item .name { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 1px; color: #94a3b8; margin-bottom: 0.3rem; }
|
|
1440
|
-
.score-item .bar-container { background: #1e293b; border-radius: 99px; height: 8px; margin-top: 0.5rem; overflow: hidden; }
|
|
1441
|
-
.score-item .bar { height: 100%; border-radius: 99px; transition: width 1.5s cubic-bezier(0.4, 0, 0.2, 1); }
|
|
1442
|
-
.score-item .val { font-size: 1.5rem; font-weight: 700; }
|
|
1443
|
-
|
|
1444
|
-
/* ── Stats Grid ── */
|
|
1445
|
-
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; margin-bottom: 2rem; }
|
|
1446
|
-
.stat-card {
|
|
1447
|
-
background: linear-gradient(135deg, #1e293b, #0f172a);
|
|
1448
|
-
border: 1px solid #334155; border-radius: 16px; padding: 1.5rem; text-align: center;
|
|
1449
|
-
}
|
|
1450
|
-
.stat-card .value {
|
|
1451
|
-
font-size: 2rem; font-weight: 800;
|
|
1452
|
-
background: linear-gradient(135deg, #818cf8, #c084fc);
|
|
1453
|
-
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
|
|
1454
|
-
}
|
|
1455
|
-
.stat-card .label { font-size: 0.85rem; color: #94a3b8; margin-top: 0.3rem; }
|
|
1456
|
-
|
|
1457
|
-
/* ── Section Title ── */
|
|
1458
|
-
.section-title {
|
|
1459
|
-
font-size: 1.4rem; font-weight: 700; margin: 2.5rem 0 1rem;
|
|
1460
|
-
display: flex; align-items: center; gap: 0.5rem;
|
|
1461
|
-
}
|
|
1462
|
-
|
|
1463
|
-
/* ── Section Accordion ── */
|
|
1464
|
-
.section-accordion {
|
|
1465
|
-
margin: 1.5rem 0; border: 1px solid #334155; border-radius: 16px;
|
|
1466
|
-
background: transparent; overflow: hidden;
|
|
1467
|
-
}
|
|
1468
|
-
.section-accordion-header {
|
|
1469
|
-
cursor: pointer; list-style: none; display: flex; align-items: center; gap: 0.75rem;
|
|
1470
|
-
font-size: 1.3rem; font-weight: 700; color: #e2e8f0;
|
|
1471
|
-
padding: 1.25rem 1.5rem; background: linear-gradient(135deg, #1e293b, #0f172a);
|
|
1472
|
-
border-bottom: 1px solid transparent; transition: all 0.3s; user-select: none;
|
|
1473
|
-
}
|
|
1474
|
-
.section-accordion-header:hover { background: linear-gradient(135deg, #334155, #1e293b); }
|
|
1475
|
-
.section-accordion[open] > .section-accordion-header { border-bottom-color: #334155; }
|
|
1476
|
-
.section-accordion-header::after {
|
|
1477
|
-
content: '\\25B6'; margin-left: auto; font-size: 0.8rem; color: #818cf8;
|
|
1478
|
-
transition: transform 0.3s;
|
|
1479
|
-
}
|
|
1480
|
-
.section-accordion[open] > .section-accordion-header::after { transform: rotate(90deg); }
|
|
1481
|
-
.section-accordion-header::-webkit-details-marker { display: none; }
|
|
1482
|
-
.section-accordion-body { padding: 0.5rem 0; }
|
|
1483
|
-
|
|
1484
|
-
/* ── Project Overview ── */
|
|
1485
|
-
.overview-grid {
|
|
1486
|
-
display: grid;
|
|
1487
|
-
grid-template-columns: 1fr 1fr;
|
|
1488
|
-
gap: 1rem;
|
|
1489
|
-
margin-bottom: 1.5rem;
|
|
1490
|
-
}
|
|
1491
|
-
.overview-card {
|
|
1492
|
-
background: rgba(255,255,255,0.03);
|
|
1493
|
-
border: 1px solid #334155;
|
|
1494
|
-
border-radius: 12px;
|
|
1495
|
-
padding: 1.25rem;
|
|
1496
|
-
}
|
|
1497
|
-
.overview-main {
|
|
1498
|
-
grid-column: 1 / -1;
|
|
1499
|
-
background: linear-gradient(135deg, rgba(59,130,246,0.08), rgba(139,92,246,0.08));
|
|
1500
|
-
border-color: #3b82f6;
|
|
1501
|
-
}
|
|
1502
|
-
.overview-label {
|
|
1503
|
-
font-size: 0.75rem;
|
|
1504
|
-
font-weight: 600;
|
|
1505
|
-
text-transform: uppercase;
|
|
1506
|
-
letter-spacing: 0.05em;
|
|
1507
|
-
color: #94a3b8;
|
|
1508
|
-
margin-bottom: 0.75rem;
|
|
1509
|
-
}
|
|
1510
|
-
.overview-description {
|
|
1511
|
-
font-size: 1.1rem;
|
|
1512
|
-
color: #e2e8f0;
|
|
1513
|
-
line-height: 1.6;
|
|
1514
|
-
margin-bottom: 0.75rem;
|
|
1515
|
-
}
|
|
1516
|
-
.overview-purpose-row {
|
|
1517
|
-
display: flex;
|
|
1518
|
-
align-items: center;
|
|
1519
|
-
gap: 0.5rem;
|
|
1520
|
-
}
|
|
1521
|
-
.overview-purpose-label {
|
|
1522
|
-
font-size: 0.8rem;
|
|
1523
|
-
color: #64748b;
|
|
1524
|
-
}
|
|
1525
|
-
.overview-purpose-value {
|
|
1526
|
-
font-size: 0.85rem;
|
|
1527
|
-
color: #a78bfa;
|
|
1528
|
-
font-weight: 600;
|
|
1529
|
-
background: rgba(139,92,246,0.1);
|
|
1530
|
-
padding: 0.2rem 0.6rem;
|
|
1531
|
-
border-radius: 6px;
|
|
1532
|
-
}
|
|
1533
|
-
.overview-tags {
|
|
1534
|
-
display: flex;
|
|
1535
|
-
flex-wrap: wrap;
|
|
1536
|
-
gap: 0.4rem;
|
|
1537
|
-
}
|
|
1538
|
-
.overview-tag {
|
|
1539
|
-
font-size: 0.75rem;
|
|
1540
|
-
padding: 0.25rem 0.6rem;
|
|
1541
|
-
border-radius: 6px;
|
|
1542
|
-
font-weight: 500;
|
|
1543
|
-
}
|
|
1544
|
-
.tech-tag {
|
|
1545
|
-
background: rgba(59,130,246,0.15);
|
|
1546
|
-
color: #60a5fa;
|
|
1547
|
-
border: 1px solid rgba(59,130,246,0.3);
|
|
1548
|
-
}
|
|
1549
|
-
.keyword-tag {
|
|
1550
|
-
background: rgba(16,185,129,0.1);
|
|
1551
|
-
color: #34d399;
|
|
1552
|
-
border: 1px solid rgba(16,185,129,0.2);
|
|
1553
|
-
}
|
|
1554
|
-
.overview-entry {
|
|
1555
|
-
font-size: 0.8rem;
|
|
1556
|
-
background: rgba(255,255,255,0.05);
|
|
1557
|
-
padding: 0.25rem 0.5rem;
|
|
1558
|
-
border-radius: 4px;
|
|
1559
|
-
color: #e2e8f0;
|
|
1560
|
-
font-family: 'SF Mono', monospace;
|
|
1561
|
-
}
|
|
1562
|
-
.overview-entries {
|
|
1563
|
-
display: flex;
|
|
1564
|
-
flex-wrap: wrap;
|
|
1565
|
-
gap: 0.4rem;
|
|
1566
|
-
}
|
|
1567
|
-
.overview-modules-section {
|
|
1568
|
-
margin-top: 0.5rem;
|
|
1569
|
-
}
|
|
1570
|
-
.overview-modules-grid {
|
|
1571
|
-
display: grid;
|
|
1572
|
-
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
1573
|
-
gap: 0.75rem;
|
|
1574
|
-
margin-top: 0.5rem;
|
|
1575
|
-
}
|
|
1576
|
-
.overview-module {
|
|
1577
|
-
background: rgba(255,255,255,0.03);
|
|
1578
|
-
border: 1px solid #1e293b;
|
|
1579
|
-
border-radius: 8px;
|
|
1580
|
-
padding: 0.75rem 1rem;
|
|
1581
|
-
transition: border-color 0.2s;
|
|
1582
|
-
}
|
|
1583
|
-
.overview-module:hover {
|
|
1584
|
-
border-color: #3b82f6;
|
|
1585
|
-
}
|
|
1586
|
-
.overview-module-name {
|
|
1587
|
-
font-weight: 600;
|
|
1588
|
-
color: #e2e8f0;
|
|
1589
|
-
font-size: 0.9rem;
|
|
1590
|
-
margin-bottom: 0.25rem;
|
|
1591
|
-
}
|
|
1592
|
-
.overview-module-desc {
|
|
1593
|
-
color: #94a3b8;
|
|
1594
|
-
font-size: 0.75rem;
|
|
1595
|
-
margin-bottom: 0.25rem;
|
|
1596
|
-
}
|
|
1597
|
-
.overview-module-files {
|
|
1598
|
-
color: #64748b;
|
|
1599
|
-
font-size: 0.7rem;
|
|
1600
|
-
}
|
|
1601
|
-
.overview-empty {
|
|
1602
|
-
color: #475569;
|
|
1603
|
-
font-size: 0.85rem;
|
|
1604
|
-
font-style: italic;
|
|
1605
|
-
}
|
|
1606
|
-
@media (max-width: 768px) {
|
|
1607
|
-
.overview-grid { grid-template-columns: 1fr; }
|
|
1608
|
-
}
|
|
1609
|
-
|
|
1610
|
-
/* ── Operations Accordion (inside refactoring steps) ── */
|
|
1611
|
-
.rstep-ops-accordion {
|
|
1612
|
-
margin: 0.75rem 0; border: 1px solid #1e293b; border-radius: 10px; overflow: hidden;
|
|
1613
|
-
}
|
|
1614
|
-
.rstep-ops-toggle {
|
|
1615
|
-
cursor: pointer; list-style: none; display: flex; align-items: center; gap: 0.5rem;
|
|
1616
|
-
font-size: 0.9rem; font-weight: 600; color: #94a3b8;
|
|
1617
|
-
padding: 0.75rem 1rem; background: #0f172a; transition: all 0.2s;
|
|
1618
|
-
}
|
|
1619
|
-
.rstep-ops-toggle:hover { background: #1e293b; color: #e2e8f0; }
|
|
1620
|
-
.rstep-ops-toggle::after {
|
|
1621
|
-
content: '\\25B6'; margin-left: auto; font-size: 0.65rem; color: #818cf8;
|
|
1622
|
-
transition: transform 0.3s;
|
|
1623
|
-
}
|
|
1624
|
-
.rstep-ops-accordion[open] > .rstep-ops-toggle::after { transform: rotate(90deg); }
|
|
1625
|
-
.rstep-ops-toggle::-webkit-details-marker { display: none; }
|
|
1626
|
-
|
|
1627
|
-
/* ── Cards ── */
|
|
1628
|
-
.card {
|
|
1629
|
-
background: #1e293b; border-radius: 16px; border: 1px solid #334155;
|
|
1630
|
-
padding: 1.5rem; margin-bottom: 1rem; overflow-x: auto;
|
|
1631
|
-
}
|
|
1632
|
-
.success-card { border-color: #22c55e40; color: #22c55e; text-align: center; padding: 2rem; font-size: 1.1rem; }
|
|
1633
|
-
|
|
1634
|
-
/* ── Graph ── */
|
|
1635
|
-
.graph-card { padding: 1rem; }
|
|
1636
|
-
.graph-controls { margin-bottom: 0.75rem; }
|
|
1637
|
-
.graph-legend {
|
|
1638
|
-
display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.5rem;
|
|
1639
|
-
justify-content: center;
|
|
1640
|
-
}
|
|
1641
|
-
.legend-item { display: flex; align-items: center; gap: 4px; font-size: 0.75rem; color: #94a3b8; }
|
|
1642
|
-
.legend-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
|
|
1643
|
-
.graph-filters {
|
|
1644
|
-
display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap;
|
|
1645
|
-
justify-content: center; margin-top: 0.5rem;
|
|
1646
|
-
}
|
|
1647
|
-
.graph-search {
|
|
1648
|
-
background: #0f172a; border: 1px solid #334155; border-radius: 8px;
|
|
1649
|
-
padding: 0.4rem 0.75rem; color: #e2e8f0; font-size: 0.8rem;
|
|
1650
|
-
outline: none; width: 180px; transition: border-color 0.2s;
|
|
1651
|
-
}
|
|
1652
|
-
.graph-search:focus { border-color: #818cf8; }
|
|
1653
|
-
.graph-layer-filters {
|
|
1654
|
-
display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center;
|
|
1655
|
-
}
|
|
1656
|
-
.graph-filter-check {
|
|
1657
|
-
display: flex; align-items: center; gap: 4px;
|
|
1658
|
-
font-size: 0.75rem; color: #94a3b8; cursor: pointer;
|
|
1659
|
-
}
|
|
1660
|
-
.graph-filter-check input { width: 14px; height: 14px; accent-color: #818cf8; }
|
|
1661
|
-
.graph-limit-notice {
|
|
1662
|
-
text-align: center; font-size: 0.75rem; color: #f59e0b;
|
|
1663
|
-
background: #f59e0b15; padding: 0.3rem 0.75rem; border-radius: 6px;
|
|
1664
|
-
margin-top: 0.5rem;
|
|
1665
|
-
}
|
|
1666
|
-
.graph-hint {
|
|
1667
|
-
text-align: center; font-size: 0.75rem; color: #475569; margin-top: 0.5rem;
|
|
1668
|
-
font-style: italic;
|
|
1669
|
-
}
|
|
1670
|
-
#dep-graph svg { background: rgba(0,0,0,0.2); border-radius: 12px; cursor: grab; }
|
|
1671
|
-
#dep-graph svg:active { cursor: grabbing; }
|
|
1672
|
-
|
|
1673
|
-
/* ── Layers Grid ── */
|
|
1674
|
-
.layers-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; }
|
|
1675
|
-
.layer-card {
|
|
1676
|
-
background: linear-gradient(135deg, #1e293b, #0f172a);
|
|
1677
|
-
border: 1px solid #334155; border-radius: 16px; padding: 1.5rem;
|
|
1678
|
-
text-align: center; position: relative; overflow: hidden;
|
|
1679
|
-
}
|
|
1680
|
-
.layer-card::before {
|
|
1681
|
-
content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
|
|
1682
|
-
background: var(--layer-color, #64748b);
|
|
1683
|
-
}
|
|
1684
|
-
.layer-card .count { font-size: 2.5rem; font-weight: 900; line-height: 1; }
|
|
1685
|
-
.layer-card .name { font-size: 1rem; color: #94a3b8; margin-top: 0.3rem; font-weight: 600; }
|
|
1686
|
-
.layer-card .desc { font-size: 0.75rem; color: #475569; margin-top: 0.5rem; }
|
|
1687
|
-
|
|
1688
|
-
/* ── Tables ── */
|
|
1689
|
-
table { width: 100%; border-collapse: collapse; }
|
|
1690
|
-
th, td { text-align: left; padding: 0.75rem 1rem; border-bottom: 1px solid #334155; }
|
|
1691
|
-
th { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 1px; color: #64748b; font-weight: 600; }
|
|
1692
|
-
.count-cell { font-weight: 700; font-size: 1.1rem; }
|
|
1693
|
-
.impact { color: #94a3b8; font-size: 0.85rem; }
|
|
1694
|
-
.suggestion { color: #64748b; font-size: 0.8rem; }
|
|
1695
|
-
|
|
1696
|
-
.severity-badge {
|
|
1697
|
-
display: inline-block; padding: 0.2rem 0.6rem; border-radius: 99px;
|
|
1698
|
-
font-size: 0.72rem; font-weight: 600; letter-spacing: 0.5px;
|
|
1699
|
-
}
|
|
1700
|
-
.severity-CRITICAL { background: #dc262620; color: #ef4444; border: 1px solid #ef444440; }
|
|
1701
|
-
.severity-HIGH { background: #f59e0b20; color: #f59e0b; border: 1px solid #f59e0b40; }
|
|
1702
|
-
.severity-MEDIUM { background: #3b82f620; color: #60a5fa; border: 1px solid #60a5fa40; }
|
|
1703
|
-
.severity-LOW { background: #22c55e20; color: #22c55e; border: 1px solid #22c55e40; }
|
|
1704
|
-
|
|
1705
|
-
.count-badge {
|
|
1706
|
-
display: inline-block; background: #818cf820; color: #818cf8; padding: 0.1rem 0.4rem;
|
|
1707
|
-
border-radius: 99px; font-size: 0.7rem; margin-left: 0.5rem; font-weight: 600;
|
|
1708
|
-
}
|
|
1709
|
-
|
|
1710
|
-
.locations { font-size: 0.75rem; color: #64748b; }
|
|
1711
|
-
.locations code { background: #0f172a; padding: 1px 4px; border-radius: 3px; font-size: 0.7rem; }
|
|
1712
|
-
|
|
1713
|
-
/* ── Footer ── */
|
|
1714
|
-
.footer {
|
|
1715
|
-
text-align: center; padding: 2rem; color: #475569; font-size: 0.85rem;
|
|
1716
|
-
border-top: 1px solid #1e293b; margin-top: 3rem;
|
|
1717
|
-
}
|
|
1718
|
-
.footer a { color: #818cf8; text-decoration: none; }
|
|
1719
|
-
.footer a:hover { text-decoration: underline; }
|
|
1720
|
-
|
|
1721
|
-
/* ── Refactoring Plan ── */
|
|
1722
|
-
.refactor-score { padding: 2rem; }
|
|
1723
|
-
.refactor-score-pair {
|
|
1724
|
-
display: flex; align-items: center; justify-content: center; gap: 1.5rem;
|
|
1725
|
-
margin-bottom: 2rem; flex-wrap: wrap;
|
|
1726
|
-
}
|
|
1727
|
-
.rscore-box { text-align: center; }
|
|
1728
|
-
.rscore-num { font-size: 3rem; font-weight: 900; line-height: 1; }
|
|
1729
|
-
.rscore-label { font-size: 0.8rem; color: #94a3b8; text-transform: uppercase; letter-spacing: 1px; }
|
|
1730
|
-
.rscore-improvement { font-size: 1.3rem; font-weight: 700; }
|
|
1731
|
-
|
|
1732
|
-
.refactor-legend { display: flex; gap: 1rem; margin-bottom: 0.5rem; }
|
|
1733
|
-
.rlegend-tag { font-size: 0.75rem; padding: 0.2rem 0.6rem; border-radius: 6px; }
|
|
1734
|
-
.rlegend-tag.rbefore { background: rgba(255,255,255,0.05); color: #94a3b8; }
|
|
1735
|
-
.rlegend-tag.rafter { background: rgba(129,140,248,0.2); color: #818cf8; }
|
|
1736
|
-
|
|
1737
|
-
.refactor-metric-name { width: 100px; font-size: 0.8rem; text-transform: uppercase; color: #94a3b8; font-weight: 600; }
|
|
1738
|
-
.refactor-metric-bars { flex: 1; position: relative; height: 30px; }
|
|
1739
|
-
.rbar-before, .rbar-after {
|
|
1740
|
-
position: absolute; left: 0; height: 14px; border-radius: 4px;
|
|
1741
|
-
display: flex; align-items: center; padding-left: 6px;
|
|
1742
|
-
font-size: 0.7rem; font-weight: 600;
|
|
1743
|
-
}
|
|
1744
|
-
.rbar-before { top: 0; }
|
|
1745
|
-
.rbar-after { top: 15px; }
|
|
1746
|
-
.refactor-metric-diff { width: 50px; text-align: right; font-weight: 700; font-size: 0.85rem; }
|
|
1747
|
-
|
|
1748
|
-
.refactor-stats-row {
|
|
1749
|
-
display: flex; gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap;
|
|
1750
|
-
}
|
|
1751
|
-
.rstat {
|
|
1752
|
-
background: #1e293b; border: 1px solid #334155; border-radius: 99px;
|
|
1753
|
-
padding: 0.4rem 1rem; font-size: 0.85rem; color: #94a3b8; font-weight: 500;
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
.priority-bar {
|
|
1757
|
-
display: flex; border-radius: 12px; overflow: hidden; height: 32px; margin-bottom: 2rem;
|
|
1758
|
-
}
|
|
1759
|
-
.prio-seg {
|
|
1760
|
-
display: flex; align-items: center; justify-content: center;
|
|
1761
|
-
font-size: 0.75rem; font-weight: 600;
|
|
1762
|
-
}
|
|
1763
|
-
.prio-critical { background: #ef444430; color: #ef4444; }
|
|
1764
|
-
.prio-high { background: #f59e0b30; color: #f59e0b; }
|
|
1765
|
-
.prio-medium { background: #3b82f630; color: #60a5fa; }
|
|
1766
|
-
.prio-low { background: #22c55e30; color: #22c55e; }
|
|
1767
|
-
|
|
1768
|
-
.refactor-roadmap { display: flex; flex-direction: column; gap: 1rem; }
|
|
1769
|
-
.rstep-card {
|
|
1770
|
-
background: #1e293b; border-radius: 16px; border: 1px solid #334155;
|
|
1771
|
-
padding: 1.5rem; transition: border-color 0.2s;
|
|
1772
|
-
}
|
|
1773
|
-
.rstep-card:hover { border-color: #818cf8; }
|
|
1774
|
-
.rstep-header { display: flex; gap: 1rem; margin-bottom: 1rem; }
|
|
1775
|
-
.rstep-number {
|
|
1776
|
-
width: 40px; height: 40px; border-radius: 50%;
|
|
1777
|
-
background: linear-gradient(135deg, #818cf8, #c084fc);
|
|
1778
|
-
display: flex; align-items: center; justify-content: center;
|
|
1779
|
-
font-weight: 800; font-size: 1rem; color: white; flex-shrink: 0;
|
|
1780
|
-
}
|
|
1781
|
-
.rstep-info { flex: 1; }
|
|
1782
|
-
.rstep-title-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
|
|
1783
|
-
.rstep-title-row h3 { font-size: 1.1rem; font-weight: 700; }
|
|
1784
|
-
.rstep-desc { color: #94a3b8; font-size: 0.9rem; margin-top: 0.3rem; }
|
|
1785
|
-
.tier-badge {
|
|
1786
|
-
background: #818cf815; color: #818cf8; border: 1px solid #818cf830;
|
|
1787
|
-
padding: 0.15rem 0.5rem; border-radius: 99px; font-size: 0.65rem; font-weight: 600;
|
|
1788
|
-
}
|
|
1789
|
-
.rstep-details { margin-top: 0.5rem; }
|
|
1790
|
-
.rstep-details summary { cursor: pointer; color: #818cf8; font-size: 0.85rem; font-weight: 500; }
|
|
1791
|
-
.rstep-rationale { color: #64748b; font-size: 0.85rem; margin-top: 0.3rem; font-style: italic; }
|
|
1792
|
-
|
|
1793
|
-
.rstep-ops { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid #334155; }
|
|
1794
|
-
.rstep-ops h4 { font-size: 0.85rem; color: #94a3b8; margin-bottom: 0.5rem; }
|
|
1795
|
-
.rop { display: flex; align-items: flex-start; gap: 0.5rem; margin-bottom: 0.5rem; flex-wrap: wrap; }
|
|
1796
|
-
.rop-icon { font-size: 0.9rem; }
|
|
1797
|
-
.rop-badge { padding: 0.1rem 0.4rem; border-radius: 6px; font-size: 0.65rem; font-weight: 700; }
|
|
1798
|
-
.rop-path { background: #0f172a; padding: 1px 6px; border-radius: 4px; font-size: 0.8rem; color: #c084fc; }
|
|
1799
|
-
.rop-arrow { color: #818cf8; font-weight: 700; }
|
|
1800
|
-
.rop-desc { width: 100%; color: #64748b; font-size: 0.8rem; padding-left: 1.8rem; }
|
|
1801
|
-
|
|
1802
|
-
.rstep-impact { margin-top: 0.5rem; }
|
|
1803
|
-
.rstep-impact h4 { font-size: 0.85rem; color: #94a3b8; margin-bottom: 0.3rem; }
|
|
1804
|
-
.rimpact-tags { display: flex; gap: 0.5rem; flex-wrap: wrap; }
|
|
1805
|
-
.rimpact-tag {
|
|
1806
|
-
background: #22c55e10; color: #22c55e; border: 1px solid #22c55e30;
|
|
1807
|
-
padding: 0.2rem 0.6rem; border-radius: 8px; font-size: 0.75rem; font-weight: 500;
|
|
1808
|
-
}
|
|
1809
|
-
|
|
1810
|
-
/* ── Responsive ── */
|
|
1811
|
-
@media (max-width: 768px) {
|
|
1812
|
-
.score-hero { flex-direction: column; gap: 1.5rem; }
|
|
1813
|
-
.score-breakdown { grid-template-columns: 1fr; }
|
|
1814
|
-
.header h1 { font-size: 1.8rem; }
|
|
1815
|
-
.container { padding: 1rem; }
|
|
1816
|
-
.refactor-score-pair { flex-direction: column; }
|
|
1817
|
-
}
|
|
1818
|
-
|
|
1819
|
-
/* ── Print ── */
|
|
1820
|
-
@media print {
|
|
1821
|
-
body { background: white; color: #1e293b; }
|
|
1822
|
-
.header { background: white; border-bottom: 2px solid #e2e8f0; }
|
|
1823
|
-
.header h1 { -webkit-text-fill-color: #4f46e5; }
|
|
1824
|
-
.card, .stat-card, .score-hero, .layer-card, .score-item {
|
|
1825
|
-
background: white; border-color: #e2e8f0;
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1828
|
-
</style>`;
|
|
1829
|
-
}
|
|
1830
|
-
}
|