@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,30 +0,0 @@
|
|
|
1
|
-
// src/cli/autoregress-bridge.ts
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { spawnSync } from 'node:child_process';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const SCRIPT = path.resolve(__dirname, '../../scripts/autoregress.ts');
|
|
8
|
-
|
|
9
|
-
const VALID_MODES = ['run', 'update', 'generate', 'diff'];
|
|
10
|
-
|
|
11
|
-
export function buildAutoregressArgs(args: string[]): string[] {
|
|
12
|
-
const mode = args[0] && VALID_MODES.includes(args[0]) ? args[0] : 'run';
|
|
13
|
-
const rest = args[0] && VALID_MODES.includes(args[0]) ? args.slice(1) : args;
|
|
14
|
-
return [mode, ...rest];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function runAutoregress(args: string[]): number {
|
|
18
|
-
const resolvedArgs = buildAutoregressArgs(args);
|
|
19
|
-
const result = spawnSync(
|
|
20
|
-
process.execPath,
|
|
21
|
-
['--import', 'tsx', SCRIPT, ...resolvedArgs],
|
|
22
|
-
{ stdio: 'inherit', cwd: process.cwd() },
|
|
23
|
-
);
|
|
24
|
-
if (result.error) {
|
|
25
|
-
console.error(`[autoregress] failed to launch: ${result.error.message}`);
|
|
26
|
-
console.error(` script: ${SCRIPT}`);
|
|
27
|
-
return 1;
|
|
28
|
-
}
|
|
29
|
-
return result.status ?? 1;
|
|
30
|
-
}
|
package/src/cli/baseline.ts
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import * as path from 'node:path';
|
|
2
|
-
import * as fs from 'node:fs';
|
|
3
|
-
import {
|
|
4
|
-
loadBaseline, saveBaseline, clearBaseline, diffAgainstBaseline,
|
|
5
|
-
baselineFilePath,
|
|
6
|
-
} from '../core/persist/baseline.ts';
|
|
7
|
-
import { loadCachedFindings } from '../core/persist/findings-cache.ts';
|
|
8
|
-
|
|
9
|
-
const C = {
|
|
10
|
-
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
11
|
-
green: '\x1b[32m', yellow: '\x1b[33m', red: '\x1b[31m', cyan: '\x1b[36m',
|
|
12
|
-
};
|
|
13
|
-
const fmt = (c: keyof typeof C, t: string) => `${C[c]}${t}${C.reset}`;
|
|
14
|
-
|
|
15
|
-
export interface BaselineCommandOptions {
|
|
16
|
-
cwd?: string;
|
|
17
|
-
note?: string;
|
|
18
|
-
baselinePath?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function runBaseline(sub: string, options: BaselineCommandOptions = {}): Promise<number> {
|
|
22
|
-
const cwd = options.cwd ?? process.cwd();
|
|
23
|
-
const bPath = baselineFilePath(cwd, options.baselinePath);
|
|
24
|
-
const relPath = path.relative(cwd, bPath);
|
|
25
|
-
|
|
26
|
-
switch (sub) {
|
|
27
|
-
case 'create': {
|
|
28
|
-
if (fs.existsSync(bPath)) {
|
|
29
|
-
console.log(fmt('yellow', `[baseline] ${relPath} already exists — use \`guardrail baseline update\` to refresh, or \`guardrail baseline clear\` to reset`));
|
|
30
|
-
return 1;
|
|
31
|
-
}
|
|
32
|
-
return createOrUpdate(cwd, bPath, relPath, options.note, 'Created');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
case 'update': {
|
|
36
|
-
return createOrUpdate(cwd, bPath, relPath, options.note, 'Updated');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
case 'show': {
|
|
40
|
-
const baseline = loadBaseline(cwd, options.baselinePath);
|
|
41
|
-
if (!baseline) {
|
|
42
|
-
console.log(fmt('yellow', `[baseline] No baseline found at ${relPath}`));
|
|
43
|
-
console.log(fmt('dim', ' Run: guardrail baseline create'));
|
|
44
|
-
return 0;
|
|
45
|
-
}
|
|
46
|
-
console.log(`\n${fmt('bold', '[baseline]')} ${fmt('dim', relPath)}`);
|
|
47
|
-
console.log(fmt('dim', ` Created: ${baseline.createdAt} Updated: ${baseline.updatedAt}`));
|
|
48
|
-
if (baseline.note) console.log(fmt('dim', ` Note: ${baseline.note}`));
|
|
49
|
-
console.log(` ${baseline.entries.length} pinned finding${baseline.entries.length !== 1 ? 's' : ''}\n`);
|
|
50
|
-
for (const e of baseline.entries) {
|
|
51
|
-
const sev = e.severity === 'critical' ? fmt('red', 'CRIT') : e.severity === 'warning' ? fmt('yellow', 'WARN') : fmt('dim', 'NOTE');
|
|
52
|
-
console.log(` [${sev}] ${fmt('dim', `${e.file}${e.line ? `:${e.line}` : ''}`)} ${e.message.slice(0, 70)}`);
|
|
53
|
-
}
|
|
54
|
-
console.log('');
|
|
55
|
-
return 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
case 'diff': {
|
|
59
|
-
const baseline = loadBaseline(cwd, options.baselinePath);
|
|
60
|
-
if (!baseline) {
|
|
61
|
-
console.log(fmt('yellow', `[baseline] No baseline found — run: guardrail baseline create`));
|
|
62
|
-
return 1;
|
|
63
|
-
}
|
|
64
|
-
const current = loadCachedFindings(cwd);
|
|
65
|
-
if (current.length === 0) {
|
|
66
|
-
console.log(fmt('yellow', '[baseline] No cached findings — run `guardrail run` or `guardrail scan` first'));
|
|
67
|
-
return 1;
|
|
68
|
-
}
|
|
69
|
-
const diff = diffAgainstBaseline(current, baseline);
|
|
70
|
-
console.log(`\n${fmt('bold', '[guardrail baseline diff]')} vs ${fmt('dim', relPath)}\n`);
|
|
71
|
-
|
|
72
|
-
if (diff.added.length > 0) {
|
|
73
|
-
console.log(fmt('red', ` ${diff.added.length} new finding${diff.added.length !== 1 ? 's' : ''} (not in baseline):`));
|
|
74
|
-
for (const f of diff.added) {
|
|
75
|
-
const sev = f.severity === 'critical' ? fmt('red', 'CRIT') : f.severity === 'warning' ? fmt('yellow', 'WARN') : fmt('dim', 'NOTE');
|
|
76
|
-
console.log(` [${sev}] ${fmt('dim', `${f.file}${f.line ? `:${f.line}` : ''}`)} ${f.message.slice(0, 70)}`);
|
|
77
|
-
}
|
|
78
|
-
console.log('');
|
|
79
|
-
}
|
|
80
|
-
if (diff.resolved.length > 0) {
|
|
81
|
-
console.log(fmt('green', ` ${diff.resolved.length} resolved (in baseline but not in current):`));
|
|
82
|
-
for (const e of diff.resolved) {
|
|
83
|
-
console.log(` ${fmt('dim', `${e.file}${e.line ? `:${e.line}` : ''}`)} ${e.message.slice(0, 70)}`);
|
|
84
|
-
}
|
|
85
|
-
console.log('');
|
|
86
|
-
}
|
|
87
|
-
if (diff.added.length === 0 && diff.resolved.length === 0) {
|
|
88
|
-
console.log(fmt('green', ` ✓ No changes vs baseline (${diff.unchanged.length} pinned findings unchanged)\n`));
|
|
89
|
-
} else {
|
|
90
|
-
console.log(fmt('dim', ` ${diff.unchanged.length} unchanged · run \`guardrail baseline update\` to pin new state\n`));
|
|
91
|
-
}
|
|
92
|
-
return diff.added.some(f => f.severity === 'critical') ? 1 : 0;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
case 'clear': {
|
|
96
|
-
if (!fs.existsSync(bPath)) {
|
|
97
|
-
console.log(fmt('dim', `[baseline] No baseline at ${relPath} — nothing to clear`));
|
|
98
|
-
return 0;
|
|
99
|
-
}
|
|
100
|
-
clearBaseline(cwd, options.baselinePath);
|
|
101
|
-
console.log(fmt('green', `[baseline] Cleared ${relPath}`));
|
|
102
|
-
return 0;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
default:
|
|
106
|
-
console.error(fmt('red', `[baseline] Unknown subcommand: "${sub}"`));
|
|
107
|
-
console.error(fmt('dim', ' Usage: guardrail baseline <create|update|show|diff|clear> [--note "..."]'));
|
|
108
|
-
return 1;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function createOrUpdate(cwd: string, bPath: string, relPath: string, note: string | undefined, verb: string): number {
|
|
113
|
-
const findings = loadCachedFindings(cwd);
|
|
114
|
-
if (findings.length === 0) {
|
|
115
|
-
console.log(fmt('yellow', '[baseline] No cached findings to snapshot — run `guardrail run` or `guardrail scan` first'));
|
|
116
|
-
return 1;
|
|
117
|
-
}
|
|
118
|
-
const baseline = saveBaseline(cwd, findings, { note, overridePath: bPath === path.join(cwd, '.guardrail-baseline.json') ? undefined : bPath });
|
|
119
|
-
console.log(`\n${fmt('green', `[baseline] ${verb}`)} ${fmt('dim', relPath)}`);
|
|
120
|
-
console.log(` ${baseline.entries.length} finding${baseline.entries.length !== 1 ? 's' : ''} pinned as accepted baseline`);
|
|
121
|
-
if (note) console.log(` Note: ${note}`);
|
|
122
|
-
console.log(fmt('dim', `\n Commit this file to share the baseline with your team:`));
|
|
123
|
-
console.log(fmt('cyan', ` git add ${relPath} && git commit -m "chore: update guardrail baseline"\n`));
|
|
124
|
-
return 0;
|
|
125
|
-
}
|
package/src/cli/ci.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { runCommand } from './run.ts';
|
|
2
|
-
|
|
3
|
-
export interface CiCommandOptions {
|
|
4
|
-
cwd?: string;
|
|
5
|
-
configPath?: string;
|
|
6
|
-
base?: string;
|
|
7
|
-
postComments?: boolean;
|
|
8
|
-
sarifOutput?: string;
|
|
9
|
-
diff?: boolean;
|
|
10
|
-
inlineComments?: boolean;
|
|
11
|
-
newOnly?: boolean;
|
|
12
|
-
failOn?: 'critical' | 'warning' | 'note' | 'none';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* `guardrail ci` — opinionated single-command CI entrypoint.
|
|
17
|
-
*
|
|
18
|
-
* Defaults:
|
|
19
|
-
* base GITHUB_BASE_REF → HEAD~1
|
|
20
|
-
* output guardrail.sarif
|
|
21
|
-
* post-comments true
|
|
22
|
-
* fail-on critical (or policy.failOn from config)
|
|
23
|
-
* new-only false (or policy.newOnly from config)
|
|
24
|
-
*/
|
|
25
|
-
export async function runCi(options: CiCommandOptions = {}): Promise<number> {
|
|
26
|
-
const base = options.base
|
|
27
|
-
?? process.env.GITHUB_BASE_REF
|
|
28
|
-
?? process.env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME // GitLab
|
|
29
|
-
?? 'HEAD~1';
|
|
30
|
-
|
|
31
|
-
const sarifOutput = options.sarifOutput ?? 'guardrail.sarif';
|
|
32
|
-
|
|
33
|
-
return runCommand({
|
|
34
|
-
cwd: options.cwd,
|
|
35
|
-
configPath: options.configPath,
|
|
36
|
-
base,
|
|
37
|
-
postComments: options.postComments ?? true,
|
|
38
|
-
format: 'sarif',
|
|
39
|
-
outputPath: sarifOutput,
|
|
40
|
-
diff: options.diff,
|
|
41
|
-
inlineComments: options.inlineComments ?? true,
|
|
42
|
-
newOnly: options.newOnly,
|
|
43
|
-
failOn: options.failOn,
|
|
44
|
-
});
|
|
45
|
-
}
|
package/src/cli/costs.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { readCostLog } from '../core/persist/cost-log.ts';
|
|
2
|
-
import type { CostLogEntry } from '../core/persist/cost-log.ts';
|
|
3
|
-
|
|
4
|
-
const C = {
|
|
5
|
-
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
6
|
-
green: '\x1b[32m', yellow: '\x1b[33m', cyan: '\x1b[36m',
|
|
7
|
-
};
|
|
8
|
-
const fmt = (c: keyof typeof C, t: string) => `${C[c]}${t}${C.reset}`;
|
|
9
|
-
|
|
10
|
-
function formatDate(iso: string): string {
|
|
11
|
-
try {
|
|
12
|
-
const d = new Date(iso);
|
|
13
|
-
return `${d.toLocaleDateString()} ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;
|
|
14
|
-
} catch { return iso; }
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function fmtUSD(n: number): string {
|
|
18
|
-
return n === 0 ? fmt('dim', '$0.0000') : `$${n.toFixed(4)}`;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function fmtTokens(n: number): string {
|
|
22
|
-
return n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export async function runCosts(cwd = process.cwd()): Promise<number> {
|
|
26
|
-
const log = readCostLog(cwd);
|
|
27
|
-
|
|
28
|
-
if (log.length === 0) {
|
|
29
|
-
console.log(fmt('yellow', '[costs] No run history found — run `guardrail run` first.'));
|
|
30
|
-
return 0;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// 7-day window
|
|
34
|
-
const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
|
|
35
|
-
const recent = log.filter(e => new Date(e.timestamp).getTime() >= sevenDaysAgo);
|
|
36
|
-
const last10 = log.slice(-10).reverse();
|
|
37
|
-
|
|
38
|
-
const totalCost = log.reduce((s, e) => s + e.costUSD, 0);
|
|
39
|
-
const totalInput = log.reduce((s, e) => s + e.inputTokens, 0);
|
|
40
|
-
const totalOutput = log.reduce((s, e) => s + e.outputTokens, 0);
|
|
41
|
-
const recentCost = recent.reduce((s, e) => s + e.costUSD, 0);
|
|
42
|
-
|
|
43
|
-
console.log(`\n${fmt('bold', '[costs]')}\n`);
|
|
44
|
-
|
|
45
|
-
// Summary row
|
|
46
|
-
console.log(fmt('bold', 'Summary'));
|
|
47
|
-
console.log(` All-time runs: ${log.length}`);
|
|
48
|
-
console.log(` All-time cost: ${fmtUSD(totalCost)} (${fmtTokens(totalInput)} in / ${fmtTokens(totalOutput)} out)`);
|
|
49
|
-
console.log(` Last 7 days: ${fmtUSD(recentCost)} (${recent.length} run${recent.length !== 1 ? 's' : ''})`);
|
|
50
|
-
console.log('');
|
|
51
|
-
|
|
52
|
-
// Last 10 runs table
|
|
53
|
-
console.log(fmt('bold', `Recent runs (last ${last10.length})`));
|
|
54
|
-
const COL = { date: 22, files: 7, input: 8, output: 8, cost: 10, dur: 8 };
|
|
55
|
-
const header = [
|
|
56
|
-
'Date'.padEnd(COL.date),
|
|
57
|
-
'Files'.padStart(COL.files),
|
|
58
|
-
'In tok'.padStart(COL.input),
|
|
59
|
-
'Out tok'.padStart(COL.output),
|
|
60
|
-
'Cost'.padStart(COL.cost),
|
|
61
|
-
'Time'.padStart(COL.dur),
|
|
62
|
-
].join(' ');
|
|
63
|
-
console.log(fmt('dim', ' ' + header));
|
|
64
|
-
console.log(fmt('dim', ' ' + '─'.repeat(header.length)));
|
|
65
|
-
|
|
66
|
-
for (const e of last10) {
|
|
67
|
-
const row = [
|
|
68
|
-
formatDate(e.timestamp).padEnd(COL.date),
|
|
69
|
-
String(e.files).padStart(COL.files),
|
|
70
|
-
fmtTokens(e.inputTokens).padStart(COL.input),
|
|
71
|
-
fmtTokens(e.outputTokens).padStart(COL.output),
|
|
72
|
-
fmtUSD(e.costUSD).padStart(COL.cost + 9), // +9 for ANSI codes in dim
|
|
73
|
-
`${e.durationMs}ms`.padStart(COL.dur),
|
|
74
|
-
].join(' ');
|
|
75
|
-
console.log(' ' + row);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
console.log('');
|
|
79
|
-
return 0;
|
|
80
|
-
}
|
package/src/cli/council.ts
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// src/cli/council.ts
|
|
2
|
-
import * as fs from 'node:fs';
|
|
3
|
-
import * as path from 'node:path';
|
|
4
|
-
import { loadConfig } from '../core/config/loader.ts';
|
|
5
|
-
import { parseCouncilConfig } from '../core/council/config.ts';
|
|
6
|
-
import { runCouncil } from '../core/council/runner.ts';
|
|
7
|
-
import { makeClaudeCouncilAdapter } from '../adapters/council/claude.ts';
|
|
8
|
-
import { makeOpenAICouncilAdapter } from '../adapters/council/openai.ts';
|
|
9
|
-
import type { CouncilAdapter } from '../adapters/council/types.ts';
|
|
10
|
-
import type { CouncilModelEntry } from '../core/council/types.ts';
|
|
11
|
-
import { GuardrailError } from '../core/errors.ts';
|
|
12
|
-
|
|
13
|
-
function makeAdapter(entry: CouncilModelEntry): CouncilAdapter {
|
|
14
|
-
switch (entry.adapter) {
|
|
15
|
-
case 'claude': return makeClaudeCouncilAdapter(entry.model, entry.label);
|
|
16
|
-
case 'openai': return makeOpenAICouncilAdapter(entry.model, entry.label);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export async function runCouncilCmd(opts: {
|
|
21
|
-
prompt?: string;
|
|
22
|
-
contextFile?: string;
|
|
23
|
-
configPath?: string;
|
|
24
|
-
dryRun?: boolean;
|
|
25
|
-
noSynthesize?: boolean;
|
|
26
|
-
}): Promise<number> {
|
|
27
|
-
const cwd = process.cwd();
|
|
28
|
-
const configPath = opts.configPath ?? path.join(cwd, 'guardrail.config.yaml');
|
|
29
|
-
|
|
30
|
-
let config;
|
|
31
|
-
try {
|
|
32
|
-
config = await loadConfig(configPath);
|
|
33
|
-
} catch (err) {
|
|
34
|
-
console.error(err instanceof GuardrailError ? err.message : String(err));
|
|
35
|
-
return 1;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!config.council) {
|
|
39
|
-
console.error('[council] No "council" section in guardrail.config.yaml — add council.models and council.synthesizer');
|
|
40
|
-
return 1;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
let councilConfig;
|
|
44
|
-
try {
|
|
45
|
-
councilConfig = parseCouncilConfig(config.council as Record<string, unknown>);
|
|
46
|
-
} catch (err) {
|
|
47
|
-
console.error(err instanceof GuardrailError ? err.message : String(err));
|
|
48
|
-
return 1;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (opts.dryRun) {
|
|
52
|
-
process.stdout.write(JSON.stringify({ schema_version: 1, status: 'dry_run', config: councilConfig }, null, 2) + '\n');
|
|
53
|
-
return 0;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (!opts.prompt) {
|
|
57
|
-
console.error('[council] --prompt is required');
|
|
58
|
-
return 1;
|
|
59
|
-
}
|
|
60
|
-
if (!opts.contextFile) {
|
|
61
|
-
console.error('[council] --context-file is required');
|
|
62
|
-
return 1;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
let contextDoc: string;
|
|
66
|
-
try {
|
|
67
|
-
contextDoc = fs.readFileSync(opts.contextFile, 'utf8');
|
|
68
|
-
} catch {
|
|
69
|
-
console.error(`[council] Cannot read context file: ${opts.contextFile}`);
|
|
70
|
-
return 1;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const adapters = councilConfig.models.map(makeAdapter);
|
|
74
|
-
const synthesizer = opts.noSynthesize
|
|
75
|
-
? { label: 'none', consult: async () => '' } as CouncilAdapter
|
|
76
|
-
: makeAdapter(councilConfig.synthesizer);
|
|
77
|
-
|
|
78
|
-
const result = await runCouncil(
|
|
79
|
-
councilConfig,
|
|
80
|
-
adapters,
|
|
81
|
-
synthesizer,
|
|
82
|
-
opts.prompt,
|
|
83
|
-
contextDoc,
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
// When no-synthesize, clear the empty synthesis object
|
|
87
|
-
if (opts.noSynthesize && result.synthesis?.text === '') {
|
|
88
|
-
delete (result as unknown as Record<string, unknown>)['synthesis'];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
92
|
-
|
|
93
|
-
if (result.status === 'failed') return 2;
|
|
94
|
-
if (result.status === 'partial') return 1;
|
|
95
|
-
return 0;
|
|
96
|
-
}
|
package/src/cli/detector.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
|
|
4
|
-
export interface DetectionResult {
|
|
5
|
-
preset: string;
|
|
6
|
-
testCommand: string;
|
|
7
|
-
confidence: 'high' | 'low';
|
|
8
|
-
evidence: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function readJson(filePath: string): Record<string, unknown> | null {
|
|
12
|
-
try {
|
|
13
|
-
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
14
|
-
} catch {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function fileContains(filePath: string, needle: string): boolean {
|
|
20
|
-
try {
|
|
21
|
-
return fs.readFileSync(filePath, 'utf8').includes(needle);
|
|
22
|
-
} catch {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const DEFAULT_TEST_PLACEHOLDER = /^echo .error: no test specified/i;
|
|
28
|
-
|
|
29
|
-
function nodeTestCommand(cwd: string): string {
|
|
30
|
-
const pkg = readJson(path.join(cwd, 'package.json'));
|
|
31
|
-
const scripts = pkg?.['scripts'] as Record<string, string> | undefined;
|
|
32
|
-
const cmd = scripts?.['test'];
|
|
33
|
-
if (!cmd || DEFAULT_TEST_PLACEHOLDER.test(cmd)) return 'npm test';
|
|
34
|
-
return cmd;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Detects Supabase signals beyond package.json deps — env vars, config files, or client
|
|
38
|
-
// usage. Required because many Next.js projects reference Supabase via the CLI/SSR tooling
|
|
39
|
-
// before installing the JS client.
|
|
40
|
-
function hasSupabaseSignals(cwd: string, deps: Record<string, string>): boolean {
|
|
41
|
-
if ('@supabase/supabase-js' in deps) return true;
|
|
42
|
-
if ('@supabase/ssr' in deps) return true;
|
|
43
|
-
if ('@supabase/auth-helpers-nextjs' in deps) return true;
|
|
44
|
-
if (fs.existsSync(path.join(cwd, 'supabase', 'config.toml'))) return true;
|
|
45
|
-
for (const envFile of ['.env', '.env.local', '.env.development']) {
|
|
46
|
-
const p = path.join(cwd, envFile);
|
|
47
|
-
if (fs.existsSync(p) && fileContains(p, 'SUPABASE_')) return true;
|
|
48
|
-
}
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function detectProject(cwd: string): DetectionResult {
|
|
53
|
-
if (fs.existsSync(path.join(cwd, 'go.mod'))) {
|
|
54
|
-
return { preset: 'go', testCommand: 'go test ./...', confidence: 'high', evidence: 'found go.mod' };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const gemfile = path.join(cwd, 'Gemfile');
|
|
58
|
-
if (fs.existsSync(gemfile) && fileContains(gemfile, 'rails')) {
|
|
59
|
-
return { preset: 'rails-postgres', testCommand: 'bundle exec rails test', confidence: 'high', evidence: "found Gemfile with 'rails'" };
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const reqTxt = path.join(cwd, 'requirements.txt');
|
|
63
|
-
const pyproject = path.join(cwd, 'pyproject.toml');
|
|
64
|
-
if ((fs.existsSync(reqTxt) && fileContains(reqTxt, 'fastapi')) ||
|
|
65
|
-
(fs.existsSync(pyproject) && fileContains(pyproject, 'fastapi'))) {
|
|
66
|
-
return { preset: 'python-fastapi', testCommand: 'pytest', confidence: 'high', evidence: 'found fastapi in requirements' };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const pkgPath = path.join(cwd, 'package.json');
|
|
70
|
-
if (fs.existsSync(pkgPath)) {
|
|
71
|
-
const pkg = readJson(pkgPath);
|
|
72
|
-
const deps = {
|
|
73
|
-
...(pkg?.['dependencies'] as Record<string, string> ?? {}),
|
|
74
|
-
...(pkg?.['devDependencies'] as Record<string, string> ?? {}),
|
|
75
|
-
};
|
|
76
|
-
const testCmd = nodeTestCommand(cwd);
|
|
77
|
-
|
|
78
|
-
if ('@trpc/server' in deps) {
|
|
79
|
-
return { preset: 't3', testCommand: testCmd, confidence: 'high', evidence: 'found @trpc/server in package.json' };
|
|
80
|
-
}
|
|
81
|
-
if ('next' in deps && hasSupabaseSignals(cwd, deps)) {
|
|
82
|
-
return { preset: 'nextjs-supabase', testCommand: testCmd, confidence: 'high', evidence: 'found next + supabase signals (deps/env/config)' };
|
|
83
|
-
}
|
|
84
|
-
if ('next' in deps) {
|
|
85
|
-
// Plain Next.js — fall through to generic rather than mislabel as nextjs-supabase.
|
|
86
|
-
return { preset: 'generic', testCommand: testCmd, confidence: 'low', evidence: 'found next in package.json but no Supabase signals — using generic preset (pass --preset nextjs-supabase if you do use Supabase)' };
|
|
87
|
-
}
|
|
88
|
-
return { preset: 'generic', testCommand: testCmd, confidence: 'low', evidence: 'found package.json (no strong framework signals) — using generic preset' };
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return { preset: 'generic', testCommand: 'npm test', confidence: 'low', evidence: 'no project signals found — using generic preset' };
|
|
92
|
-
}
|
package/src/cli/explain.ts
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { loadCachedFindings } from '../core/persist/findings-cache.ts';
|
|
4
|
-
import { loadConfig } from '../core/config/loader.ts';
|
|
5
|
-
import { loadAdapter } from '../adapters/loader.ts';
|
|
6
|
-
import type { Finding } from '../core/findings/types.ts';
|
|
7
|
-
import type { ReviewEngine } from '../adapters/review-engine/types.ts';
|
|
8
|
-
|
|
9
|
-
const C = {
|
|
10
|
-
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
11
|
-
green: '\x1b[32m', yellow: '\x1b[33m', red: '\x1b[31m', cyan: '\x1b[36m',
|
|
12
|
-
};
|
|
13
|
-
const fmt = (c: keyof typeof C, t: string) => `${C[c]}${t}${C.reset}`;
|
|
14
|
-
|
|
15
|
-
const CONTEXT_LINES = 30;
|
|
16
|
-
|
|
17
|
-
const SECTION_ORDER = ['Root Cause', 'Risk', 'How to Fix', 'Example', 'When to Suppress'] as const;
|
|
18
|
-
type SectionName = typeof SECTION_ORDER[number];
|
|
19
|
-
|
|
20
|
-
export interface ExplainCommandOptions {
|
|
21
|
-
cwd?: string;
|
|
22
|
-
configPath?: string;
|
|
23
|
-
target?: string; // "file:line" or finding index (1-based) or finding id
|
|
24
|
-
index?: number; // 1-based index into cached findings
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function pickFinding(findings: Finding[], target: string): Finding | null {
|
|
28
|
-
// Try "file:line" format
|
|
29
|
-
const colonIdx = target.lastIndexOf(':');
|
|
30
|
-
if (colonIdx > 0) {
|
|
31
|
-
const file = target.slice(0, colonIdx);
|
|
32
|
-
const line = parseInt(target.slice(colonIdx + 1), 10);
|
|
33
|
-
if (!isNaN(line)) {
|
|
34
|
-
const match = findings.find(f => f.file.endsWith(file) && f.line === line);
|
|
35
|
-
if (match) return match;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
// Try numeric index (1-based)
|
|
39
|
-
const n = parseInt(target, 10);
|
|
40
|
-
if (!isNaN(n) && n >= 1 && n <= findings.length) return findings[n - 1]!;
|
|
41
|
-
// Try finding id prefix
|
|
42
|
-
const byId = findings.find(f => f.id.startsWith(target));
|
|
43
|
-
if (byId) return byId;
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** Parse LLM output into named sections by ## headers. */
|
|
48
|
-
function parseSections(text: string): Map<string, string> {
|
|
49
|
-
const map = new Map<string, string>();
|
|
50
|
-
const parts = text.split(/^##\s+/m);
|
|
51
|
-
for (const part of parts) {
|
|
52
|
-
const newline = part.indexOf('\n');
|
|
53
|
-
if (newline < 0) continue;
|
|
54
|
-
const header = part.slice(0, newline).trim();
|
|
55
|
-
const body = part.slice(newline + 1).trim();
|
|
56
|
-
if (header && body) map.set(header, body);
|
|
57
|
-
}
|
|
58
|
-
return map;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function printSection(label: SectionName, body: string): void {
|
|
62
|
-
const icon: Record<SectionName, string> = {
|
|
63
|
-
'Root Cause': '🔍',
|
|
64
|
-
'Risk': '⚠️ ',
|
|
65
|
-
'How to Fix': '🔧',
|
|
66
|
-
'Example': '📝',
|
|
67
|
-
'When to Suppress': '✅',
|
|
68
|
-
};
|
|
69
|
-
console.log(`\n${fmt('bold', `${icon[label]} ${label}`)}`);
|
|
70
|
-
console.log(fmt('dim', '─'.repeat(50)));
|
|
71
|
-
console.log(body);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export async function runExplain(options: ExplainCommandOptions = {}): Promise<number> {
|
|
75
|
-
const cwd = options.cwd ?? process.cwd();
|
|
76
|
-
const configPath = options.configPath ?? path.join(cwd, 'guardrail.config.yaml');
|
|
77
|
-
|
|
78
|
-
const findings = loadCachedFindings(cwd);
|
|
79
|
-
if (findings.length === 0) {
|
|
80
|
-
console.log(fmt('yellow', '[explain] No cached findings — run `guardrail run` or `guardrail scan` first.'));
|
|
81
|
-
return 0;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
let finding: Finding | null = null;
|
|
85
|
-
|
|
86
|
-
if (options.target) {
|
|
87
|
-
finding = pickFinding(findings, options.target);
|
|
88
|
-
if (!finding) {
|
|
89
|
-
console.error(fmt('red', `[explain] No finding matching "${options.target}"`));
|
|
90
|
-
console.error(fmt('dim', ' Use file:line, finding index (1–' + findings.length + '), or rule id'));
|
|
91
|
-
return 1;
|
|
92
|
-
}
|
|
93
|
-
} else {
|
|
94
|
-
// No target — list findings and prompt
|
|
95
|
-
console.log(`\n${fmt('bold', '[explain]')} ${findings.length} cached finding${findings.length !== 1 ? 's' : ''}:\n`);
|
|
96
|
-
findings.forEach((f, i) => {
|
|
97
|
-
const sev = f.severity === 'critical' ? fmt('red', 'CRIT') : f.severity === 'warning' ? fmt('yellow', 'WARN') : fmt('dim', 'NOTE');
|
|
98
|
-
const loc = f.file !== '<unspecified>' ? fmt('dim', ` ${f.file}${f.line ? `:${f.line}` : ''}`) : '';
|
|
99
|
-
console.log(` ${String(i + 1).padStart(2)}. [${sev}]${loc} ${f.message.slice(0, 70)}`);
|
|
100
|
-
});
|
|
101
|
-
console.log(fmt('dim', '\n Run: guardrail explain <index|file:line|rule-id>\n'));
|
|
102
|
-
return 0;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Load engine
|
|
106
|
-
let engine;
|
|
107
|
-
try {
|
|
108
|
-
const config = fs.existsSync(configPath) ? await loadConfig(configPath) : { configVersion: 1 as const };
|
|
109
|
-
const ref = typeof config.reviewEngine === 'string' ? config.reviewEngine
|
|
110
|
-
: (config.reviewEngine?.adapter ?? 'auto');
|
|
111
|
-
engine = await loadAdapter({ point: 'review-engine', ref,
|
|
112
|
-
options: typeof config.reviewEngine === 'object' ? config.reviewEngine.options : undefined });
|
|
113
|
-
} catch (err) {
|
|
114
|
-
console.error(fmt('red', `[explain] Could not load review engine: ${err instanceof Error ? err.message : String(err)}`));
|
|
115
|
-
return 1;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Read file context
|
|
119
|
-
let codeContext = '';
|
|
120
|
-
if (finding.file && finding.file !== '<unspecified>' && finding.file !== '<pipeline>' && finding.line) {
|
|
121
|
-
const absPath = path.resolve(cwd, finding.file);
|
|
122
|
-
if (fs.existsSync(absPath)) {
|
|
123
|
-
const lines = fs.readFileSync(absPath, 'utf8').split('\n');
|
|
124
|
-
const lineIdx = finding.line - 1;
|
|
125
|
-
const start = Math.max(0, lineIdx - CONTEXT_LINES);
|
|
126
|
-
const end = Math.min(lines.length - 1, lineIdx + CONTEXT_LINES);
|
|
127
|
-
const numbered = lines.slice(start, end + 1).map((l, i) => {
|
|
128
|
-
const n = start + i + 1;
|
|
129
|
-
return `${n === finding!.line ? '>>>' : ' '} ${String(n).padStart(4)}: ${l}`;
|
|
130
|
-
}).join('\n');
|
|
131
|
-
codeContext = `\n\nRelevant code from ${finding.file} (>>> marks the finding):\n\`\`\`\n${numbered}\n\`\`\``;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const prompt = [
|
|
136
|
-
`I need a structured explanation of this code finding:`,
|
|
137
|
-
``,
|
|
138
|
-
`Rule: ${finding.id}`,
|
|
139
|
-
`Severity: ${finding.severity.toUpperCase()}`,
|
|
140
|
-
`File: ${finding.file}${finding.line ? `:${finding.line}` : ''}`,
|
|
141
|
-
`Message: ${finding.message}`,
|
|
142
|
-
finding.suggestion ? `Suggestion: ${finding.suggestion}` : '',
|
|
143
|
-
codeContext,
|
|
144
|
-
``,
|
|
145
|
-
`Respond using EXACTLY these five section headers (no other headers):`,
|
|
146
|
-
``,
|
|
147
|
-
`## Root Cause`,
|
|
148
|
-
`[technical explanation of why this problem exists]`,
|
|
149
|
-
``,
|
|
150
|
-
`## Risk`,
|
|
151
|
-
`[real-world impact, exploitability, and severity rationale]`,
|
|
152
|
-
``,
|
|
153
|
-
`## How to Fix`,
|
|
154
|
-
`[concrete, code-level remediation steps]`,
|
|
155
|
-
``,
|
|
156
|
-
`## Example`,
|
|
157
|
-
`[before/after code snippet showing the fix, in a fenced code block]`,
|
|
158
|
-
``,
|
|
159
|
-
`## When to Suppress`,
|
|
160
|
-
`[legitimate cases where this finding can be safely ignored]`,
|
|
161
|
-
].filter(s => s !== undefined && s !== null).join('\n');
|
|
162
|
-
|
|
163
|
-
const sev = finding.severity === 'critical' ? fmt('red', 'CRITICAL')
|
|
164
|
-
: finding.severity === 'warning' ? fmt('yellow', 'WARNING') : fmt('dim', 'NOTE');
|
|
165
|
-
|
|
166
|
-
console.log(`\n${fmt('bold', '[explain]')}`);
|
|
167
|
-
console.log(` [${sev}] ${fmt('dim', `${finding.file}${finding.line ? `:${finding.line}` : ''}`)} — ${finding.message}`);
|
|
168
|
-
if (finding.suggestion) console.log(` ${fmt('dim', `→ ${finding.suggestion}`)}`);
|
|
169
|
-
console.log('');
|
|
170
|
-
|
|
171
|
-
try {
|
|
172
|
-
const output = await (engine as unknown as ReviewEngine).review({ content: prompt, kind: 'file-batch' });
|
|
173
|
-
const text = output.rawOutput.trim();
|
|
174
|
-
const sections = parseSections(text);
|
|
175
|
-
|
|
176
|
-
let printed = false;
|
|
177
|
-
for (const label of SECTION_ORDER) {
|
|
178
|
-
const body = sections.get(label);
|
|
179
|
-
if (body) {
|
|
180
|
-
printSection(label, body);
|
|
181
|
-
printed = true;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (!printed) {
|
|
186
|
-
// LLM didn't follow the structure — print raw
|
|
187
|
-
console.log(text);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
console.log('');
|
|
191
|
-
} catch (err) {
|
|
192
|
-
console.error(fmt('red', `[explain] LLM error: ${err instanceof Error ? err.message : String(err)}`));
|
|
193
|
-
return 1;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return 0;
|
|
197
|
-
}
|