@delegance/claude-autopilot 5.0.0 → 5.0.2
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/dist/presets/go/rules/go-sql-injection.d.ts +4 -0
- package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.d.ts +4 -0
- package/dist/presets/python-fastapi/rules/fastapi-missing-auth.d.ts +4 -0
- package/dist/presets/rails-postgres/rules/rails-sql-injection.d.ts +4 -0
- package/dist/presets/t3/rules/t3-server-only.d.ts +4 -0
- package/dist/src/adapters/base.d.ts +11 -0
- package/dist/src/adapters/council/claude.d.ts +3 -0
- package/dist/src/adapters/council/openai.d.ts +3 -0
- package/dist/src/adapters/council/types.d.ts +5 -0
- package/dist/src/adapters/loader.d.ts +11 -0
- package/dist/src/adapters/migration-runner/supabase.d.ts +4 -0
- package/dist/src/adapters/migration-runner/types.d.ts +31 -0
- package/dist/src/adapters/review-bot-parser/cursor.d.ts +3 -0
- package/dist/src/adapters/review-bot-parser/declarative-base.d.ts +13 -0
- package/{src/adapters/review-bot-parser/types.ts → dist/src/adapters/review-bot-parser/types.d.ts} +4 -4
- package/dist/src/adapters/review-engine/auto.d.ts +4 -0
- package/dist/src/adapters/review-engine/claude.d.ts +4 -0
- package/dist/src/adapters/review-engine/codex.d.ts +4 -0
- package/dist/src/adapters/review-engine/gemini.d.ts +4 -0
- package/dist/src/adapters/review-engine/openai-compatible.d.ts +4 -0
- package/dist/src/adapters/review-engine/parse-output.d.ts +13 -0
- package/dist/src/adapters/review-engine/prompt-builder.d.ts +4 -0
- package/dist/src/adapters/review-engine/types.d.ts +28 -0
- package/dist/src/adapters/vcs-host/commit-status.d.ts +12 -0
- package/dist/src/adapters/vcs-host/github.d.ts +4 -0
- package/dist/src/adapters/vcs-host/types.d.ts +42 -0
- package/{src/cli/_pkg-root.ts → dist/src/cli/_pkg-root.d.ts} +4 -42
- package/dist/src/cli/autoregress-bridge.d.ts +3 -0
- package/dist/src/cli/baseline.d.ts +7 -0
- package/dist/src/cli/ci.d.ts +23 -0
- package/dist/src/cli/costs.d.ts +2 -0
- package/dist/src/cli/council.d.ts +8 -0
- package/dist/src/cli/detector.d.ts +8 -0
- package/dist/src/cli/explain.d.ts +8 -0
- package/dist/src/cli/fix.d.ts +10 -0
- package/dist/src/cli/hook.d.ts +9 -0
- package/dist/src/cli/ignore-helper.d.ts +7 -0
- package/dist/src/cli/index.d.ts +3 -0
- package/dist/src/cli/index.js +39 -1
- package/dist/src/cli/lsp.d.ts +29 -0
- package/dist/src/cli/mcp.d.ts +5 -0
- package/dist/src/cli/migrate-v4.d.ts +28 -0
- package/dist/src/cli/pr-comment.d.ts +13 -0
- package/dist/src/cli/pr-desc.d.ts +31 -0
- package/dist/src/cli/pr-review-comments.d.ts +12 -0
- package/dist/src/cli/pr.d.ts +9 -0
- package/dist/src/cli/preflight.d.ts +8 -0
- package/dist/src/cli/preflight.js +17 -4
- package/dist/src/cli/report.d.ts +7 -0
- package/dist/src/cli/run.d.ts +23 -0
- package/dist/src/cli/scan.d.ts +11 -0
- package/dist/src/cli/setup.d.ts +9 -0
- package/dist/src/cli/test-gen.d.ts +10 -0
- package/dist/src/cli/triage.d.ts +5 -0
- package/dist/src/cli/watch.d.ts +18 -0
- package/dist/src/cli/worker.d.ts +5 -0
- package/dist/src/core/cache/cached-engine.d.ts +8 -0
- package/dist/src/core/cache/review-cache.d.ts +21 -0
- package/dist/src/core/chunking/index.d.ts +18 -0
- package/dist/src/core/chunking/risk-ranker.d.ts +10 -0
- package/dist/src/core/config/loader.d.ts +3 -0
- package/dist/src/core/config/preset-resolver.d.ts +9 -0
- package/dist/src/core/config/schema.d.ts +342 -0
- package/dist/src/core/config/types.d.ts +115 -0
- package/dist/src/core/council/config.d.ts +3 -0
- package/dist/src/core/council/context.d.ts +2 -0
- package/dist/src/core/council/runner.d.ts +4 -0
- package/dist/src/core/council/types.d.ts +36 -0
- package/dist/src/core/detect/git-context.d.ts +12 -0
- package/dist/src/core/detect/llm-key.d.ts +38 -0
- package/dist/src/core/detect/protected-paths.d.ts +6 -0
- package/dist/src/core/detect/provider-usage.d.ts +17 -0
- package/dist/src/core/detect/stack.d.ts +6 -0
- package/dist/src/core/detect/workspaces.d.ts +11 -0
- package/dist/src/core/errors.d.ts +17 -0
- package/dist/src/core/findings/dedup.d.ts +4 -0
- package/dist/src/core/findings/types.d.ts +33 -0
- package/dist/src/core/fix/generator.d.ts +17 -0
- package/dist/src/core/git/diff-hunks.d.ts +22 -0
- package/dist/src/core/git/touched-files.d.ts +11 -0
- package/dist/src/core/ignore/index.d.ts +11 -0
- package/dist/src/core/index.d.ts +2 -0
- package/dist/src/core/logging/ndjson-writer.d.ts +16 -0
- package/dist/src/core/logging/redaction.d.ts +4 -0
- package/dist/src/core/mcp/concurrency.d.ts +2 -0
- package/dist/src/core/mcp/handlers/fix-finding.d.ts +17 -0
- package/dist/src/core/mcp/handlers/get-capabilities.d.ts +14 -0
- package/dist/src/core/mcp/handlers/get-findings.d.ts +13 -0
- package/dist/src/core/mcp/handlers/review-diff.d.ts +18 -0
- package/dist/src/core/mcp/handlers/scan-files.d.ts +15 -0
- package/dist/src/core/mcp/handlers/validate-fix.d.ts +12 -0
- package/dist/src/core/mcp/run-store.d.ts +12 -0
- package/dist/src/core/mcp/workspace.d.ts +3 -0
- package/dist/src/core/persist/baseline.d.ts +39 -0
- package/dist/src/core/persist/cost-log.d.ts +11 -0
- package/dist/src/core/persist/findings-cache.d.ts +9 -0
- package/dist/src/core/persist/triage.d.ts +30 -0
- package/dist/src/core/phases/static-rules.d.ts +24 -0
- package/dist/src/core/phases/tests.d.ts +15 -0
- package/dist/src/core/pipeline/review-phase.d.ts +27 -0
- package/dist/src/core/pipeline/run.d.ts +27 -0
- package/dist/src/core/runtime/idempotency.d.ts +2 -0
- package/dist/src/core/runtime/lock.d.ts +5 -0
- package/dist/src/core/runtime/state.d.ts +39 -0
- package/dist/src/core/schema-alignment/detector.d.ts +3 -0
- package/dist/src/core/schema-alignment/extractor/index.d.ts +3 -0
- package/dist/src/core/schema-alignment/extractor/prisma.d.ts +3 -0
- package/dist/src/core/schema-alignment/extractor/sql.d.ts +3 -0
- package/dist/src/core/schema-alignment/llm-check.d.ts +4 -0
- package/dist/src/core/schema-alignment/scanner.d.ts +3 -0
- package/dist/src/core/schema-alignment/types.d.ts +38 -0
- package/dist/src/core/shell.d.ts +15 -0
- package/dist/src/core/static-rules/registry.d.ts +5 -0
- package/dist/src/core/static-rules/rules/brand-tokens.d.ts +3 -0
- package/dist/src/core/static-rules/rules/console-log.d.ts +3 -0
- package/dist/src/core/static-rules/rules/hardcoded-secrets.d.ts +3 -0
- package/dist/src/core/static-rules/rules/insecure-redirect.d.ts +3 -0
- package/dist/src/core/static-rules/rules/large-file.d.ts +3 -0
- package/dist/src/core/static-rules/rules/missing-auth.d.ts +3 -0
- package/dist/src/core/static-rules/rules/missing-tests.d.ts +3 -0
- package/dist/src/core/static-rules/rules/npm-audit.d.ts +3 -0
- package/dist/src/core/static-rules/rules/package-lock-sync.d.ts +3 -0
- package/dist/src/core/static-rules/rules/schema-alignment.d.ts +3 -0
- package/dist/src/core/static-rules/rules/sql-injection.d.ts +3 -0
- package/dist/src/core/static-rules/rules/ssrf.d.ts +3 -0
- package/dist/src/core/static-rules/rules/todo-fixme.d.ts +3 -0
- package/dist/src/core/static-rules/tailwind-extractor.d.ts +7 -0
- package/dist/src/core/test-gen/coverage-analyzer.d.ts +7 -0
- package/dist/src/core/test-gen/framework-detector.d.ts +3 -0
- package/dist/src/core/test-gen/test-writer.d.ts +4 -0
- package/dist/src/core/ui/design-context-loader.d.ts +7 -0
- package/dist/src/core/worker/client.d.ts +23 -0
- package/dist/src/core/worker/lockfile.d.ts +12 -0
- package/dist/src/core/worker/server.d.ts +17 -0
- package/dist/src/formatters/github-annotations.d.ts +5 -0
- package/{src/formatters/index.ts → dist/src/formatters/index.d.ts} +1 -0
- package/dist/src/formatters/junit.d.ts +5 -0
- package/dist/src/formatters/sarif.d.ts +56 -0
- package/{src/index.ts → dist/src/index.d.ts} +1 -0
- package/package.json +7 -6
- package/dist/presets/go/rules/go-sql-injection.js.map +0 -1
- package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.js.map +0 -1
- package/dist/presets/python-fastapi/rules/fastapi-missing-auth.js.map +0 -1
- package/dist/presets/rails-postgres/rules/rails-sql-injection.js.map +0 -1
- package/dist/presets/t3/rules/t3-server-only.js.map +0 -1
- package/dist/src/adapters/base.js.map +0 -1
- package/dist/src/adapters/council/claude.js.map +0 -1
- package/dist/src/adapters/council/openai.js.map +0 -1
- package/dist/src/adapters/council/types.js.map +0 -1
- package/dist/src/adapters/loader.js.map +0 -1
- package/dist/src/adapters/migration-runner/supabase.js.map +0 -1
- package/dist/src/adapters/migration-runner/types.js.map +0 -1
- package/dist/src/adapters/review-bot-parser/cursor.js.map +0 -1
- package/dist/src/adapters/review-bot-parser/declarative-base.js.map +0 -1
- package/dist/src/adapters/review-bot-parser/types.js.map +0 -1
- package/dist/src/adapters/review-engine/auto.js.map +0 -1
- package/dist/src/adapters/review-engine/claude.js.map +0 -1
- package/dist/src/adapters/review-engine/codex.js.map +0 -1
- package/dist/src/adapters/review-engine/gemini.js.map +0 -1
- package/dist/src/adapters/review-engine/openai-compatible.js.map +0 -1
- package/dist/src/adapters/review-engine/parse-output.js.map +0 -1
- package/dist/src/adapters/review-engine/prompt-builder.js.map +0 -1
- package/dist/src/adapters/review-engine/types.js.map +0 -1
- package/dist/src/adapters/vcs-host/commit-status.js.map +0 -1
- package/dist/src/adapters/vcs-host/github.js.map +0 -1
- package/dist/src/adapters/vcs-host/types.js.map +0 -1
- package/dist/src/cli/_pkg-root.js.map +0 -1
- package/dist/src/cli/autoregress-bridge.js.map +0 -1
- package/dist/src/cli/baseline.js.map +0 -1
- package/dist/src/cli/ci.js.map +0 -1
- package/dist/src/cli/costs.js.map +0 -1
- package/dist/src/cli/council.js.map +0 -1
- package/dist/src/cli/detector.js.map +0 -1
- package/dist/src/cli/explain.js.map +0 -1
- package/dist/src/cli/fix.js.map +0 -1
- package/dist/src/cli/hook.js.map +0 -1
- package/dist/src/cli/ignore-helper.js.map +0 -1
- package/dist/src/cli/index.js.map +0 -1
- package/dist/src/cli/lsp.js.map +0 -1
- package/dist/src/cli/mcp.js.map +0 -1
- package/dist/src/cli/migrate-v4.js.map +0 -1
- package/dist/src/cli/pr-comment.js.map +0 -1
- package/dist/src/cli/pr-desc.js.map +0 -1
- package/dist/src/cli/pr-review-comments.js.map +0 -1
- package/dist/src/cli/pr.js.map +0 -1
- package/dist/src/cli/preflight.js.map +0 -1
- package/dist/src/cli/report.js.map +0 -1
- package/dist/src/cli/run.js.map +0 -1
- package/dist/src/cli/scan.js.map +0 -1
- package/dist/src/cli/setup.js.map +0 -1
- package/dist/src/cli/test-gen.js.map +0 -1
- package/dist/src/cli/triage.js.map +0 -1
- package/dist/src/cli/watch.js.map +0 -1
- package/dist/src/cli/worker.js.map +0 -1
- package/dist/src/core/cache/cached-engine.js.map +0 -1
- package/dist/src/core/cache/review-cache.js.map +0 -1
- package/dist/src/core/chunking/index.js.map +0 -1
- package/dist/src/core/chunking/risk-ranker.js.map +0 -1
- package/dist/src/core/config/loader.js.map +0 -1
- package/dist/src/core/config/preset-resolver.js.map +0 -1
- package/dist/src/core/config/schema.js.map +0 -1
- package/dist/src/core/config/types.js.map +0 -1
- package/dist/src/core/council/config.js.map +0 -1
- package/dist/src/core/council/context.js.map +0 -1
- package/dist/src/core/council/runner.js.map +0 -1
- package/dist/src/core/council/types.js.map +0 -1
- package/dist/src/core/detect/git-context.js.map +0 -1
- package/dist/src/core/detect/llm-key.js.map +0 -1
- package/dist/src/core/detect/protected-paths.js.map +0 -1
- package/dist/src/core/detect/provider-usage.js.map +0 -1
- package/dist/src/core/detect/stack.js.map +0 -1
- package/dist/src/core/detect/workspaces.js.map +0 -1
- package/dist/src/core/errors.js.map +0 -1
- package/dist/src/core/findings/dedup.js.map +0 -1
- package/dist/src/core/findings/types.js.map +0 -1
- package/dist/src/core/fix/generator.js.map +0 -1
- package/dist/src/core/git/diff-hunks.js.map +0 -1
- package/dist/src/core/git/touched-files.js.map +0 -1
- package/dist/src/core/ignore/index.js.map +0 -1
- package/dist/src/core/index.js.map +0 -1
- package/dist/src/core/logging/ndjson-writer.js.map +0 -1
- package/dist/src/core/logging/redaction.js.map +0 -1
- package/dist/src/core/mcp/concurrency.js.map +0 -1
- package/dist/src/core/mcp/handlers/fix-finding.js.map +0 -1
- package/dist/src/core/mcp/handlers/get-capabilities.js.map +0 -1
- package/dist/src/core/mcp/handlers/get-findings.js.map +0 -1
- package/dist/src/core/mcp/handlers/review-diff.js.map +0 -1
- package/dist/src/core/mcp/handlers/scan-files.js.map +0 -1
- package/dist/src/core/mcp/handlers/validate-fix.js.map +0 -1
- package/dist/src/core/mcp/run-store.js.map +0 -1
- package/dist/src/core/mcp/workspace.js.map +0 -1
- package/dist/src/core/persist/baseline.js.map +0 -1
- package/dist/src/core/persist/cost-log.js.map +0 -1
- package/dist/src/core/persist/findings-cache.js.map +0 -1
- package/dist/src/core/persist/triage.js.map +0 -1
- package/dist/src/core/phases/static-rules.js.map +0 -1
- package/dist/src/core/phases/tests.js.map +0 -1
- package/dist/src/core/pipeline/review-phase.js.map +0 -1
- package/dist/src/core/pipeline/run.js.map +0 -1
- package/dist/src/core/runtime/idempotency.js.map +0 -1
- package/dist/src/core/runtime/lock.js.map +0 -1
- package/dist/src/core/runtime/state.js.map +0 -1
- package/dist/src/core/schema-alignment/detector.js.map +0 -1
- package/dist/src/core/schema-alignment/extractor/index.js.map +0 -1
- package/dist/src/core/schema-alignment/extractor/prisma.js.map +0 -1
- package/dist/src/core/schema-alignment/extractor/sql.js.map +0 -1
- package/dist/src/core/schema-alignment/llm-check.js.map +0 -1
- package/dist/src/core/schema-alignment/scanner.js.map +0 -1
- package/dist/src/core/schema-alignment/types.js.map +0 -1
- package/dist/src/core/shell.js.map +0 -1
- package/dist/src/core/static-rules/registry.js.map +0 -1
- package/dist/src/core/static-rules/rules/brand-tokens.js.map +0 -1
- package/dist/src/core/static-rules/rules/console-log.js.map +0 -1
- package/dist/src/core/static-rules/rules/hardcoded-secrets.js.map +0 -1
- package/dist/src/core/static-rules/rules/insecure-redirect.js.map +0 -1
- package/dist/src/core/static-rules/rules/large-file.js.map +0 -1
- package/dist/src/core/static-rules/rules/missing-auth.js.map +0 -1
- package/dist/src/core/static-rules/rules/missing-tests.js.map +0 -1
- package/dist/src/core/static-rules/rules/npm-audit.js.map +0 -1
- package/dist/src/core/static-rules/rules/package-lock-sync.js.map +0 -1
- package/dist/src/core/static-rules/rules/schema-alignment.js.map +0 -1
- package/dist/src/core/static-rules/rules/sql-injection.js.map +0 -1
- package/dist/src/core/static-rules/rules/ssrf.js.map +0 -1
- package/dist/src/core/static-rules/rules/todo-fixme.js.map +0 -1
- package/dist/src/core/static-rules/tailwind-extractor.js.map +0 -1
- package/dist/src/core/test-gen/coverage-analyzer.js.map +0 -1
- package/dist/src/core/test-gen/framework-detector.js.map +0 -1
- package/dist/src/core/test-gen/test-writer.js.map +0 -1
- package/dist/src/core/ui/design-context-loader.js.map +0 -1
- package/dist/src/core/worker/client.js.map +0 -1
- package/dist/src/core/worker/lockfile.js.map +0 -1
- package/dist/src/core/worker/server.js.map +0 -1
- package/dist/src/formatters/github-annotations.js.map +0 -1
- package/dist/src/formatters/index.js.map +0 -1
- package/dist/src/formatters/junit.js.map +0 -1
- package/dist/src/formatters/sarif.js.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/src/adapters/base.ts +0 -19
- package/src/adapters/council/claude.ts +0 -41
- package/src/adapters/council/openai.ts +0 -40
- package/src/adapters/council/types.ts +0 -7
- package/src/adapters/loader.ts +0 -108
- package/src/adapters/migration-runner/supabase.ts +0 -56
- package/src/adapters/migration-runner/types.ts +0 -36
- package/src/adapters/review-bot-parser/cursor.ts +0 -13
- package/src/adapters/review-bot-parser/declarative-base.ts +0 -64
- package/src/adapters/review-engine/auto.ts +0 -94
- package/src/adapters/review-engine/claude.ts +0 -100
- package/src/adapters/review-engine/codex.ts +0 -82
- package/src/adapters/review-engine/gemini.ts +0 -105
- package/src/adapters/review-engine/openai-compatible.ts +0 -100
- package/src/adapters/review-engine/parse-output.ts +0 -74
- package/src/adapters/review-engine/prompt-builder.ts +0 -19
- package/src/adapters/review-engine/types.ts +0 -19
- package/src/adapters/vcs-host/commit-status.ts +0 -39
- package/src/adapters/vcs-host/github.ts +0 -77
- package/src/adapters/vcs-host/types.ts +0 -44
- package/src/cli/autoregress-bridge.ts +0 -30
- package/src/cli/baseline.ts +0 -125
- package/src/cli/ci.ts +0 -45
- package/src/cli/costs.ts +0 -80
- package/src/cli/council.ts +0 -96
- package/src/cli/detector.ts +0 -92
- package/src/cli/explain.ts +0 -197
- package/src/cli/fix.ts +0 -249
- package/src/cli/hook.ts +0 -124
- package/src/cli/ignore-helper.ts +0 -116
- package/src/cli/index.ts +0 -612
- package/src/cli/lsp.ts +0 -200
- package/src/cli/mcp.ts +0 -206
- package/src/cli/migrate-v4.ts +0 -388
- package/src/cli/pr-comment.ts +0 -139
- package/src/cli/pr-desc.ts +0 -168
- package/src/cli/pr-review-comments.ts +0 -92
- package/src/cli/pr.ts +0 -76
- package/src/cli/preflight.ts +0 -235
- package/src/cli/report.ts +0 -186
- package/src/cli/run.ts +0 -425
- package/src/cli/scan.ts +0 -233
- package/src/cli/setup.ts +0 -191
- package/src/cli/test-gen.ts +0 -125
- package/src/cli/triage.ts +0 -137
- package/src/cli/watch.ts +0 -190
- package/src/cli/worker.ts +0 -109
- package/src/core/.gitkeep +0 -0
- package/src/core/cache/cached-engine.ts +0 -32
- package/src/core/cache/review-cache.ts +0 -70
- package/src/core/chunking/index.ts +0 -113
- package/src/core/chunking/risk-ranker.ts +0 -56
- package/src/core/config/loader.ts +0 -53
- package/src/core/config/preset-resolver.ts +0 -46
- package/src/core/config/schema.ts +0 -181
- package/src/core/config/types.ts +0 -98
- package/src/core/council/config.ts +0 -71
- package/src/core/council/context.ts +0 -17
- package/src/core/council/runner.ts +0 -83
- package/src/core/council/types.ts +0 -45
- package/src/core/detect/git-context.ts +0 -27
- package/src/core/detect/llm-key.ts +0 -89
- package/src/core/detect/protected-paths.ts +0 -63
- package/src/core/detect/provider-usage.ts +0 -74
- package/src/core/detect/stack.ts +0 -153
- package/src/core/detect/workspaces.ts +0 -103
- package/src/core/errors.ts +0 -37
- package/src/core/findings/dedup.ts +0 -14
- package/src/core/findings/types.ts +0 -39
- package/src/core/fix/generator.ts +0 -149
- package/src/core/git/diff-hunks.ts +0 -86
- package/src/core/git/touched-files.ts +0 -73
- package/src/core/ignore/index.ts +0 -54
- package/src/core/index.ts +0 -1
- package/src/core/logging/ndjson-writer.ts +0 -37
- package/src/core/logging/redaction.ts +0 -19
- package/src/core/mcp/concurrency.ts +0 -16
- package/src/core/mcp/handlers/fix-finding.ts +0 -126
- package/src/core/mcp/handlers/get-capabilities.ts +0 -62
- package/src/core/mcp/handlers/get-findings.ts +0 -36
- package/src/core/mcp/handlers/review-diff.ts +0 -65
- package/src/core/mcp/handlers/scan-files.ts +0 -65
- package/src/core/mcp/handlers/validate-fix.ts +0 -41
- package/src/core/mcp/run-store.ts +0 -85
- package/src/core/mcp/workspace.ts +0 -35
- package/src/core/persist/baseline.ts +0 -112
- package/src/core/persist/cost-log.ts +0 -30
- package/src/core/persist/findings-cache.ts +0 -43
- package/src/core/persist/triage.ts +0 -112
- package/src/core/phases/static-rules.ts +0 -93
- package/src/core/phases/tests.ts +0 -51
- package/src/core/pipeline/review-phase.ts +0 -182
- package/src/core/pipeline/run.ts +0 -116
- package/src/core/runtime/idempotency.ts +0 -6
- package/src/core/runtime/lock.ts +0 -29
- package/src/core/runtime/state.ts +0 -97
- package/src/core/schema-alignment/detector.ts +0 -59
- package/src/core/schema-alignment/extractor/index.ts +0 -24
- package/src/core/schema-alignment/extractor/prisma.ts +0 -21
- package/src/core/schema-alignment/extractor/sql.ts +0 -99
- package/src/core/schema-alignment/llm-check.ts +0 -91
- package/src/core/schema-alignment/scanner.ts +0 -107
- package/src/core/schema-alignment/types.ts +0 -43
- package/src/core/shell.ts +0 -48
- package/src/core/static-rules/registry.ts +0 -59
- package/src/core/static-rules/rules/brand-tokens.ts +0 -145
- package/src/core/static-rules/rules/console-log.ts +0 -42
- package/src/core/static-rules/rules/hardcoded-secrets.ts +0 -83
- package/src/core/static-rules/rules/insecure-redirect.ts +0 -67
- package/src/core/static-rules/rules/large-file.ts +0 -37
- package/src/core/static-rules/rules/missing-auth.ts +0 -70
- package/src/core/static-rules/rules/missing-tests.ts +0 -57
- package/src/core/static-rules/rules/npm-audit.ts +0 -38
- package/src/core/static-rules/rules/package-lock-sync.ts +0 -54
- package/src/core/static-rules/rules/schema-alignment.ts +0 -132
- package/src/core/static-rules/rules/sql-injection.ts +0 -71
- package/src/core/static-rules/rules/ssrf.ts +0 -63
- package/src/core/static-rules/rules/todo-fixme.ts +0 -40
- package/src/core/static-rules/tailwind-extractor.ts +0 -38
- package/src/core/test-gen/coverage-analyzer.ts +0 -93
- package/src/core/test-gen/framework-detector.ts +0 -21
- package/src/core/test-gen/test-writer.ts +0 -33
- package/src/core/ui/design-context-loader.ts +0 -87
- package/src/core/worker/client.ts +0 -46
- package/src/core/worker/lockfile.ts +0 -38
- package/src/core/worker/server.ts +0 -81
- package/src/formatters/github-annotations.ts +0 -36
- package/src/formatters/junit.ts +0 -52
- package/src/formatters/sarif.ts +0 -103
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import type { Finding } from '../findings/types.ts';
|
|
4
|
-
|
|
5
|
-
const BASELINE_FILE = '.guardrail-baseline.json';
|
|
6
|
-
|
|
7
|
-
export interface BaselineEntry {
|
|
8
|
-
id: string;
|
|
9
|
-
file: string;
|
|
10
|
-
line?: number;
|
|
11
|
-
severity: string;
|
|
12
|
-
message: string;
|
|
13
|
-
pinnedAt: string;
|
|
14
|
-
note?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface Baseline {
|
|
18
|
-
version: 1;
|
|
19
|
-
createdAt: string;
|
|
20
|
-
updatedAt: string;
|
|
21
|
-
note?: string;
|
|
22
|
-
entries: BaselineEntry[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** Stable key for matching a finding against a baseline entry. */
|
|
26
|
-
function baselineKey(f: { id: string; file: string; line?: number }): string {
|
|
27
|
-
return `${f.id}::${f.file}::${f.line ?? ''}`;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function baselineFilePath(cwd: string, overridePath?: string): string {
|
|
31
|
-
return overridePath
|
|
32
|
-
? path.isAbsolute(overridePath) ? overridePath : path.join(cwd, overridePath)
|
|
33
|
-
: path.join(cwd, BASELINE_FILE);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function loadBaseline(cwd: string, overridePath?: string): Baseline | null {
|
|
37
|
-
const p = baselineFilePath(cwd, overridePath);
|
|
38
|
-
if (!fs.existsSync(p)) return null;
|
|
39
|
-
try {
|
|
40
|
-
return JSON.parse(fs.readFileSync(p, 'utf8')) as Baseline;
|
|
41
|
-
} catch {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function saveBaseline(cwd: string, findings: Finding[], options: { note?: string; overridePath?: string } = {}): Baseline {
|
|
47
|
-
const existing = loadBaseline(cwd, options.overridePath);
|
|
48
|
-
const now = new Date().toISOString();
|
|
49
|
-
const baseline: Baseline = {
|
|
50
|
-
version: 1,
|
|
51
|
-
createdAt: existing?.createdAt ?? now,
|
|
52
|
-
updatedAt: now,
|
|
53
|
-
note: options.note ?? existing?.note,
|
|
54
|
-
entries: findings.map(f => ({
|
|
55
|
-
id: f.id,
|
|
56
|
-
file: f.file,
|
|
57
|
-
line: f.line,
|
|
58
|
-
severity: f.severity,
|
|
59
|
-
message: f.message,
|
|
60
|
-
pinnedAt: now,
|
|
61
|
-
})),
|
|
62
|
-
};
|
|
63
|
-
const p = baselineFilePath(cwd, options.overridePath);
|
|
64
|
-
const tmp = p + '.tmp';
|
|
65
|
-
fs.writeFileSync(tmp, JSON.stringify(baseline, null, 2), 'utf8');
|
|
66
|
-
fs.renameSync(tmp, p);
|
|
67
|
-
return baseline;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function clearBaseline(cwd: string, overridePath?: string): void {
|
|
71
|
-
const p = baselineFilePath(cwd, overridePath);
|
|
72
|
-
if (fs.existsSync(p)) fs.unlinkSync(p);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface BaselineFilterResult {
|
|
76
|
-
newFindings: Finding[];
|
|
77
|
-
baselinedFindings: Finding[];
|
|
78
|
-
baselinedCount: number;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** Returns findings NOT present in the baseline (new findings only). */
|
|
82
|
-
export function filterBaselined(findings: Finding[], baseline: Baseline): BaselineFilterResult {
|
|
83
|
-
const pinned = new Set(baseline.entries.map(baselineKey));
|
|
84
|
-
const newFindings: Finding[] = [];
|
|
85
|
-
const baselinedFindings: Finding[] = [];
|
|
86
|
-
for (const f of findings) {
|
|
87
|
-
if (pinned.has(baselineKey(f))) {
|
|
88
|
-
baselinedFindings.push(f);
|
|
89
|
-
} else {
|
|
90
|
-
newFindings.push(f);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return { newFindings, baselinedFindings, baselinedCount: baselinedFindings.length };
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export interface BaselineDiff {
|
|
97
|
-
added: Finding[]; // in current but not in baseline
|
|
98
|
-
resolved: BaselineEntry[]; // in baseline but not in current
|
|
99
|
-
unchanged: Finding[]; // in both
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/** Diff current findings against a baseline snapshot. */
|
|
103
|
-
export function diffAgainstBaseline(current: Finding[], baseline: Baseline): BaselineDiff {
|
|
104
|
-
const currentKeys = new Set(current.map(baselineKey));
|
|
105
|
-
const baselineKeys = new Set(baseline.entries.map(baselineKey));
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
added: current.filter(f => !baselineKeys.has(baselineKey(f))),
|
|
109
|
-
resolved: baseline.entries.filter(e => !currentKeys.has(baselineKey(e))),
|
|
110
|
-
unchanged: current.filter(f => baselineKeys.has(baselineKey(f))),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
|
|
4
|
-
const CACHE_DIR = '.guardrail-cache';
|
|
5
|
-
const LOG_FILE = 'costs.jsonl';
|
|
6
|
-
|
|
7
|
-
export interface CostLogEntry {
|
|
8
|
-
timestamp: string;
|
|
9
|
-
files: number;
|
|
10
|
-
inputTokens: number;
|
|
11
|
-
outputTokens: number;
|
|
12
|
-
costUSD: number;
|
|
13
|
-
durationMs: number;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function appendCostLog(cwd: string, entry: CostLogEntry): void {
|
|
17
|
-
const dir = path.join(cwd, CACHE_DIR);
|
|
18
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
19
|
-
fs.appendFileSync(path.join(dir, LOG_FILE), JSON.stringify(entry) + '\n', 'utf8');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function readCostLog(cwd: string): CostLogEntry[] {
|
|
23
|
-
const p = path.join(cwd, CACHE_DIR, LOG_FILE);
|
|
24
|
-
if (!fs.existsSync(p)) return [];
|
|
25
|
-
return fs.readFileSync(p, 'utf8')
|
|
26
|
-
.split('\n')
|
|
27
|
-
.filter(Boolean)
|
|
28
|
-
.map(line => { try { return JSON.parse(line) as CostLogEntry; } catch { return null; } })
|
|
29
|
-
.filter((e): e is CostLogEntry => e !== null);
|
|
30
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import type { Finding } from '../findings/types.ts';
|
|
4
|
-
|
|
5
|
-
const CACHE_DIR = '.guardrail-cache';
|
|
6
|
-
const CACHE_FILE = 'findings.json';
|
|
7
|
-
|
|
8
|
-
function cacheFilePath(cwd: string): string {
|
|
9
|
-
return path.join(cwd, CACHE_DIR, CACHE_FILE);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function findingKey(f: Finding): string {
|
|
13
|
-
return `${f.id}::${f.file}::${f.line ?? ''}`;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function loadCachedFindings(cwd: string): Finding[] {
|
|
17
|
-
const p = cacheFilePath(cwd);
|
|
18
|
-
if (!fs.existsSync(p)) return [];
|
|
19
|
-
try {
|
|
20
|
-
return JSON.parse(fs.readFileSync(p, 'utf8')) as Finding[];
|
|
21
|
-
} catch {
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function saveCachedFindings(cwd: string, findings: Finding[]): void {
|
|
27
|
-
const dir = path.join(cwd, CACHE_DIR);
|
|
28
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
29
|
-
// atomic write
|
|
30
|
-
const tmp = cacheFilePath(cwd) + '.tmp';
|
|
31
|
-
fs.writeFileSync(tmp, JSON.stringify(findings, null, 2), 'utf8');
|
|
32
|
-
fs.renameSync(tmp, cacheFilePath(cwd));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Returns only findings not present in the cached baseline.
|
|
37
|
-
* Two findings are considered the same when id + file + line all match.
|
|
38
|
-
*/
|
|
39
|
-
export function filterNewFindings(current: Finding[], cached: Finding[]): Finding[] {
|
|
40
|
-
if (cached.length === 0) return current;
|
|
41
|
-
const seen = new Set(cached.map(findingKey));
|
|
42
|
-
return current.filter(f => !seen.has(findingKey(f)));
|
|
43
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import type { Finding } from '../findings/types.ts';
|
|
4
|
-
|
|
5
|
-
const TRIAGE_FILE = '.guardrail-triage.json';
|
|
6
|
-
|
|
7
|
-
export type TriageState = 'accepted-risk' | 'false-positive';
|
|
8
|
-
|
|
9
|
-
export interface TriageEntry {
|
|
10
|
-
id: string;
|
|
11
|
-
file: string;
|
|
12
|
-
line?: number;
|
|
13
|
-
state: TriageState;
|
|
14
|
-
reason?: string;
|
|
15
|
-
triagedAt: string;
|
|
16
|
-
expiresAt?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface TriageStore {
|
|
20
|
-
version: 1;
|
|
21
|
-
entries: TriageEntry[];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function triageFilePath(cwd: string): string {
|
|
25
|
-
return path.join(cwd, TRIAGE_FILE);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function entryKey(e: { id: string; file: string; line?: number }): string {
|
|
29
|
-
return `${e.id}::${e.file}::${e.line ?? ''}`;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function loadTriage(cwd: string): TriageStore {
|
|
33
|
-
const p = triageFilePath(cwd);
|
|
34
|
-
if (!fs.existsSync(p)) return { version: 1, entries: [] };
|
|
35
|
-
try {
|
|
36
|
-
return JSON.parse(fs.readFileSync(p, 'utf8')) as TriageStore;
|
|
37
|
-
} catch {
|
|
38
|
-
return { version: 1, entries: [] };
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function saveTriage(cwd: string, store: TriageStore): void {
|
|
43
|
-
const p = triageFilePath(cwd);
|
|
44
|
-
const tmp = p + '.tmp';
|
|
45
|
-
fs.writeFileSync(tmp, JSON.stringify(store, null, 2), 'utf8');
|
|
46
|
-
fs.renameSync(tmp, p);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function addTriageEntry(
|
|
50
|
-
cwd: string,
|
|
51
|
-
finding: Finding,
|
|
52
|
-
state: TriageState,
|
|
53
|
-
options: { reason?: string; expiresInDays?: number } = {},
|
|
54
|
-
): void {
|
|
55
|
-
const store = loadTriage(cwd);
|
|
56
|
-
const key = entryKey(finding);
|
|
57
|
-
store.entries = store.entries.filter(e => entryKey(e) !== key);
|
|
58
|
-
const entry: TriageEntry = {
|
|
59
|
-
id: finding.id,
|
|
60
|
-
file: finding.file,
|
|
61
|
-
line: finding.line,
|
|
62
|
-
state,
|
|
63
|
-
reason: options.reason,
|
|
64
|
-
triagedAt: new Date().toISOString(),
|
|
65
|
-
};
|
|
66
|
-
if (options.expiresInDays !== undefined) {
|
|
67
|
-
const exp = new Date();
|
|
68
|
-
exp.setDate(exp.getDate() + options.expiresInDays);
|
|
69
|
-
entry.expiresAt = exp.toISOString();
|
|
70
|
-
}
|
|
71
|
-
store.entries.push(entry);
|
|
72
|
-
saveTriage(cwd, store);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function removeTriageEntry(cwd: string, ids: string[]): number {
|
|
76
|
-
const store = loadTriage(cwd);
|
|
77
|
-
const before = store.entries.length;
|
|
78
|
-
store.entries = store.entries.filter(e => !ids.some(id => e.id === id || e.id.startsWith(id)));
|
|
79
|
-
saveTriage(cwd, store);
|
|
80
|
-
return before - store.entries.length;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function clearExpiredEntries(cwd: string): number {
|
|
84
|
-
const store = loadTriage(cwd);
|
|
85
|
-
const now = new Date().toISOString();
|
|
86
|
-
const before = store.entries.length;
|
|
87
|
-
store.entries = store.entries.filter(e => !e.expiresAt || e.expiresAt > now);
|
|
88
|
-
saveTriage(cwd, store);
|
|
89
|
-
return before - store.entries.length;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export interface TriageFilterResult {
|
|
93
|
-
active: Finding[];
|
|
94
|
-
triaged: Finding[];
|
|
95
|
-
triageCount: number;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function filterTriaged(findings: Finding[], store: TriageStore): TriageFilterResult {
|
|
99
|
-
const now = new Date().toISOString();
|
|
100
|
-
const activeKeys = new Set(
|
|
101
|
-
store.entries
|
|
102
|
-
.filter(e => !e.expiresAt || e.expiresAt > now)
|
|
103
|
-
.map(entryKey),
|
|
104
|
-
);
|
|
105
|
-
const active: Finding[] = [];
|
|
106
|
-
const triaged: Finding[] = [];
|
|
107
|
-
for (const f of findings) {
|
|
108
|
-
if (activeKeys.has(entryKey(f))) triaged.push(f);
|
|
109
|
-
else active.push(f);
|
|
110
|
-
}
|
|
111
|
-
return { active, triaged, triageCount: triaged.length };
|
|
112
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import type { Finding, FixAttempt, FixStatus } from '../findings/types.ts';
|
|
2
|
-
import type { GuardrailConfig } from '../config/types.ts';
|
|
3
|
-
import type { ReviewEngine } from '../../adapters/review-engine/types.ts';
|
|
4
|
-
import { dedupFindings, findingContentKey } from '../findings/dedup.ts';
|
|
5
|
-
|
|
6
|
-
export interface StaticRule {
|
|
7
|
-
name: string;
|
|
8
|
-
severity: 'critical' | 'warning' | 'note';
|
|
9
|
-
check(touchedFiles: string[], config?: Record<string, unknown>): Promise<Finding[]>;
|
|
10
|
-
autofix?(finding: Finding): Promise<FixStatus>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface StaticRulesPhaseInput {
|
|
14
|
-
touchedFiles: string[];
|
|
15
|
-
rules: StaticRule[];
|
|
16
|
-
config?: GuardrailConfig;
|
|
17
|
-
engine?: ReviewEngine;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface StaticRulesPhaseResult {
|
|
21
|
-
phase: 'static-rules';
|
|
22
|
-
status: 'pass' | 'warn' | 'fail';
|
|
23
|
-
findings: Finding[];
|
|
24
|
-
fixAttempts: FixAttempt[];
|
|
25
|
-
durationMs: number;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export async function runStaticRulesPhase(input: StaticRulesPhaseInput): Promise<StaticRulesPhaseResult> {
|
|
29
|
-
const start = Date.now();
|
|
30
|
-
|
|
31
|
-
const preFixFindings = dedupFindings(await runAllChecks(input.rules, input.touchedFiles, input.config, input.engine));
|
|
32
|
-
|
|
33
|
-
const fixAttempts: FixAttempt[] = [];
|
|
34
|
-
let anyFixApplied = false;
|
|
35
|
-
|
|
36
|
-
for (const finding of preFixFindings) {
|
|
37
|
-
const rule = findRuleForFinding(input.rules, finding);
|
|
38
|
-
if (!rule?.autofix) continue;
|
|
39
|
-
|
|
40
|
-
if (finding.protectedPath) {
|
|
41
|
-
fixAttempts.push({
|
|
42
|
-
findingId: finding.id,
|
|
43
|
-
attemptedAt: new Date().toISOString(),
|
|
44
|
-
status: 'skipped',
|
|
45
|
-
notes: 'protected path',
|
|
46
|
-
});
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const status = await rule.autofix(finding);
|
|
51
|
-
if (status === 'fixed') anyFixApplied = true;
|
|
52
|
-
fixAttempts.push({ findingId: finding.id, attemptedAt: new Date().toISOString(), status });
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Re-check is the source of truth for what persists after autofix.
|
|
56
|
-
// findings always returns preFixFindings so callers have a complete record;
|
|
57
|
-
// fixAttempts + re-check set-difference tells them what was resolved.
|
|
58
|
-
const postFixFindings = anyFixApplied
|
|
59
|
-
? dedupFindings(await runAllChecks(input.rules, input.touchedFiles, input.config, input.engine))
|
|
60
|
-
: preFixFindings;
|
|
61
|
-
|
|
62
|
-
const postFixKeys = new Set(postFixFindings.map(findingContentKey));
|
|
63
|
-
const isFixed = (f: Finding): boolean => !postFixKeys.has(findingContentKey(f));
|
|
64
|
-
|
|
65
|
-
const unfixedCritical = preFixFindings.some(f => f.severity === 'critical' && !isFixed(f));
|
|
66
|
-
const unfixedWarning = preFixFindings.some(f => f.severity === 'warning' && !isFixed(f));
|
|
67
|
-
|
|
68
|
-
let status: StaticRulesPhaseResult['status'];
|
|
69
|
-
if (unfixedCritical) status = 'fail';
|
|
70
|
-
else if (unfixedWarning) status = 'warn';
|
|
71
|
-
else status = 'pass';
|
|
72
|
-
|
|
73
|
-
return { phase: 'static-rules', status, findings: preFixFindings, fixAttempts, durationMs: Date.now() - start };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function runAllChecks(
|
|
77
|
-
rules: StaticRule[],
|
|
78
|
-
files: string[],
|
|
79
|
-
config?: GuardrailConfig,
|
|
80
|
-
engine?: ReviewEngine,
|
|
81
|
-
): Promise<Finding[]> {
|
|
82
|
-
const ruleConfig: Record<string, unknown> = {
|
|
83
|
-
...(config ? (config as unknown as Record<string, unknown>) : {}),
|
|
84
|
-
_engine: engine,
|
|
85
|
-
};
|
|
86
|
-
const all: Finding[] = [];
|
|
87
|
-
for (const rule of rules) all.push(...(await rule.check(files, ruleConfig)));
|
|
88
|
-
return all;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function findRuleForFinding(rules: StaticRule[], finding: Finding): StaticRule | undefined {
|
|
92
|
-
return rules.find(r => r.name === finding.category) ?? rules.find(r => finding.category.includes(r.name));
|
|
93
|
-
}
|
package/src/core/phases/tests.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
|
-
import type { Finding } from '../findings/types.ts';
|
|
3
|
-
|
|
4
|
-
export interface TestsPhaseInput {
|
|
5
|
-
touchedFiles: string[];
|
|
6
|
-
testCommand?: string | null;
|
|
7
|
-
cwd?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface TestsPhaseResult {
|
|
11
|
-
phase: 'tests';
|
|
12
|
-
status: 'pass' | 'fail' | 'skip';
|
|
13
|
-
findings: Finding[];
|
|
14
|
-
output?: string;
|
|
15
|
-
durationMs: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function runTestsPhase(input: TestsPhaseInput): Promise<TestsPhaseResult> {
|
|
19
|
-
const start = Date.now();
|
|
20
|
-
|
|
21
|
-
if (!input.testCommand) {
|
|
22
|
-
return { phase: 'tests', status: 'skip', findings: [], durationMs: Date.now() - start };
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
let output: string | undefined;
|
|
26
|
-
try {
|
|
27
|
-
// shell:true is intentional — testCommand is developer-supplied config, supports quoted args + pipes.
|
|
28
|
-
output = execSync(input.testCommand, {
|
|
29
|
-
encoding: 'utf8',
|
|
30
|
-
cwd: input.cwd,
|
|
31
|
-
timeout: 120000,
|
|
32
|
-
shell: process.env.SHELL ?? "/bin/sh",
|
|
33
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
34
|
-
});
|
|
35
|
-
} catch {
|
|
36
|
-
const finding: Finding = {
|
|
37
|
-
id: 'tests-phase-fail',
|
|
38
|
-
source: 'static-rules',
|
|
39
|
-
severity: 'critical',
|
|
40
|
-
category: 'test-failure',
|
|
41
|
-
file: '<tests>',
|
|
42
|
-
message: `Test command failed: ${input.testCommand}`,
|
|
43
|
-
suggestion: 'Fix failing tests before merging',
|
|
44
|
-
protectedPath: false,
|
|
45
|
-
createdAt: new Date().toISOString(),
|
|
46
|
-
};
|
|
47
|
-
return { phase: 'tests', status: 'fail', findings: [finding], output: undefined, durationMs: Date.now() - start };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return { phase: 'tests', status: 'pass', findings: [], output, durationMs: Date.now() - start };
|
|
51
|
-
}
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import type { ReviewEngine } from '../../adapters/review-engine/types.ts';
|
|
2
|
-
import type { Finding } from '../findings/types.ts';
|
|
3
|
-
import type { GuardrailConfig } from '../config/types.ts';
|
|
4
|
-
import { buildReviewChunks, type ReviewChunk } from '../chunking/index.ts';
|
|
5
|
-
import { GuardrailError } from '../errors.ts';
|
|
6
|
-
import { hasFrontendFiles, loadDesignContext } from '../ui/design-context-loader.ts';
|
|
7
|
-
|
|
8
|
-
export interface ReviewPhaseResult {
|
|
9
|
-
phase: 'review';
|
|
10
|
-
status: 'pass' | 'warn' | 'fail' | 'skip';
|
|
11
|
-
findings: Finding[];
|
|
12
|
-
rawOutputs?: string[];
|
|
13
|
-
costUSD?: number;
|
|
14
|
-
usage?: { input: number; output: number };
|
|
15
|
-
durationMs: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ReviewPhaseInput {
|
|
19
|
-
touchedFiles: string[];
|
|
20
|
-
engine: ReviewEngine;
|
|
21
|
-
config: GuardrailConfig;
|
|
22
|
-
cwd?: string;
|
|
23
|
-
gitSummary?: string;
|
|
24
|
-
designSchema?: string;
|
|
25
|
-
budgetRemainingUSD?: number;
|
|
26
|
-
base?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface ChunkResult {
|
|
30
|
-
findings: Finding[];
|
|
31
|
-
rawOutput: string;
|
|
32
|
-
inputTokens: number;
|
|
33
|
-
outputTokens: number;
|
|
34
|
-
costUSD: number;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function backoffMs(attempt: number, strategy: 'exp' | 'linear' | 'none'): number {
|
|
38
|
-
if (strategy === 'none') return 0;
|
|
39
|
-
if (strategy === 'linear') return attempt * 2000;
|
|
40
|
-
return Math.min(Math.pow(2, attempt) * 1000, 32000); // exp: 1s, 2s, 4s, 8s … 32s cap
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function reviewChunkWithRetry(chunk: ReviewChunk, input: ReviewPhaseInput): Promise<ChunkResult> {
|
|
44
|
-
const strategy = input.config.chunking?.rateLimitBackoff ?? 'exp';
|
|
45
|
-
const maxAttempts = strategy === 'none' ? 1 : 4;
|
|
46
|
-
|
|
47
|
-
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
48
|
-
try {
|
|
49
|
-
const output = await input.engine.review({
|
|
50
|
-
content: chunk.content,
|
|
51
|
-
kind: chunk.kind,
|
|
52
|
-
context: { stack: input.config.stack, cwd: input.cwd, gitSummary: input.gitSummary, designSchema: input.designSchema },
|
|
53
|
-
});
|
|
54
|
-
return {
|
|
55
|
-
findings: output.findings,
|
|
56
|
-
rawOutput: output.rawOutput,
|
|
57
|
-
inputTokens: output.usage?.input ?? 0,
|
|
58
|
-
outputTokens: output.usage?.output ?? 0,
|
|
59
|
-
costUSD: output.usage?.costUSD ?? 0,
|
|
60
|
-
};
|
|
61
|
-
} catch (err) {
|
|
62
|
-
const isRateLimit = err instanceof GuardrailError && err.code === 'rate_limit';
|
|
63
|
-
const isLast = attempt === maxAttempts - 1;
|
|
64
|
-
if (!isRateLimit || isLast) throw err;
|
|
65
|
-
const delay = backoffMs(attempt + 1, strategy);
|
|
66
|
-
await new Promise(r => setTimeout(r, delay));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
throw new Error('unreachable');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/** Run up to `limit` promises concurrently, preserving result order. */
|
|
73
|
-
async function pMap<T, R>(
|
|
74
|
-
items: T[],
|
|
75
|
-
fn: (item: T, index: number) => Promise<R>,
|
|
76
|
-
limit: number,
|
|
77
|
-
): Promise<R[]> {
|
|
78
|
-
const results: R[] = new Array(items.length);
|
|
79
|
-
let next = 0;
|
|
80
|
-
|
|
81
|
-
async function worker(): Promise<void> {
|
|
82
|
-
while (next < items.length) {
|
|
83
|
-
const i = next++;
|
|
84
|
-
results[i] = await fn(items[i]!, i);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const workers = Array.from({ length: Math.min(limit, items.length) }, () => worker());
|
|
89
|
-
await Promise.all(workers);
|
|
90
|
-
return results;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export async function runReviewPhase(input: ReviewPhaseInput): Promise<ReviewPhaseResult> {
|
|
94
|
-
const start = Date.now();
|
|
95
|
-
|
|
96
|
-
if (input.touchedFiles.length === 0) {
|
|
97
|
-
return { phase: 'review', status: 'skip', findings: [], durationMs: Date.now() - start };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
let designSchema: string | undefined;
|
|
101
|
-
if (hasFrontendFiles(input.touchedFiles) && input.config.brand?.componentLibrary) {
|
|
102
|
-
const loaded = loadDesignContext(
|
|
103
|
-
input.config.brand.componentLibrary,
|
|
104
|
-
input.cwd ?? process.cwd(),
|
|
105
|
-
);
|
|
106
|
-
if (loaded) designSchema = loaded;
|
|
107
|
-
}
|
|
108
|
-
const enrichedInput: ReviewPhaseInput = designSchema ? { ...input, designSchema } : input;
|
|
109
|
-
|
|
110
|
-
const chunks = await buildReviewChunks({
|
|
111
|
-
touchedFiles: enrichedInput.touchedFiles,
|
|
112
|
-
strategy: enrichedInput.config.reviewStrategy ?? 'auto',
|
|
113
|
-
chunking: enrichedInput.config.chunking,
|
|
114
|
-
engine: enrichedInput.engine,
|
|
115
|
-
cwd: enrichedInput.cwd,
|
|
116
|
-
protectedPaths: enrichedInput.config.protectedPaths,
|
|
117
|
-
base: enrichedInput.base,
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const parallelism = enrichedInput.config.chunking?.parallelism ?? 3;
|
|
121
|
-
const budgetUSD = enrichedInput.budgetRemainingUSD;
|
|
122
|
-
|
|
123
|
-
// For budget tracking we still need to enforce it — run serially if budget set,
|
|
124
|
-
// parallel otherwise (budget check between serial chunks is the safe path).
|
|
125
|
-
let chunkResults: ChunkResult[];
|
|
126
|
-
if (budgetUSD !== undefined) {
|
|
127
|
-
chunkResults = [];
|
|
128
|
-
let spent = 0;
|
|
129
|
-
let budgetExceeded = false;
|
|
130
|
-
for (const chunk of chunks) {
|
|
131
|
-
if (spent >= budgetUSD) { budgetExceeded = true; break; }
|
|
132
|
-
const r = await reviewChunkWithRetry(chunk, enrichedInput);
|
|
133
|
-
spent += r.costUSD;
|
|
134
|
-
chunkResults.push(r);
|
|
135
|
-
}
|
|
136
|
-
if (budgetExceeded) {
|
|
137
|
-
chunkResults.push({
|
|
138
|
-
findings: [{
|
|
139
|
-
id: 'budget-exceeded',
|
|
140
|
-
source: 'pipeline',
|
|
141
|
-
severity: 'warning',
|
|
142
|
-
category: 'budget',
|
|
143
|
-
file: '<pipeline>',
|
|
144
|
-
message: `Review budget of $${budgetUSD} USD exceeded — remaining chunks skipped`,
|
|
145
|
-
protectedPath: false,
|
|
146
|
-
createdAt: new Date().toISOString(),
|
|
147
|
-
}],
|
|
148
|
-
rawOutput: '', inputTokens: 0, outputTokens: 0, costUSD: 0,
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
} else {
|
|
152
|
-
chunkResults = await pMap(chunks, chunk => reviewChunkWithRetry(chunk, enrichedInput), parallelism);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
let totalInputTokens = 0;
|
|
156
|
-
let totalOutputTokens = 0;
|
|
157
|
-
let totalCostUSD = 0;
|
|
158
|
-
const allFindings: Finding[] = [];
|
|
159
|
-
const allRawOutputs: string[] = [];
|
|
160
|
-
|
|
161
|
-
for (const r of chunkResults) {
|
|
162
|
-
allFindings.push(...r.findings);
|
|
163
|
-
if (r.rawOutput) allRawOutputs.push(r.rawOutput);
|
|
164
|
-
totalInputTokens += r.inputTokens;
|
|
165
|
-
totalOutputTokens += r.outputTokens;
|
|
166
|
-
totalCostUSD += r.costUSD;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const hasCritical = allFindings.some(f => f.severity === 'critical');
|
|
170
|
-
const hasWarning = allFindings.some(f => f.severity === 'warning');
|
|
171
|
-
const status = hasCritical ? 'fail' : hasWarning ? 'warn' : 'pass';
|
|
172
|
-
|
|
173
|
-
return {
|
|
174
|
-
phase: 'review',
|
|
175
|
-
status,
|
|
176
|
-
findings: allFindings,
|
|
177
|
-
rawOutputs: allRawOutputs.length > 0 ? allRawOutputs : undefined,
|
|
178
|
-
costUSD: totalCostUSD > 0 ? totalCostUSD : undefined,
|
|
179
|
-
usage: totalInputTokens > 0 ? { input: totalInputTokens, output: totalOutputTokens } : undefined,
|
|
180
|
-
durationMs: Date.now() - start,
|
|
181
|
-
};
|
|
182
|
-
}
|