@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/setup.ts
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as fsAsync from 'node:fs/promises';
|
|
3
|
-
import * as path from 'node:path';
|
|
4
|
-
import { detectProject } from './detector.ts';
|
|
5
|
-
import { runHook } from './hook.ts';
|
|
6
|
-
import { runDoctor } from './preflight.ts';
|
|
7
|
-
import { detectLLMKey, LLM_KEY_NAMES } from '../core/detect/llm-key.ts';
|
|
8
|
-
import { requirePackageRoot } from './_pkg-root.ts';
|
|
9
|
-
|
|
10
|
-
const PASS = '\x1b[32m✓\x1b[0m';
|
|
11
|
-
const WARN = '\x1b[33m!\x1b[0m';
|
|
12
|
-
const DIM = (t: string) => `\x1b[2m${t}\x1b[0m`;
|
|
13
|
-
const BOLD = (t: string) => `\x1b[1m${t}\x1b[0m`;
|
|
14
|
-
const CYAN = (t: string) => `\x1b[36m${t}\x1b[0m`;
|
|
15
|
-
|
|
16
|
-
const PRESET_LABELS: Record<string, string> = {
|
|
17
|
-
'nextjs-supabase': 'Next.js + Supabase',
|
|
18
|
-
't3': 'T3 Stack (Next.js + tRPC + Prisma)',
|
|
19
|
-
'rails-postgres': 'Ruby on Rails + PostgreSQL',
|
|
20
|
-
'python-fastapi': 'Python FastAPI',
|
|
21
|
-
'go': 'Go + PostgreSQL',
|
|
22
|
-
'generic': 'Generic (no stack-specific assumptions)',
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type ProfileName = 'security-strict' | 'team' | 'solo';
|
|
26
|
-
|
|
27
|
-
const PROFILES: Record<ProfileName, { label: string; overlay: string }> = {
|
|
28
|
-
'security-strict': {
|
|
29
|
-
label: 'Security Strict',
|
|
30
|
-
overlay: [
|
|
31
|
-
'staticRules:',
|
|
32
|
-
' - hardcoded-secrets',
|
|
33
|
-
' - npm-audit',
|
|
34
|
-
' - package-lock-sync',
|
|
35
|
-
' - sql-injection',
|
|
36
|
-
' - missing-auth',
|
|
37
|
-
' - ssrf',
|
|
38
|
-
' - insecure-redirect',
|
|
39
|
-
'policy:',
|
|
40
|
-
' failOn: warning',
|
|
41
|
-
' newOnly: false',
|
|
42
|
-
].join('\n'),
|
|
43
|
-
},
|
|
44
|
-
'team': {
|
|
45
|
-
label: 'Team',
|
|
46
|
-
overlay: [
|
|
47
|
-
'staticRules:',
|
|
48
|
-
' - hardcoded-secrets',
|
|
49
|
-
' - npm-audit',
|
|
50
|
-
' - package-lock-sync',
|
|
51
|
-
' - sql-injection',
|
|
52
|
-
' - missing-auth',
|
|
53
|
-
' - ssrf',
|
|
54
|
-
' - insecure-redirect',
|
|
55
|
-
'policy:',
|
|
56
|
-
' failOn: critical',
|
|
57
|
-
' newOnly: false',
|
|
58
|
-
].join('\n'),
|
|
59
|
-
},
|
|
60
|
-
'solo': {
|
|
61
|
-
label: 'Solo Dev',
|
|
62
|
-
overlay: [
|
|
63
|
-
'staticRules:',
|
|
64
|
-
' - hardcoded-secrets',
|
|
65
|
-
' - npm-audit',
|
|
66
|
-
'policy:',
|
|
67
|
-
' failOn: critical',
|
|
68
|
-
' newOnly: false',
|
|
69
|
-
].join('\n'),
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export interface SetupOptions {
|
|
74
|
-
cwd?: string;
|
|
75
|
-
force?: boolean;
|
|
76
|
-
skipHook?: boolean;
|
|
77
|
-
profile?: ProfileName;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function presetSearchPaths(name: string, cwd: string): string[] {
|
|
81
|
-
const pkgRoot = requirePackageRoot(import.meta.url);
|
|
82
|
-
return [
|
|
83
|
-
path.join(pkgRoot, 'presets', name, 'guardrail.config.yaml'),
|
|
84
|
-
path.join(cwd, 'node_modules', '@delegance', 'claude-autopilot', 'presets', name, 'guardrail.config.yaml'),
|
|
85
|
-
];
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function findPresetConfig(name: string, cwd: string): string | null {
|
|
89
|
-
for (const p of presetSearchPaths(name, cwd)) {
|
|
90
|
-
if (fs.existsSync(p)) return p;
|
|
91
|
-
}
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export async function runSetup(options: SetupOptions = {}): Promise<void> {
|
|
96
|
-
const cwd = options.cwd ?? process.cwd();
|
|
97
|
-
const dest = path.join(cwd, 'guardrail.config.yaml');
|
|
98
|
-
|
|
99
|
-
if (fs.existsSync(dest) && !options.force) {
|
|
100
|
-
throw new Error('guardrail.config.yaml already exists — use --force to overwrite');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
console.log(`\n${BOLD('[setup]')} ${DIM(cwd)}\n`);
|
|
104
|
-
console.log(`${BOLD('Detecting project…')}\n`);
|
|
105
|
-
|
|
106
|
-
const detection = detectProject(cwd);
|
|
107
|
-
const label = PRESET_LABELS[detection.preset] ?? detection.preset;
|
|
108
|
-
|
|
109
|
-
if (detection.confidence === 'high') {
|
|
110
|
-
console.log(` ${PASS} Stack: ${label}`);
|
|
111
|
-
console.log(` ${PASS} Evidence: ${DIM(detection.evidence)}`);
|
|
112
|
-
} else {
|
|
113
|
-
console.log(` ${WARN} Stack: ${label} ${DIM('(low confidence — fallback preset)')}`);
|
|
114
|
-
console.log(` ${DIM(detection.evidence)}`);
|
|
115
|
-
console.log(` ${DIM('Edit guardrail.config.yaml to switch presets if needed')}`);
|
|
116
|
-
}
|
|
117
|
-
console.log(` ${PASS} Test command: ${DIM(detection.testCommand)}`);
|
|
118
|
-
|
|
119
|
-
const { hasKey, preferred } = detectLLMKey();
|
|
120
|
-
if (hasKey) {
|
|
121
|
-
console.log(` ${PASS} LLM API key: detected (${preferred})`);
|
|
122
|
-
} else {
|
|
123
|
-
console.log(` ${WARN} LLM API key: not found`);
|
|
124
|
-
console.log(` ${DIM(`Set one of: ${LLM_KEY_NAMES.join(', ')}`)}`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const presetConfigPath = findPresetConfig(detection.preset, cwd);
|
|
128
|
-
if (!presetConfigPath) {
|
|
129
|
-
throw new Error(`Preset config not found for: ${detection.preset}. Looked in:\n ${presetSearchPaths(detection.preset, cwd).join('\n ')}`);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
let presetContent = await fsAsync.readFile(presetConfigPath, 'utf8');
|
|
133
|
-
presetContent = presetContent.trimEnd() + `\ntestCommand: "${detection.testCommand}"\n`;
|
|
134
|
-
|
|
135
|
-
// Apply profile overlay if specified
|
|
136
|
-
if (options.profile) {
|
|
137
|
-
const profile = PROFILES[options.profile];
|
|
138
|
-
if (profile) {
|
|
139
|
-
console.log(` ${PASS} Profile: ${profile.label}`);
|
|
140
|
-
// Profile overlay replaces staticRules + policy sections from preset
|
|
141
|
-
presetContent = presetContent
|
|
142
|
-
.replace(/^staticRules:.*?(?=^\w|\z)/ms, '')
|
|
143
|
-
.replace(/^policy:.*?(?=^\w|\z)/ms, '');
|
|
144
|
-
presetContent = presetContent.trimEnd() + `\n${profile.overlay}\n`;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
await fsAsync.writeFile(dest, presetContent, 'utf8');
|
|
149
|
-
|
|
150
|
-
console.log(`\n${BOLD('Config written to guardrail.config.yaml:')}\n`);
|
|
151
|
-
for (const line of presetContent.trimEnd().split('\n')) {
|
|
152
|
-
console.log(` ${DIM(line)}`);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
let hookInstalled = false;
|
|
156
|
-
if (!options.skipHook) {
|
|
157
|
-
const hookCode = await runHook('install', { cwd, silent: true });
|
|
158
|
-
hookInstalled = hookCode === 0;
|
|
159
|
-
if (hookInstalled) {
|
|
160
|
-
console.log(`\n ${PASS} Pre-push git hook installed`);
|
|
161
|
-
} else {
|
|
162
|
-
console.log(`\n ${WARN} Hook install failed (run: npx guardrail hook install)`);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
console.log('\nChecking prerequisites…');
|
|
167
|
-
await runDoctor();
|
|
168
|
-
|
|
169
|
-
console.log(`\n${BOLD('Next steps:')}\n`);
|
|
170
|
-
if (!hasKey) {
|
|
171
|
-
console.log(` 1. ${CYAN('Set an LLM API key')} — guardrail needs one to review code:`);
|
|
172
|
-
console.log(` export ANTHROPIC_API_KEY=sk-ant-... # https://console.anthropic.com/`);
|
|
173
|
-
console.log(` export OPENAI_API_KEY=sk-... # https://platform.openai.com/api-keys`);
|
|
174
|
-
console.log(` export GROQ_API_KEY=gsk_... # https://console.groq.com/keys (free)\n`);
|
|
175
|
-
console.log(` 2. ${CYAN('Review your changes:')}`);
|
|
176
|
-
console.log(` npx guardrail run --base main\n`);
|
|
177
|
-
console.log(` 3. ${CYAN('Scan any path directly:')}`);
|
|
178
|
-
console.log(` npx guardrail scan src/auth/\n`);
|
|
179
|
-
} else {
|
|
180
|
-
console.log(` ${CYAN('Review git-changed files:')}`);
|
|
181
|
-
console.log(` npx guardrail run --base main\n`);
|
|
182
|
-
console.log(` ${CYAN('Scan any path (no git needed):')}`);
|
|
183
|
-
console.log(` npx guardrail scan src/auth/\n`);
|
|
184
|
-
console.log(` ${CYAN('Ask a targeted question:')}`);
|
|
185
|
-
console.log(` npx guardrail scan --ask "is there SQL injection here?" src/db/\n`);
|
|
186
|
-
if (!hookInstalled && !options.skipHook) {
|
|
187
|
-
console.log(` ${CYAN('Install pre-push hook (auto-runs before git push):')}`);
|
|
188
|
-
console.log(` npx guardrail hook install\n`);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
package/src/cli/test-gen.ts
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { execFileSync } from 'node:child_process';
|
|
4
|
-
import { loadConfig } from '../core/config/loader.ts';
|
|
5
|
-
import { loadAdapter } from '../adapters/loader.ts';
|
|
6
|
-
import type { ReviewEngine } from '../adapters/review-engine/types.ts';
|
|
7
|
-
import { findCoverageGaps } from '../core/test-gen/coverage-analyzer.ts';
|
|
8
|
-
import { detectTestFramework } from '../core/test-gen/framework-detector.ts';
|
|
9
|
-
import { writeGeneratedTest, buildGenerationPrompt } from '../core/test-gen/test-writer.ts';
|
|
10
|
-
|
|
11
|
-
const C = { reset: '\x1b[0m', green: '\x1b[32m', yellow: '\x1b[33m', red: '\x1b[31m', dim: '\x1b[2m', bold: '\x1b[1m', cyan: '\x1b[36m' };
|
|
12
|
-
|
|
13
|
-
export interface TestGenOptions {
|
|
14
|
-
cwd?: string;
|
|
15
|
-
configPath?: string;
|
|
16
|
-
targets?: string[];
|
|
17
|
-
base?: string;
|
|
18
|
-
dryRun?: boolean;
|
|
19
|
-
verify?: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function runTestGen(options: TestGenOptions = {}): Promise<number> {
|
|
23
|
-
const cwd = options.cwd ?? process.cwd();
|
|
24
|
-
const configPath = options.configPath ?? path.join(cwd, 'guardrail.config.yaml');
|
|
25
|
-
|
|
26
|
-
let config = { configVersion: 1 as const, testCommand: null as string | null };
|
|
27
|
-
if (fs.existsSync(configPath)) {
|
|
28
|
-
try {
|
|
29
|
-
const loaded = await loadConfig(configPath);
|
|
30
|
-
if (loaded) config = loaded as typeof config;
|
|
31
|
-
} catch {
|
|
32
|
-
// proceed with defaults if config fails to load
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Collect files to analyze
|
|
37
|
-
let files: string[];
|
|
38
|
-
if (options.targets && options.targets.length > 0) {
|
|
39
|
-
files = options.targets.map(t => path.isAbsolute(t) ? t : path.resolve(cwd, t));
|
|
40
|
-
} else {
|
|
41
|
-
// Fall back to git-changed files
|
|
42
|
-
try {
|
|
43
|
-
const base = options.base ?? 'HEAD~1';
|
|
44
|
-
const out = execFileSync('git', ['diff', '--name-only', base, 'HEAD'], { cwd, encoding: 'utf8' });
|
|
45
|
-
files = out.trim().split('\n').filter(Boolean).map(f => path.resolve(cwd, f));
|
|
46
|
-
} catch {
|
|
47
|
-
console.error(`${C.red}[test-gen] No targets specified and git diff failed. Pass a path: guardrail test-gen src/${C.reset}`);
|
|
48
|
-
return 1;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
console.log(`${C.bold}[test-gen]${C.reset} Analyzing ${files.length} file(s)...`);
|
|
53
|
-
const gaps = findCoverageGaps(files);
|
|
54
|
-
|
|
55
|
-
if (gaps.length === 0) {
|
|
56
|
-
console.log(`${C.green}[test-gen] No coverage gaps found${C.reset}`);
|
|
57
|
-
return 0;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
for (const gap of gaps) {
|
|
61
|
-
const rel = path.relative(cwd, gap.file);
|
|
62
|
-
const covered = gap.exports.length;
|
|
63
|
-
console.log(` ${C.cyan}${rel}${C.reset} ${covered} uncovered export(s): ${gap.exports.join(', ')}`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (options.dryRun) {
|
|
67
|
-
console.log(`\n${C.yellow}[test-gen] Dry run — not generating tests${C.reset}`);
|
|
68
|
-
return 0;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Load review engine for generation
|
|
72
|
-
const engineRef = (config as { reviewEngine?: unknown }).reviewEngine ?? 'auto';
|
|
73
|
-
let engine: Awaited<ReturnType<typeof loadAdapter>>;
|
|
74
|
-
try {
|
|
75
|
-
engine = await loadAdapter({ point: 'review-engine', ref: engineRef as string });
|
|
76
|
-
} catch (err) {
|
|
77
|
-
console.error(`${C.red}[test-gen] Could not load review engine: ${err}${C.reset}`);
|
|
78
|
-
return 1;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const framework = detectTestFramework(cwd);
|
|
82
|
-
const written: string[] = [];
|
|
83
|
-
|
|
84
|
-
for (const gap of gaps) {
|
|
85
|
-
let sourceContent: string;
|
|
86
|
-
try { sourceContent = fs.readFileSync(gap.file, 'utf8'); } catch { continue; }
|
|
87
|
-
|
|
88
|
-
const prompt = buildGenerationPrompt(gap, sourceContent, framework);
|
|
89
|
-
|
|
90
|
-
process.stdout.write(` Generating ${path.relative(cwd, gap.testFile)}... `);
|
|
91
|
-
try {
|
|
92
|
-
const result = await (engine as unknown as ReviewEngine).review({ content: prompt, kind: 'spec', context: { cwd } });
|
|
93
|
-
|
|
94
|
-
// Extract code block if wrapped in markdown
|
|
95
|
-
let code = result.rawOutput.trim();
|
|
96
|
-
const fenceMatch = code.match(/```(?:typescript|ts|javascript|js)?\n([\s\S]*?)```/);
|
|
97
|
-
if (fenceMatch) code = fenceMatch[1]!.trim();
|
|
98
|
-
|
|
99
|
-
const testPath = writeGeneratedTest(gap, code);
|
|
100
|
-
written.push(testPath);
|
|
101
|
-
console.log(`${C.green}done${C.reset}`);
|
|
102
|
-
|
|
103
|
-
// Verify mode
|
|
104
|
-
if (options.verify && config.testCommand) {
|
|
105
|
-
try {
|
|
106
|
-
const [cmd, ...cmdArgs] = config.testCommand.split(/\s+/);
|
|
107
|
-
execFileSync(cmd!, cmdArgs, { cwd, stdio: 'ignore', timeout: 60_000 });
|
|
108
|
-
} catch {
|
|
109
|
-
fs.unlinkSync(testPath);
|
|
110
|
-
written.pop();
|
|
111
|
-
console.log(` ${C.yellow} ↳ tests failed — reverted${C.reset}`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
} catch (err) {
|
|
115
|
-
console.log(`${C.red}failed: ${err}${C.reset}`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (written.length > 0) {
|
|
120
|
-
console.log(`\n${C.green}[test-gen] Generated ${written.length} test file(s):${C.reset}`);
|
|
121
|
-
for (const f of written) console.log(` ${path.relative(cwd, f)}`);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return 0;
|
|
125
|
-
}
|
package/src/cli/triage.ts
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { loadCachedFindings } from '../core/persist/findings-cache.ts';
|
|
2
|
-
import {
|
|
3
|
-
loadTriage, saveTriage, addTriageEntry, removeTriageEntry, clearExpiredEntries,
|
|
4
|
-
type TriageState,
|
|
5
|
-
} from '../core/persist/triage.ts';
|
|
6
|
-
|
|
7
|
-
const C = {
|
|
8
|
-
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
9
|
-
green: '\x1b[32m', yellow: '\x1b[33m', red: '\x1b[31m',
|
|
10
|
-
};
|
|
11
|
-
const fmt = (c: keyof typeof C, t: string) => `${C[c]}${t}${C.reset}`;
|
|
12
|
-
|
|
13
|
-
export interface TriageCommandOptions {
|
|
14
|
-
cwd?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function parseTriageArgs(rest: string[]): { reason?: string; expiresInDays?: number; positional: string[] } {
|
|
18
|
-
let reason: string | undefined;
|
|
19
|
-
let expiresInDays: number | undefined;
|
|
20
|
-
const positional: string[] = [];
|
|
21
|
-
for (let i = 0; i < rest.length; i++) {
|
|
22
|
-
if (rest[i] === '--reason' && rest[i + 1]) { reason = rest[++i]; }
|
|
23
|
-
else if (rest[i] === '--expires' && rest[i + 1]) { expiresInDays = parseInt(rest[++i]!, 10); }
|
|
24
|
-
else if (!rest[i]!.startsWith('--')) { positional.push(rest[i]!); }
|
|
25
|
-
}
|
|
26
|
-
return { reason, expiresInDays, positional };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export async function runTriage(
|
|
30
|
-
subcommand: string | undefined,
|
|
31
|
-
rest: string[],
|
|
32
|
-
options: TriageCommandOptions = {},
|
|
33
|
-
): Promise<number> {
|
|
34
|
-
const cwd = options.cwd ?? process.cwd();
|
|
35
|
-
|
|
36
|
-
if (subcommand === 'list' || subcommand === 'show') {
|
|
37
|
-
return cmdList(cwd);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (subcommand === 'clear') {
|
|
41
|
-
const { positional } = parseTriageArgs(rest);
|
|
42
|
-
return cmdClear(cwd, positional, rest.includes('--expired'));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Default: triage <finding-id> <state>
|
|
46
|
-
const findingId = subcommand;
|
|
47
|
-
const { reason, expiresInDays, positional } = parseTriageArgs(rest);
|
|
48
|
-
const stateArg = positional[0];
|
|
49
|
-
|
|
50
|
-
if (!findingId || !stateArg) {
|
|
51
|
-
printUsage();
|
|
52
|
-
return 1;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (stateArg !== 'accepted-risk' && stateArg !== 'false-positive') {
|
|
56
|
-
console.error(fmt('red', `[triage] State must be "accepted-risk" or "false-positive", got: "${stateArg}"`));
|
|
57
|
-
return 1;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const findings = loadCachedFindings(cwd);
|
|
61
|
-
const finding = findings.find(f => f.id === findingId || f.id.startsWith(findingId));
|
|
62
|
-
if (!finding) {
|
|
63
|
-
console.error(fmt('red', `[triage] Finding not found: "${findingId}"`));
|
|
64
|
-
console.error(fmt('dim', ' Run `guardrail run` or `guardrail scan` first, then `guardrail report` to list IDs'));
|
|
65
|
-
return 1;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
addTriageEntry(cwd, finding, stateArg as TriageState, { reason, expiresInDays });
|
|
69
|
-
|
|
70
|
-
const expNote = expiresInDays !== undefined ? fmt('dim', ` (expires in ${expiresInDays} days)`) : '';
|
|
71
|
-
console.log(`${fmt('green', '✓')} ${fmt('bold', stateArg)} ${finding.file}${finding.line ? `:${finding.line}` : ''} — ${finding.message}${expNote}`);
|
|
72
|
-
if (reason) console.log(fmt('dim', ` Reason: ${reason}`));
|
|
73
|
-
console.log(fmt('dim', ' Suppressed from future runs. Commit .guardrail-triage.json to share with team.'));
|
|
74
|
-
return 0;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function cmdList(cwd: string): number {
|
|
78
|
-
const store = loadTriage(cwd);
|
|
79
|
-
const now = new Date().toISOString();
|
|
80
|
-
const active = store.entries.filter(e => !e.expiresAt || e.expiresAt > now);
|
|
81
|
-
const expired = store.entries.filter(e => e.expiresAt && e.expiresAt <= now);
|
|
82
|
-
|
|
83
|
-
if (store.entries.length === 0) {
|
|
84
|
-
console.log(fmt('dim', '[triage] No triaged findings.'));
|
|
85
|
-
return 0;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
console.log(`\n${fmt('bold', '[triage]')} ${active.length} active, ${expired.length} expired\n`);
|
|
89
|
-
for (const e of active) {
|
|
90
|
-
const tag = e.state === 'false-positive'
|
|
91
|
-
? fmt('dim', 'false-positive ')
|
|
92
|
-
: fmt('yellow', 'accepted-risk ');
|
|
93
|
-
const exp = e.expiresAt ? fmt('dim', ` expires ${e.expiresAt.slice(0, 10)}`) : '';
|
|
94
|
-
console.log(` [${tag}] ${fmt('dim', `${e.file}${e.line ? `:${e.line}` : ''}`)} — ${e.id}${exp}`);
|
|
95
|
-
if (e.reason) console.log(fmt('dim', ` Reason: ${e.reason}`));
|
|
96
|
-
}
|
|
97
|
-
if (expired.length > 0) {
|
|
98
|
-
console.log(fmt('dim', `\n ${expired.length} expired — run \`guardrail triage clear --expired\` to remove`));
|
|
99
|
-
}
|
|
100
|
-
console.log('');
|
|
101
|
-
return 0;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function cmdClear(cwd: string, ids: string[], expired: boolean): number {
|
|
105
|
-
if (expired) {
|
|
106
|
-
const removed = clearExpiredEntries(cwd);
|
|
107
|
-
console.log(fmt('dim', `[triage] Cleared ${removed} expired entr${removed === 1 ? 'y' : 'ies'}`));
|
|
108
|
-
return 0;
|
|
109
|
-
}
|
|
110
|
-
if (ids.length === 0) {
|
|
111
|
-
console.error(fmt('red', '[triage] clear requires a finding ID or --expired'));
|
|
112
|
-
return 1;
|
|
113
|
-
}
|
|
114
|
-
const removed = removeTriageEntry(cwd, ids);
|
|
115
|
-
console.log(fmt('dim', `[triage] Cleared ${removed} entr${removed === 1 ? 'y' : 'ies'}`));
|
|
116
|
-
return 0;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function printUsage(): void {
|
|
120
|
-
console.error(`
|
|
121
|
-
${fmt('bold', 'Usage:')}
|
|
122
|
-
guardrail triage <finding-id> accepted-risk|false-positive [options]
|
|
123
|
-
guardrail triage list
|
|
124
|
-
guardrail triage clear <finding-id> [<id>...]
|
|
125
|
-
guardrail triage clear --expired
|
|
126
|
-
|
|
127
|
-
${fmt('bold', 'Options:')}
|
|
128
|
-
--reason <text> Explain why this finding was triaged
|
|
129
|
-
--expires <days> Auto-expire triage after N days
|
|
130
|
-
|
|
131
|
-
${fmt('bold', 'States:')}
|
|
132
|
-
accepted-risk Known issue, risk accepted — suppress without fixing
|
|
133
|
-
false-positive Finding is incorrect — suppress permanently (or with expiry)
|
|
134
|
-
|
|
135
|
-
${fmt('dim', 'Finding IDs come from `guardrail report` or the run output.')}
|
|
136
|
-
`);
|
|
137
|
-
}
|
package/src/cli/watch.ts
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { loadConfig } from '../core/config/loader.ts';
|
|
4
|
-
import { resolvePreset, mergeConfigs } from '../core/config/preset-resolver.ts';
|
|
5
|
-
import { loadAdapter } from '../adapters/loader.ts';
|
|
6
|
-
import { runGuardrail } from '../core/pipeline/run.ts';
|
|
7
|
-
import type { ReviewEngine } from '../adapters/review-engine/types.ts';
|
|
8
|
-
import type { GuardrailConfig } from '../core/config/types.ts';
|
|
9
|
-
|
|
10
|
-
const C = {
|
|
11
|
-
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
12
|
-
green: '\x1b[32m', yellow: '\x1b[33m', red: '\x1b[31m', cyan: '\x1b[36m',
|
|
13
|
-
};
|
|
14
|
-
const fmt = (c: keyof typeof C, t: string) => `${C[c]}${t}${C.reset}`;
|
|
15
|
-
|
|
16
|
-
// Anchored to path segment boundaries — avoids matching "mynode_modules" or similar
|
|
17
|
-
export const IGNORED_PATTERNS: readonly RegExp[] = [
|
|
18
|
-
/(^|[/\\])node_modules([/\\]|$)/,
|
|
19
|
-
/(^|[/\\])\.git([/\\]|$)/,
|
|
20
|
-
/(^|[/\\])\.guardrail-cache([/\\]|$)/,
|
|
21
|
-
/\.(log|tmp|swp|swo|DS_Store)$/,
|
|
22
|
-
/~$/,
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
export function isIgnored(p: string): boolean {
|
|
26
|
-
return IGNORED_PATTERNS.some(r => r.test(p));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Pure debounce accumulator — returned functions are the testable core of watch logic.
|
|
31
|
-
* schedule(file) → adds file, starts/resets timer; when debounce fires, calls flush(batch).
|
|
32
|
-
* onSchedule (optional) is called on every schedule() with the file and current queue size.
|
|
33
|
-
*/
|
|
34
|
-
export function makeDebouncer(
|
|
35
|
-
flushFn: (batch: string[]) => void,
|
|
36
|
-
debounceMs: number,
|
|
37
|
-
onSchedule?: (file: string, queueSize: number) => void,
|
|
38
|
-
): { schedule: (file: string) => void; pending: () => string[] } {
|
|
39
|
-
const pending = new Set<string>();
|
|
40
|
-
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
41
|
-
return {
|
|
42
|
-
schedule(file: string) {
|
|
43
|
-
pending.add(file);
|
|
44
|
-
if (timer) clearTimeout(timer);
|
|
45
|
-
timer = setTimeout(() => {
|
|
46
|
-
const batch = [...pending];
|
|
47
|
-
pending.clear();
|
|
48
|
-
timer = null;
|
|
49
|
-
flushFn(batch);
|
|
50
|
-
}, debounceMs);
|
|
51
|
-
onSchedule?.(file, pending.size);
|
|
52
|
-
},
|
|
53
|
-
pending() { return [...pending]; },
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface WatchOptions {
|
|
58
|
-
cwd?: string;
|
|
59
|
-
configPath?: string;
|
|
60
|
-
debounceMs?: number;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export async function runWatch(options: WatchOptions = {}): Promise<void> {
|
|
64
|
-
const cwd = options.cwd ?? process.cwd();
|
|
65
|
-
const configPath = options.configPath ?? path.join(cwd, 'guardrail.config.yaml');
|
|
66
|
-
const debounceMs = options.debounceMs ?? 300;
|
|
67
|
-
|
|
68
|
-
// Zero-config fallback — same as `run`
|
|
69
|
-
let config: GuardrailConfig;
|
|
70
|
-
if (!fs.existsSync(configPath)) {
|
|
71
|
-
config = { configVersion: 1, reviewEngine: { adapter: 'auto' }, testCommand: null };
|
|
72
|
-
} else {
|
|
73
|
-
try {
|
|
74
|
-
const userConfig = await loadConfig(configPath);
|
|
75
|
-
config = userConfig.preset
|
|
76
|
-
? mergeConfigs((await resolvePreset(userConfig.preset)).config, userConfig)
|
|
77
|
-
: userConfig;
|
|
78
|
-
} catch (err) {
|
|
79
|
-
console.error(fmt('red', `[watch] Config error: ${err instanceof Error ? err.message : String(err)}`));
|
|
80
|
-
process.exit(1);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const hasAnyKey = !!(process.env.ANTHROPIC_API_KEY || process.env.GEMINI_API_KEY ||
|
|
85
|
-
process.env.GOOGLE_API_KEY || process.env.OPENAI_API_KEY || process.env.GROQ_API_KEY);
|
|
86
|
-
|
|
87
|
-
let reviewEngine: ReviewEngine | undefined;
|
|
88
|
-
if (config.reviewEngine && hasAnyKey) {
|
|
89
|
-
const ref = typeof config.reviewEngine === 'string' ? config.reviewEngine : config.reviewEngine.adapter;
|
|
90
|
-
try {
|
|
91
|
-
reviewEngine = await loadAdapter<ReviewEngine>({
|
|
92
|
-
point: 'review-engine', ref,
|
|
93
|
-
options: typeof config.reviewEngine === 'string' ? undefined : config.reviewEngine.options,
|
|
94
|
-
});
|
|
95
|
-
} catch { /* skip — static rules still run */ }
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const keyStatus = hasAnyKey
|
|
99
|
-
? fmt('green', '✓ LLM review enabled')
|
|
100
|
-
: fmt('yellow', '! No API key — static rules only (set ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, or GROQ_API_KEY)');
|
|
101
|
-
|
|
102
|
-
console.log(`\n${fmt('bold', '[watch]')} ${fmt('dim', cwd)}`);
|
|
103
|
-
console.log(fmt('dim', ` debounce: ${debounceMs}ms | Ctrl+C to exit`));
|
|
104
|
-
console.log(` ${keyStatus}\n`);
|
|
105
|
-
console.log(fmt('dim', ' Watching for changes…\n'));
|
|
106
|
-
|
|
107
|
-
let running = false;
|
|
108
|
-
const nextPending = new Set<string>();
|
|
109
|
-
let debounceLineShown = false;
|
|
110
|
-
|
|
111
|
-
const runBatch = async (batch: string[]) => {
|
|
112
|
-
debounceLineShown = false;
|
|
113
|
-
if (running) {
|
|
114
|
-
for (const f of batch) nextPending.add(f);
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
running = true;
|
|
118
|
-
|
|
119
|
-
const rel = batch.map(f => path.isAbsolute(f) ? path.relative(cwd, f) : f);
|
|
120
|
-
const ts = new Date().toLocaleTimeString();
|
|
121
|
-
console.log(`\n${fmt('cyan', `─── ${ts} ──────────────────────────────────`)}`);
|
|
122
|
-
console.log(fmt('dim', ` changed: ${rel.slice(0, 4).join(', ')}${rel.length > 4 ? ` +${rel.length - 4} more` : ''}`));
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
const result = await runGuardrail({ touchedFiles: rel, config, reviewEngine, cwd });
|
|
126
|
-
|
|
127
|
-
for (const phase of result.phases) {
|
|
128
|
-
const icon = phase.status === 'pass' ? fmt('green', '✓')
|
|
129
|
-
: phase.status === 'skip' ? fmt('dim', '–')
|
|
130
|
-
: phase.status === 'warn' ? fmt('yellow', '!')
|
|
131
|
-
: fmt('red', '✗');
|
|
132
|
-
console.log(` ${icon} ${phase.phase.padEnd(14)}${fmt('dim', ` ${(phase as {durationMs?: number}).durationMs ?? 0}ms`)}`);
|
|
133
|
-
for (const f of phase.findings) {
|
|
134
|
-
if (f.severity === 'critical' || f.severity === 'warning') {
|
|
135
|
-
const sev = f.severity === 'critical' ? fmt('red', 'CRITICAL') : fmt('yellow', 'WARNING ');
|
|
136
|
-
console.log(` ${sev} ${f.file}${f.line ? `:${f.line}` : ''} — ${f.message}`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const verdict = result.status === 'pass' ? fmt('green', '✓ pass')
|
|
142
|
-
: result.status === 'warn' ? fmt('yellow', '! warn')
|
|
143
|
-
: fmt('red', '✗ fail');
|
|
144
|
-
const cost = result.totalCostUSD !== undefined ? fmt('dim', ` $${result.totalCostUSD.toFixed(4)}`) : '';
|
|
145
|
-
console.log(`\n ${verdict}${cost} ${fmt('dim', `${result.durationMs}ms`)}`);
|
|
146
|
-
} catch (err) {
|
|
147
|
-
console.error(fmt('red', ` error: ${err instanceof Error ? err.message : String(err)}`));
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
running = false;
|
|
151
|
-
console.log(fmt('dim', '\n Watching for changes…'));
|
|
152
|
-
|
|
153
|
-
if (nextPending.size > 0) {
|
|
154
|
-
const queued = [...nextPending];
|
|
155
|
-
nextPending.clear();
|
|
156
|
-
runBatch(queued);
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
const debouncer = makeDebouncer(
|
|
161
|
-
batch => { runBatch(batch); },
|
|
162
|
-
debounceMs,
|
|
163
|
-
(_file, queueSize) => {
|
|
164
|
-
if (!debounceLineShown && !running) {
|
|
165
|
-
process.stdout.write(fmt('dim', ` ⋯ ${queueSize} file(s) queued — reviewing in ${debounceMs}ms…\r`));
|
|
166
|
-
debounceLineShown = true;
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
const onEvent = (_event: string, filename: string | null) => {
|
|
172
|
-
if (!filename) return;
|
|
173
|
-
const full = path.isAbsolute(filename) ? filename : path.join(cwd, filename);
|
|
174
|
-
if (isIgnored(full)) return;
|
|
175
|
-
debouncer.schedule(full);
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
// fs.watch recursive is supported on macOS/Linux kernel ≥5.1; Windows uses ReadDirectoryChangesW.
|
|
179
|
-
// Alpha limitation: not battle-tested in Docker/container contexts — upgrade to chokidar for beta.
|
|
180
|
-
const watcher = fs.watch(cwd, { recursive: true }, onEvent);
|
|
181
|
-
|
|
182
|
-
process.on('SIGINT', () => {
|
|
183
|
-
console.log(fmt('dim', '\n[watch] exiting'));
|
|
184
|
-
watcher.close();
|
|
185
|
-
process.exit(0);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
// Keep the process alive
|
|
189
|
-
await new Promise<void>(() => { /* never resolves — watch loop runs until SIGINT */ });
|
|
190
|
-
}
|