@delegance/claude-autopilot 5.0.1 → 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/src/cli/index.js +39 -1
- package/dist/src/cli/preflight.js +17 -4
- 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/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
|
-
}
|