vibecheck-ai 2.0.1 → 5.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/bin/.generated +25 -0
- package/bin/_deprecations.js +463 -0
- package/bin/_router.js +46 -0
- package/bin/cli-hygiene.js +241 -0
- package/bin/dev/run-v2-torture.js +30 -0
- package/bin/registry.js +656 -0
- package/bin/runners/CLI_REFACTOR_SUMMARY.md +229 -0
- package/bin/runners/ENHANCEMENT_GUIDE.md +121 -0
- package/bin/runners/REPORT_AUDIT.md +64 -0
- package/bin/runners/cli-utils.js +1070 -0
- package/bin/runners/context/ai-task-decomposer.js +337 -0
- package/bin/runners/context/analyzer.js +513 -0
- package/bin/runners/context/api-contracts.js +427 -0
- package/bin/runners/context/context-diff.js +342 -0
- package/bin/runners/context/context-pruner.js +291 -0
- package/bin/runners/context/dependency-graph.js +414 -0
- package/bin/runners/context/generators/claude.js +107 -0
- package/bin/runners/context/generators/codex.js +108 -0
- package/bin/runners/context/generators/copilot.js +119 -0
- package/bin/runners/context/generators/cursor-enhanced.js +2525 -0
- package/bin/runners/context/generators/cursor.js +514 -0
- package/bin/runners/context/generators/mcp.js +169 -0
- package/bin/runners/context/generators/windsurf.js +180 -0
- package/bin/runners/context/git-context.js +304 -0
- package/bin/runners/context/index.js +1110 -0
- package/bin/runners/context/insights.js +173 -0
- package/bin/runners/context/mcp-server/generate-rules.js +337 -0
- package/bin/runners/context/mcp-server/index.js +1176 -0
- package/bin/runners/context/mcp-server/package.json +24 -0
- package/bin/runners/context/memory.js +200 -0
- package/bin/runners/context/monorepo.js +215 -0
- package/bin/runners/context/multi-repo-federation.js +404 -0
- package/bin/runners/context/patterns.js +253 -0
- package/bin/runners/context/proof-context.js +1264 -0
- package/bin/runners/context/security-scanner.js +541 -0
- package/bin/runners/context/semantic-search.js +350 -0
- package/bin/runners/context/shared.js +264 -0
- package/bin/runners/context/team-conventions.js +336 -0
- package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -0
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -0
- package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
- package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
- package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
- package/bin/runners/lib/agent-firewall/claims/extractor.js +303 -0
- package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
- package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
- package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
- package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
- package/bin/runners/lib/agent-firewall/enforcement/gateway.js +1059 -0
- package/bin/runners/lib/agent-firewall/enforcement/index.js +98 -0
- package/bin/runners/lib/agent-firewall/enforcement/mode.js +318 -0
- package/bin/runners/lib/agent-firewall/enforcement/orchestrator.js +484 -0
- package/bin/runners/lib/agent-firewall/enforcement/proof-artifact.js +418 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/change-event.schema.json +173 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/intent.schema.json +181 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/verdict.schema.json +222 -0
- package/bin/runners/lib/agent-firewall/enforcement/verdict-v2.js +333 -0
- package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
- package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +127 -0
- package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -0
- package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
- package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
- package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
- package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
- package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
- package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
- package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
- package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
- package/bin/runners/lib/agent-firewall/index.js +200 -0
- package/bin/runners/lib/agent-firewall/integration/index.js +20 -0
- package/bin/runners/lib/agent-firewall/integration/ship-gate.js +437 -0
- package/bin/runners/lib/agent-firewall/intent/alignment-engine.js +634 -0
- package/bin/runners/lib/agent-firewall/intent/auto-detect.js +426 -0
- package/bin/runners/lib/agent-firewall/intent/index.js +102 -0
- package/bin/runners/lib/agent-firewall/intent/schema.js +352 -0
- package/bin/runners/lib/agent-firewall/intent/store.js +283 -0
- package/bin/runners/lib/agent-firewall/interception/fs-interceptor.js +502 -0
- package/bin/runners/lib/agent-firewall/interception/index.js +23 -0
- package/bin/runners/lib/agent-firewall/interceptor/base.js +308 -0
- package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
- package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
- package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
- package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
- package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
- package/bin/runners/lib/agent-firewall/logger.js +141 -0
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
- package/bin/runners/lib/agent-firewall/policy/loader.js +451 -0
- package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +79 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +227 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +191 -0
- package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
- package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
- package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
- package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
- package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
- package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
- package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
- package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
- package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
- package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
- package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
- package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
- package/bin/runners/lib/agent-firewall/session/collector.js +451 -0
- package/bin/runners/lib/agent-firewall/session/index.js +26 -0
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
- package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
- package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
- package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
- package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
- package/bin/runners/lib/ai-bridge.js +416 -0
- package/bin/runners/lib/analysis-core.js +309 -0
- package/bin/runners/lib/analyzers.js +2500 -0
- package/bin/runners/lib/api-client.js +269 -0
- package/bin/runners/lib/approve-output.js +235 -0
- package/bin/runners/lib/artifact-envelope.js +540 -0
- package/bin/runners/lib/assets/vibecheck-logo.png +0 -0
- package/bin/runners/lib/audit-bridge.js +391 -0
- package/bin/runners/lib/auth-shared.js +977 -0
- package/bin/runners/lib/auth-truth.js +193 -0
- package/bin/runners/lib/auth.js +215 -0
- package/bin/runners/lib/authority-badge.js +425 -0
- package/bin/runners/lib/backup.js +62 -0
- package/bin/runners/lib/billing.js +107 -0
- package/bin/runners/lib/checkpoint.js +941 -0
- package/bin/runners/lib/claims.js +118 -0
- package/bin/runners/lib/classify-output.js +204 -0
- package/bin/runners/lib/cleanup/engine.js +571 -0
- package/bin/runners/lib/cleanup/index.js +53 -0
- package/bin/runners/lib/cleanup/output.js +375 -0
- package/bin/runners/lib/cleanup/rules.js +1060 -0
- package/bin/runners/lib/cli-output.js +400 -0
- package/bin/runners/lib/cli-ui.js +540 -0
- package/bin/runners/lib/compliance-bridge-new.js +0 -0
- package/bin/runners/lib/compliance-bridge.js +165 -0
- package/bin/runners/lib/contracts/auth-contract.js +202 -0
- package/bin/runners/lib/contracts/env-contract.js +181 -0
- package/bin/runners/lib/contracts/external-contract.js +206 -0
- package/bin/runners/lib/contracts/guard.js +168 -0
- package/bin/runners/lib/contracts/index.js +89 -0
- package/bin/runners/lib/contracts/plan-validator.js +311 -0
- package/bin/runners/lib/contracts/route-contract.js +199 -0
- package/bin/runners/lib/contracts.js +804 -0
- package/bin/runners/lib/default-config.js +127 -0
- package/bin/runners/lib/detect.js +89 -0
- package/bin/runners/lib/detectors-v2.js +622 -0
- package/bin/runners/lib/doctor/autofix.js +254 -0
- package/bin/runners/lib/doctor/diagnosis-receipt.js +454 -0
- package/bin/runners/lib/doctor/failure-signatures.js +526 -0
- package/bin/runners/lib/doctor/fix-script.js +336 -0
- package/bin/runners/lib/doctor/index.js +37 -0
- package/bin/runners/lib/doctor/modules/build-tools.js +453 -0
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
- package/bin/runners/lib/doctor/modules/index.js +105 -0
- package/bin/runners/lib/doctor/modules/network.js +250 -0
- package/bin/runners/lib/doctor/modules/os-quirks.js +706 -0
- package/bin/runners/lib/doctor/modules/project.js +312 -0
- package/bin/runners/lib/doctor/modules/repo-integrity.js +485 -0
- package/bin/runners/lib/doctor/modules/runtime.js +224 -0
- package/bin/runners/lib/doctor/modules/security.js +350 -0
- package/bin/runners/lib/doctor/modules/system.js +213 -0
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
- package/bin/runners/lib/doctor/reporter.js +262 -0
- package/bin/runners/lib/doctor/safe-repair.js +384 -0
- package/bin/runners/lib/doctor/service.js +262 -0
- package/bin/runners/lib/doctor/types.js +113 -0
- package/bin/runners/lib/doctor/ui.js +263 -0
- package/bin/runners/lib/doctor-enhanced.js +233 -0
- package/bin/runners/lib/doctor-output.js +226 -0
- package/bin/runners/lib/doctor-v2.js +608 -0
- package/bin/runners/lib/drift.js +425 -0
- package/bin/runners/lib/enforcement.js +72 -0
- package/bin/runners/lib/engine/ast-cache.js +210 -0
- package/bin/runners/lib/engine/auth-extractor.js +211 -0
- package/bin/runners/lib/engine/billing-extractor.js +112 -0
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
- package/bin/runners/lib/engine/env-extractor.js +207 -0
- package/bin/runners/lib/engine/express-extractor.js +208 -0
- package/bin/runners/lib/engine/extractors.js +849 -0
- package/bin/runners/lib/engine/index.js +207 -0
- package/bin/runners/lib/engine/repo-index.js +514 -0
- package/bin/runners/lib/engine/types.js +124 -0
- package/bin/runners/lib/engines/accessibility-engine.js +190 -0
- package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
- package/bin/runners/lib/engines/ast-cache.js +99 -0
- package/bin/runners/lib/engines/attack-detector.js +1192 -0
- package/bin/runners/lib/engines/code-quality-engine.js +255 -0
- package/bin/runners/lib/engines/console-logs-engine.js +115 -0
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
- package/bin/runners/lib/engines/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
- package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
- package/bin/runners/lib/engines/file-filter.js +131 -0
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
- package/bin/runners/lib/engines/mock-data-engine.js +272 -0
- package/bin/runners/lib/engines/parallel-processor.js +71 -0
- package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
- package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
- package/bin/runners/lib/engines/type-aware-engine.js +152 -0
- package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
- package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
- package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
- package/bin/runners/lib/enterprise-detect.js +603 -0
- package/bin/runners/lib/enterprise-init.js +942 -0
- package/bin/runners/lib/entitlements-v2.js +265 -0
- package/bin/runners/lib/entitlements.generated.js +0 -0
- package/bin/runners/lib/entitlements.js +340 -0
- package/bin/runners/lib/env-resolver.js +417 -0
- package/bin/runners/lib/env-template.js +66 -0
- package/bin/runners/lib/env.js +189 -0
- package/bin/runners/lib/error-handler.js +368 -0
- package/bin/runners/lib/error-messages.js +289 -0
- package/bin/runners/lib/evidence-pack.js +684 -0
- package/bin/runners/lib/exit-codes.js +275 -0
- package/bin/runners/lib/extractors/client-calls.js +990 -0
- package/bin/runners/lib/extractors/fastify-route-dump.js +573 -0
- package/bin/runners/lib/extractors/fastify-routes.js +426 -0
- package/bin/runners/lib/extractors/index.js +363 -0
- package/bin/runners/lib/extractors/next-routes.js +524 -0
- package/bin/runners/lib/extractors/proof-graph.js +431 -0
- package/bin/runners/lib/extractors/route-matcher.js +451 -0
- package/bin/runners/lib/extractors/truthpack-v2.js +377 -0
- package/bin/runners/lib/extractors/ui-bindings.js +547 -0
- package/bin/runners/lib/finding-id.js +69 -0
- package/bin/runners/lib/finding-sorter.js +89 -0
- package/bin/runners/lib/findings-schema.js +281 -0
- package/bin/runners/lib/fingerprint.js +377 -0
- package/bin/runners/lib/firewall-prompt.js +50 -0
- package/bin/runners/lib/fix-output.js +228 -0
- package/bin/runners/lib/global-flags.js +250 -0
- package/bin/runners/lib/graph/graph-builder.js +265 -0
- package/bin/runners/lib/graph/html-renderer.js +413 -0
- package/bin/runners/lib/graph/index.js +32 -0
- package/bin/runners/lib/graph/runtime-collector.js +215 -0
- package/bin/runners/lib/graph/static-extractor.js +518 -0
- package/bin/runners/lib/help-formatter.js +413 -0
- package/bin/runners/lib/html-proof-report.js +913 -0
- package/bin/runners/lib/html-report.js +650 -0
- package/bin/runners/lib/init-wizard.js +601 -0
- package/bin/runners/lib/interactive-menu.js +1496 -0
- package/bin/runners/lib/json-output.js +76 -0
- package/bin/runners/lib/llm.js +75 -0
- package/bin/runners/lib/logger.js +38 -0
- package/bin/runners/lib/meter.js +61 -0
- package/bin/runners/lib/missions/briefing.js +427 -0
- package/bin/runners/lib/missions/checkpoint.js +753 -0
- package/bin/runners/lib/missions/evidence.js +126 -0
- package/bin/runners/lib/missions/hardening.js +851 -0
- package/bin/runners/lib/missions/plan.js +648 -0
- package/bin/runners/lib/missions/safety-gates.js +645 -0
- package/bin/runners/lib/missions/schema.js +478 -0
- package/bin/runners/lib/missions/templates.js +317 -0
- package/bin/runners/lib/next-action.js +560 -0
- package/bin/runners/lib/packs/bundle.js +675 -0
- package/bin/runners/lib/packs/evidence-pack.js +671 -0
- package/bin/runners/lib/packs/pack-factory.js +837 -0
- package/bin/runners/lib/packs/permissions-pack.js +686 -0
- package/bin/runners/lib/packs/proof-graph-pack.js +779 -0
- package/bin/runners/lib/patch.js +40 -0
- package/bin/runners/lib/permissions/auth-model.js +213 -0
- package/bin/runners/lib/permissions/idor-prover.js +205 -0
- package/bin/runners/lib/permissions/index.js +45 -0
- package/bin/runners/lib/permissions/matrix-builder.js +198 -0
- package/bin/runners/lib/pkgjson.js +28 -0
- package/bin/runners/lib/policy.js +295 -0
- package/bin/runners/lib/polish/accessibility.js +62 -0
- package/bin/runners/lib/polish/analyzer.js +93 -0
- package/bin/runners/lib/polish/backend.js +87 -0
- package/bin/runners/lib/polish/configuration.js +83 -0
- package/bin/runners/lib/polish/documentation.js +83 -0
- package/bin/runners/lib/polish/frontend.js +817 -0
- package/bin/runners/lib/polish/index.js +27 -0
- package/bin/runners/lib/polish/infrastructure.js +80 -0
- package/bin/runners/lib/polish/internationalization.js +85 -0
- package/bin/runners/lib/polish/libraries.js +180 -0
- package/bin/runners/lib/polish/observability.js +75 -0
- package/bin/runners/lib/polish/performance.js +64 -0
- package/bin/runners/lib/polish/privacy.js +110 -0
- package/bin/runners/lib/polish/resilience.js +92 -0
- package/bin/runners/lib/polish/security.js +78 -0
- package/bin/runners/lib/polish/seo.js +71 -0
- package/bin/runners/lib/polish/styles.js +62 -0
- package/bin/runners/lib/polish/utils.js +104 -0
- package/bin/runners/lib/preflight.js +142 -0
- package/bin/runners/lib/prerequisites.js +149 -0
- package/bin/runners/lib/prove-output.js +220 -0
- package/bin/runners/lib/reality/correlation-detectors.js +359 -0
- package/bin/runners/lib/reality/index.js +318 -0
- package/bin/runners/lib/reality/request-hashing.js +416 -0
- package/bin/runners/lib/reality/request-mapper.js +453 -0
- package/bin/runners/lib/reality/safety-rails.js +463 -0
- package/bin/runners/lib/reality/semantic-snapshot.js +408 -0
- package/bin/runners/lib/reality/toast-detector.js +393 -0
- package/bin/runners/lib/reality-findings.js +84 -0
- package/bin/runners/lib/reality-output.js +231 -0
- package/bin/runners/lib/receipts.js +179 -0
- package/bin/runners/lib/redact.js +29 -0
- package/bin/runners/lib/replay/capsule-manager.js +154 -0
- package/bin/runners/lib/replay/index.js +263 -0
- package/bin/runners/lib/replay/player.js +348 -0
- package/bin/runners/lib/replay/recorder.js +331 -0
- package/bin/runners/lib/report-engine.js +626 -0
- package/bin/runners/lib/report-html.js +1233 -0
- package/bin/runners/lib/report-output.js +366 -0
- package/bin/runners/lib/report-templates.js +967 -0
- package/bin/runners/lib/report.js +135 -0
- package/bin/runners/lib/route-detection.js +1209 -0
- package/bin/runners/lib/route-truth.js +1322 -0
- package/bin/runners/lib/safelist/index.js +96 -0
- package/bin/runners/lib/safelist/integration.js +334 -0
- package/bin/runners/lib/safelist/matcher.js +696 -0
- package/bin/runners/lib/safelist/schema.js +948 -0
- package/bin/runners/lib/safelist/store.js +438 -0
- package/bin/runners/lib/sandbox/index.js +59 -0
- package/bin/runners/lib/sandbox/proof-chain.js +399 -0
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
- package/bin/runners/lib/sandbox/worktree.js +174 -0
- package/bin/runners/lib/scan-cache.js +330 -0
- package/bin/runners/lib/scan-output-schema.js +344 -0
- package/bin/runners/lib/scan-output.js +631 -0
- package/bin/runners/lib/scan-runner.js +135 -0
- package/bin/runners/lib/schema-validator.js +350 -0
- package/bin/runners/lib/schemas/ajv-validator.js +464 -0
- package/bin/runners/lib/schemas/contracts.schema.json +160 -0
- package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
- package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
- package/bin/runners/lib/schemas/finding.schema.json +100 -0
- package/bin/runners/lib/schemas/mission-pack.schema.json +206 -0
- package/bin/runners/lib/schemas/proof-graph.schema.json +176 -0
- package/bin/runners/lib/schemas/reality-report.schema.json +162 -0
- package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
- package/bin/runners/lib/schemas/run-request.schema.json +108 -0
- package/bin/runners/lib/schemas/share-pack.schema.json +180 -0
- package/bin/runners/lib/schemas/ship-manifest.schema.json +251 -0
- package/bin/runners/lib/schemas/ship-report.schema.json +117 -0
- package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -0
- package/bin/runners/lib/schemas/validator.js +465 -0
- package/bin/runners/lib/schemas/verdict.schema.json +140 -0
- package/bin/runners/lib/score-history.js +282 -0
- package/bin/runners/lib/security-bridge.js +249 -0
- package/bin/runners/lib/server-usage.js +513 -0
- package/bin/runners/lib/share-pack.js +239 -0
- package/bin/runners/lib/ship-gate.js +832 -0
- package/bin/runners/lib/ship-manifest.js +1153 -0
- package/bin/runners/lib/ship-output-enterprise.js +239 -0
- package/bin/runners/lib/ship-output.js +1128 -0
- package/bin/runners/lib/snippets.js +67 -0
- package/bin/runners/lib/status-output.js +340 -0
- package/bin/runners/lib/terminal-ui.js +356 -0
- package/bin/runners/lib/truth.js +1691 -0
- package/bin/runners/lib/ui.js +562 -0
- package/bin/runners/lib/unified-cli-output.js +947 -0
- package/bin/runners/lib/unified-output.js +197 -0
- package/bin/runners/lib/upsell.js +410 -0
- package/bin/runners/lib/usage.js +153 -0
- package/bin/runners/lib/validate-patch.js +156 -0
- package/bin/runners/lib/verdict-engine.js +628 -0
- package/bin/runners/lib/verification.js +345 -0
- package/bin/runners/lib/why-tree.js +650 -0
- package/bin/runners/reality/engine.js +917 -0
- package/bin/runners/reality/flows.js +122 -0
- package/bin/runners/reality/report.js +378 -0
- package/bin/runners/reality/session.js +193 -0
- package/bin/runners/runAIAgent.js +229 -0
- package/bin/runners/runAgent.d.ts +5 -0
- package/bin/runners/runAgent.js +161 -0
- package/bin/runners/runAllowlist.js +418 -0
- package/bin/runners/runApprove.js +320 -0
- package/bin/runners/runAudit.js +692 -0
- package/bin/runners/runAuth.js +731 -0
- package/bin/runners/runCI.js +353 -0
- package/bin/runners/runCheckpoint.js +530 -0
- package/bin/runners/runClassify.js +928 -0
- package/bin/runners/runCleanup.js +343 -0
- package/bin/runners/runContext.d.ts +4 -0
- package/bin/runners/runContext.js +175 -0
- package/bin/runners/runDoctor.js +877 -0
- package/bin/runners/runEvidencePack.js +362 -0
- package/bin/runners/runFirewall.d.ts +5 -0
- package/bin/runners/runFirewall.js +134 -0
- package/bin/runners/runFirewallHook.d.ts +5 -0
- package/bin/runners/runFirewallHook.js +56 -0
- package/bin/runners/runFix.js +1355 -0
- package/bin/runners/runForge.js +451 -0
- package/bin/runners/runGuard.js +262 -0
- package/bin/runners/runInit.js +1927 -0
- package/bin/runners/runIntent.js +906 -0
- package/bin/runners/runKickoff.js +878 -0
- package/bin/runners/runLabs.js +424 -0
- package/bin/runners/runLaunch.js +2000 -0
- package/bin/runners/runLink.js +785 -0
- package/bin/runners/runMcp.js +1875 -0
- package/bin/runners/runPacks.js +2089 -0
- package/bin/runners/runPolish.d.ts +4 -0
- package/bin/runners/runPolish.js +390 -0
- package/bin/runners/runPromptFirewall.js +211 -0
- package/bin/runners/runProve.js +1411 -0
- package/bin/runners/runQuickstart.js +531 -0
- package/bin/runners/runReality.js +2260 -0
- package/bin/runners/runReport.js +726 -0
- package/bin/runners/runRuntime.js +110 -0
- package/bin/runners/runSafelist.js +1190 -0
- package/bin/runners/runScan.js +688 -0
- package/bin/runners/runShield.js +1282 -0
- package/bin/runners/runShip.js +1660 -0
- package/bin/runners/runTruth.d.ts +5 -0
- package/bin/runners/runTruth.js +101 -0
- package/bin/runners/runValidate.js +179 -0
- package/bin/runners/runWatch.js +478 -0
- package/bin/runners/utils.js +360 -0
- package/bin/scan.js +617 -0
- package/bin/vibecheck.js +1617 -0
- package/dist/guardrail/index.d.ts +2405 -0
- package/dist/guardrail/index.js +9747 -0
- package/dist/guardrail/index.js.map +1 -0
- package/dist/scanner/index.d.ts +282 -0
- package/dist/scanner/index.js +3395 -0
- package/dist/scanner/index.js.map +1 -0
- package/package.json +123 -104
- package/README.md +0 -491
- package/dist/index.js +0 -99711
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,817 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frontend Polish Engine
|
|
3
|
+
*
|
|
4
|
+
* Checks: Error boundaries, loading states, empty states, toasts,
|
|
5
|
+
* form validation, animations, hover states, haptics, ARIA,
|
|
6
|
+
* focus traps, skip links, data caching, memoization, logging,
|
|
7
|
+
* error tracking, lazy images, dark mode, confirm dialogs,
|
|
8
|
+
* optimistic updates, keyboard shortcuts, scroll-to-top, progress bars.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require("path");
|
|
12
|
+
const {
|
|
13
|
+
pathExists,
|
|
14
|
+
findFile,
|
|
15
|
+
findAllFiles,
|
|
16
|
+
readFileSafe,
|
|
17
|
+
} = require("./utils");
|
|
18
|
+
const {
|
|
19
|
+
LIBRARY_ALTERNATIVES,
|
|
20
|
+
hasLibrary,
|
|
21
|
+
detectProjectType,
|
|
22
|
+
adjustSeverity,
|
|
23
|
+
} = require("./libraries");
|
|
24
|
+
|
|
25
|
+
module.exports = async function frontendEngine(projectPath) {
|
|
26
|
+
const issues = [];
|
|
27
|
+
const srcPath = path.join(projectPath, "src");
|
|
28
|
+
const appPath = path.join(projectPath, "app");
|
|
29
|
+
const pagesPath = path.join(projectPath, "pages");
|
|
30
|
+
const componentsPath = path.join(srcPath, "components");
|
|
31
|
+
|
|
32
|
+
const hasSrc = await pathExists(srcPath);
|
|
33
|
+
const hasApp = await pathExists(appPath);
|
|
34
|
+
const hasPages = await pathExists(pagesPath);
|
|
35
|
+
|
|
36
|
+
if (!hasSrc && !hasApp && !hasPages) return issues;
|
|
37
|
+
|
|
38
|
+
const searchPath = hasSrc ? srcPath : hasApp ? appPath : pagesPath;
|
|
39
|
+
const packageJson = await readFileSafe(path.join(projectPath, "package.json"));
|
|
40
|
+
|
|
41
|
+
const projectType = await detectProjectType(projectPath, packageJson);
|
|
42
|
+
if (projectType.skipFrontend) return issues;
|
|
43
|
+
|
|
44
|
+
// Detect installed libraries
|
|
45
|
+
const errorBoundaryLib = hasLibrary(packageJson, LIBRARY_ALTERNATIVES.errorBoundary);
|
|
46
|
+
const toastLib = hasLibrary(packageJson, LIBRARY_ALTERNATIVES.toast);
|
|
47
|
+
const spinnerLib = hasLibrary(packageJson, LIBRARY_ALTERNATIVES.spinner);
|
|
48
|
+
const skeletonLib = hasLibrary(packageJson, LIBRARY_ALTERNATIVES.skeleton);
|
|
49
|
+
const formLib = hasLibrary(packageJson, LIBRARY_ALTERNATIVES.formValidation);
|
|
50
|
+
|
|
51
|
+
// ── Error Handling & Boundaries ──────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
const hasErrorBoundary = await findFile(searchPath, /ErrorBoundary|error\.(tsx?|jsx?)$/i);
|
|
54
|
+
if (!hasErrorBoundary && !errorBoundaryLib && !projectType.uiLibrary) {
|
|
55
|
+
issues.push({
|
|
56
|
+
id: "missing-error-boundary",
|
|
57
|
+
category: "Frontend",
|
|
58
|
+
severity: adjustSeverity("critical", projectType, "missing-error-boundary"),
|
|
59
|
+
title: "Missing Error Boundary",
|
|
60
|
+
description: "No error boundary component found. React errors will crash the entire app.",
|
|
61
|
+
suggestion: "Add ErrorBoundary component to catch and handle React errors gracefully.",
|
|
62
|
+
autoFixable: true,
|
|
63
|
+
confidence: 0.9,
|
|
64
|
+
aiPrompt: `Create a reusable ErrorBoundary component for React/Next.js that:
|
|
65
|
+
1. Catches JavaScript errors anywhere in the child component tree
|
|
66
|
+
2. Logs errors to console and optionally to an error tracking service
|
|
67
|
+
3. Displays a user-friendly fallback UI with:
|
|
68
|
+
- A friendly error message
|
|
69
|
+
- A "Try Again" button that resets the error state
|
|
70
|
+
- Option to report the error
|
|
71
|
+
4. Supports custom fallback UI via props
|
|
72
|
+
5. Uses TypeScript with proper typing
|
|
73
|
+
6. Includes a useErrorBoundary hook for functional components
|
|
74
|
+
7. Has smooth fade-in animation for the fallback UI
|
|
75
|
+
|
|
76
|
+
Place it in src/components/ErrorBoundary.tsx`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const has404 = await findFile(searchPath, /not-found|NotFound|404/i);
|
|
81
|
+
const hasNextAppRouter404 = hasApp && (await pathExists(path.join(appPath, "not-found.tsx")));
|
|
82
|
+
if (!has404 && !hasNextAppRouter404) {
|
|
83
|
+
issues.push({
|
|
84
|
+
id: "missing-404",
|
|
85
|
+
category: "Frontend",
|
|
86
|
+
severity: adjustSeverity("medium", projectType, "missing-404"),
|
|
87
|
+
title: "Missing 404 Page",
|
|
88
|
+
description: "No custom 404/NotFound page found. Users will see default browser error.",
|
|
89
|
+
suggestion: "Add a custom 404 page with navigation options.",
|
|
90
|
+
autoFixable: true,
|
|
91
|
+
confidence: 0.85,
|
|
92
|
+
aiPrompt: `Create a beautiful, user-friendly 404 Not Found page that:
|
|
93
|
+
1. Has a visually appealing design with subtle animations
|
|
94
|
+
2. Shows a clear "Page Not Found" message
|
|
95
|
+
3. Includes helpful navigation options:
|
|
96
|
+
- Go back to previous page button
|
|
97
|
+
- Go to homepage button
|
|
98
|
+
- Search functionality (if applicable)
|
|
99
|
+
- Popular/suggested links
|
|
100
|
+
4. Has a fun illustration or animation (CSS-based, no external images)
|
|
101
|
+
5. Is fully responsive for mobile
|
|
102
|
+
6. Maintains the site's design language
|
|
103
|
+
7. Includes proper meta tags for SEO
|
|
104
|
+
|
|
105
|
+
For Next.js App Router: Create app/not-found.tsx
|
|
106
|
+
For Pages Router: Create pages/404.tsx`,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ── Loading States & Skeletons ───────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
const hasLoadingSpinner = await findFile(searchPath, /Spinner|LoadingSpinner|Loading\.(tsx?|jsx?)$/i);
|
|
113
|
+
if (!hasLoadingSpinner && !spinnerLib && !projectType.uiLibrary) {
|
|
114
|
+
issues.push({
|
|
115
|
+
id: "missing-spinner",
|
|
116
|
+
category: "Frontend",
|
|
117
|
+
severity: adjustSeverity("high", projectType, "missing-spinner"),
|
|
118
|
+
title: "Missing Loading Spinner",
|
|
119
|
+
description: "No spinner component found. Users need visual feedback during loading.",
|
|
120
|
+
suggestion: spinnerLib
|
|
121
|
+
? `Consider using the ${spinnerLib} library you have installed.`
|
|
122
|
+
: "Add a reusable Spinner component with multiple sizes and variants.",
|
|
123
|
+
autoFixable: true,
|
|
124
|
+
confidence: 0.7,
|
|
125
|
+
aiPrompt: `Create a modern, reusable Spinner/Loading component that:
|
|
126
|
+
1. Has multiple size variants: sm, md, lg, xl
|
|
127
|
+
2. Supports custom colors via props or CSS variables
|
|
128
|
+
3. Has multiple styles: circular spinner, dots, pulse, bars
|
|
129
|
+
4. Uses pure CSS animations (no external dependencies)
|
|
130
|
+
5. Is accessible with proper ARIA attributes (role="status", aria-label)
|
|
131
|
+
6. Supports dark/light mode automatically
|
|
132
|
+
7. Can be used inline or as an overlay
|
|
133
|
+
8. Has smooth entrance/exit animations
|
|
134
|
+
9. TypeScript with proper prop types
|
|
135
|
+
|
|
136
|
+
Create: src/components/ui/Spinner.tsx and src/components/ui/Spinner.css`,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const hasSkeleton = await findFile(searchPath, /Skeleton|Shimmer|ContentLoader/i);
|
|
141
|
+
if (!hasSkeleton && !skeletonLib && !projectType.uiLibrary) {
|
|
142
|
+
issues.push({
|
|
143
|
+
id: "missing-skeleton",
|
|
144
|
+
category: "Frontend",
|
|
145
|
+
severity: adjustSeverity("high", projectType, "missing-skeleton"),
|
|
146
|
+
title: "Missing Skeleton Loaders",
|
|
147
|
+
description: "No skeleton/shimmer components found. Skeleton loaders provide better perceived performance than spinners.",
|
|
148
|
+
suggestion: skeletonLib
|
|
149
|
+
? `Consider using the ${skeletonLib} library you have installed.`
|
|
150
|
+
: "Add skeleton components for content placeholders.",
|
|
151
|
+
autoFixable: true,
|
|
152
|
+
confidence: 0.65,
|
|
153
|
+
aiPrompt: `Create a comprehensive Skeleton loading system with:
|
|
154
|
+
|
|
155
|
+
1. Base Skeleton component with:
|
|
156
|
+
- Shimmer animation effect
|
|
157
|
+
- Multiple variants: text, circular, rectangular, rounded
|
|
158
|
+
- Customizable width, height, border-radius
|
|
159
|
+
- Animation that flows left-to-right with gradient
|
|
160
|
+
|
|
161
|
+
2. Pre-built skeleton patterns:
|
|
162
|
+
- SkeletonText (paragraph lines with varying widths)
|
|
163
|
+
- SkeletonAvatar (circular profile picture placeholder)
|
|
164
|
+
- SkeletonCard (card layout placeholder)
|
|
165
|
+
- SkeletonTable (table rows placeholder)
|
|
166
|
+
- SkeletonList (list items placeholder)
|
|
167
|
+
- SkeletonImage (image placeholder with aspect ratio)
|
|
168
|
+
|
|
169
|
+
3. Features:
|
|
170
|
+
- CSS-only animations (performant)
|
|
171
|
+
- Dark/light mode support
|
|
172
|
+
- Customizable animation speed
|
|
173
|
+
- Can disable animation for reduced motion preference
|
|
174
|
+
- TypeScript with proper types
|
|
175
|
+
|
|
176
|
+
Create: src/components/ui/Skeleton.tsx with all variants`,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const hasLoadingPage = await findFile(searchPath, /loading\.(tsx?|jsx?)$/i);
|
|
181
|
+
if (!hasLoadingPage && hasApp) {
|
|
182
|
+
issues.push({
|
|
183
|
+
id: "missing-loading-page",
|
|
184
|
+
category: "Frontend",
|
|
185
|
+
severity: "medium",
|
|
186
|
+
title: "Missing Next.js Loading State",
|
|
187
|
+
description: "No loading.tsx found. Next.js App Router supports automatic loading states.",
|
|
188
|
+
suggestion: "Add loading.tsx files for route segments.",
|
|
189
|
+
autoFixable: true,
|
|
190
|
+
aiPrompt: `Create a loading.tsx file for Next.js App Router that:
|
|
191
|
+
1. Shows a full-page skeleton loader matching your layout
|
|
192
|
+
2. Uses your Skeleton components for consistency
|
|
193
|
+
3. Includes a subtle progress indicator
|
|
194
|
+
4. Maintains layout structure to prevent layout shift
|
|
195
|
+
5. Has smooth fade-out when content loads
|
|
196
|
+
|
|
197
|
+
Create: app/loading.tsx (root level) and consider adding to major route segments`,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ── Empty States & Feedback ──────────────────────────────────────────────
|
|
202
|
+
|
|
203
|
+
const hasEmptyState = await findFile(searchPath, /EmptyState|Empty|NoData|NoResults/i);
|
|
204
|
+
if (!hasEmptyState) {
|
|
205
|
+
issues.push({
|
|
206
|
+
id: "missing-empty-states",
|
|
207
|
+
category: "Frontend",
|
|
208
|
+
severity: "medium",
|
|
209
|
+
title: "Missing Empty States",
|
|
210
|
+
description: "No empty state components found. Users need helpful messages when data is empty.",
|
|
211
|
+
suggestion: "Add EmptyState components for lists and data displays.",
|
|
212
|
+
autoFixable: true,
|
|
213
|
+
aiPrompt: `Create a versatile EmptyState component system with:
|
|
214
|
+
|
|
215
|
+
1. Base EmptyState component with:
|
|
216
|
+
- Icon slot (customizable)
|
|
217
|
+
- Title and description
|
|
218
|
+
- Action button(s)
|
|
219
|
+
- Illustration option
|
|
220
|
+
|
|
221
|
+
2. Pre-built variants:
|
|
222
|
+
- EmptySearch: "No results found" with search tips
|
|
223
|
+
- EmptyList: "No items yet" with add item CTA
|
|
224
|
+
- EmptyInbox: "All caught up!" positive empty state
|
|
225
|
+
- EmptyError: "Something went wrong" with retry
|
|
226
|
+
- EmptyPermission: "Access denied" with request access
|
|
227
|
+
- EmptyOffline: "You're offline" with retry when online
|
|
228
|
+
|
|
229
|
+
3. Features:
|
|
230
|
+
- Subtle entrance animation
|
|
231
|
+
- Responsive design
|
|
232
|
+
- Supports custom illustrations
|
|
233
|
+
- Action buttons with loading states
|
|
234
|
+
- TypeScript with proper props
|
|
235
|
+
|
|
236
|
+
Create: src/components/ui/EmptyState.tsx with all variants`,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const hasToast = await findFile(searchPath, /Toast|Notification|Snackbar|Toaster/i);
|
|
241
|
+
if (!hasToast && !toastLib && !projectType.uiLibrary) {
|
|
242
|
+
issues.push({
|
|
243
|
+
id: "missing-toast",
|
|
244
|
+
category: "Frontend",
|
|
245
|
+
severity: adjustSeverity("high", projectType, "missing-toast"),
|
|
246
|
+
title: "Missing Toast/Notification System",
|
|
247
|
+
description: "No toast or notification component found for user feedback.",
|
|
248
|
+
suggestion: toastLib
|
|
249
|
+
? `Consider using the ${toastLib} library you have installed.`
|
|
250
|
+
: "Add a toast/notification system for user feedback on actions.",
|
|
251
|
+
autoFixable: true,
|
|
252
|
+
confidence: 0.75,
|
|
253
|
+
aiPrompt: `Create a complete Toast notification system with:
|
|
254
|
+
|
|
255
|
+
1. Toast component with:
|
|
256
|
+
- Variants: success, error, warning, info, loading
|
|
257
|
+
- Auto-dismiss with configurable duration
|
|
258
|
+
- Manual dismiss button
|
|
259
|
+
- Progress bar showing time remaining
|
|
260
|
+
- Stack multiple toasts
|
|
261
|
+
- Position options: top-right, top-center, bottom-right, etc.
|
|
262
|
+
|
|
263
|
+
2. Toast provider/context:
|
|
264
|
+
- useToast() hook for easy triggering
|
|
265
|
+
- toast.success(), toast.error(), etc. methods
|
|
266
|
+
- toast.promise() for async operations
|
|
267
|
+
- Global configuration
|
|
268
|
+
|
|
269
|
+
3. Features:
|
|
270
|
+
- Smooth slide-in/out animations
|
|
271
|
+
- Swipe to dismiss on mobile
|
|
272
|
+
- Pause on hover
|
|
273
|
+
- Accessible with ARIA live regions
|
|
274
|
+
- Queue management
|
|
275
|
+
- TypeScript with proper types
|
|
276
|
+
|
|
277
|
+
Create: src/components/ui/Toast.tsx and src/hooks/useToast.ts`,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ── Forms & Input Feedback ───────────────────────────────────────────────
|
|
282
|
+
|
|
283
|
+
const hasFormValidation = await findFile(searchPath, /FormError|FieldError|ValidationMessage/i);
|
|
284
|
+
if (!hasFormValidation && !formLib && !projectType.uiLibrary) {
|
|
285
|
+
issues.push({
|
|
286
|
+
id: "missing-form-validation-ui",
|
|
287
|
+
category: "Frontend",
|
|
288
|
+
severity: adjustSeverity("high", projectType, "missing-form-validation-ui"),
|
|
289
|
+
title: "Missing Form Validation UI",
|
|
290
|
+
description: "No form validation components found. Users need clear feedback on form errors.",
|
|
291
|
+
suggestion: formLib
|
|
292
|
+
? `The ${formLib} library you have installed provides form validation. Make sure to display errors.`
|
|
293
|
+
: "Add form validation components with clear error states.",
|
|
294
|
+
autoFixable: true,
|
|
295
|
+
confidence: 0.65,
|
|
296
|
+
aiPrompt: `Create a comprehensive form validation UI system with:
|
|
297
|
+
|
|
298
|
+
1. FormField wrapper component with:
|
|
299
|
+
- Label with required indicator
|
|
300
|
+
- Help text / description
|
|
301
|
+
- Error message display
|
|
302
|
+
- Success state indicator
|
|
303
|
+
- Character counter for text inputs
|
|
304
|
+
|
|
305
|
+
2. Input components with built-in validation states:
|
|
306
|
+
- TextInput with error/success borders
|
|
307
|
+
- SelectInput with validation
|
|
308
|
+
- Checkbox/Radio with error states
|
|
309
|
+
- TextArea with validation
|
|
310
|
+
|
|
311
|
+
3. Validation feedback:
|
|
312
|
+
- Inline error messages with icons
|
|
313
|
+
- Shake animation on error
|
|
314
|
+
- Real-time validation feedback
|
|
315
|
+
- Form-level error summary
|
|
316
|
+
- Success checkmark animation
|
|
317
|
+
|
|
318
|
+
4. Features:
|
|
319
|
+
- Works with react-hook-form or standalone
|
|
320
|
+
- Accessible error announcements
|
|
321
|
+
- Touch-friendly error targets
|
|
322
|
+
- TypeScript with proper types
|
|
323
|
+
|
|
324
|
+
Create: src/components/ui/FormField.tsx and related input components`,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// ── Micro-Interactions & Animations ──────────────────────────────────────
|
|
329
|
+
|
|
330
|
+
const hasAnimationLib =
|
|
331
|
+
packageJson && /framer-motion|react-spring|@react-spring|gsap|animejs/i.test(packageJson);
|
|
332
|
+
const hasAnimations = await findFile(searchPath, /animate|motion|transition|useSpring/i);
|
|
333
|
+
if (!hasAnimationLib && !hasAnimations) {
|
|
334
|
+
issues.push({
|
|
335
|
+
id: "missing-animations",
|
|
336
|
+
category: "Frontend",
|
|
337
|
+
severity: "medium",
|
|
338
|
+
title: "Missing Animation System",
|
|
339
|
+
description: "No animation library or utilities found. Animations make UX feel polished.",
|
|
340
|
+
suggestion: "Add framer-motion or CSS animations for micro-interactions.",
|
|
341
|
+
autoFixable: true,
|
|
342
|
+
aiPrompt: `Create a lightweight animation system with:
|
|
343
|
+
|
|
344
|
+
1. CSS animation utilities (no library needed):
|
|
345
|
+
- Fade in/out
|
|
346
|
+
- Slide in from directions
|
|
347
|
+
- Scale up/down
|
|
348
|
+
- Bounce, pulse, shake
|
|
349
|
+
- Stagger children animations
|
|
350
|
+
|
|
351
|
+
2. Animation wrapper components:
|
|
352
|
+
- <FadeIn> - fade in on mount
|
|
353
|
+
- <SlideIn direction="up|down|left|right">
|
|
354
|
+
- <ScaleIn> - scale from 0 to 1
|
|
355
|
+
- <AnimatePresence> - animate on unmount
|
|
356
|
+
- <StaggerChildren> - stagger child animations
|
|
357
|
+
|
|
358
|
+
3. CSS utilities:
|
|
359
|
+
- .animate-fade-in, .animate-slide-up, etc.
|
|
360
|
+
- Animation delay utilities
|
|
361
|
+
- Reduced motion media query support
|
|
362
|
+
- Duration and easing variables
|
|
363
|
+
|
|
364
|
+
4. Hooks:
|
|
365
|
+
- useInView() - trigger animation when element is visible
|
|
366
|
+
- useAnimation() - programmatic control
|
|
367
|
+
|
|
368
|
+
Create: src/styles/animations.css and src/components/ui/Animate.tsx
|
|
369
|
+
|
|
370
|
+
Or install framer-motion: npm install framer-motion`,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const cssFiles = await findAllFiles(searchPath, /\.(css|scss|tsx?|jsx?)$/);
|
|
375
|
+
let foundHoverStates = false;
|
|
376
|
+
for (const file of cssFiles.slice(0, 20)) {
|
|
377
|
+
const content = await readFileSafe(file);
|
|
378
|
+
if (content && /:hover|onMouseEnter|hover:/i.test(content)) {
|
|
379
|
+
foundHoverStates = true;
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (!foundHoverStates) {
|
|
384
|
+
issues.push({
|
|
385
|
+
id: "missing-hover-states",
|
|
386
|
+
category: "Frontend",
|
|
387
|
+
severity: "medium",
|
|
388
|
+
title: "Missing Hover States",
|
|
389
|
+
description: "No hover effects detected. Interactive elements need visual feedback on hover.",
|
|
390
|
+
suggestion: "Add hover states to buttons, links, and interactive elements.",
|
|
391
|
+
autoFixable: true,
|
|
392
|
+
aiPrompt: `Add comprehensive hover states to your components:
|
|
393
|
+
|
|
394
|
+
1. Button hover effects:
|
|
395
|
+
- Subtle background color shift
|
|
396
|
+
- Slight scale transform (1.02)
|
|
397
|
+
- Shadow elevation change
|
|
398
|
+
- Underline animation for text buttons
|
|
399
|
+
|
|
400
|
+
2. Card hover effects:
|
|
401
|
+
- Lift effect with shadow
|
|
402
|
+
- Border color change
|
|
403
|
+
- Subtle background shift
|
|
404
|
+
- Scale transform
|
|
405
|
+
|
|
406
|
+
3. Link hover effects:
|
|
407
|
+
- Underline animation (slide in)
|
|
408
|
+
- Color transition
|
|
409
|
+
- Arrow/icon movement
|
|
410
|
+
|
|
411
|
+
4. Interactive elements:
|
|
412
|
+
- Focus-visible states (keyboard users)
|
|
413
|
+
- Active/pressed states
|
|
414
|
+
- Disabled state styling
|
|
415
|
+
|
|
416
|
+
5. CSS utilities to add:
|
|
417
|
+
\`\`\`css
|
|
418
|
+
.hover-lift:hover {
|
|
419
|
+
transform: translateY(-2px);
|
|
420
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.hover-scale:hover {
|
|
424
|
+
transform: scale(1.02);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.hover-glow:hover {
|
|
428
|
+
box-shadow: 0 0 20px rgba(var(--primary-rgb), 0.3);
|
|
429
|
+
}
|
|
430
|
+
\`\`\`
|
|
431
|
+
|
|
432
|
+
Add to: src/styles/interactions.css or your global styles`,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// ── Haptic Feedback & Mobile UX ──────────────────────────────────────────
|
|
437
|
+
|
|
438
|
+
const hasHapticFeedback = await findFile(searchPath, /haptic|vibrate|navigator\.vibrate/i);
|
|
439
|
+
if (!hasHapticFeedback) {
|
|
440
|
+
issues.push({
|
|
441
|
+
id: "missing-haptic-feedback",
|
|
442
|
+
category: "Frontend",
|
|
443
|
+
severity: "low",
|
|
444
|
+
title: "Missing Haptic Feedback",
|
|
445
|
+
description: "No haptic feedback found. Mobile users benefit from tactile feedback on interactions.",
|
|
446
|
+
suggestion: "Add haptic feedback for key interactions on mobile.",
|
|
447
|
+
autoFixable: true,
|
|
448
|
+
aiPrompt: `Create a haptic feedback utility system:
|
|
449
|
+
|
|
450
|
+
1. useHaptic() hook:
|
|
451
|
+
\`\`\`typescript
|
|
452
|
+
const useHaptic = () => {
|
|
453
|
+
const trigger = (type: 'light' | 'medium' | 'heavy' | 'success' | 'error') => {
|
|
454
|
+
if (!navigator.vibrate) return;
|
|
455
|
+
const patterns = {
|
|
456
|
+
light: [10],
|
|
457
|
+
medium: [20],
|
|
458
|
+
heavy: [30],
|
|
459
|
+
success: [10, 50, 10],
|
|
460
|
+
error: [50, 30, 50, 30, 50],
|
|
461
|
+
};
|
|
462
|
+
navigator.vibrate(patterns[type]);
|
|
463
|
+
};
|
|
464
|
+
return { trigger };
|
|
465
|
+
};
|
|
466
|
+
\`\`\`
|
|
467
|
+
|
|
468
|
+
2. Integration points:
|
|
469
|
+
- Button clicks (light)
|
|
470
|
+
- Form submission success (success)
|
|
471
|
+
- Form validation error (error)
|
|
472
|
+
- Toggle switches (light)
|
|
473
|
+
- Pull-to-refresh complete (medium)
|
|
474
|
+
- Delete/destructive actions (heavy)
|
|
475
|
+
|
|
476
|
+
Create: src/hooks/useHaptic.ts`,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const hasPullToRefresh = await findFile(searchPath, /PullToRefresh|pull-to-refresh|usePullRefresh/i);
|
|
481
|
+
if (!hasPullToRefresh && packageJson && /react-native|mobile|pwa/i.test(packageJson)) {
|
|
482
|
+
issues.push({
|
|
483
|
+
id: "missing-pull-refresh",
|
|
484
|
+
category: "Frontend",
|
|
485
|
+
severity: "low",
|
|
486
|
+
title: "Missing Pull-to-Refresh",
|
|
487
|
+
description: "No pull-to-refresh found. Mobile/PWA apps benefit from this gesture.",
|
|
488
|
+
suggestion: "Add pull-to-refresh for mobile list views.",
|
|
489
|
+
autoFixable: true,
|
|
490
|
+
aiPrompt: `Create a pull-to-refresh component for mobile:
|
|
491
|
+
|
|
492
|
+
1. PullToRefresh wrapper component:
|
|
493
|
+
- Touch gesture detection
|
|
494
|
+
- Visual pull indicator
|
|
495
|
+
- Loading spinner during refresh
|
|
496
|
+
- Haptic feedback on trigger
|
|
497
|
+
- Smooth animations
|
|
498
|
+
|
|
499
|
+
2. Features:
|
|
500
|
+
- Configurable pull threshold
|
|
501
|
+
- Custom pull indicator
|
|
502
|
+
- Callback on refresh
|
|
503
|
+
- Disable on desktop
|
|
504
|
+
|
|
505
|
+
Create: src/components/ui/PullToRefresh.tsx`,
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// ── Accessibility (ARIA & A11Y) ──────────────────────────────────────────
|
|
510
|
+
|
|
511
|
+
const hasAriaLive = await findFile(searchPath, /aria-live|role="alert"|role="status"/i);
|
|
512
|
+
if (!hasAriaLive) {
|
|
513
|
+
issues.push({
|
|
514
|
+
id: "missing-aria-live",
|
|
515
|
+
category: "Frontend",
|
|
516
|
+
severity: "high",
|
|
517
|
+
title: "Missing ARIA Live Regions",
|
|
518
|
+
description: "No ARIA live regions found. Screen readers won't announce dynamic content changes.",
|
|
519
|
+
suggestion: "Add aria-live regions for toasts, alerts, and dynamic updates.",
|
|
520
|
+
autoFixable: true,
|
|
521
|
+
aiPrompt: `Add ARIA live regions for accessibility:
|
|
522
|
+
|
|
523
|
+
1. Create an Announcer component for screen readers:
|
|
524
|
+
\`\`\`tsx
|
|
525
|
+
const Announcer = () => {
|
|
526
|
+
const [message, setMessage] = useState('');
|
|
527
|
+
useEffect(() => {
|
|
528
|
+
window.announce = (msg: string) => setMessage(msg);
|
|
529
|
+
return () => delete window.announce;
|
|
530
|
+
}, []);
|
|
531
|
+
return (
|
|
532
|
+
<div role="status" aria-live="polite" aria-atomic="true" className="sr-only">
|
|
533
|
+
{message}
|
|
534
|
+
</div>
|
|
535
|
+
);
|
|
536
|
+
};
|
|
537
|
+
\`\`\`
|
|
538
|
+
|
|
539
|
+
2. Places to add aria-live:
|
|
540
|
+
- Toast notifications: aria-live="polite"
|
|
541
|
+
- Error alerts: aria-live="assertive"
|
|
542
|
+
- Loading states: aria-live="polite" aria-busy="true"
|
|
543
|
+
- Search results count
|
|
544
|
+
- Form validation errors
|
|
545
|
+
|
|
546
|
+
Create: src/components/ui/Announcer.tsx`,
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const hasFocusTrap = await findFile(searchPath, /FocusTrap|focus-trap|useFocusTrap/i);
|
|
551
|
+
const hasModal = await findFile(searchPath, /Modal|Dialog|Drawer/i);
|
|
552
|
+
if (hasModal && !hasFocusTrap) {
|
|
553
|
+
issues.push({
|
|
554
|
+
id: "missing-focus-trap",
|
|
555
|
+
category: "Frontend",
|
|
556
|
+
severity: "high",
|
|
557
|
+
title: "Missing Focus Trap for Modals",
|
|
558
|
+
description: "Modal/Dialog found but no focus trap. Keyboard users can tab outside the modal.",
|
|
559
|
+
suggestion: "Add focus trap to modals and dialogs.",
|
|
560
|
+
autoFixable: true,
|
|
561
|
+
aiPrompt: `Add focus trapping to modals and dialogs:
|
|
562
|
+
|
|
563
|
+
1. Create useFocusTrap hook that:
|
|
564
|
+
- Traps Tab/Shift+Tab within the modal
|
|
565
|
+
- Focuses first focusable element on open
|
|
566
|
+
- Returns focus to trigger element on close
|
|
567
|
+
- Handles Escape key to close
|
|
568
|
+
- Prevents body scroll when open
|
|
569
|
+
- Sets aria-modal="true" on modal
|
|
570
|
+
|
|
571
|
+
Create: src/hooks/useFocusTrap.ts`,
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
const hasSkipLink = await findFile(searchPath, /SkipLink|skip-to-content|skip-nav/i);
|
|
576
|
+
if (!hasSkipLink) {
|
|
577
|
+
issues.push({
|
|
578
|
+
id: "missing-skip-link",
|
|
579
|
+
category: "Frontend",
|
|
580
|
+
severity: "medium",
|
|
581
|
+
title: "Missing Skip Link",
|
|
582
|
+
description: "No skip-to-content link found. Keyboard users can't skip navigation.",
|
|
583
|
+
suggestion: "Add a skip-to-main-content link at the top of pages.",
|
|
584
|
+
autoFixable: true,
|
|
585
|
+
aiPrompt: `Add a skip link for keyboard navigation:
|
|
586
|
+
|
|
587
|
+
\`\`\`tsx
|
|
588
|
+
export const SkipLink = () => (
|
|
589
|
+
<a href="#main-content" className="skip-link">
|
|
590
|
+
Skip to main content
|
|
591
|
+
</a>
|
|
592
|
+
);
|
|
593
|
+
\`\`\`
|
|
594
|
+
|
|
595
|
+
Place at the very top of your layout, before the header.
|
|
596
|
+
Add id="main-content" to your <main> element.`,
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// ── Caching & Performance ────────────────────────────────────────────────
|
|
601
|
+
|
|
602
|
+
const hasSWR = packageJson && /swr|@tanstack\/react-query|react-query/i.test(packageJson);
|
|
603
|
+
if (!hasSWR) {
|
|
604
|
+
issues.push({
|
|
605
|
+
id: "missing-data-caching",
|
|
606
|
+
category: "Frontend",
|
|
607
|
+
severity: "high",
|
|
608
|
+
title: "Missing Data Caching Library",
|
|
609
|
+
description: "No SWR or React Query found. Data fetching lacks caching, revalidation, and deduplication.",
|
|
610
|
+
suggestion: "Add SWR or TanStack Query for data caching and synchronization.",
|
|
611
|
+
autoFixable: false,
|
|
612
|
+
aiPrompt: `Add a data fetching and caching solution:
|
|
613
|
+
|
|
614
|
+
Option 1: SWR (lighter weight) - npm install swr
|
|
615
|
+
Option 2: TanStack Query (more features) - npm install @tanstack/react-query
|
|
616
|
+
|
|
617
|
+
Benefits: automatic caching, background revalidation, request deduplication, optimistic updates, offline support, retry logic.`,
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
const hasMemoization = await findFile(searchPath, /useMemo|useCallback|React\.memo/i);
|
|
622
|
+
if (!hasMemoization) {
|
|
623
|
+
issues.push({
|
|
624
|
+
id: "missing-memoization",
|
|
625
|
+
category: "Frontend",
|
|
626
|
+
severity: "low",
|
|
627
|
+
title: "No Memoization Detected",
|
|
628
|
+
description: "No useMemo/useCallback/React.memo usage found. May have unnecessary re-renders.",
|
|
629
|
+
suggestion: "Review components for memoization opportunities.",
|
|
630
|
+
autoFixable: false,
|
|
631
|
+
aiPrompt: `Review components for memoization opportunities:
|
|
632
|
+
- useMemo for expensive calculations
|
|
633
|
+
- useCallback for functions passed as props
|
|
634
|
+
- React.memo for components receiving same props
|
|
635
|
+
Focus on: list items, charts, components receiving objects/arrays as props.`,
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// ── Logging & Debugging ──────────────────────────────────────────────────
|
|
640
|
+
|
|
641
|
+
const hasLogger = await findFile(searchPath, /logger|logging|winston|pino|loglevel/i);
|
|
642
|
+
if (!hasLogger) {
|
|
643
|
+
issues.push({
|
|
644
|
+
id: "missing-frontend-logger",
|
|
645
|
+
category: "Frontend",
|
|
646
|
+
severity: "medium",
|
|
647
|
+
title: "Missing Logging System",
|
|
648
|
+
description: "No structured logging found. console.log statements are not suitable for production.",
|
|
649
|
+
suggestion: "Add a logging utility that can be disabled in production.",
|
|
650
|
+
autoFixable: true,
|
|
651
|
+
aiPrompt: `Create a frontend logging utility (lib/logger.ts) with:
|
|
652
|
+
- Log levels: debug, info, warn, error
|
|
653
|
+
- Silent in production (except warn/error)
|
|
654
|
+
- Error-level logs sent to error tracking service
|
|
655
|
+
- Performance timing helpers (time/timeEnd)
|
|
656
|
+
- Group logging support`,
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
const hasErrorTracking =
|
|
661
|
+
packageJson && /sentry|bugsnag|rollbar|logrocket|@sentry/i.test(packageJson);
|
|
662
|
+
if (!hasErrorTracking) {
|
|
663
|
+
issues.push({
|
|
664
|
+
id: "missing-error-tracking",
|
|
665
|
+
category: "Frontend",
|
|
666
|
+
severity: "high",
|
|
667
|
+
title: "Missing Error Tracking",
|
|
668
|
+
description: "No error tracking service found. Production errors will go unnoticed.",
|
|
669
|
+
suggestion: "Add Sentry, Bugsnag, or similar for production error monitoring.",
|
|
670
|
+
autoFixable: false,
|
|
671
|
+
aiPrompt: `Set up error tracking with Sentry:
|
|
672
|
+
1. npm install @sentry/nextjs
|
|
673
|
+
2. npx @sentry/wizard@latest -i nextjs
|
|
674
|
+
3. Configure SENTRY_DSN and SENTRY_AUTH_TOKEN env vars
|
|
675
|
+
4. Integrate with error boundary
|
|
676
|
+
5. Set user context on auth`,
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// ── Image & Media Optimization ───────────────────────────────────────────
|
|
681
|
+
|
|
682
|
+
const hasLazyImages = await findFile(searchPath, /loading="lazy"|LazyImage|Image.*priority/i);
|
|
683
|
+
if (!hasLazyImages) {
|
|
684
|
+
issues.push({
|
|
685
|
+
id: "missing-lazy-images",
|
|
686
|
+
category: "Frontend",
|
|
687
|
+
severity: "medium",
|
|
688
|
+
title: "Missing Lazy Loading for Images",
|
|
689
|
+
description: "No lazy loading for images detected. All images load immediately.",
|
|
690
|
+
suggestion: "Add lazy loading to below-the-fold images.",
|
|
691
|
+
autoFixable: true,
|
|
692
|
+
aiPrompt: `Implement lazy loading for images:
|
|
693
|
+
- Next.js: Use next/image (lazy by default, add priority for above-fold)
|
|
694
|
+
- Regular img: Add loading="lazy" decoding="async"
|
|
695
|
+
- Create a LazyImage wrapper component`,
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// ── Theme & Dark Mode ────────────────────────────────────────────────────
|
|
700
|
+
|
|
701
|
+
const hasDarkMode = await findFile(searchPath, /dark-mode|darkMode|theme-toggle|ThemeProvider|useTheme/i);
|
|
702
|
+
if (!hasDarkMode) {
|
|
703
|
+
issues.push({
|
|
704
|
+
id: "missing-dark-mode",
|
|
705
|
+
category: "Frontend",
|
|
706
|
+
severity: "low",
|
|
707
|
+
title: "Missing Dark Mode Support",
|
|
708
|
+
description: "No dark mode implementation found. Many users prefer dark mode.",
|
|
709
|
+
suggestion: "Add dark mode toggle with system preference detection.",
|
|
710
|
+
autoFixable: true,
|
|
711
|
+
aiPrompt: `Implement dark mode with system preference detection:
|
|
712
|
+
1. ThemeProvider context + useTheme hook
|
|
713
|
+
2. CSS variables for light/dark themes
|
|
714
|
+
3. System preference detection via prefers-color-scheme
|
|
715
|
+
4. Persist choice in localStorage
|
|
716
|
+
5. Theme toggle component`,
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// ── Confirmation & Destructive Actions ───────────────────────────────────
|
|
721
|
+
|
|
722
|
+
const hasConfirmDialog = await findFile(searchPath, /ConfirmDialog|Confirm|AlertDialog|useConfirm/i);
|
|
723
|
+
if (!hasConfirmDialog) {
|
|
724
|
+
issues.push({
|
|
725
|
+
id: "missing-confirm-dialog",
|
|
726
|
+
category: "Frontend",
|
|
727
|
+
severity: "high",
|
|
728
|
+
title: "Missing Confirmation Dialog",
|
|
729
|
+
description: "No confirmation dialog found. Destructive actions should require confirmation.",
|
|
730
|
+
suggestion: "Add a confirmation dialog for delete, logout, and irreversible actions.",
|
|
731
|
+
autoFixable: true,
|
|
732
|
+
aiPrompt: `Create a confirmation dialog system:
|
|
733
|
+
1. ConfirmDialog component with danger/warning/info variants
|
|
734
|
+
2. useConfirm() hook returning a promise-based API:
|
|
735
|
+
const shouldDelete = await confirm({ title: 'Delete?', message: '...' });
|
|
736
|
+
3. Loading state support on confirm button
|
|
737
|
+
4. Focus trap and keyboard handling`,
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// ── Optimistic Updates ───────────────────────────────────────────────────
|
|
742
|
+
|
|
743
|
+
const hasOptimisticUpdates = await findFile(searchPath, /optimistic|mutate.*onMutate|useMutation/i);
|
|
744
|
+
if (!hasOptimisticUpdates && hasSWR) {
|
|
745
|
+
issues.push({
|
|
746
|
+
id: "missing-optimistic-updates",
|
|
747
|
+
category: "Frontend",
|
|
748
|
+
severity: "low",
|
|
749
|
+
title: "No Optimistic Updates",
|
|
750
|
+
description: "Data mutations may feel slow without optimistic updates.",
|
|
751
|
+
suggestion: "Add optimistic updates for better perceived performance.",
|
|
752
|
+
autoFixable: false,
|
|
753
|
+
aiPrompt: `Implement optimistic updates for mutations with SWR or TanStack Query.
|
|
754
|
+
Pattern: update cache immediately, send request, revert on error.`,
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// ── Keyboard Shortcuts ───────────────────────────────────────────────────
|
|
759
|
+
|
|
760
|
+
const hasKeyboardShortcuts = await findFile(searchPath, /useHotkeys|Keyboard|shortcut|Cmd\+|Ctrl\+/i);
|
|
761
|
+
if (!hasKeyboardShortcuts) {
|
|
762
|
+
issues.push({
|
|
763
|
+
id: "missing-keyboard-shortcuts",
|
|
764
|
+
category: "Frontend",
|
|
765
|
+
severity: "low",
|
|
766
|
+
title: "Missing Keyboard Shortcuts",
|
|
767
|
+
description: "No keyboard shortcuts detected. Power users benefit from keyboard navigation.",
|
|
768
|
+
suggestion: "Add keyboard shortcuts for common actions.",
|
|
769
|
+
autoFixable: true,
|
|
770
|
+
aiPrompt: `Implement keyboard shortcuts:
|
|
771
|
+
1. useHotkey hook with cross-platform Cmd/Ctrl support
|
|
772
|
+
2. Common shortcuts: Cmd+K (search), Cmd+S (save), Escape (close), ? (help)
|
|
773
|
+
3. Display shortcut hints in UI via <kbd> elements`,
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// ── Scroll Behavior ──────────────────────────────────────────────────────
|
|
778
|
+
|
|
779
|
+
const hasScrollToTop = await findFile(searchPath, /ScrollToTop|scroll-to-top|BackToTop/i);
|
|
780
|
+
if (!hasScrollToTop) {
|
|
781
|
+
issues.push({
|
|
782
|
+
id: "missing-scroll-to-top",
|
|
783
|
+
category: "Frontend",
|
|
784
|
+
severity: "low",
|
|
785
|
+
title: "Missing Scroll-to-Top Button",
|
|
786
|
+
description: "No scroll-to-top button found. Long pages need easy navigation back to top.",
|
|
787
|
+
suggestion: "Add a scroll-to-top button for long pages.",
|
|
788
|
+
autoFixable: true,
|
|
789
|
+
aiPrompt: `Create a scroll-to-top button:
|
|
790
|
+
- Show after scrolling 500px
|
|
791
|
+
- Smooth scroll animation
|
|
792
|
+
- Fixed position bottom-right
|
|
793
|
+
- Accessible with aria-label`,
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// ── Progress Indicators ──────────────────────────────────────────────────
|
|
798
|
+
|
|
799
|
+
const hasProgressBar = await findFile(searchPath, /Progress|ProgressBar|NProgress|nprogress/i);
|
|
800
|
+
if (!hasProgressBar) {
|
|
801
|
+
issues.push({
|
|
802
|
+
id: "missing-progress-bar",
|
|
803
|
+
category: "Frontend",
|
|
804
|
+
severity: "medium",
|
|
805
|
+
title: "Missing Progress Indicators",
|
|
806
|
+
description: "No progress bar found. Users need visual feedback for page transitions and uploads.",
|
|
807
|
+
suggestion: "Add progress bar for navigation and long operations.",
|
|
808
|
+
autoFixable: true,
|
|
809
|
+
aiPrompt: `Add progress indicators:
|
|
810
|
+
1. NProgress-style page transition bar (npm install nprogress)
|
|
811
|
+
2. Custom ProgressBar component with role="progressbar"
|
|
812
|
+
3. File upload progress indicator`,
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
return issues;
|
|
817
|
+
};
|