@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
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { runSafe } from '../core/shell.ts';
|
|
2
|
-
import type { Finding } from '../core/findings/types.ts';
|
|
3
|
-
|
|
4
|
-
const REVIEW_MARKER = '<!-- guardrail-inline -->';
|
|
5
|
-
|
|
6
|
-
function getRepoNwo(cwd: string): string | null {
|
|
7
|
-
const raw = runSafe('gh', ['repo', 'view', '--json', 'nameWithOwner', '--jq', '.nameWithOwner'], { cwd });
|
|
8
|
-
return raw ? raw.trim() : null;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/** True when a review with our marker already exists on this PR (avoids duplicates on re-runs). */
|
|
12
|
-
function findExistingReviewId(pr: number, nwo: string, cwd: string): number | null {
|
|
13
|
-
const raw = runSafe('gh', [
|
|
14
|
-
'api', `repos/${nwo}/pulls/${pr}/reviews`,
|
|
15
|
-
'--jq', `[.[] | select(.body | startswith("${REVIEW_MARKER}")) | .id] | first`,
|
|
16
|
-
], { cwd });
|
|
17
|
-
if (!raw) return null;
|
|
18
|
-
const n = parseInt(raw.trim(), 10);
|
|
19
|
-
return isNaN(n) ? null : n;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface PostReviewCommentsResult {
|
|
23
|
-
posted: number;
|
|
24
|
-
skipped: number; // findings with no line number
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Posts (or re-submits) a PR review with inline comments for each finding
|
|
29
|
-
* that has a file + line number. Findings without line numbers are skipped.
|
|
30
|
-
* Re-runs dismiss the previous autopilot review first to avoid stacking.
|
|
31
|
-
*/
|
|
32
|
-
export async function postReviewComments(
|
|
33
|
-
pr: number,
|
|
34
|
-
findings: Finding[],
|
|
35
|
-
cwd: string,
|
|
36
|
-
): Promise<PostReviewCommentsResult> {
|
|
37
|
-
const nwo = getRepoNwo(cwd);
|
|
38
|
-
if (!nwo) throw new Error('Could not determine repository name โ is gh authenticated?');
|
|
39
|
-
|
|
40
|
-
const commentable = findings.filter(
|
|
41
|
-
f => f.line !== undefined && f.file && f.file !== '<unspecified>' && f.file !== '<pipeline>',
|
|
42
|
-
);
|
|
43
|
-
const skipped = findings.length - commentable.length;
|
|
44
|
-
|
|
45
|
-
if (commentable.length === 0) return { posted: 0, skipped };
|
|
46
|
-
|
|
47
|
-
// Dismiss existing review so we don't stack on re-runs
|
|
48
|
-
const existingId = findExistingReviewId(pr, nwo, cwd);
|
|
49
|
-
if (existingId) {
|
|
50
|
-
runSafe('gh', [
|
|
51
|
-
'api', `repos/${nwo}/pulls/${pr}/reviews/${existingId}/dismissals`,
|
|
52
|
-
'--method', 'PUT',
|
|
53
|
-
'--field', 'message=Superseded by updated guardrail review',
|
|
54
|
-
], { cwd });
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Build review body
|
|
58
|
-
const body = [
|
|
59
|
-
REVIEW_MARKER,
|
|
60
|
-
`**Autopilot** found ${commentable.length} inline finding${commentable.length !== 1 ? 's' : ''}.`,
|
|
61
|
-
].join('\n');
|
|
62
|
-
|
|
63
|
-
// Build comments array as JSON
|
|
64
|
-
const comments = commentable.map(f => ({
|
|
65
|
-
path: f.file,
|
|
66
|
-
line: f.line,
|
|
67
|
-
side: 'RIGHT',
|
|
68
|
-
body: formatFindingBody(f),
|
|
69
|
-
}));
|
|
70
|
-
|
|
71
|
-
// gh api doesn't support array fields well via --field, use --input with JSON
|
|
72
|
-
const payload = JSON.stringify({ body, event: 'COMMENT', comments });
|
|
73
|
-
const result = runSafe('gh', [
|
|
74
|
-
'api', `repos/${nwo}/pulls/${pr}/reviews`,
|
|
75
|
-
'--method', 'POST',
|
|
76
|
-
'--input', '-',
|
|
77
|
-
], { cwd, input: payload });
|
|
78
|
-
|
|
79
|
-
if (!result) throw new Error('Failed to post review โ gh api returned no output');
|
|
80
|
-
|
|
81
|
-
return { posted: commentable.length, skipped };
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function formatFindingBody(f: Finding): string {
|
|
85
|
-
const sev = f.severity === 'critical' ? '๐จ **CRITICAL**'
|
|
86
|
-
: f.severity === 'warning' ? 'โ ๏ธ **Warning**'
|
|
87
|
-
: '๐ก **Note**';
|
|
88
|
-
const lines = [`${sev} โ ${f.message}`];
|
|
89
|
-
if (f.suggestion) lines.push(`\n> **Suggestion:** ${f.suggestion}`);
|
|
90
|
-
lines.push(`\n*[@delegance/guardrail](https://github.com/axledbetter/guardrail)*`);
|
|
91
|
-
return lines.join('');
|
|
92
|
-
}
|
package/src/cli/pr.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import * as path from 'node:path';
|
|
2
|
-
import * as fs from 'node:fs';
|
|
3
|
-
import { spawnSync } from 'node:child_process';
|
|
4
|
-
import { runCommand } from './run.ts';
|
|
5
|
-
|
|
6
|
-
const C = {
|
|
7
|
-
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
8
|
-
green: '\x1b[32m', yellow: '\x1b[33m', red: '\x1b[31m',
|
|
9
|
-
};
|
|
10
|
-
const fmt = (c: keyof typeof C, t: string) => `${C[c]}${t}${C.reset}`;
|
|
11
|
-
|
|
12
|
-
export interface PrCommandOptions {
|
|
13
|
-
cwd?: string;
|
|
14
|
-
configPath?: string;
|
|
15
|
-
prNumber?: string;
|
|
16
|
-
noPostComments?: boolean;
|
|
17
|
-
noInlineComments?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function ghJson<T>(args: string[], cwd: string): T | null {
|
|
21
|
-
const r = spawnSync('gh', args, { cwd, encoding: 'utf8' });
|
|
22
|
-
if (r.status !== 0) return null;
|
|
23
|
-
try { return JSON.parse(r.stdout) as T; } catch { return null; }
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function gitFetch(remote: string, ref: string, cwd: string): boolean {
|
|
27
|
-
const r = spawnSync('git', ['fetch', remote, ref], { cwd, encoding: 'utf8', stdio: 'pipe' });
|
|
28
|
-
return r.status === 0;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function runPr(options: PrCommandOptions = {}): Promise<number> {
|
|
32
|
-
const cwd = options.cwd ?? process.cwd();
|
|
33
|
-
const configPath = options.configPath ?? path.join(cwd, 'guardrail.config.yaml');
|
|
34
|
-
|
|
35
|
-
if (!fs.existsSync(configPath)) {
|
|
36
|
-
console.error(fmt('red', `[pr] guardrail.config.yaml not found at ${configPath}`));
|
|
37
|
-
return 1;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Resolve PR number
|
|
41
|
-
let prNumber = options.prNumber;
|
|
42
|
-
if (!prNumber) {
|
|
43
|
-
const detected = ghJson<{ number: number }>(['pr', 'view', '--json', 'number'], cwd);
|
|
44
|
-
if (!detected) {
|
|
45
|
-
console.error(fmt('red', '[pr] No PR number given and no open PR found for current branch.'));
|
|
46
|
-
console.error(fmt('dim', ' Usage: guardrail pr <number>'));
|
|
47
|
-
return 1;
|
|
48
|
-
}
|
|
49
|
-
prNumber = String(detected.number);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Look up PR metadata
|
|
53
|
-
interface PrMeta { number: number; baseRefName: string; headRefName: string; title: string }
|
|
54
|
-
const pr = ghJson<PrMeta>(['pr', 'view', prNumber, '--json', 'number,baseRefName,headRefName,title'], cwd);
|
|
55
|
-
if (!pr) {
|
|
56
|
-
console.error(fmt('red', `[pr] Could not fetch PR #${prNumber} โ is gh authenticated?`));
|
|
57
|
-
return 1;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
console.log(`\n${fmt('bold', `[pr]`)} #${pr.number} ${fmt('dim', pr.title)}`);
|
|
61
|
-
console.log(fmt('dim', ` base: ${pr.baseRefName} head: ${pr.headRefName}`));
|
|
62
|
-
|
|
63
|
-
// Fetch base ref so diff works locally
|
|
64
|
-
const fetched = gitFetch('origin', pr.baseRefName, cwd);
|
|
65
|
-
if (!fetched) {
|
|
66
|
-
console.log(fmt('yellow', ` [pr] Warning: could not fetch origin/${pr.baseRefName} โ diff may be stale`));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return runCommand({
|
|
70
|
-
cwd,
|
|
71
|
-
configPath,
|
|
72
|
-
base: `origin/${pr.baseRefName}`,
|
|
73
|
-
postComments: !options.noPostComments,
|
|
74
|
-
inlineComments: !options.noInlineComments,
|
|
75
|
-
});
|
|
76
|
-
}
|
package/src/cli/preflight.ts
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import * as fs from 'node:fs';
|
|
3
|
-
import * as path from 'node:path';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { runSafe } from '../core/shell.ts';
|
|
6
|
-
import { detectLLMKey, loadEnvFile, LLM_KEY_NAMES } from '../core/detect/llm-key.ts';
|
|
7
|
-
|
|
8
|
-
const PASS = '\x1b[32mโ\x1b[0m';
|
|
9
|
-
const FAIL = '\x1b[31mโ\x1b[0m';
|
|
10
|
-
const WARN = '\x1b[33m!\x1b[0m';
|
|
11
|
-
|
|
12
|
-
const ENV_CANDIDATES = ['.env.local', '.env.dev', '.env.development', '.env'];
|
|
13
|
-
|
|
14
|
-
interface Check {
|
|
15
|
-
name: string;
|
|
16
|
-
result: 'pass' | 'fail' | 'warn';
|
|
17
|
-
message?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface DoctorResult {
|
|
21
|
-
blockers: number;
|
|
22
|
-
warnings: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Checks that the superpowers plugin skills required by the pipeline are resolvable
|
|
27
|
-
* from the usual Claude Code plugin paths. Returns skill names that weren't found.
|
|
28
|
-
*/
|
|
29
|
-
const REQUIRED_SUPERPOWERS_SKILLS = [
|
|
30
|
-
'writing-plans',
|
|
31
|
-
'using-git-worktrees',
|
|
32
|
-
'subagent-driven-development',
|
|
33
|
-
] as const;
|
|
34
|
-
|
|
35
|
-
function skillRoots(): string[] {
|
|
36
|
-
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
37
|
-
const cwd = process.cwd();
|
|
38
|
-
const roots: string[] = [];
|
|
39
|
-
// Project-local plugin install
|
|
40
|
-
roots.push(path.join(cwd, '.claude', 'plugins'));
|
|
41
|
-
// User-global plugin install
|
|
42
|
-
if (home) roots.push(path.join(home, '.claude', 'plugins'));
|
|
43
|
-
return roots.filter(p => fs.existsSync(p));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function findMissingSuperpowersSkills(): string[] {
|
|
47
|
-
// Traverse each root once, collect all discovered skill names, then diff against
|
|
48
|
-
// the required set. Previous implementation did N ร roots separate recursive walks.
|
|
49
|
-
const discovered = new Set<string>();
|
|
50
|
-
const MAX_DIRS_PER_ROOT = 2000; // safety cap to prevent pathological plugin trees
|
|
51
|
-
|
|
52
|
-
for (const root of skillRoots()) {
|
|
53
|
-
collectSkills(root, discovered, { visited: { n: 0 }, max: MAX_DIRS_PER_ROOT });
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return REQUIRED_SUPERPOWERS_SKILLS.filter(s => !discovered.has(s));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Walks up to 8 levels deep, capped at `max` directories total. When it finds a
|
|
60
|
-
// `skills/` directory, records every `<skill-name>/SKILL.md` and `<skill-name>.md`
|
|
61
|
-
// entry directly into the Set. Never revisits by name (Claude Code plugin caches
|
|
62
|
-
// can contain many parallel copies โ we only care whether a skill exists *somewhere*).
|
|
63
|
-
function collectSkills(
|
|
64
|
-
dir: string,
|
|
65
|
-
out: Set<string>,
|
|
66
|
-
ctx: { visited: { n: number }; max: number },
|
|
67
|
-
depth = 0,
|
|
68
|
-
): void {
|
|
69
|
-
if (depth > 8) return;
|
|
70
|
-
if (ctx.visited.n >= ctx.max) return;
|
|
71
|
-
ctx.visited.n++;
|
|
72
|
-
|
|
73
|
-
let entries: fs.Dirent[];
|
|
74
|
-
try {
|
|
75
|
-
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
76
|
-
} catch {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// If this dir has a skills/ child, record every skill inside it
|
|
81
|
-
for (const entry of entries) {
|
|
82
|
-
if (entry.isDirectory() && entry.name === 'skills') {
|
|
83
|
-
const skillsDir = path.join(dir, 'skills');
|
|
84
|
-
try {
|
|
85
|
-
for (const skill of fs.readdirSync(skillsDir, { withFileTypes: true })) {
|
|
86
|
-
if (skill.isDirectory() && fs.existsSync(path.join(skillsDir, skill.name, 'SKILL.md'))) {
|
|
87
|
-
out.add(skill.name);
|
|
88
|
-
} else if (skill.isFile() && skill.name.endsWith('.md') && skill.name !== 'README.md') {
|
|
89
|
-
out.add(skill.name.slice(0, -3)); // strip .md
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
} catch { /* ignore */ }
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Recurse into non-skills dirs (bounded depth + visit cap prevent pathological scans)
|
|
97
|
-
for (const entry of entries) {
|
|
98
|
-
if (!entry.isDirectory()) continue;
|
|
99
|
-
if (entry.name.startsWith('.')) continue;
|
|
100
|
-
if (entry.name === 'node_modules') continue;
|
|
101
|
-
if (entry.name === 'skills') continue; // already handled above
|
|
102
|
-
collectSkills(path.join(dir, entry.name), out, ctx, depth + 1);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export async function runDoctor(): Promise<DoctorResult> {
|
|
107
|
-
const checks: Check[] = [];
|
|
108
|
-
|
|
109
|
-
// 1. Node version
|
|
110
|
-
const nodeVersion = process.version;
|
|
111
|
-
const nodeMajor = parseInt(nodeVersion.slice(1).split('.')[0]!, 10);
|
|
112
|
-
checks.push({
|
|
113
|
-
name: `Node.js ${nodeVersion}`,
|
|
114
|
-
result: nodeMajor >= 22 ? 'pass' : 'fail',
|
|
115
|
-
message: nodeMajor < 22 ? `Node 22+ required โ current: ${nodeVersion}. Install via nvm: nvm install 22` : undefined,
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// 2. tsx available
|
|
119
|
-
const localTsx = path.join(process.cwd(), 'node_modules', '.bin', 'tsx');
|
|
120
|
-
const tsxVersion = fs.existsSync(localTsx)
|
|
121
|
-
? runSafe(localTsx, ['--version'])
|
|
122
|
-
: runSafe('tsx', ['--version']);
|
|
123
|
-
checks.push({
|
|
124
|
-
name: 'tsx available',
|
|
125
|
-
result: tsxVersion ? 'pass' : 'fail',
|
|
126
|
-
message: !tsxVersion ? 'tsx not found โ run: npm install @delegance/claude-autopilot@alpha (includes tsx for dev builds)' : undefined,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// 3. gh CLI authenticated
|
|
130
|
-
const ghAuth = runSafe('gh', ['auth', 'status']);
|
|
131
|
-
checks.push({
|
|
132
|
-
name: 'gh CLI authenticated',
|
|
133
|
-
result: ghAuth !== null ? 'pass' : 'fail',
|
|
134
|
-
message: ghAuth === null ? 'gh CLI not authenticated โ run: gh auth login' : undefined,
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// 4. guardrail.config.yaml in cwd
|
|
138
|
-
const configYaml = path.join(process.cwd(), 'guardrail.config.yaml');
|
|
139
|
-
checks.push({
|
|
140
|
-
name: 'guardrail.config.yaml',
|
|
141
|
-
result: fs.existsSync(configYaml) ? 'pass' : 'warn',
|
|
142
|
-
message: !fs.existsSync(configYaml)
|
|
143
|
-
? 'guardrail.config.yaml not found in current directory โ copy from a preset: presets/nextjs-supabase/guardrail.config.yaml'
|
|
144
|
-
: undefined,
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// 5. Local env file exists
|
|
148
|
-
const envFile = ENV_CANDIDATES.find(f => fs.existsSync(f));
|
|
149
|
-
checks.push({
|
|
150
|
-
name: `Local env file (${envFile ?? 'none found'})`,
|
|
151
|
-
result: envFile ? 'pass' : 'warn',
|
|
152
|
-
message: !envFile
|
|
153
|
-
? `No env file found. Looked for: ${ENV_CANDIDATES.join(', ')}. Create one with one of: ${LLM_KEY_NAMES.join(', ')}.`
|
|
154
|
-
: undefined,
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
// 6. LLM API key โ shared detection with setup/scan/run (all 5 providers)
|
|
158
|
-
const envVars = envFile ? loadEnvFile(envFile) : {};
|
|
159
|
-
const { hasKey, preferred } = detectLLMKey({ extraEnv: envVars });
|
|
160
|
-
checks.push({
|
|
161
|
-
name: `LLM API key (${preferred ?? 'none'})`,
|
|
162
|
-
result: hasKey ? 'pass' : 'warn',
|
|
163
|
-
message: !hasKey
|
|
164
|
-
? `No LLM API key found โ set one of: ${LLM_KEY_NAMES.join(', ')} to enable review`
|
|
165
|
-
: undefined,
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// 7. claude CLI available
|
|
169
|
-
const claudeVersion = runSafe('claude', ['--version']);
|
|
170
|
-
checks.push({
|
|
171
|
-
name: 'claude CLI',
|
|
172
|
-
result: claudeVersion ? 'pass' : 'fail',
|
|
173
|
-
message: !claudeVersion
|
|
174
|
-
? 'claude CLI not found โ required for autofix. Install Claude Code: https://claude.ai/claude-code'
|
|
175
|
-
: undefined,
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// 8. git user config
|
|
179
|
-
const gitName = runSafe('git', ['config', 'user.name']);
|
|
180
|
-
const gitEmail = runSafe('git', ['config', 'user.email']);
|
|
181
|
-
const gitConfigOk = !!(gitName?.trim()) && !!(gitEmail?.trim());
|
|
182
|
-
checks.push({
|
|
183
|
-
name: 'git user config',
|
|
184
|
-
result: gitConfigOk ? 'pass' : 'warn',
|
|
185
|
-
message: !gitConfigOk
|
|
186
|
-
? 'git user.name / user.email not set โ commits will fail.'
|
|
187
|
-
: undefined,
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
// 9. Superpowers plugin โ required for pipeline phases, optional for review-only use
|
|
191
|
-
const missingSkills = findMissingSuperpowersSkills();
|
|
192
|
-
const allSkillsFound = missingSkills.length === 0;
|
|
193
|
-
checks.push({
|
|
194
|
-
name: `Superpowers plugin${allSkillsFound ? '' : ` (missing: ${missingSkills.join(', ')})`}`,
|
|
195
|
-
// Treat as warn, not fail โ users who only run `claude-autopilot run` (review phase)
|
|
196
|
-
// don't need superpowers. Pipeline invocations (`autopilot` skill) will hard-fail at
|
|
197
|
-
// their own entry point.
|
|
198
|
-
result: allSkillsFound ? 'pass' : 'warn',
|
|
199
|
-
message: !allSkillsFound
|
|
200
|
-
? 'Install: `claude plugin install superpowers` (required for pipeline phases โ brainstorm/plan/implement)'
|
|
201
|
-
: undefined,
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
// Print results
|
|
205
|
-
console.log('\n\x1b[1m[doctor] claude-autopilot prerequisite check\x1b[0m\n');
|
|
206
|
-
let blockers = 0;
|
|
207
|
-
let warnings = 0;
|
|
208
|
-
for (const check of checks) {
|
|
209
|
-
const icon = check.result === 'pass' ? PASS : check.result === 'warn' ? WARN : FAIL;
|
|
210
|
-
console.log(` ${icon} ${check.name}`);
|
|
211
|
-
if (check.message) {
|
|
212
|
-
console.log(` \x1b[2m${check.message}\x1b[0m`);
|
|
213
|
-
}
|
|
214
|
-
if (check.result === 'fail') blockers++;
|
|
215
|
-
if (check.result === 'warn') warnings++;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
console.log('');
|
|
219
|
-
if (blockers > 0) {
|
|
220
|
-
console.log(`\x1b[31m[doctor] ${blockers} blocker(s) โ fix before running npx guardrail run\x1b[0m\n`);
|
|
221
|
-
} else if (warnings > 0) {
|
|
222
|
-
console.log(`\x1b[33m[doctor] ${warnings} warning(s) โ pipeline will run but some steps may be skipped\x1b[0m\n`);
|
|
223
|
-
} else {
|
|
224
|
-
console.log(`\x1b[32m[doctor] All checks passed โ ready to run\x1b[0m\n`);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return { blockers, warnings };
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Run when invoked directly
|
|
231
|
-
const isMain = process.argv[1] !== undefined &&
|
|
232
|
-
fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
233
|
-
if (isMain) {
|
|
234
|
-
runDoctor().then(r => process.exit(r.blockers > 0 ? 1 : 0));
|
|
235
|
-
}
|
package/src/cli/report.ts
DELETED
|
@@ -1,186 +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 { readCostLog } from '../core/persist/cost-log.ts';
|
|
5
|
-
import type { Finding } from '../core/findings/types.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 ReportCommandOptions {
|
|
14
|
-
cwd?: string;
|
|
15
|
-
output?: string; // file path to write markdown (default: stdout)
|
|
16
|
-
trend?: boolean; // include trend analysis from cost log run history
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function severityOrder(s: Finding['severity']): number {
|
|
20
|
-
return s === 'critical' ? 0 : s === 'warning' ? 1 : 2;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function buildTrendSection(cwd: string): string {
|
|
24
|
-
const log = readCostLog(cwd);
|
|
25
|
-
if (log.length === 0) return '';
|
|
26
|
-
|
|
27
|
-
const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
|
|
28
|
-
const recent = log.filter(e => new Date(e.timestamp).getTime() >= sevenDaysAgo);
|
|
29
|
-
const totalCost = log.reduce((s, e) => s + e.costUSD, 0);
|
|
30
|
-
const avgFiles = log.reduce((s, e) => s + e.files, 0) / log.length;
|
|
31
|
-
|
|
32
|
-
const lines: string[] = [
|
|
33
|
-
'## ๐ Trend',
|
|
34
|
-
'',
|
|
35
|
-
`| Metric | Value |`,
|
|
36
|
-
`|--------|-------|`,
|
|
37
|
-
`| Runs (7d) | ${recent.length} |`,
|
|
38
|
-
`| Runs (all-time) | ${log.length} |`,
|
|
39
|
-
`| All-time cost | $${totalCost.toFixed(4)} |`,
|
|
40
|
-
`| Avg files/run | ${avgFiles.toFixed(1)} |`,
|
|
41
|
-
'',
|
|
42
|
-
];
|
|
43
|
-
|
|
44
|
-
if (recent.length > 0) {
|
|
45
|
-
lines.push('### Recent runs', '');
|
|
46
|
-
lines.push('| Date | Files | Cost |');
|
|
47
|
-
lines.push('|------|-------|------|');
|
|
48
|
-
for (const e of recent.slice(-7).reverse()) {
|
|
49
|
-
const d = new Date(e.timestamp).toLocaleDateString();
|
|
50
|
-
lines.push(`| ${d} | ${e.files} | $${e.costUSD.toFixed(4)} |`);
|
|
51
|
-
}
|
|
52
|
-
lines.push('');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return lines.join('\n');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function buildFileBreakdown(findings: Finding[]): string {
|
|
59
|
-
const withFiles = findings.filter(f => f.file && f.file !== '<unspecified>' && f.file !== '<pipeline>');
|
|
60
|
-
if (withFiles.length === 0) return '';
|
|
61
|
-
|
|
62
|
-
const counts = new Map<string, { critical: number; warning: number; note: number; total: number }>();
|
|
63
|
-
for (const f of withFiles) {
|
|
64
|
-
const entry = counts.get(f.file) ?? { critical: 0, warning: 0, note: 0, total: 0 };
|
|
65
|
-
entry[f.severity]++;
|
|
66
|
-
entry.total++;
|
|
67
|
-
counts.set(f.file, entry);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const sorted = [...counts.entries()].sort((a, b) => b[1].total - a[1].total).slice(0, 10);
|
|
71
|
-
if (sorted.length < 2) return ''; // single file โ not worth a table
|
|
72
|
-
|
|
73
|
-
const lines = [
|
|
74
|
-
'## ๐ By File',
|
|
75
|
-
'',
|
|
76
|
-
'| File | Critical | Warning | Note | Total |',
|
|
77
|
-
'|------|----------|---------|------|-------|',
|
|
78
|
-
];
|
|
79
|
-
for (const [file, c] of sorted) {
|
|
80
|
-
lines.push(`| \`${file}\` | ${c.critical || 'โ'} | ${c.warning || 'โ'} | ${c.note || 'โ'} | **${c.total}** |`);
|
|
81
|
-
}
|
|
82
|
-
if (counts.size > 10) lines.push(`| *(${counts.size - 10} more files)* | | | | |`);
|
|
83
|
-
lines.push('');
|
|
84
|
-
return lines.join('\n');
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function buildSourceBreakdown(findings: Finding[]): string {
|
|
88
|
-
const counts = new Map<string, number>();
|
|
89
|
-
for (const f of findings) {
|
|
90
|
-
counts.set(f.source, (counts.get(f.source) ?? 0) + 1);
|
|
91
|
-
}
|
|
92
|
-
if (counts.size < 2) return '';
|
|
93
|
-
|
|
94
|
-
const lines = ['## ๐ฌ By Source', '', '| Source | Findings |', '|--------|----------|'];
|
|
95
|
-
for (const [source, n] of [...counts.entries()].sort((a, b) => b[1] - a[1])) {
|
|
96
|
-
lines.push(`| ${source} | ${n} |`);
|
|
97
|
-
}
|
|
98
|
-
lines.push('');
|
|
99
|
-
return lines.join('\n');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function buildMarkdown(findings: Finding[], cwd: string, trend: boolean): string {
|
|
103
|
-
const critical = findings.filter(f => f.severity === 'critical');
|
|
104
|
-
const warnings = findings.filter(f => f.severity === 'warning');
|
|
105
|
-
const notes = findings.filter(f => f.severity === 'note');
|
|
106
|
-
const fixable = critical.length + warnings.length;
|
|
107
|
-
|
|
108
|
-
const lines: string[] = [
|
|
109
|
-
'# Guardrail Report',
|
|
110
|
-
'',
|
|
111
|
-
`> Generated ${new Date().toISOString()}`,
|
|
112
|
-
'',
|
|
113
|
-
'## Summary',
|
|
114
|
-
'',
|
|
115
|
-
`| Severity | Count |`,
|
|
116
|
-
`|----------|-------|`,
|
|
117
|
-
`| ๐จ Critical | ${critical.length} |`,
|
|
118
|
-
`| โ ๏ธ Warning | ${warnings.length} |`,
|
|
119
|
-
`| โน๏ธ Note | ${notes.length} |`,
|
|
120
|
-
`| **Total** | **${findings.length}** |`,
|
|
121
|
-
'',
|
|
122
|
-
];
|
|
123
|
-
|
|
124
|
-
if (fixable > 0) {
|
|
125
|
-
lines.push(`> **${fixable} finding${fixable !== 1 ? 's' : ''} can be auto-fixed** โ run \`guardrail fix\` to attempt repairs.`, '');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (trend) {
|
|
129
|
-
const trendSection = buildTrendSection(cwd);
|
|
130
|
-
if (trendSection) lines.push(trendSection);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const fileBreakdown = buildFileBreakdown(findings);
|
|
134
|
-
if (fileBreakdown) lines.push(fileBreakdown);
|
|
135
|
-
|
|
136
|
-
const sourceBreakdown = buildSourceBreakdown(findings);
|
|
137
|
-
if (sourceBreakdown) lines.push(sourceBreakdown);
|
|
138
|
-
|
|
139
|
-
function renderGroup(label: string, icon: string, group: Finding[]) {
|
|
140
|
-
if (group.length === 0) return;
|
|
141
|
-
lines.push(`## ${icon} ${label}`, '');
|
|
142
|
-
for (const f of group) {
|
|
143
|
-
const loc = f.file && f.file !== '<unspecified>' && f.file !== '<pipeline>'
|
|
144
|
-
? `\`${f.file}${f.line ? `:${f.line}` : ''}\``
|
|
145
|
-
: null;
|
|
146
|
-
lines.push(`### ${loc ? `${loc} โ ` : ''}${f.message}`);
|
|
147
|
-
if (f.suggestion) lines.push('', `> **Suggestion:** ${f.suggestion}`);
|
|
148
|
-
lines.push('', `*Source: ${f.source} ยท Rule: ${f.id}*`, '');
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
renderGroup('Critical', '๐จ', critical);
|
|
153
|
-
renderGroup('Warnings', 'โ ๏ธ', warnings);
|
|
154
|
-
renderGroup('Notes', 'โน๏ธ', notes);
|
|
155
|
-
|
|
156
|
-
if (findings.length === 0) {
|
|
157
|
-
lines.push('## โ
No findings', '', 'No cached findings โ run `guardrail run` or `guardrail scan` first.', '');
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return lines.join('\n');
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
export async function runReport(options: ReportCommandOptions = {}): Promise<number> {
|
|
164
|
-
const cwd = options.cwd ?? process.cwd();
|
|
165
|
-
const findings = loadCachedFindings(cwd);
|
|
166
|
-
|
|
167
|
-
if (findings.length === 0) {
|
|
168
|
-
console.log(fmt('yellow', '[report] No cached findings โ run `guardrail run` or `guardrail scan` first.'));
|
|
169
|
-
return 0;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const sorted = [...findings].sort((a, b) => severityOrder(a.severity) - severityOrder(b.severity));
|
|
173
|
-
const md = buildMarkdown(sorted, cwd, options.trend ?? false);
|
|
174
|
-
|
|
175
|
-
if (options.output) {
|
|
176
|
-
fs.writeFileSync(options.output, md, 'utf8');
|
|
177
|
-
const critical = findings.filter(f => f.severity === 'critical').length;
|
|
178
|
-
const warnings = findings.filter(f => f.severity === 'warning').length;
|
|
179
|
-
console.log(fmt('bold', `[report] Written to ${options.output}`));
|
|
180
|
-
console.log(` ${critical > 0 ? fmt('red', `${critical} critical`) : fmt('green', '0 critical')} ${warnings > 0 ? fmt('yellow', `${warnings} warning${warnings !== 1 ? 's' : ''}`) : fmt('dim', '0 warnings')}`);
|
|
181
|
-
} else {
|
|
182
|
-
process.stdout.write(md + '\n');
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return findings.some(f => f.severity === 'critical') ? 1 : 0;
|
|
186
|
-
}
|