@delegance/claude-autopilot 5.0.1 → 5.0.3
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/src/adapters/review-engine/codex.js +13 -1
- package/dist/src/cli/index.js +39 -1
- package/dist/src/cli/preflight.js +17 -4
- package/dist/src/cli/scan.js +12 -0
- package/package.json +4 -3
- package/dist/presets/go/rules/go-sql-injection.d.ts.map +0 -1
- package/dist/presets/go/rules/go-sql-injection.js.map +0 -1
- package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.d.ts.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.d.ts.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.d.ts.map +0 -1
- package/dist/presets/rails-postgres/rules/rails-sql-injection.js.map +0 -1
- package/dist/presets/t3/rules/t3-server-only.d.ts.map +0 -1
- package/dist/presets/t3/rules/t3-server-only.js.map +0 -1
- package/dist/src/adapters/base.d.ts.map +0 -1
- package/dist/src/adapters/base.js.map +0 -1
- package/dist/src/adapters/council/claude.d.ts.map +0 -1
- package/dist/src/adapters/council/claude.js.map +0 -1
- package/dist/src/adapters/council/openai.d.ts.map +0 -1
- package/dist/src/adapters/council/openai.js.map +0 -1
- package/dist/src/adapters/council/types.d.ts.map +0 -1
- package/dist/src/adapters/council/types.js.map +0 -1
- package/dist/src/adapters/loader.d.ts.map +0 -1
- package/dist/src/adapters/loader.js.map +0 -1
- package/dist/src/adapters/migration-runner/supabase.d.ts.map +0 -1
- package/dist/src/adapters/migration-runner/supabase.js.map +0 -1
- package/dist/src/adapters/migration-runner/types.d.ts.map +0 -1
- package/dist/src/adapters/migration-runner/types.js.map +0 -1
- package/dist/src/adapters/review-bot-parser/cursor.d.ts.map +0 -1
- package/dist/src/adapters/review-bot-parser/cursor.js.map +0 -1
- package/dist/src/adapters/review-bot-parser/declarative-base.d.ts.map +0 -1
- package/dist/src/adapters/review-bot-parser/declarative-base.js.map +0 -1
- package/dist/src/adapters/review-bot-parser/types.d.ts.map +0 -1
- package/dist/src/adapters/review-bot-parser/types.js.map +0 -1
- package/dist/src/adapters/review-engine/auto.d.ts.map +0 -1
- package/dist/src/adapters/review-engine/auto.js.map +0 -1
- package/dist/src/adapters/review-engine/claude.d.ts.map +0 -1
- package/dist/src/adapters/review-engine/claude.js.map +0 -1
- package/dist/src/adapters/review-engine/codex.d.ts.map +0 -1
- package/dist/src/adapters/review-engine/codex.js.map +0 -1
- package/dist/src/adapters/review-engine/gemini.d.ts.map +0 -1
- package/dist/src/adapters/review-engine/gemini.js.map +0 -1
- package/dist/src/adapters/review-engine/openai-compatible.d.ts.map +0 -1
- package/dist/src/adapters/review-engine/openai-compatible.js.map +0 -1
- package/dist/src/adapters/review-engine/parse-output.d.ts.map +0 -1
- package/dist/src/adapters/review-engine/parse-output.js.map +0 -1
- package/dist/src/adapters/review-engine/prompt-builder.d.ts.map +0 -1
- package/dist/src/adapters/review-engine/prompt-builder.js.map +0 -1
- package/dist/src/adapters/review-engine/types.d.ts.map +0 -1
- package/dist/src/adapters/review-engine/types.js.map +0 -1
- package/dist/src/adapters/vcs-host/commit-status.d.ts.map +0 -1
- package/dist/src/adapters/vcs-host/commit-status.js.map +0 -1
- package/dist/src/adapters/vcs-host/github.d.ts.map +0 -1
- package/dist/src/adapters/vcs-host/github.js.map +0 -1
- package/dist/src/adapters/vcs-host/types.d.ts.map +0 -1
- package/dist/src/adapters/vcs-host/types.js.map +0 -1
- package/dist/src/cli/_pkg-root.d.ts.map +0 -1
- package/dist/src/cli/_pkg-root.js.map +0 -1
- package/dist/src/cli/autoregress-bridge.d.ts.map +0 -1
- package/dist/src/cli/autoregress-bridge.js.map +0 -1
- package/dist/src/cli/baseline.d.ts.map +0 -1
- package/dist/src/cli/baseline.js.map +0 -1
- package/dist/src/cli/ci.d.ts.map +0 -1
- package/dist/src/cli/ci.js.map +0 -1
- package/dist/src/cli/costs.d.ts.map +0 -1
- package/dist/src/cli/costs.js.map +0 -1
- package/dist/src/cli/council.d.ts.map +0 -1
- package/dist/src/cli/council.js.map +0 -1
- package/dist/src/cli/detector.d.ts.map +0 -1
- package/dist/src/cli/detector.js.map +0 -1
- package/dist/src/cli/explain.d.ts.map +0 -1
- package/dist/src/cli/explain.js.map +0 -1
- package/dist/src/cli/fix.d.ts.map +0 -1
- package/dist/src/cli/fix.js.map +0 -1
- package/dist/src/cli/hook.d.ts.map +0 -1
- package/dist/src/cli/hook.js.map +0 -1
- package/dist/src/cli/ignore-helper.d.ts.map +0 -1
- package/dist/src/cli/ignore-helper.js.map +0 -1
- package/dist/src/cli/index.d.ts.map +0 -1
- package/dist/src/cli/index.js.map +0 -1
- package/dist/src/cli/lsp.d.ts.map +0 -1
- package/dist/src/cli/lsp.js.map +0 -1
- package/dist/src/cli/mcp.d.ts.map +0 -1
- package/dist/src/cli/mcp.js.map +0 -1
- package/dist/src/cli/migrate-v4.d.ts.map +0 -1
- package/dist/src/cli/migrate-v4.js.map +0 -1
- package/dist/src/cli/pr-comment.d.ts.map +0 -1
- package/dist/src/cli/pr-comment.js.map +0 -1
- package/dist/src/cli/pr-desc.d.ts.map +0 -1
- package/dist/src/cli/pr-desc.js.map +0 -1
- package/dist/src/cli/pr-review-comments.d.ts.map +0 -1
- package/dist/src/cli/pr-review-comments.js.map +0 -1
- package/dist/src/cli/pr.d.ts.map +0 -1
- package/dist/src/cli/pr.js.map +0 -1
- package/dist/src/cli/preflight.d.ts.map +0 -1
- package/dist/src/cli/preflight.js.map +0 -1
- package/dist/src/cli/report.d.ts.map +0 -1
- package/dist/src/cli/report.js.map +0 -1
- package/dist/src/cli/run.d.ts.map +0 -1
- package/dist/src/cli/run.js.map +0 -1
- package/dist/src/cli/scan.d.ts.map +0 -1
- package/dist/src/cli/scan.js.map +0 -1
- package/dist/src/cli/setup.d.ts.map +0 -1
- package/dist/src/cli/setup.js.map +0 -1
- package/dist/src/cli/test-gen.d.ts.map +0 -1
- package/dist/src/cli/test-gen.js.map +0 -1
- package/dist/src/cli/triage.d.ts.map +0 -1
- package/dist/src/cli/triage.js.map +0 -1
- package/dist/src/cli/watch.d.ts.map +0 -1
- package/dist/src/cli/watch.js.map +0 -1
- package/dist/src/cli/worker.d.ts.map +0 -1
- package/dist/src/cli/worker.js.map +0 -1
- package/dist/src/core/cache/cached-engine.d.ts.map +0 -1
- package/dist/src/core/cache/cached-engine.js.map +0 -1
- package/dist/src/core/cache/review-cache.d.ts.map +0 -1
- package/dist/src/core/cache/review-cache.js.map +0 -1
- package/dist/src/core/chunking/index.d.ts.map +0 -1
- package/dist/src/core/chunking/index.js.map +0 -1
- package/dist/src/core/chunking/risk-ranker.d.ts.map +0 -1
- package/dist/src/core/chunking/risk-ranker.js.map +0 -1
- package/dist/src/core/config/loader.d.ts.map +0 -1
- package/dist/src/core/config/loader.js.map +0 -1
- package/dist/src/core/config/preset-resolver.d.ts.map +0 -1
- package/dist/src/core/config/preset-resolver.js.map +0 -1
- package/dist/src/core/config/schema.d.ts.map +0 -1
- package/dist/src/core/config/schema.js.map +0 -1
- package/dist/src/core/config/types.d.ts.map +0 -1
- package/dist/src/core/config/types.js.map +0 -1
- package/dist/src/core/council/config.d.ts.map +0 -1
- package/dist/src/core/council/config.js.map +0 -1
- package/dist/src/core/council/context.d.ts.map +0 -1
- package/dist/src/core/council/context.js.map +0 -1
- package/dist/src/core/council/runner.d.ts.map +0 -1
- package/dist/src/core/council/runner.js.map +0 -1
- package/dist/src/core/council/types.d.ts.map +0 -1
- package/dist/src/core/council/types.js.map +0 -1
- package/dist/src/core/detect/git-context.d.ts.map +0 -1
- package/dist/src/core/detect/git-context.js.map +0 -1
- package/dist/src/core/detect/llm-key.d.ts.map +0 -1
- package/dist/src/core/detect/llm-key.js.map +0 -1
- package/dist/src/core/detect/protected-paths.d.ts.map +0 -1
- package/dist/src/core/detect/protected-paths.js.map +0 -1
- package/dist/src/core/detect/provider-usage.d.ts.map +0 -1
- package/dist/src/core/detect/provider-usage.js.map +0 -1
- package/dist/src/core/detect/stack.d.ts.map +0 -1
- package/dist/src/core/detect/stack.js.map +0 -1
- package/dist/src/core/detect/workspaces.d.ts.map +0 -1
- package/dist/src/core/detect/workspaces.js.map +0 -1
- package/dist/src/core/errors.d.ts.map +0 -1
- package/dist/src/core/errors.js.map +0 -1
- package/dist/src/core/findings/dedup.d.ts.map +0 -1
- package/dist/src/core/findings/dedup.js.map +0 -1
- package/dist/src/core/findings/types.d.ts.map +0 -1
- package/dist/src/core/findings/types.js.map +0 -1
- package/dist/src/core/fix/generator.d.ts.map +0 -1
- package/dist/src/core/fix/generator.js.map +0 -1
- package/dist/src/core/git/diff-hunks.d.ts.map +0 -1
- package/dist/src/core/git/diff-hunks.js.map +0 -1
- package/dist/src/core/git/touched-files.d.ts.map +0 -1
- package/dist/src/core/git/touched-files.js.map +0 -1
- package/dist/src/core/ignore/index.d.ts.map +0 -1
- package/dist/src/core/ignore/index.js.map +0 -1
- package/dist/src/core/index.d.ts.map +0 -1
- package/dist/src/core/index.js.map +0 -1
- package/dist/src/core/logging/ndjson-writer.d.ts.map +0 -1
- package/dist/src/core/logging/ndjson-writer.js.map +0 -1
- package/dist/src/core/logging/redaction.d.ts.map +0 -1
- package/dist/src/core/logging/redaction.js.map +0 -1
- package/dist/src/core/mcp/concurrency.d.ts.map +0 -1
- package/dist/src/core/mcp/concurrency.js.map +0 -1
- package/dist/src/core/mcp/handlers/fix-finding.d.ts.map +0 -1
- package/dist/src/core/mcp/handlers/fix-finding.js.map +0 -1
- package/dist/src/core/mcp/handlers/get-capabilities.d.ts.map +0 -1
- package/dist/src/core/mcp/handlers/get-capabilities.js.map +0 -1
- package/dist/src/core/mcp/handlers/get-findings.d.ts.map +0 -1
- package/dist/src/core/mcp/handlers/get-findings.js.map +0 -1
- package/dist/src/core/mcp/handlers/review-diff.d.ts.map +0 -1
- package/dist/src/core/mcp/handlers/review-diff.js.map +0 -1
- package/dist/src/core/mcp/handlers/scan-files.d.ts.map +0 -1
- package/dist/src/core/mcp/handlers/scan-files.js.map +0 -1
- package/dist/src/core/mcp/handlers/validate-fix.d.ts.map +0 -1
- package/dist/src/core/mcp/handlers/validate-fix.js.map +0 -1
- package/dist/src/core/mcp/run-store.d.ts.map +0 -1
- package/dist/src/core/mcp/run-store.js.map +0 -1
- package/dist/src/core/mcp/workspace.d.ts.map +0 -1
- package/dist/src/core/mcp/workspace.js.map +0 -1
- package/dist/src/core/persist/baseline.d.ts.map +0 -1
- package/dist/src/core/persist/baseline.js.map +0 -1
- package/dist/src/core/persist/cost-log.d.ts.map +0 -1
- package/dist/src/core/persist/cost-log.js.map +0 -1
- package/dist/src/core/persist/findings-cache.d.ts.map +0 -1
- package/dist/src/core/persist/findings-cache.js.map +0 -1
- package/dist/src/core/persist/triage.d.ts.map +0 -1
- package/dist/src/core/persist/triage.js.map +0 -1
- package/dist/src/core/phases/static-rules.d.ts.map +0 -1
- package/dist/src/core/phases/static-rules.js.map +0 -1
- package/dist/src/core/phases/tests.d.ts.map +0 -1
- package/dist/src/core/phases/tests.js.map +0 -1
- package/dist/src/core/pipeline/review-phase.d.ts.map +0 -1
- package/dist/src/core/pipeline/review-phase.js.map +0 -1
- package/dist/src/core/pipeline/run.d.ts.map +0 -1
- package/dist/src/core/pipeline/run.js.map +0 -1
- package/dist/src/core/runtime/idempotency.d.ts.map +0 -1
- package/dist/src/core/runtime/idempotency.js.map +0 -1
- package/dist/src/core/runtime/lock.d.ts.map +0 -1
- package/dist/src/core/runtime/lock.js.map +0 -1
- package/dist/src/core/runtime/state.d.ts.map +0 -1
- package/dist/src/core/runtime/state.js.map +0 -1
- package/dist/src/core/schema-alignment/detector.d.ts.map +0 -1
- package/dist/src/core/schema-alignment/detector.js.map +0 -1
- package/dist/src/core/schema-alignment/extractor/index.d.ts.map +0 -1
- package/dist/src/core/schema-alignment/extractor/index.js.map +0 -1
- package/dist/src/core/schema-alignment/extractor/prisma.d.ts.map +0 -1
- package/dist/src/core/schema-alignment/extractor/prisma.js.map +0 -1
- package/dist/src/core/schema-alignment/extractor/sql.d.ts.map +0 -1
- package/dist/src/core/schema-alignment/extractor/sql.js.map +0 -1
- package/dist/src/core/schema-alignment/llm-check.d.ts.map +0 -1
- package/dist/src/core/schema-alignment/llm-check.js.map +0 -1
- package/dist/src/core/schema-alignment/scanner.d.ts.map +0 -1
- package/dist/src/core/schema-alignment/scanner.js.map +0 -1
- package/dist/src/core/schema-alignment/types.d.ts.map +0 -1
- package/dist/src/core/schema-alignment/types.js.map +0 -1
- package/dist/src/core/shell.d.ts.map +0 -1
- package/dist/src/core/shell.js.map +0 -1
- package/dist/src/core/static-rules/registry.d.ts.map +0 -1
- package/dist/src/core/static-rules/registry.js.map +0 -1
- package/dist/src/core/static-rules/rules/brand-tokens.d.ts.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.d.ts.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.d.ts.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.d.ts.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.d.ts.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.d.ts.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.d.ts.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.d.ts.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.d.ts.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.d.ts.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.d.ts.map +0 -1
- package/dist/src/core/static-rules/rules/sql-injection.js.map +0 -1
- package/dist/src/core/static-rules/rules/ssrf.d.ts.map +0 -1
- package/dist/src/core/static-rules/rules/ssrf.js.map +0 -1
- package/dist/src/core/static-rules/rules/todo-fixme.d.ts.map +0 -1
- package/dist/src/core/static-rules/rules/todo-fixme.js.map +0 -1
- package/dist/src/core/static-rules/tailwind-extractor.d.ts.map +0 -1
- package/dist/src/core/static-rules/tailwind-extractor.js.map +0 -1
- package/dist/src/core/test-gen/coverage-analyzer.d.ts.map +0 -1
- package/dist/src/core/test-gen/coverage-analyzer.js.map +0 -1
- package/dist/src/core/test-gen/framework-detector.d.ts.map +0 -1
- package/dist/src/core/test-gen/framework-detector.js.map +0 -1
- package/dist/src/core/test-gen/test-writer.d.ts.map +0 -1
- package/dist/src/core/test-gen/test-writer.js.map +0 -1
- package/dist/src/core/ui/design-context-loader.d.ts.map +0 -1
- package/dist/src/core/ui/design-context-loader.js.map +0 -1
- package/dist/src/core/worker/client.d.ts.map +0 -1
- package/dist/src/core/worker/client.js.map +0 -1
- package/dist/src/core/worker/lockfile.d.ts.map +0 -1
- package/dist/src/core/worker/lockfile.js.map +0 -1
- package/dist/src/core/worker/server.d.ts.map +0 -1
- package/dist/src/core/worker/server.js.map +0 -1
- package/dist/src/formatters/github-annotations.d.ts.map +0 -1
- package/dist/src/formatters/github-annotations.js.map +0 -1
- package/dist/src/formatters/index.d.ts.map +0 -1
- package/dist/src/formatters/index.js.map +0 -1
- package/dist/src/formatters/junit.d.ts.map +0 -1
- package/dist/src/formatters/junit.js.map +0 -1
- package/dist/src/formatters/sarif.d.ts.map +0 -1
- package/dist/src/formatters/sarif.js.map +0 -1
- package/dist/src/index.d.ts.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-bot-parser/types.ts +0 -9
- 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/_pkg-root.ts +0 -85
- 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/index.ts +0 -3
- package/src/formatters/junit.ts +0 -52
- package/src/formatters/sarif.ts +0 -103
- package/src/index.ts +0 -3
package/src/core/ignore/index.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { minimatch } from 'minimatch';
|
|
4
|
-
import type { Finding } from '../findings/types.ts';
|
|
5
|
-
import type { GuardrailConfig } from '../config/types.ts';
|
|
6
|
-
|
|
7
|
-
export interface IgnoreRule {
|
|
8
|
-
ruleId: string | '*'; // finding id prefix or '*' for any
|
|
9
|
-
pathGlob: string | null; // null = match all paths
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function loadIgnoreRules(cwd: string): IgnoreRule[] {
|
|
13
|
-
const filePath = path.join(cwd, '.guardrail-ignore');
|
|
14
|
-
if (!fs.existsSync(filePath)) return [];
|
|
15
|
-
|
|
16
|
-
const rules: IgnoreRule[] = [];
|
|
17
|
-
for (const raw of fs.readFileSync(filePath, 'utf8').split('\n')) {
|
|
18
|
-
const line = raw.trim();
|
|
19
|
-
if (!line || line.startsWith('#')) continue;
|
|
20
|
-
|
|
21
|
-
const parts = line.split(/\s+/);
|
|
22
|
-
if (parts.length === 1) {
|
|
23
|
-
// bare glob — suppress any finding whose file matches
|
|
24
|
-
rules.push({ ruleId: '*', pathGlob: parts[0]! });
|
|
25
|
-
} else {
|
|
26
|
-
// <rule-id-or-*> <path-glob>
|
|
27
|
-
rules.push({ ruleId: parts[0]!, pathGlob: parts[1]! });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return rules;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function matchesRule(finding: Finding, rule: IgnoreRule): boolean {
|
|
34
|
-
const ruleMatches = rule.ruleId === '*' || finding.id.startsWith(rule.ruleId);
|
|
35
|
-
if (!ruleMatches) return false;
|
|
36
|
-
if (rule.pathGlob === null) return true;
|
|
37
|
-
return minimatch(finding.file.replace(/\\/g, '/'), rule.pathGlob, { matchBase: true });
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Convert `ignore:` entries from guardrail.config.yaml into IgnoreRules. */
|
|
41
|
-
export function parseConfigIgnore(entries: GuardrailConfig['ignore']): IgnoreRule[] {
|
|
42
|
-
if (!entries || entries.length === 0) return [];
|
|
43
|
-
return entries.map(entry => {
|
|
44
|
-
if (typeof entry === 'string') {
|
|
45
|
-
return { ruleId: '*', pathGlob: entry };
|
|
46
|
-
}
|
|
47
|
-
return { ruleId: entry.rule ?? '*', pathGlob: entry.path };
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function applyIgnoreRules(findings: Finding[], rules: IgnoreRule[]): Finding[] {
|
|
52
|
-
if (rules.length === 0) return findings;
|
|
53
|
-
return findings.filter(f => !rules.some(r => matchesRule(f, r)));
|
|
54
|
-
}
|
package/src/core/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { applyRedaction, DEFAULT_REDACTION_PATTERNS } from './redaction.ts';
|
|
4
|
-
|
|
5
|
-
export interface NdjsonLoggerOptions {
|
|
6
|
-
runId: string;
|
|
7
|
-
logsDir?: string;
|
|
8
|
-
redactionPatterns?: readonly string[];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export class NdjsonLogger {
|
|
12
|
-
private readonly runId: string;
|
|
13
|
-
private readonly filePath: string;
|
|
14
|
-
private readonly stream: fs.WriteStream;
|
|
15
|
-
private readonly redactionPatterns: readonly string[];
|
|
16
|
-
|
|
17
|
-
constructor(options: NdjsonLoggerOptions) {
|
|
18
|
-
this.runId = options.runId;
|
|
19
|
-
this.redactionPatterns = options.redactionPatterns ?? DEFAULT_REDACTION_PATTERNS;
|
|
20
|
-
const logsDir = options.logsDir ?? path.join('.claude', 'logs');
|
|
21
|
-
fs.mkdirSync(logsDir, { recursive: true });
|
|
22
|
-
this.filePath = path.join(logsDir, `${this.runId}.ndjson`);
|
|
23
|
-
this.stream = fs.createWriteStream(this.filePath, { flags: 'a' });
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
log(event: string, fields: Record<string, unknown> = {}): void {
|
|
27
|
-
const entry = { ts: new Date().toISOString(), runId: this.runId, event, ...fields };
|
|
28
|
-
const serialized = applyRedaction(JSON.stringify(entry), this.redactionPatterns);
|
|
29
|
-
this.stream.write(serialized + '\n');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
close(): Promise<void> {
|
|
33
|
-
return new Promise(resolve => this.stream.end(() => resolve()));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
getFilePath(): string { return this.filePath; }
|
|
37
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_REDACTION_PATTERNS: readonly string[] = Object.freeze([
|
|
2
|
-
'\\bsk-[a-zA-Z0-9_-]{20,}',
|
|
3
|
-
'\\beyJ[a-zA-Z0-9_-]{30,}',
|
|
4
|
-
'\\bghp_[a-zA-Z0-9]{30,}',
|
|
5
|
-
'\\bxoxb-[a-zA-Z0-9-]{20,}',
|
|
6
|
-
'\\bAKIA[A-Z0-9]{16}\\b',
|
|
7
|
-
]);
|
|
8
|
-
|
|
9
|
-
export function applyRedaction(text: string, patterns: readonly string[]): string {
|
|
10
|
-
let result = text;
|
|
11
|
-
for (const pattern of patterns) {
|
|
12
|
-
result = result.replace(new RegExp(pattern, 'g'), '[REDACTED]');
|
|
13
|
-
}
|
|
14
|
-
return result;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function containsSecret(text: string, patterns: readonly string[]): boolean {
|
|
18
|
-
return patterns.some(p => new RegExp(p).test(text));
|
|
19
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const mutexes = new Map<string, Promise<void>>();
|
|
2
|
-
|
|
3
|
-
export async function withWriteLock<T>(workspace: string, fn: () => Promise<T>): Promise<T> {
|
|
4
|
-
let unlock!: () => void;
|
|
5
|
-
const current = new Promise<void>(resolve => { unlock = resolve; });
|
|
6
|
-
const prev = mutexes.get(workspace) ?? Promise.resolve();
|
|
7
|
-
mutexes.set(workspace, current);
|
|
8
|
-
|
|
9
|
-
await prev;
|
|
10
|
-
try {
|
|
11
|
-
return await fn();
|
|
12
|
-
} finally {
|
|
13
|
-
unlock();
|
|
14
|
-
if (mutexes.get(workspace) === current) mutexes.delete(workspace);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
// src/core/mcp/handlers/fix-finding.ts
|
|
2
|
-
import * as fs from 'node:fs';
|
|
3
|
-
import * as path from 'node:path';
|
|
4
|
-
import { resolveWorkspace, assertInWorkspace } from '../workspace.ts';
|
|
5
|
-
import { loadRun, checksumFile } from '../run-store.ts';
|
|
6
|
-
import { withWriteLock } from '../concurrency.ts';
|
|
7
|
-
import { generateFix, buildUnifiedDiff } from '../../fix/generator.ts';
|
|
8
|
-
import type { ReviewEngine } from '../../../adapters/review-engine/types.ts';
|
|
9
|
-
import type { GuardrailConfig } from '../../config/types.ts';
|
|
10
|
-
|
|
11
|
-
export interface FixFindingResult {
|
|
12
|
-
schema_version: 1;
|
|
13
|
-
status: 'fixed' | 'reverted' | 'human_required' | 'skipped';
|
|
14
|
-
reason?: string;
|
|
15
|
-
patch?: string;
|
|
16
|
-
commitSha?: string;
|
|
17
|
-
appliedFiles: string[];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export async function handleFixFinding(
|
|
21
|
-
input: { run_id: string; finding_id: string; cwd?: string; dry_run?: boolean },
|
|
22
|
-
config: GuardrailConfig,
|
|
23
|
-
engine: ReviewEngine,
|
|
24
|
-
): Promise<FixFindingResult> {
|
|
25
|
-
const workspace = resolveWorkspace(input.cwd);
|
|
26
|
-
|
|
27
|
-
const record = loadRun(workspace, input.run_id);
|
|
28
|
-
if (!record) {
|
|
29
|
-
throw Object.assign(
|
|
30
|
-
new Error(`run_not_found: no run with id "${input.run_id}"`),
|
|
31
|
-
{ code: 'run_not_found' },
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const finding = record.findings.find(f => f.id === input.finding_id);
|
|
36
|
-
if (!finding) {
|
|
37
|
-
throw Object.assign(
|
|
38
|
-
new Error(`finding_not_found: no finding with id "${input.finding_id}"`),
|
|
39
|
-
{ code: 'finding_not_found' },
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Protected path check
|
|
44
|
-
if (finding.protectedPath) {
|
|
45
|
-
return { schema_version: 1, status: 'human_required', reason: 'protected_path', appliedFiles: [] };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Validate finding.file against workspace boundary (run records could be tampered)
|
|
49
|
-
const absFile = assertInWorkspace(workspace, finding.file);
|
|
50
|
-
|
|
51
|
-
// Look up checksum under both the raw finding.file and its relative form,
|
|
52
|
-
// so the drift check works whether older runs stored absolute or relative keys.
|
|
53
|
-
const relKey = path.relative(workspace, absFile);
|
|
54
|
-
const savedChecksum = record.fileChecksums[finding.file] ?? record.fileChecksums[relKey] ?? '';
|
|
55
|
-
|
|
56
|
-
// Dry-run path: generate fix, return patch, no mutations
|
|
57
|
-
if (input.dry_run) {
|
|
58
|
-
const currentChecksum = checksumFile(absFile);
|
|
59
|
-
if (savedChecksum && currentChecksum !== savedChecksum) {
|
|
60
|
-
return { schema_version: 1, status: 'human_required', reason: 'file_changed', appliedFiles: [] };
|
|
61
|
-
}
|
|
62
|
-
const genResult = await generateFix(finding, engine, workspace);
|
|
63
|
-
if (genResult.status !== 'ok') {
|
|
64
|
-
return { schema_version: 1, status: 'human_required', reason: genResult.reason, appliedFiles: [] };
|
|
65
|
-
}
|
|
66
|
-
const patch = buildUnifiedDiff(
|
|
67
|
-
genResult.originalLines!,
|
|
68
|
-
genResult.replacementLines!,
|
|
69
|
-
finding.file,
|
|
70
|
-
genResult.startLine!,
|
|
71
|
-
{ color: false }, // MCP clients parse patch text — no ANSI
|
|
72
|
-
);
|
|
73
|
-
return { schema_version: 1, status: 'skipped', reason: 'dry_run', patch, appliedFiles: [] };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Apply path: checksum validation + fix generation run INSIDE the lock to
|
|
77
|
-
// prevent TOCTOU between two concurrent fix_finding calls on the same file.
|
|
78
|
-
return withWriteLock(workspace, async () => {
|
|
79
|
-
const currentChecksum = checksumFile(absFile);
|
|
80
|
-
if (savedChecksum && currentChecksum !== savedChecksum) {
|
|
81
|
-
return { schema_version: 1 as const, status: 'human_required' as const, reason: 'file_changed', appliedFiles: [] };
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const genResult = await generateFix(finding, engine, workspace);
|
|
85
|
-
if (genResult.status !== 'ok') {
|
|
86
|
-
return { schema_version: 1 as const, status: 'human_required' as const, reason: genResult.reason, appliedFiles: [] };
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const patch = buildUnifiedDiff(
|
|
90
|
-
genResult.originalLines!,
|
|
91
|
-
genResult.replacementLines!,
|
|
92
|
-
finding.file,
|
|
93
|
-
genResult.startLine!,
|
|
94
|
-
{ color: false },
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
const originalContent = fs.readFileSync(absFile, 'utf8');
|
|
98
|
-
const allLines = originalContent.split('\n');
|
|
99
|
-
const newLines = [
|
|
100
|
-
...allLines.slice(0, genResult.startLine! - 1),
|
|
101
|
-
...genResult.replacementLines!,
|
|
102
|
-
...allLines.slice(genResult.endLine!),
|
|
103
|
-
];
|
|
104
|
-
|
|
105
|
-
const tmpFile = absFile + '.guardrail.tmp';
|
|
106
|
-
fs.writeFileSync(tmpFile, newLines.join('\n'), 'utf8');
|
|
107
|
-
fs.renameSync(tmpFile, absFile);
|
|
108
|
-
|
|
109
|
-
// Test verification
|
|
110
|
-
if (config.testCommand) {
|
|
111
|
-
const { spawnSync } = await import('node:child_process');
|
|
112
|
-
const testResult = spawnSync('/bin/sh', ['-c', config.testCommand], {
|
|
113
|
-
cwd: workspace,
|
|
114
|
-
shell: false,
|
|
115
|
-
timeout: 120_000,
|
|
116
|
-
encoding: 'utf8',
|
|
117
|
-
});
|
|
118
|
-
if (testResult.status !== 0) {
|
|
119
|
-
fs.writeFileSync(absFile, originalContent, 'utf8');
|
|
120
|
-
return { schema_version: 1 as const, status: 'reverted' as const, patch, appliedFiles: [] };
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return { schema_version: 1 as const, status: 'fixed' as const, patch, appliedFiles: [finding.file] };
|
|
125
|
-
});
|
|
126
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import * as child_process from 'node:child_process';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { resolveWorkspace } from '../workspace.ts';
|
|
6
|
-
import type { GuardrailConfig, StaticRuleReference } from '../../config/types.ts';
|
|
7
|
-
|
|
8
|
-
export interface CapabilitiesResult {
|
|
9
|
-
schema_version: 1;
|
|
10
|
-
adapter: string;
|
|
11
|
-
enabledRules: string[];
|
|
12
|
-
writeable: boolean;
|
|
13
|
-
gitAvailable: boolean;
|
|
14
|
-
testCommandConfigured: boolean;
|
|
15
|
-
guardrailVersion: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function readVersion(): string {
|
|
19
|
-
try {
|
|
20
|
-
const pkgPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '../../../../package.json');
|
|
21
|
-
return (JSON.parse(fs.readFileSync(pkgPath, 'utf8')) as { version: string }).version;
|
|
22
|
-
} catch {
|
|
23
|
-
return 'unknown';
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function isGitAvailable(workspace: string): boolean {
|
|
28
|
-
try {
|
|
29
|
-
// Safe: no user input, static arguments only
|
|
30
|
-
child_process.execFileSync('git', ['rev-parse', '--git-dir'], {
|
|
31
|
-
cwd: workspace,
|
|
32
|
-
stdio: 'ignore',
|
|
33
|
-
});
|
|
34
|
-
return true;
|
|
35
|
-
} catch {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function extractRuleName(rule: StaticRuleReference): string {
|
|
41
|
-
return typeof rule === 'string' ? rule : rule.adapter;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export async function handleGetCapabilities(
|
|
45
|
-
input: { cwd?: string },
|
|
46
|
-
config: GuardrailConfig,
|
|
47
|
-
adapterName: string,
|
|
48
|
-
): Promise<CapabilitiesResult> {
|
|
49
|
-
const workspace = resolveWorkspace(input.cwd);
|
|
50
|
-
const staticRules = config.staticRules ?? [];
|
|
51
|
-
const enabledRules = staticRules.map(extractRuleName);
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
schema_version: 1,
|
|
55
|
-
adapter: adapterName,
|
|
56
|
-
enabledRules,
|
|
57
|
-
writeable: true,
|
|
58
|
-
gitAvailable: isGitAvailable(workspace),
|
|
59
|
-
testCommandConfigured: !!config.testCommand,
|
|
60
|
-
guardrailVersion: readVersion(),
|
|
61
|
-
};
|
|
62
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { resolveWorkspace } from '../workspace.ts';
|
|
2
|
-
import { loadRun } from '../run-store.ts';
|
|
3
|
-
import type { Finding, Severity } from '../../findings/types.ts';
|
|
4
|
-
|
|
5
|
-
export interface GetFindingsResult {
|
|
6
|
-
schema_version: 1;
|
|
7
|
-
run_id: string;
|
|
8
|
-
findings: Finding[];
|
|
9
|
-
cachedAt: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Severity order: index 0 = highest priority
|
|
13
|
-
const SEVERITY_ORDER = ['critical', 'warning', 'note'] as const;
|
|
14
|
-
|
|
15
|
-
export async function handleGetFindings(input: {
|
|
16
|
-
run_id: string;
|
|
17
|
-
severity?: Severity;
|
|
18
|
-
cwd?: string;
|
|
19
|
-
}): Promise<GetFindingsResult> {
|
|
20
|
-
const workspace = resolveWorkspace(input.cwd);
|
|
21
|
-
const record = loadRun(workspace, input.run_id);
|
|
22
|
-
if (!record) {
|
|
23
|
-
throw Object.assign(
|
|
24
|
-
new Error(`run_not_found: no run with id "${input.run_id}"`),
|
|
25
|
-
{ code: 'run_not_found' }
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
let findings = record.findings;
|
|
30
|
-
if (input.severity) {
|
|
31
|
-
const minIdx = SEVERITY_ORDER.indexOf(input.severity);
|
|
32
|
-
findings = findings.filter(f => SEVERITY_ORDER.indexOf(f.severity) <= minIdx);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return { schema_version: 1, run_id: input.run_id, findings, cachedAt: record.createdAt };
|
|
36
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import * as crypto from 'node:crypto';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { resolveWorkspace } from '../workspace.ts';
|
|
4
|
-
import { saveRun, checksumFile, pruneOldRuns } from '../run-store.ts';
|
|
5
|
-
import { runGuardrail } from '../../pipeline/run.ts';
|
|
6
|
-
import { resolveGitTouchedFiles } from '../../git/touched-files.ts';
|
|
7
|
-
import { loadRulesFromConfig } from '../../static-rules/registry.ts';
|
|
8
|
-
import { detectGitContext } from '../../detect/git-context.ts';
|
|
9
|
-
import type { ReviewEngine } from '../../../adapters/review-engine/types.ts';
|
|
10
|
-
import type { GuardrailConfig } from '../../config/types.ts';
|
|
11
|
-
import type { Finding } from '../../findings/types.ts';
|
|
12
|
-
|
|
13
|
-
export interface ReviewDiffResult {
|
|
14
|
-
schema_version: 1;
|
|
15
|
-
run_id: string;
|
|
16
|
-
findings: Finding[];
|
|
17
|
-
human_summary: string;
|
|
18
|
-
usage?: { costUSD?: number };
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function handleReviewDiff(
|
|
22
|
-
input: { base?: string; cwd?: string; static_only?: boolean },
|
|
23
|
-
config: GuardrailConfig,
|
|
24
|
-
engine: ReviewEngine,
|
|
25
|
-
): Promise<ReviewDiffResult> {
|
|
26
|
-
const workspace = resolveWorkspace(input.cwd);
|
|
27
|
-
pruneOldRuns(workspace, 24 * 60 * 60 * 1000);
|
|
28
|
-
|
|
29
|
-
const touchedFiles = resolveGitTouchedFiles({ cwd: workspace, base: input.base });
|
|
30
|
-
const staticRules = config.staticRules ? await loadRulesFromConfig(config.staticRules) : [];
|
|
31
|
-
const gitCtx = detectGitContext(workspace);
|
|
32
|
-
|
|
33
|
-
const result = await runGuardrail({
|
|
34
|
-
touchedFiles,
|
|
35
|
-
config,
|
|
36
|
-
reviewEngine: engine,
|
|
37
|
-
staticRules,
|
|
38
|
-
cwd: workspace,
|
|
39
|
-
gitSummary: gitCtx.summary ?? undefined,
|
|
40
|
-
base: input.base,
|
|
41
|
-
skipReview: input.static_only ?? false,
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const run_id = crypto.randomUUID();
|
|
45
|
-
const fileChecksums: Record<string, string> = {};
|
|
46
|
-
for (const f of touchedFiles) {
|
|
47
|
-
const abs = path.isAbsolute(f) ? f : path.resolve(workspace, f);
|
|
48
|
-
fileChecksums[f] = checksumFile(abs);
|
|
49
|
-
}
|
|
50
|
-
saveRun(workspace, run_id, result.allFindings, fileChecksums);
|
|
51
|
-
|
|
52
|
-
const critCount = result.allFindings.filter(f => f.severity === 'critical').length;
|
|
53
|
-
const warnCount = result.allFindings.filter(f => f.severity === 'warning').length;
|
|
54
|
-
const human_summary = result.allFindings.length === 0
|
|
55
|
-
? 'No findings — looks clean.'
|
|
56
|
-
: `${result.allFindings.length} finding${result.allFindings.length !== 1 ? 's' : ''}: ${critCount} critical, ${warnCount} warning.`;
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
schema_version: 1,
|
|
60
|
-
run_id,
|
|
61
|
-
findings: result.allFindings,
|
|
62
|
-
human_summary,
|
|
63
|
-
usage: result.totalCostUSD !== undefined ? { costUSD: result.totalCostUSD } : undefined,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import * as crypto from 'node:crypto';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { resolveWorkspace, assertInWorkspace } from '../workspace.ts';
|
|
4
|
-
import { saveRun, checksumFile, pruneOldRuns } from '../run-store.ts';
|
|
5
|
-
import { runReviewPhase } from '../../pipeline/review-phase.ts';
|
|
6
|
-
import { detectStack } from '../../detect/stack.ts';
|
|
7
|
-
import type { ReviewEngine } from '../../../adapters/review-engine/types.ts';
|
|
8
|
-
import type { GuardrailConfig } from '../../config/types.ts';
|
|
9
|
-
import type { Finding } from '../../findings/types.ts';
|
|
10
|
-
|
|
11
|
-
export interface ScanFilesResult {
|
|
12
|
-
schema_version: 1;
|
|
13
|
-
run_id: string;
|
|
14
|
-
findings: Finding[];
|
|
15
|
-
human_summary: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function handleScanFiles(
|
|
19
|
-
input: { files: string[]; cwd?: string; ask?: string },
|
|
20
|
-
config: GuardrailConfig,
|
|
21
|
-
engine: ReviewEngine,
|
|
22
|
-
): Promise<ScanFilesResult> {
|
|
23
|
-
const workspace = resolveWorkspace(input.cwd);
|
|
24
|
-
pruneOldRuns(workspace, 24 * 60 * 60 * 1000);
|
|
25
|
-
|
|
26
|
-
// Validate all paths before any I/O
|
|
27
|
-
const resolvedFiles = input.files.map(f => assertInWorkspace(workspace, f));
|
|
28
|
-
|
|
29
|
-
const stack = detectStack(workspace) ?? config.stack;
|
|
30
|
-
const effectiveConfig: GuardrailConfig = input.ask
|
|
31
|
-
? { ...config, stack: `${stack ?? 'unknown'}\n\nFocus: ${input.ask}` }
|
|
32
|
-
: config;
|
|
33
|
-
|
|
34
|
-
const result = await runReviewPhase({
|
|
35
|
-
touchedFiles: resolvedFiles,
|
|
36
|
-
config: effectiveConfig,
|
|
37
|
-
engine,
|
|
38
|
-
cwd: workspace,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const run_id = crypto.randomUUID();
|
|
42
|
-
const fileChecksums: Record<string, string> = {};
|
|
43
|
-
for (const f of resolvedFiles) {
|
|
44
|
-
// Store relative key so fix_finding's finding.file lookup matches
|
|
45
|
-
const relKey = path.relative(workspace, f);
|
|
46
|
-
fileChecksums[relKey] = checksumFile(f);
|
|
47
|
-
}
|
|
48
|
-
// Normalize finding.file to relative paths so downstream lookups against
|
|
49
|
-
// fileChecksums (keyed by relative paths) work regardless of whether the
|
|
50
|
-
// review engine echoed absolute or relative paths.
|
|
51
|
-
const normalizedFindings = result.findings.map(f => {
|
|
52
|
-
if (!f.file) return f;
|
|
53
|
-
const rel = path.isAbsolute(f.file) ? path.relative(workspace, f.file) : f.file;
|
|
54
|
-
return rel === f.file ? f : { ...f, file: rel };
|
|
55
|
-
});
|
|
56
|
-
saveRun(workspace, run_id, normalizedFindings, fileChecksums);
|
|
57
|
-
|
|
58
|
-
const critCount = result.findings.filter(f => f.severity === 'critical').length;
|
|
59
|
-
const warnCount = result.findings.filter(f => f.severity === 'warning').length;
|
|
60
|
-
const human_summary = result.findings.length === 0
|
|
61
|
-
? 'No findings.'
|
|
62
|
-
: `${result.findings.length} finding${result.findings.length !== 1 ? 's' : ''}: ${critCount} critical, ${warnCount} warning.`;
|
|
63
|
-
|
|
64
|
-
return { schema_version: 1, run_id, findings: normalizedFindings, human_summary };
|
|
65
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { resolveWorkspace } from '../workspace.ts';
|
|
3
|
-
import { withWriteLock } from '../concurrency.ts';
|
|
4
|
-
import type { GuardrailConfig } from '../../config/types.ts';
|
|
5
|
-
|
|
6
|
-
export interface ValidateFixResult {
|
|
7
|
-
schema_version: 1;
|
|
8
|
-
passed: boolean;
|
|
9
|
-
output: string;
|
|
10
|
-
durationMs: number;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export async function handleValidateFix(
|
|
14
|
-
input: { cwd?: string; files?: string[] },
|
|
15
|
-
config: GuardrailConfig,
|
|
16
|
-
): Promise<ValidateFixResult> {
|
|
17
|
-
const workspace = resolveWorkspace(input.cwd);
|
|
18
|
-
|
|
19
|
-
if (!config.testCommand) {
|
|
20
|
-
return { schema_version: 1, passed: true, output: '', durationMs: 0 };
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return withWriteLock(workspace, async () => {
|
|
24
|
-
const start = Date.now();
|
|
25
|
-
const result = spawnSync('/bin/sh', ['-c', config.testCommand!], {
|
|
26
|
-
cwd: workspace,
|
|
27
|
-
shell: false,
|
|
28
|
-
timeout: 120_000,
|
|
29
|
-
encoding: 'utf8',
|
|
30
|
-
});
|
|
31
|
-
const durationMs = Date.now() - start;
|
|
32
|
-
const raw = ((result.stdout ?? '') + (result.stderr ?? '')).slice(0, 4000);
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
schema_version: 1 as const,
|
|
36
|
-
passed: result.status === 0,
|
|
37
|
-
output: raw,
|
|
38
|
-
durationMs,
|
|
39
|
-
};
|
|
40
|
-
});
|
|
41
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import * as crypto from 'node:crypto';
|
|
4
|
-
import type { Finding } from '../findings/types.ts';
|
|
5
|
-
|
|
6
|
-
const RUNS_DIR = '.guardrail-cache/runs';
|
|
7
|
-
|
|
8
|
-
export interface RunRecord {
|
|
9
|
-
run_id: string;
|
|
10
|
-
createdAt: string;
|
|
11
|
-
findings: Finding[];
|
|
12
|
-
fileChecksums: Record<string, string>;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function runsDir(cwd: string): string {
|
|
16
|
-
return path.join(cwd, RUNS_DIR);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Reject any run_id that isn't a safe filename component — path separators,
|
|
20
|
-
// relative segments, hidden files, or empty strings.
|
|
21
|
-
// run_ids are generated server-side as UUIDs (crypto.randomUUID) so strict
|
|
22
|
-
// validation here is safe. MCP clients that fabricate run_ids get a clear
|
|
23
|
-
// rejection instead of silently reading outside RUNS_DIR.
|
|
24
|
-
const VALID_RUN_ID = /^[A-Za-z0-9_-]+$/;
|
|
25
|
-
|
|
26
|
-
function assertValidRunId(runId: string): void {
|
|
27
|
-
if (!runId || typeof runId !== 'string' || !VALID_RUN_ID.test(runId)) {
|
|
28
|
-
throw Object.assign(
|
|
29
|
-
new Error(`invalid run_id: "${runId}" (expected alphanumeric + dash/underscore)`),
|
|
30
|
-
{ code: 'invalid_run_id' },
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function runFilePath(cwd: string, runId: string): string {
|
|
36
|
-
assertValidRunId(runId);
|
|
37
|
-
return path.join(runsDir(cwd), `${runId}.json`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function saveRun(
|
|
41
|
-
cwd: string,
|
|
42
|
-
runId: string,
|
|
43
|
-
findings: Finding[],
|
|
44
|
-
fileChecksums: Record<string, string>,
|
|
45
|
-
): void {
|
|
46
|
-
const dir = runsDir(cwd);
|
|
47
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
48
|
-
const record: RunRecord = { run_id: runId, createdAt: new Date().toISOString(), findings, fileChecksums };
|
|
49
|
-
const tmp = runFilePath(cwd, runId) + '.tmp';
|
|
50
|
-
fs.writeFileSync(tmp, JSON.stringify(record, null, 2), 'utf8');
|
|
51
|
-
fs.renameSync(tmp, runFilePath(cwd, runId));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function loadRun(cwd: string, runId: string): RunRecord | null {
|
|
55
|
-
const p = runFilePath(cwd, runId);
|
|
56
|
-
if (!fs.existsSync(p)) return null;
|
|
57
|
-
try {
|
|
58
|
-
return JSON.parse(fs.readFileSync(p, 'utf8')) as RunRecord;
|
|
59
|
-
} catch {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function checksumFile(filePath: string): string {
|
|
65
|
-
try {
|
|
66
|
-
const content = fs.readFileSync(filePath);
|
|
67
|
-
return crypto.createHash('sha256').update(content).digest('hex');
|
|
68
|
-
} catch {
|
|
69
|
-
return '';
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function pruneOldRuns(cwd: string, maxAgeMs: number): void {
|
|
74
|
-
const dir = runsDir(cwd);
|
|
75
|
-
if (!fs.existsSync(dir)) return;
|
|
76
|
-
const cutoff = Date.now() - maxAgeMs;
|
|
77
|
-
for (const entry of fs.readdirSync(dir)) {
|
|
78
|
-
if (!entry.endsWith('.json')) continue;
|
|
79
|
-
const full = path.join(dir, entry);
|
|
80
|
-
try {
|
|
81
|
-
const stat = fs.statSync(full);
|
|
82
|
-
if (stat.mtimeMs < cutoff) fs.unlinkSync(full);
|
|
83
|
-
} catch { /* ignore */ }
|
|
84
|
-
}
|
|
85
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
|
|
4
|
-
export function resolveWorkspace(cwd?: string): string {
|
|
5
|
-
return fs.realpathSync(cwd ?? process.cwd());
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function assertInWorkspace(workspace: string, filePath: string): string {
|
|
9
|
-
const resolvedWorkspace = fs.realpathSync(workspace);
|
|
10
|
-
const abs = path.isAbsolute(filePath)
|
|
11
|
-
? filePath
|
|
12
|
-
: path.resolve(resolvedWorkspace, filePath);
|
|
13
|
-
|
|
14
|
-
let resolved: string;
|
|
15
|
-
try {
|
|
16
|
-
resolved = fs.realpathSync(abs);
|
|
17
|
-
} catch {
|
|
18
|
-
// File doesn't exist yet — check the directory
|
|
19
|
-
const dir = path.dirname(abs);
|
|
20
|
-
let resolvedDir: string;
|
|
21
|
-
try {
|
|
22
|
-
resolvedDir = fs.realpathSync(dir);
|
|
23
|
-
} catch {
|
|
24
|
-
// Parent directory doesn't exist — resolve what we can
|
|
25
|
-
resolvedDir = path.resolve(dir);
|
|
26
|
-
}
|
|
27
|
-
resolved = path.join(resolvedDir, path.basename(abs));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const root = resolvedWorkspace.endsWith(path.sep) ? resolvedWorkspace : resolvedWorkspace + path.sep;
|
|
31
|
-
if (!resolved.startsWith(root) && resolved !== resolvedWorkspace) {
|
|
32
|
-
throw new Error(`Path "${filePath}" is outside workspace "${workspace}"`);
|
|
33
|
-
}
|
|
34
|
-
return resolved;
|
|
35
|
-
}
|