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,1060 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vibecheck polish --cleanup Safe Rule Set
|
|
3
|
+
*
|
|
4
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
* PRODUCTION-GRADE CLEANUP WITHOUT CHAOS
|
|
6
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
7
|
+
*
|
|
8
|
+
* Safe transformations that improve code quality without surprise refactors.
|
|
9
|
+
*
|
|
10
|
+
* Design principles:
|
|
11
|
+
* - Safe by default: Only transformations that cannot change behavior
|
|
12
|
+
* - Aggressive opt-in: Requires explicit --aggressive --yes-i-am-sure
|
|
13
|
+
* - Checkpoint integration: Automatic backup before any changes
|
|
14
|
+
* - Transparent: Full diff preview before applying
|
|
15
|
+
*
|
|
16
|
+
* Rule structure:
|
|
17
|
+
* - id: Unique identifier for the rule
|
|
18
|
+
* - name: Human-readable name
|
|
19
|
+
* - description: What this rule detects
|
|
20
|
+
* - severity: critical | high | medium | low | info
|
|
21
|
+
* - pattern: RegExp or function(content, filePath) => Match[]
|
|
22
|
+
* - fix: string | function(match) => string | null (null = flag only)
|
|
23
|
+
* - riskLevel: safe | moderate | aggressive
|
|
24
|
+
* - category: Category for grouping in output
|
|
25
|
+
* - autoFixable: Whether this can be auto-fixed
|
|
26
|
+
* - fileTypes: Array of extensions this applies to (optional, defaults to all)
|
|
27
|
+
* - exclude: Array of path patterns to exclude (optional)
|
|
28
|
+
* - aiPrompt: Prompt for AI to fix this issue (optional)
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
"use strict";
|
|
32
|
+
|
|
33
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
34
|
+
// HELPER FUNCTIONS FOR COMPLEX PATTERNS
|
|
35
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create a pattern that handles nested parentheses in console statements
|
|
39
|
+
* This is more robust than simple regex for console.log(complex(nested(args)))
|
|
40
|
+
*/
|
|
41
|
+
function createConsolePattern(method) {
|
|
42
|
+
return {
|
|
43
|
+
type: "function",
|
|
44
|
+
fn: (content) => {
|
|
45
|
+
const matches = [];
|
|
46
|
+
const regex = new RegExp(`console\\.${method}\\s*\\(`, "g");
|
|
47
|
+
let match;
|
|
48
|
+
|
|
49
|
+
while ((match = regex.exec(content)) !== null) {
|
|
50
|
+
const startIndex = match.index;
|
|
51
|
+
let depth = 1;
|
|
52
|
+
let i = match.index + match[0].length;
|
|
53
|
+
|
|
54
|
+
// Find matching closing parenthesis
|
|
55
|
+
while (i < content.length && depth > 0) {
|
|
56
|
+
if (content[i] === "(") depth++;
|
|
57
|
+
else if (content[i] === ")") depth--;
|
|
58
|
+
i++;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Include trailing semicolon if present
|
|
62
|
+
if (content[i] === ";") i++;
|
|
63
|
+
|
|
64
|
+
// Only add if we found the closing paren
|
|
65
|
+
if (depth === 0) {
|
|
66
|
+
matches.push({
|
|
67
|
+
index: startIndex,
|
|
68
|
+
length: i - startIndex,
|
|
69
|
+
match: content.substring(startIndex, i),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return matches;
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Detect empty catch blocks more accurately
|
|
81
|
+
*/
|
|
82
|
+
function detectEmptyCatch(content) {
|
|
83
|
+
const matches = [];
|
|
84
|
+
// Match catch blocks - handles various formatting
|
|
85
|
+
const regex = /catch\s*\(\s*(\w+)?\s*\)\s*\{([^}]*)\}/g;
|
|
86
|
+
let match;
|
|
87
|
+
|
|
88
|
+
while ((match = regex.exec(content)) !== null) {
|
|
89
|
+
const body = match[2].trim();
|
|
90
|
+
// Empty if only whitespace, comments, or nothing
|
|
91
|
+
const isEmpty = body === "" || /^(\s*\/\/[^\n]*\s*|\s*\/\*[\s\S]*?\*\/\s*)*$/.test(body);
|
|
92
|
+
|
|
93
|
+
if (isEmpty) {
|
|
94
|
+
matches.push({
|
|
95
|
+
index: match.index,
|
|
96
|
+
length: match[0].length,
|
|
97
|
+
match: match[0],
|
|
98
|
+
catchVar: match[1] || "error",
|
|
99
|
+
body: body,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return matches;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Detect potentially unsafe regex patterns (ReDoS)
|
|
109
|
+
*/
|
|
110
|
+
function detectUnsafeRegex(content) {
|
|
111
|
+
const matches = [];
|
|
112
|
+
// Find regex literals and RegExp constructors
|
|
113
|
+
const regexLiteralPattern = /\/(?![*\/])(?:[^\\/\[\n]|\\.|\[(?:[^\\\]\n]|\\.)*\])+\/[gimsuvy]*/g;
|
|
114
|
+
const regexConstructorPattern = /new\s+RegExp\s*\(\s*(['"`])(.+?)\1/g;
|
|
115
|
+
|
|
116
|
+
const dangerousPatterns = [
|
|
117
|
+
/\([^)]*\+\)\+/, // (a+)+
|
|
118
|
+
/\([^)]*\*\)\+/, // (a*)+
|
|
119
|
+
/\([^)]*\+\)\*/, // (a+)*
|
|
120
|
+
/\([^)]*\*\)\*/, // (a*)*
|
|
121
|
+
/\.\*[^?].*\.\*/, // .* followed by .* (greedy)
|
|
122
|
+
/\([^)]+\|[^)]+\)\+/, // (a|b)+ with overlapping
|
|
123
|
+
/\\d\+.*\\d\+/, // \d+...\d+ backtracking
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
let match;
|
|
127
|
+
|
|
128
|
+
// Check regex literals
|
|
129
|
+
while ((match = regexLiteralPattern.exec(content)) !== null) {
|
|
130
|
+
const regexStr = match[0];
|
|
131
|
+
for (const dangerous of dangerousPatterns) {
|
|
132
|
+
if (dangerous.test(regexStr)) {
|
|
133
|
+
matches.push({
|
|
134
|
+
index: match.index,
|
|
135
|
+
length: match[0].length,
|
|
136
|
+
match: match[0],
|
|
137
|
+
reason: "Potential ReDoS: nested quantifiers or overlapping patterns",
|
|
138
|
+
});
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Check RegExp constructors
|
|
145
|
+
while ((match = regexConstructorPattern.exec(content)) !== null) {
|
|
146
|
+
const regexStr = match[2];
|
|
147
|
+
for (const dangerous of dangerousPatterns) {
|
|
148
|
+
if (dangerous.test(regexStr)) {
|
|
149
|
+
matches.push({
|
|
150
|
+
index: match.index,
|
|
151
|
+
length: match[0].length,
|
|
152
|
+
match: match[0],
|
|
153
|
+
reason: "Potential ReDoS: nested quantifiers or overlapping patterns",
|
|
154
|
+
});
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return matches;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
164
|
+
// SAFE RULES - Cannot change program behavior
|
|
165
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Safe rules that can be auto-applied without confirmation.
|
|
169
|
+
* These transformations are guaranteed to not change program behavior.
|
|
170
|
+
*/
|
|
171
|
+
const SAFE_RULES = {
|
|
172
|
+
// ─────────────────────────────────────────────────────────────
|
|
173
|
+
// Console statements (safe to remove in production)
|
|
174
|
+
// Uses function-based detection for proper parenthesis matching
|
|
175
|
+
// ─────────────────────────────────────────────────────────────
|
|
176
|
+
"console-log": {
|
|
177
|
+
id: "console-log",
|
|
178
|
+
name: "console.log statements",
|
|
179
|
+
description: "Remove console.log statements (debug leftovers)",
|
|
180
|
+
severity: "low",
|
|
181
|
+
pattern: createConsolePattern("log"),
|
|
182
|
+
fix: "",
|
|
183
|
+
riskLevel: "safe",
|
|
184
|
+
category: "debug-cleanup",
|
|
185
|
+
autoFixable: true,
|
|
186
|
+
exclude: ["*.test.*", "*.spec.*", "**/__tests__/**", "**/test/**"],
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
"console-debug": {
|
|
190
|
+
id: "console-debug",
|
|
191
|
+
name: "console.debug statements",
|
|
192
|
+
description: "Remove console.debug statements",
|
|
193
|
+
severity: "low",
|
|
194
|
+
pattern: createConsolePattern("debug"),
|
|
195
|
+
fix: "",
|
|
196
|
+
riskLevel: "safe",
|
|
197
|
+
category: "debug-cleanup",
|
|
198
|
+
autoFixable: true,
|
|
199
|
+
exclude: ["*.test.*", "*.spec.*"],
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
"console-info": {
|
|
203
|
+
id: "console-info",
|
|
204
|
+
name: "console.info statements",
|
|
205
|
+
description: "Remove console.info statements",
|
|
206
|
+
severity: "low",
|
|
207
|
+
pattern: createConsolePattern("info"),
|
|
208
|
+
fix: "",
|
|
209
|
+
riskLevel: "safe",
|
|
210
|
+
category: "debug-cleanup",
|
|
211
|
+
autoFixable: true,
|
|
212
|
+
exclude: ["*.test.*", "*.spec.*"],
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
"console-trace": {
|
|
216
|
+
id: "console-trace",
|
|
217
|
+
name: "console.trace statements",
|
|
218
|
+
description: "Remove console.trace statements",
|
|
219
|
+
severity: "low",
|
|
220
|
+
pattern: createConsolePattern("trace"),
|
|
221
|
+
fix: "",
|
|
222
|
+
riskLevel: "safe",
|
|
223
|
+
category: "debug-cleanup",
|
|
224
|
+
autoFixable: true,
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
"console-dir": {
|
|
228
|
+
id: "console-dir",
|
|
229
|
+
name: "console.dir statements",
|
|
230
|
+
description: "Remove console.dir statements",
|
|
231
|
+
severity: "low",
|
|
232
|
+
pattern: createConsolePattern("dir"),
|
|
233
|
+
fix: "",
|
|
234
|
+
riskLevel: "safe",
|
|
235
|
+
category: "debug-cleanup",
|
|
236
|
+
autoFixable: true,
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
"console-table": {
|
|
240
|
+
id: "console-table",
|
|
241
|
+
name: "console.table statements",
|
|
242
|
+
description: "Remove console.table statements",
|
|
243
|
+
severity: "low",
|
|
244
|
+
pattern: createConsolePattern("table"),
|
|
245
|
+
fix: "",
|
|
246
|
+
riskLevel: "safe",
|
|
247
|
+
category: "debug-cleanup",
|
|
248
|
+
autoFixable: true,
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
"console-time": {
|
|
252
|
+
id: "console-time",
|
|
253
|
+
name: "console.time/timeEnd statements",
|
|
254
|
+
description: "Remove console.time/timeEnd statements (profiling)",
|
|
255
|
+
severity: "low",
|
|
256
|
+
pattern: createConsolePattern("time(?:End|Log)?"),
|
|
257
|
+
fix: "",
|
|
258
|
+
riskLevel: "safe",
|
|
259
|
+
category: "debug-cleanup",
|
|
260
|
+
autoFixable: true,
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
"console-count": {
|
|
264
|
+
id: "console-count",
|
|
265
|
+
name: "console.count statements",
|
|
266
|
+
description: "Remove console.count/countReset statements",
|
|
267
|
+
severity: "low",
|
|
268
|
+
pattern: createConsolePattern("count(?:Reset)?"),
|
|
269
|
+
fix: "",
|
|
270
|
+
riskLevel: "safe",
|
|
271
|
+
category: "debug-cleanup",
|
|
272
|
+
autoFixable: true,
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
"console-group": {
|
|
276
|
+
id: "console-group",
|
|
277
|
+
name: "console.group statements",
|
|
278
|
+
description: "Remove console.group/groupEnd statements",
|
|
279
|
+
severity: "low",
|
|
280
|
+
pattern: createConsolePattern("group(?:End|Collapsed)?"),
|
|
281
|
+
fix: "",
|
|
282
|
+
riskLevel: "safe",
|
|
283
|
+
category: "debug-cleanup",
|
|
284
|
+
autoFixable: true,
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
"console-clear": {
|
|
288
|
+
id: "console-clear",
|
|
289
|
+
name: "console.clear statements",
|
|
290
|
+
description: "Remove console.clear statements",
|
|
291
|
+
severity: "low",
|
|
292
|
+
pattern: createConsolePattern("clear"),
|
|
293
|
+
fix: "",
|
|
294
|
+
riskLevel: "safe",
|
|
295
|
+
category: "debug-cleanup",
|
|
296
|
+
autoFixable: true,
|
|
297
|
+
},
|
|
298
|
+
|
|
299
|
+
"console-profile": {
|
|
300
|
+
id: "console-profile",
|
|
301
|
+
name: "console.profile statements",
|
|
302
|
+
description: "Remove console.profile/profileEnd statements",
|
|
303
|
+
severity: "low",
|
|
304
|
+
pattern: createConsolePattern("profile(?:End)?"),
|
|
305
|
+
fix: "",
|
|
306
|
+
riskLevel: "safe",
|
|
307
|
+
category: "debug-cleanup",
|
|
308
|
+
autoFixable: true,
|
|
309
|
+
},
|
|
310
|
+
|
|
311
|
+
// ─────────────────────────────────────────────────────────────
|
|
312
|
+
// Debug artifacts
|
|
313
|
+
// ─────────────────────────────────────────────────────────────
|
|
314
|
+
"debugger-statement": {
|
|
315
|
+
id: "debugger-statement",
|
|
316
|
+
name: "debugger statements",
|
|
317
|
+
description: "Remove debugger statements (stops execution in dev tools)",
|
|
318
|
+
severity: "high",
|
|
319
|
+
pattern: /(?:^|[;\s{])(debugger)\s*;?/gm,
|
|
320
|
+
fix: "",
|
|
321
|
+
riskLevel: "safe",
|
|
322
|
+
category: "debug-cleanup",
|
|
323
|
+
autoFixable: true,
|
|
324
|
+
},
|
|
325
|
+
|
|
326
|
+
// ─────────────────────────────────────────────────────────────
|
|
327
|
+
// Trailing whitespace and formatting
|
|
328
|
+
// ─────────────────────────────────────────────────────────────
|
|
329
|
+
"trailing-whitespace": {
|
|
330
|
+
id: "trailing-whitespace",
|
|
331
|
+
name: "Trailing whitespace",
|
|
332
|
+
description: "Remove trailing whitespace at end of lines",
|
|
333
|
+
severity: "info",
|
|
334
|
+
pattern: /[ \t]+$/gm,
|
|
335
|
+
fix: "",
|
|
336
|
+
riskLevel: "safe",
|
|
337
|
+
category: "formatting",
|
|
338
|
+
autoFixable: true,
|
|
339
|
+
},
|
|
340
|
+
|
|
341
|
+
"multiple-empty-lines": {
|
|
342
|
+
id: "multiple-empty-lines",
|
|
343
|
+
name: "Multiple consecutive empty lines",
|
|
344
|
+
description: "Collapse multiple empty lines into single empty line",
|
|
345
|
+
severity: "info",
|
|
346
|
+
pattern: /\n{3,}/g,
|
|
347
|
+
fix: "\n\n",
|
|
348
|
+
riskLevel: "safe",
|
|
349
|
+
category: "formatting",
|
|
350
|
+
autoFixable: true,
|
|
351
|
+
},
|
|
352
|
+
|
|
353
|
+
"trailing-newlines": {
|
|
354
|
+
id: "trailing-newlines",
|
|
355
|
+
name: "Multiple trailing newlines",
|
|
356
|
+
description: "Ensure file ends with exactly one newline",
|
|
357
|
+
severity: "info",
|
|
358
|
+
pattern: /\n{2,}$/,
|
|
359
|
+
fix: "\n",
|
|
360
|
+
riskLevel: "safe",
|
|
361
|
+
category: "formatting",
|
|
362
|
+
autoFixable: true,
|
|
363
|
+
},
|
|
364
|
+
|
|
365
|
+
"no-final-newline": {
|
|
366
|
+
id: "no-final-newline",
|
|
367
|
+
name: "Missing final newline",
|
|
368
|
+
description: "Ensure file ends with a newline (POSIX compliance)",
|
|
369
|
+
severity: "info",
|
|
370
|
+
pattern: {
|
|
371
|
+
type: "function",
|
|
372
|
+
fn: (content) => {
|
|
373
|
+
if (content.length > 0 && !content.endsWith("\n")) {
|
|
374
|
+
return [{
|
|
375
|
+
index: content.length,
|
|
376
|
+
length: 0,
|
|
377
|
+
match: "",
|
|
378
|
+
insertAfter: "\n",
|
|
379
|
+
}];
|
|
380
|
+
}
|
|
381
|
+
return [];
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
fix: null, // Handled by insertAfter
|
|
385
|
+
riskLevel: "safe",
|
|
386
|
+
category: "formatting",
|
|
387
|
+
autoFixable: true,
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
392
|
+
// MODERATE RULES - Low risk, but worth reviewing
|
|
393
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Moderate rules that are generally safe but warrant review.
|
|
397
|
+
* Applied by default but included in diff summary for review.
|
|
398
|
+
*/
|
|
399
|
+
const MODERATE_RULES = {
|
|
400
|
+
// ─────────────────────────────────────────────────────────────
|
|
401
|
+
// Empty blocks
|
|
402
|
+
// ─────────────────────────────────────────────────────────────
|
|
403
|
+
"empty-catch-silent": {
|
|
404
|
+
id: "empty-catch-silent",
|
|
405
|
+
name: "Empty catch blocks (silent failures)",
|
|
406
|
+
description: "Catch blocks that swallow errors without any handling",
|
|
407
|
+
severity: "high",
|
|
408
|
+
pattern: {
|
|
409
|
+
type: "function",
|
|
410
|
+
fn: detectEmptyCatch,
|
|
411
|
+
},
|
|
412
|
+
suggestedFix: "Add error logging: console.error(error) or proper error handling",
|
|
413
|
+
riskLevel: "moderate",
|
|
414
|
+
category: "error-handling",
|
|
415
|
+
autoFixable: false, // Flag, don't auto-fix (behavior change)
|
|
416
|
+
aiPrompt: `Add appropriate error handling to this empty catch block. Options:
|
|
417
|
+
1. Log the error: console.error('Operation failed:', error);
|
|
418
|
+
2. Re-throw with context: throw new Error('Context: ' + error.message);
|
|
419
|
+
3. Handle gracefully with fallback behavior
|
|
420
|
+
4. If intentionally ignoring, add comment: // Intentionally ignoring error`,
|
|
421
|
+
},
|
|
422
|
+
|
|
423
|
+
"empty-function": {
|
|
424
|
+
id: "empty-function",
|
|
425
|
+
name: "Empty functions",
|
|
426
|
+
description: "Functions with no implementation (potential stub)",
|
|
427
|
+
severity: "medium",
|
|
428
|
+
pattern: /(?:async\s+)?function\s+\w+\s*\([^)]*\)\s*\{\s*\}|(?:const|let|var)\s+\w+\s*=\s*(?:async\s*)?\([^)]*\)\s*=>\s*\{\s*\}/g,
|
|
429
|
+
suggestedFix: "Implement function or add TODO comment explaining why it's empty",
|
|
430
|
+
riskLevel: "moderate",
|
|
431
|
+
category: "code-quality",
|
|
432
|
+
autoFixable: false,
|
|
433
|
+
aiPrompt: "This function has no implementation. Either implement it or add a comment explaining why it's a stub.",
|
|
434
|
+
},
|
|
435
|
+
|
|
436
|
+
"empty-if-block": {
|
|
437
|
+
id: "empty-if-block",
|
|
438
|
+
name: "Empty if blocks",
|
|
439
|
+
description: "If statements with empty bodies",
|
|
440
|
+
severity: "medium",
|
|
441
|
+
pattern: /if\s*\([^)]+\)\s*\{\s*\}/g,
|
|
442
|
+
suggestedFix: "Add implementation or remove the empty if block",
|
|
443
|
+
riskLevel: "moderate",
|
|
444
|
+
category: "code-quality",
|
|
445
|
+
autoFixable: false,
|
|
446
|
+
},
|
|
447
|
+
|
|
448
|
+
"empty-else-block": {
|
|
449
|
+
id: "empty-else-block",
|
|
450
|
+
name: "Empty else blocks",
|
|
451
|
+
description: "Else statements with empty bodies",
|
|
452
|
+
severity: "low",
|
|
453
|
+
pattern: /else\s*\{\s*\}/g,
|
|
454
|
+
suggestedFix: "Add implementation or remove the empty else block",
|
|
455
|
+
riskLevel: "moderate",
|
|
456
|
+
category: "code-quality",
|
|
457
|
+
autoFixable: false,
|
|
458
|
+
},
|
|
459
|
+
|
|
460
|
+
// ─────────────────────────────────────────────────────────────
|
|
461
|
+
// Code hygiene markers
|
|
462
|
+
// ─────────────────────────────────────────────────────────────
|
|
463
|
+
"todo-fixme-comments": {
|
|
464
|
+
id: "todo-fixme-comments",
|
|
465
|
+
name: "TODO/FIXME comments",
|
|
466
|
+
description: "Flag TODO/FIXME comments that should be addressed before shipping",
|
|
467
|
+
severity: "low",
|
|
468
|
+
pattern: /\/\/\s*(TODO|FIXME|HACK|XXX|BUG|OPTIMIZE|REFACTOR):?[^\n]*/gi,
|
|
469
|
+
fix: null, // Don't auto-remove, just flag
|
|
470
|
+
riskLevel: "moderate",
|
|
471
|
+
category: "code-hygiene",
|
|
472
|
+
autoFixable: false,
|
|
473
|
+
},
|
|
474
|
+
|
|
475
|
+
"eslint-disable-line": {
|
|
476
|
+
id: "eslint-disable-line",
|
|
477
|
+
name: "ESLint disable comments",
|
|
478
|
+
description: "Comments disabling ESLint rules - review if still needed",
|
|
479
|
+
severity: "low",
|
|
480
|
+
pattern: /\/\/\s*eslint-disable(?:-next)?-line[^\n]*/gi,
|
|
481
|
+
riskLevel: "moderate",
|
|
482
|
+
category: "code-hygiene",
|
|
483
|
+
autoFixable: false,
|
|
484
|
+
aiPrompt: "Review this ESLint disable comment. Can the underlying issue be fixed instead of suppressing the warning?",
|
|
485
|
+
},
|
|
486
|
+
|
|
487
|
+
"ts-ignore-comment": {
|
|
488
|
+
id: "ts-ignore-comment",
|
|
489
|
+
name: "@ts-ignore comments",
|
|
490
|
+
description: "@ts-ignore comments suppress TypeScript errors - review if still needed",
|
|
491
|
+
severity: "medium",
|
|
492
|
+
pattern: /\/\/\s*@ts-(?:ignore|nocheck|expect-error)[^\n]*/gi,
|
|
493
|
+
riskLevel: "moderate",
|
|
494
|
+
category: "code-hygiene",
|
|
495
|
+
autoFixable: false,
|
|
496
|
+
aiPrompt: "Review this TypeScript suppression comment. Can the type error be fixed properly instead?",
|
|
497
|
+
},
|
|
498
|
+
|
|
499
|
+
// ─────────────────────────────────────────────────────────────
|
|
500
|
+
// Potential dead code patterns
|
|
501
|
+
// ─────────────────────────────────────────────────────────────
|
|
502
|
+
"unreachable-after-return": {
|
|
503
|
+
id: "unreachable-after-return",
|
|
504
|
+
name: "Code after return/throw",
|
|
505
|
+
description: "Code that appears after return/throw statement in same block",
|
|
506
|
+
severity: "medium",
|
|
507
|
+
pattern: {
|
|
508
|
+
type: "function",
|
|
509
|
+
fn: (content) => {
|
|
510
|
+
const matches = [];
|
|
511
|
+
// Match return/throw followed by non-closing-brace code
|
|
512
|
+
const regex = /(?:return\s+[^;]+;|throw\s+[^;]+;)\s*\n\s*(?![\s}]*(?:\}|case\s|default:|else|catch|finally))[^\s}][^\n]+/g;
|
|
513
|
+
let match;
|
|
514
|
+
while ((match = regex.exec(content)) !== null) {
|
|
515
|
+
matches.push({
|
|
516
|
+
index: match.index,
|
|
517
|
+
length: match[0].length,
|
|
518
|
+
match: match[0],
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
return matches;
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
riskLevel: "moderate",
|
|
525
|
+
category: "dead-code",
|
|
526
|
+
autoFixable: false,
|
|
527
|
+
},
|
|
528
|
+
|
|
529
|
+
"constant-condition": {
|
|
530
|
+
id: "constant-condition",
|
|
531
|
+
name: "Constant conditions",
|
|
532
|
+
description: "If statements with constant true/false conditions",
|
|
533
|
+
severity: "medium",
|
|
534
|
+
pattern: /if\s*\(\s*(?:true|false|1|0|null|undefined)\s*\)/g,
|
|
535
|
+
riskLevel: "moderate",
|
|
536
|
+
category: "dead-code",
|
|
537
|
+
autoFixable: false,
|
|
538
|
+
aiPrompt: "This condition is always true/false. Remove the condition or the dead branch.",
|
|
539
|
+
},
|
|
540
|
+
|
|
541
|
+
// ─────────────────────────────────────────────────────────────
|
|
542
|
+
// Security-adjacent (flag for review)
|
|
543
|
+
// ─────────────────────────────────────────────────────────────
|
|
544
|
+
"hardcoded-localhost": {
|
|
545
|
+
id: "hardcoded-localhost",
|
|
546
|
+
name: "Hardcoded localhost URLs",
|
|
547
|
+
description: "Hardcoded localhost URLs that won't work in production",
|
|
548
|
+
severity: "medium",
|
|
549
|
+
pattern: /['"`]https?:\/\/(?:localhost|127\.0\.0\.1)(?::\d+)?[^'"`]*['"`]/g,
|
|
550
|
+
riskLevel: "moderate",
|
|
551
|
+
category: "configuration",
|
|
552
|
+
autoFixable: false,
|
|
553
|
+
aiPrompt: "Replace this hardcoded localhost URL with an environment variable like process.env.API_URL",
|
|
554
|
+
},
|
|
555
|
+
|
|
556
|
+
"hardcoded-port": {
|
|
557
|
+
id: "hardcoded-port",
|
|
558
|
+
name: "Hardcoded ports",
|
|
559
|
+
description: "Hardcoded port numbers that should be configurable",
|
|
560
|
+
severity: "low",
|
|
561
|
+
pattern: /(?:port|PORT)\s*[:=]\s*(?:['"`]?)(\d{4,5})(?:['"`]?)/g,
|
|
562
|
+
riskLevel: "moderate",
|
|
563
|
+
category: "configuration",
|
|
564
|
+
autoFixable: false,
|
|
565
|
+
exclude: ["*.test.*", "*.spec.*", "*.config.*"],
|
|
566
|
+
},
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
570
|
+
// AGGRESSIVE RULES - Require explicit opt-in
|
|
571
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Aggressive rules that could change program behavior.
|
|
575
|
+
* Requires --aggressive --yes-i-am-sure flags.
|
|
576
|
+
*/
|
|
577
|
+
const AGGRESSIVE_RULES = {
|
|
578
|
+
// ─────────────────────────────────────────────────────────────
|
|
579
|
+
// Security: Unsafe regex patterns (potential ReDoS)
|
|
580
|
+
// ─────────────────────────────────────────────────────────────
|
|
581
|
+
"unsafe-regex": {
|
|
582
|
+
id: "unsafe-regex",
|
|
583
|
+
name: "Potentially unsafe regex (ReDoS)",
|
|
584
|
+
description: "Regex patterns vulnerable to catastrophic backtracking",
|
|
585
|
+
severity: "high",
|
|
586
|
+
pattern: {
|
|
587
|
+
type: "function",
|
|
588
|
+
fn: detectUnsafeRegex,
|
|
589
|
+
},
|
|
590
|
+
riskLevel: "aggressive",
|
|
591
|
+
category: "security",
|
|
592
|
+
autoFixable: false,
|
|
593
|
+
aiPrompt: `This regex may be vulnerable to ReDoS (Regular Expression Denial of Service).
|
|
594
|
+
Rewrite to avoid:
|
|
595
|
+
- Nested quantifiers like (a+)+, (a*)*
|
|
596
|
+
- Overlapping alternations
|
|
597
|
+
- Backreferences with quantifiers
|
|
598
|
+
Consider using a regex linter or the 'safe-regex' package.`,
|
|
599
|
+
},
|
|
600
|
+
|
|
601
|
+
// ─────────────────────────────────────────────────────────────
|
|
602
|
+
// Security: Dangerous functions
|
|
603
|
+
// ─────────────────────────────────────────────────────────────
|
|
604
|
+
"eval-usage": {
|
|
605
|
+
id: "eval-usage",
|
|
606
|
+
name: "eval() usage",
|
|
607
|
+
description: "eval() can execute arbitrary code - major security risk",
|
|
608
|
+
severity: "critical",
|
|
609
|
+
pattern: /\beval\s*\(/g,
|
|
610
|
+
riskLevel: "aggressive",
|
|
611
|
+
category: "security",
|
|
612
|
+
autoFixable: false,
|
|
613
|
+
aiPrompt: "eval() is dangerous and should be avoided. Use JSON.parse() for JSON, Function() for dynamic code, or refactor to avoid dynamic code execution entirely.",
|
|
614
|
+
},
|
|
615
|
+
|
|
616
|
+
"new-function": {
|
|
617
|
+
id: "new-function",
|
|
618
|
+
name: "new Function() usage",
|
|
619
|
+
description: "new Function() is similar to eval() - security risk",
|
|
620
|
+
severity: "high",
|
|
621
|
+
pattern: /new\s+Function\s*\(/g,
|
|
622
|
+
riskLevel: "aggressive",
|
|
623
|
+
category: "security",
|
|
624
|
+
autoFixable: false,
|
|
625
|
+
aiPrompt: "new Function() is similar to eval(). Refactor to avoid dynamic code generation.",
|
|
626
|
+
},
|
|
627
|
+
|
|
628
|
+
"innerhtml-assignment": {
|
|
629
|
+
id: "innerhtml-assignment",
|
|
630
|
+
name: "innerHTML assignment",
|
|
631
|
+
description: "Direct innerHTML assignment can lead to XSS vulnerabilities",
|
|
632
|
+
severity: "high",
|
|
633
|
+
pattern: /\.innerHTML\s*=\s*(?!['"`]\s*['"`])/g,
|
|
634
|
+
riskLevel: "aggressive",
|
|
635
|
+
category: "security",
|
|
636
|
+
autoFixable: false,
|
|
637
|
+
aiPrompt: "innerHTML can lead to XSS. Use textContent for text, or sanitize HTML with DOMPurify before insertion.",
|
|
638
|
+
exclude: ["*.test.*", "*.spec.*"],
|
|
639
|
+
},
|
|
640
|
+
|
|
641
|
+
"document-write": {
|
|
642
|
+
id: "document-write",
|
|
643
|
+
name: "document.write() usage",
|
|
644
|
+
description: "document.write() is deprecated and can cause issues",
|
|
645
|
+
severity: "medium",
|
|
646
|
+
pattern: /document\.write\s*\(/g,
|
|
647
|
+
riskLevel: "aggressive",
|
|
648
|
+
category: "security",
|
|
649
|
+
autoFixable: false,
|
|
650
|
+
aiPrompt: "document.write() is deprecated. Use DOM manipulation methods instead.",
|
|
651
|
+
},
|
|
652
|
+
|
|
653
|
+
// ─────────────────────────────────────────────────────────────
|
|
654
|
+
// Security: Hardcoded secrets
|
|
655
|
+
// ─────────────────────────────────────────────────────────────
|
|
656
|
+
"hardcoded-secret": {
|
|
657
|
+
id: "hardcoded-secret",
|
|
658
|
+
name: "Potential hardcoded secrets",
|
|
659
|
+
description: "Strings that look like API keys, tokens, or passwords",
|
|
660
|
+
severity: "critical",
|
|
661
|
+
pattern: {
|
|
662
|
+
type: "function",
|
|
663
|
+
fn: (content) => {
|
|
664
|
+
const matches = [];
|
|
665
|
+
const patterns = [
|
|
666
|
+
// API keys (generic)
|
|
667
|
+
/(?:api[_-]?key|apikey|api[_-]?secret)\s*[:=]\s*['"`]([a-zA-Z0-9_\-]{20,})['"`]/gi,
|
|
668
|
+
// AWS
|
|
669
|
+
/(?:AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16}/g,
|
|
670
|
+
// GitHub tokens
|
|
671
|
+
/ghp_[a-zA-Z0-9]{36}/g,
|
|
672
|
+
/gho_[a-zA-Z0-9]{36}/g,
|
|
673
|
+
/ghu_[a-zA-Z0-9]{36}/g,
|
|
674
|
+
/ghs_[a-zA-Z0-9]{36}/g,
|
|
675
|
+
// Slack tokens
|
|
676
|
+
/xox[baprs]-[0-9a-zA-Z]{10,}/g,
|
|
677
|
+
// JWT-like (but not template literals)
|
|
678
|
+
/['"`](eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,})['"`]/g,
|
|
679
|
+
// Generic password assignments
|
|
680
|
+
/(?:password|passwd|pwd|secret)\s*[:=]\s*['"`](?![${])[^'"`]{8,}['"`]/gi,
|
|
681
|
+
];
|
|
682
|
+
|
|
683
|
+
for (const pattern of patterns) {
|
|
684
|
+
let match;
|
|
685
|
+
pattern.lastIndex = 0;
|
|
686
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
687
|
+
// Skip if in comments
|
|
688
|
+
const lineStart = content.lastIndexOf("\n", match.index) + 1;
|
|
689
|
+
const beforeMatch = content.substring(lineStart, match.index);
|
|
690
|
+
if (beforeMatch.includes("//") || beforeMatch.trim().startsWith("*")) continue;
|
|
691
|
+
|
|
692
|
+
// Skip if it's a template/example
|
|
693
|
+
if (/your[_-]?|example|placeholder|xxx|changeme/i.test(match[0])) continue;
|
|
694
|
+
|
|
695
|
+
matches.push({
|
|
696
|
+
index: match.index,
|
|
697
|
+
length: match[0].length,
|
|
698
|
+
match: match[0].substring(0, 30) + (match[0].length > 30 ? "..." : ""),
|
|
699
|
+
fullMatch: match[0],
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
return matches;
|
|
705
|
+
},
|
|
706
|
+
},
|
|
707
|
+
riskLevel: "aggressive",
|
|
708
|
+
category: "security",
|
|
709
|
+
autoFixable: false,
|
|
710
|
+
aiPrompt: "Move this secret to an environment variable. Never commit secrets to version control.",
|
|
711
|
+
},
|
|
712
|
+
|
|
713
|
+
// ─────────────────────────────────────────────────────────────
|
|
714
|
+
// Code hygiene: Commented-out code
|
|
715
|
+
// ─────────────────────────────────────────────────────────────
|
|
716
|
+
"commented-code-block": {
|
|
717
|
+
id: "commented-code-block",
|
|
718
|
+
name: "Commented-out code blocks",
|
|
719
|
+
description: "Large blocks of commented-out code (use version control)",
|
|
720
|
+
severity: "low",
|
|
721
|
+
pattern: {
|
|
722
|
+
type: "function",
|
|
723
|
+
fn: (content) => {
|
|
724
|
+
const matches = [];
|
|
725
|
+
|
|
726
|
+
// Multi-line comment blocks with code-like content
|
|
727
|
+
const multiLineRegex = /\/\*[\s\S]{50,}?\*\//g;
|
|
728
|
+
let match;
|
|
729
|
+
while ((match = multiLineRegex.exec(content)) !== null) {
|
|
730
|
+
const inner = match[0];
|
|
731
|
+
// Check if it contains code-like patterns
|
|
732
|
+
const codePatterns = /(function|const|let|var|if|for|while|return|import|export|class)\s/;
|
|
733
|
+
if (codePatterns.test(inner)) {
|
|
734
|
+
matches.push({
|
|
735
|
+
index: match.index,
|
|
736
|
+
length: match[0].length,
|
|
737
|
+
match: match[0].substring(0, 50) + "...",
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// Multiple consecutive single-line comments with code
|
|
743
|
+
const lines = content.split("\n");
|
|
744
|
+
let commentBlock = [];
|
|
745
|
+
let blockStart = 0;
|
|
746
|
+
|
|
747
|
+
for (let i = 0; i < lines.length; i++) {
|
|
748
|
+
const line = lines[i].trim();
|
|
749
|
+
if (line.startsWith("//") && /^\s*\/\/\s*(function|const|let|var|if|for|while|return|import|export|class|\w+\s*[=:({])/.test(lines[i])) {
|
|
750
|
+
if (commentBlock.length === 0) {
|
|
751
|
+
blockStart = content.indexOf(lines[i]);
|
|
752
|
+
}
|
|
753
|
+
commentBlock.push(lines[i]);
|
|
754
|
+
} else {
|
|
755
|
+
if (commentBlock.length >= 3) {
|
|
756
|
+
const blockContent = commentBlock.join("\n");
|
|
757
|
+
matches.push({
|
|
758
|
+
index: blockStart,
|
|
759
|
+
length: blockContent.length,
|
|
760
|
+
match: blockContent.substring(0, 50) + "...",
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
commentBlock = [];
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
return matches;
|
|
768
|
+
},
|
|
769
|
+
},
|
|
770
|
+
riskLevel: "aggressive",
|
|
771
|
+
category: "code-hygiene",
|
|
772
|
+
autoFixable: false,
|
|
773
|
+
aiPrompt: "Remove this commented-out code. Use version control to track code history instead.",
|
|
774
|
+
},
|
|
775
|
+
|
|
776
|
+
// ─────────────────────────────────────────────────────────────
|
|
777
|
+
// TypeScript: Type safety
|
|
778
|
+
// ─────────────────────────────────────────────────────────────
|
|
779
|
+
"any-type": {
|
|
780
|
+
id: "any-type",
|
|
781
|
+
name: "TypeScript 'any' type",
|
|
782
|
+
description: "Explicit 'any' type bypasses type checking",
|
|
783
|
+
severity: "medium",
|
|
784
|
+
pattern: /:\s*any\b(?!\s*\/\/\s*(?:intentional|necessary|required))/g,
|
|
785
|
+
riskLevel: "aggressive",
|
|
786
|
+
category: "type-safety",
|
|
787
|
+
autoFixable: false,
|
|
788
|
+
fileTypes: [".ts", ".tsx"],
|
|
789
|
+
aiPrompt: `Replace 'any' with a proper type:
|
|
790
|
+
- Use 'unknown' if the type is truly unknown (safer than any)
|
|
791
|
+
- Use a generic type parameter if this is meant to be flexible
|
|
792
|
+
- Define an interface/type for the expected shape
|
|
793
|
+
- Use 'as const' for literal types`,
|
|
794
|
+
},
|
|
795
|
+
|
|
796
|
+
"non-null-assertion": {
|
|
797
|
+
id: "non-null-assertion",
|
|
798
|
+
name: "Non-null assertions (!)",
|
|
799
|
+
description: "Non-null assertion operator bypasses null checks",
|
|
800
|
+
severity: "medium",
|
|
801
|
+
pattern: /\w+\s*!\s*\./g,
|
|
802
|
+
riskLevel: "aggressive",
|
|
803
|
+
category: "type-safety",
|
|
804
|
+
autoFixable: false,
|
|
805
|
+
fileTypes: [".ts", ".tsx"],
|
|
806
|
+
aiPrompt: "Replace the non-null assertion (!) with proper null checking using optional chaining (?.) or an if statement.",
|
|
807
|
+
},
|
|
808
|
+
|
|
809
|
+
// ─────────────────────────────────────────────────────────────
|
|
810
|
+
// Logging: console.error (might be intentional)
|
|
811
|
+
// ─────────────────────────────────────────────────────────────
|
|
812
|
+
"console-error": {
|
|
813
|
+
id: "console-error",
|
|
814
|
+
name: "console.error statements",
|
|
815
|
+
description: "console.error should be replaced with proper logging",
|
|
816
|
+
severity: "low",
|
|
817
|
+
pattern: createConsolePattern("error"),
|
|
818
|
+
riskLevel: "aggressive",
|
|
819
|
+
category: "logging",
|
|
820
|
+
autoFixable: false,
|
|
821
|
+
exclude: ["*.test.*", "*.spec.*"],
|
|
822
|
+
aiPrompt: "Replace console.error with a proper logging library (winston, pino, etc.) that supports log levels and structured logging.",
|
|
823
|
+
},
|
|
824
|
+
|
|
825
|
+
"console-warn": {
|
|
826
|
+
id: "console-warn",
|
|
827
|
+
name: "console.warn statements",
|
|
828
|
+
description: "console.warn should be replaced with proper logging",
|
|
829
|
+
severity: "low",
|
|
830
|
+
pattern: createConsolePattern("warn"),
|
|
831
|
+
riskLevel: "aggressive",
|
|
832
|
+
category: "logging",
|
|
833
|
+
autoFixable: false,
|
|
834
|
+
exclude: ["*.test.*", "*.spec.*"],
|
|
835
|
+
aiPrompt: "Replace console.warn with a proper logging library.",
|
|
836
|
+
},
|
|
837
|
+
|
|
838
|
+
// ─────────────────────────────────────────────────────────────
|
|
839
|
+
// UX: Legacy browser APIs
|
|
840
|
+
// ─────────────────────────────────────────────────────────────
|
|
841
|
+
"browser-alert": {
|
|
842
|
+
id: "browser-alert",
|
|
843
|
+
name: "Browser alert()",
|
|
844
|
+
description: "alert() blocks the thread and has poor UX",
|
|
845
|
+
severity: "medium",
|
|
846
|
+
pattern: /\balert\s*\(/g,
|
|
847
|
+
riskLevel: "aggressive",
|
|
848
|
+
category: "ux",
|
|
849
|
+
autoFixable: false,
|
|
850
|
+
aiPrompt: "Replace alert() with a modern toast/modal component from your UI library (e.g., react-hot-toast, shadcn/ui dialog).",
|
|
851
|
+
},
|
|
852
|
+
|
|
853
|
+
"browser-confirm": {
|
|
854
|
+
id: "browser-confirm",
|
|
855
|
+
name: "Browser confirm()",
|
|
856
|
+
description: "confirm() blocks the thread and has poor UX",
|
|
857
|
+
severity: "medium",
|
|
858
|
+
pattern: /\bconfirm\s*\(/g,
|
|
859
|
+
riskLevel: "aggressive",
|
|
860
|
+
category: "ux",
|
|
861
|
+
autoFixable: false,
|
|
862
|
+
aiPrompt: "Replace confirm() with a modern confirmation dialog component.",
|
|
863
|
+
},
|
|
864
|
+
|
|
865
|
+
"browser-prompt": {
|
|
866
|
+
id: "browser-prompt",
|
|
867
|
+
name: "Browser prompt()",
|
|
868
|
+
description: "prompt() blocks the thread and has poor UX",
|
|
869
|
+
severity: "medium",
|
|
870
|
+
pattern: /\bprompt\s*\(/g,
|
|
871
|
+
riskLevel: "aggressive",
|
|
872
|
+
category: "ux",
|
|
873
|
+
autoFixable: false,
|
|
874
|
+
aiPrompt: "Replace prompt() with a modern input modal/dialog component.",
|
|
875
|
+
},
|
|
876
|
+
|
|
877
|
+
// ─────────────────────────────────────────────────────────────
|
|
878
|
+
// Dead code: Unused variables (basic detection)
|
|
879
|
+
// ─────────────────────────────────────────────────────────────
|
|
880
|
+
"unused-import": {
|
|
881
|
+
id: "unused-import",
|
|
882
|
+
name: "Potentially unused imports",
|
|
883
|
+
description: "Imports that may not be used in the file",
|
|
884
|
+
severity: "low",
|
|
885
|
+
pattern: {
|
|
886
|
+
type: "function",
|
|
887
|
+
fn: (content, filePath) => {
|
|
888
|
+
const matches = [];
|
|
889
|
+
|
|
890
|
+
// Extract all imports
|
|
891
|
+
const importRegex = /import\s+(?:{([^}]+)}|(\w+))\s+from\s+['"][^'"]+['"]/g;
|
|
892
|
+
let match;
|
|
893
|
+
|
|
894
|
+
while ((match = importRegex.exec(content)) !== null) {
|
|
895
|
+
const imports = match[1] || match[2];
|
|
896
|
+
if (!imports) continue;
|
|
897
|
+
|
|
898
|
+
// Get individual import names
|
|
899
|
+
const names = imports.split(",").map(s => s.trim().split(/\s+as\s+/).pop().trim());
|
|
900
|
+
|
|
901
|
+
for (const name of names) {
|
|
902
|
+
if (!name || name === "type") continue;
|
|
903
|
+
|
|
904
|
+
// Count occurrences (excluding the import line itself)
|
|
905
|
+
const afterImport = content.substring(match.index + match[0].length);
|
|
906
|
+
const usageRegex = new RegExp(`\\b${name}\\b`, "g");
|
|
907
|
+
const usages = (afterImport.match(usageRegex) || []).length;
|
|
908
|
+
|
|
909
|
+
if (usages === 0) {
|
|
910
|
+
matches.push({
|
|
911
|
+
index: match.index,
|
|
912
|
+
length: match[0].length,
|
|
913
|
+
match: `import { ${name} } appears unused`,
|
|
914
|
+
importName: name,
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
return matches;
|
|
921
|
+
},
|
|
922
|
+
},
|
|
923
|
+
riskLevel: "aggressive",
|
|
924
|
+
category: "dead-code",
|
|
925
|
+
autoFixable: false,
|
|
926
|
+
aiPrompt: "This import appears to be unused. Remove it if not needed, or check if it's used for side effects.",
|
|
927
|
+
},
|
|
928
|
+
|
|
929
|
+
// ─────────────────────────────────────────────────────────────
|
|
930
|
+
// Performance: Synchronous operations
|
|
931
|
+
// ─────────────────────────────────────────────────────────────
|
|
932
|
+
"sync-fs-operation": {
|
|
933
|
+
id: "sync-fs-operation",
|
|
934
|
+
name: "Synchronous fs operations",
|
|
935
|
+
description: "Sync fs operations block the event loop",
|
|
936
|
+
severity: "medium",
|
|
937
|
+
pattern: /(?:readFileSync|writeFileSync|appendFileSync|mkdirSync|rmdirSync|unlinkSync|copyFileSync|renameSync|existsSync|statSync|readdirSync)\s*\(/g,
|
|
938
|
+
riskLevel: "aggressive",
|
|
939
|
+
category: "performance",
|
|
940
|
+
autoFixable: false,
|
|
941
|
+
exclude: ["*.config.*", "*.test.*", "*.spec.*", "**/scripts/**", "**/bin/**"],
|
|
942
|
+
aiPrompt: "Replace synchronous fs operations with async versions (e.g., readFileSync -> readFile with await). Sync operations block the event loop.",
|
|
943
|
+
},
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
947
|
+
// RULE CATEGORIES
|
|
948
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
949
|
+
|
|
950
|
+
const CATEGORIES = {
|
|
951
|
+
"debug-cleanup": {
|
|
952
|
+
name: "Debug Cleanup",
|
|
953
|
+
description: "Remove debug artifacts (console.log, debugger)",
|
|
954
|
+
icon: "🧹",
|
|
955
|
+
},
|
|
956
|
+
"error-handling": {
|
|
957
|
+
name: "Error Handling",
|
|
958
|
+
description: "Improve error handling patterns",
|
|
959
|
+
icon: "⚠️",
|
|
960
|
+
},
|
|
961
|
+
"dead-code": {
|
|
962
|
+
name: "Dead Code",
|
|
963
|
+
description: "Remove or flag unreachable/unused code",
|
|
964
|
+
icon: "💀",
|
|
965
|
+
},
|
|
966
|
+
"code-quality": {
|
|
967
|
+
name: "Code Quality",
|
|
968
|
+
description: "General code quality improvements",
|
|
969
|
+
icon: "✨",
|
|
970
|
+
},
|
|
971
|
+
"code-hygiene": {
|
|
972
|
+
name: "Code Hygiene",
|
|
973
|
+
description: "Code cleanliness and maintainability",
|
|
974
|
+
icon: "🧼",
|
|
975
|
+
},
|
|
976
|
+
"formatting": {
|
|
977
|
+
name: "Formatting",
|
|
978
|
+
description: "Whitespace and formatting cleanup",
|
|
979
|
+
icon: "📝",
|
|
980
|
+
},
|
|
981
|
+
"security": {
|
|
982
|
+
name: "Security",
|
|
983
|
+
description: "Security-related issues",
|
|
984
|
+
icon: "🔒",
|
|
985
|
+
},
|
|
986
|
+
"type-safety": {
|
|
987
|
+
name: "Type Safety",
|
|
988
|
+
description: "TypeScript type safety",
|
|
989
|
+
icon: "📊",
|
|
990
|
+
},
|
|
991
|
+
"logging": {
|
|
992
|
+
name: "Logging",
|
|
993
|
+
description: "Logging and observability",
|
|
994
|
+
icon: "📋",
|
|
995
|
+
},
|
|
996
|
+
"ux": {
|
|
997
|
+
name: "User Experience",
|
|
998
|
+
description: "UX-related issues",
|
|
999
|
+
icon: "👤",
|
|
1000
|
+
},
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1004
|
+
// RISK LEVELS
|
|
1005
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1006
|
+
|
|
1007
|
+
const RISK_LEVELS = {
|
|
1008
|
+
safe: {
|
|
1009
|
+
name: "Safe",
|
|
1010
|
+
description: "Cannot change program behavior",
|
|
1011
|
+
color: "green",
|
|
1012
|
+
requiresConfirmation: false,
|
|
1013
|
+
},
|
|
1014
|
+
moderate: {
|
|
1015
|
+
name: "Moderate",
|
|
1016
|
+
description: "Generally safe, but worth reviewing",
|
|
1017
|
+
color: "yellow",
|
|
1018
|
+
requiresConfirmation: false,
|
|
1019
|
+
},
|
|
1020
|
+
aggressive: {
|
|
1021
|
+
name: "Aggressive",
|
|
1022
|
+
description: "Could change program behavior",
|
|
1023
|
+
color: "red",
|
|
1024
|
+
requiresConfirmation: true,
|
|
1025
|
+
},
|
|
1026
|
+
};
|
|
1027
|
+
|
|
1028
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1029
|
+
// EXPORTS
|
|
1030
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1031
|
+
|
|
1032
|
+
module.exports = {
|
|
1033
|
+
SAFE_RULES,
|
|
1034
|
+
MODERATE_RULES,
|
|
1035
|
+
AGGRESSIVE_RULES,
|
|
1036
|
+
CATEGORIES,
|
|
1037
|
+
RISK_LEVELS,
|
|
1038
|
+
|
|
1039
|
+
// Convenience getters
|
|
1040
|
+
getAllRules: () => ({ ...SAFE_RULES, ...MODERATE_RULES, ...AGGRESSIVE_RULES }),
|
|
1041
|
+
getSafeRules: () => SAFE_RULES,
|
|
1042
|
+
getModerateRules: () => MODERATE_RULES,
|
|
1043
|
+
getAggressiveRules: () => AGGRESSIVE_RULES,
|
|
1044
|
+
|
|
1045
|
+
getRuleById: (id) => {
|
|
1046
|
+
return SAFE_RULES[id] || MODERATE_RULES[id] || AGGRESSIVE_RULES[id] || null;
|
|
1047
|
+
},
|
|
1048
|
+
|
|
1049
|
+
getRulesByCategory: (category) => {
|
|
1050
|
+
const all = { ...SAFE_RULES, ...MODERATE_RULES, ...AGGRESSIVE_RULES };
|
|
1051
|
+
return Object.values(all).filter(r => r.category === category);
|
|
1052
|
+
},
|
|
1053
|
+
|
|
1054
|
+
getRulesByRiskLevel: (level) => {
|
|
1055
|
+
if (level === "safe") return Object.values(SAFE_RULES);
|
|
1056
|
+
if (level === "moderate") return Object.values(MODERATE_RULES);
|
|
1057
|
+
if (level === "aggressive") return Object.values(AGGRESSIVE_RULES);
|
|
1058
|
+
return [];
|
|
1059
|
+
},
|
|
1060
|
+
};
|