Implements the MVP cutline from the planning artifact: - Phase A: skeleton + CLI dispatch + provider interface + stub model doctor - Phase B: scanner + git probe + 12 static analyzers + reporters + pipeline - Phase B fixtures: clean-repo, insecure-repo, degraded-repo 12 static analyzers per PROMPT.md "Suggested Static Checks For MVP": hardcoded_paths, shell_execution, raw_sql_interpolation, broad_cors, secret_patterns, large_files, todo_comments, missing_tests, env_file_committed, unsafe_file_io, exposed_mutation_endpoint, hardcoded_local_ip. Acceptance gates passing: - B1 (intake produces accurate counts) ✓ - B2 (insecure fixture fires ≥8 distinct check_ids — actually 11/12) ✓ - B3 (clean fixture produces 0 confirmed findings — no false positives) ✓ - B4 (scrum mode produces all 6 required markdown + JSON reports) ✓ - B5 (receipts.json marks degraded phases honestly) ✓ - F (self-review on this repo runs without crashing) ✓ — exit 66 (degraded because Phase C LLM review is hardcoded skipped) Phases C (LLM review), D (validation cross-check), E (memory + diff + rules subcommands) deferred per the cutline. The MVP delivers the evidence-first path; LLM is purely additive. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
59 lines
2.0 KiB
Go
59 lines
2.0 KiB
Go
// Package analyzers defines the static-analysis surface. Each
|
|
// analyzer is a function that takes the scanner's view of the repo
|
|
// and returns []Finding. The Finding shape is locked by
|
|
// docs/REPORT_SCHEMA.md — fields here are the canonical names
|
|
// that flow into reports + memory + LLM-finding cross-checks.
|
|
package analyzers
|
|
|
|
// Severity ladder from REPORT_SCHEMA.md. Stored as a string so the
|
|
// JSON shape is exactly what operators expect to grep for.
|
|
type Severity string
|
|
|
|
const (
|
|
SeverityLow Severity = "low"
|
|
SeverityMedium Severity = "medium"
|
|
SeverityHigh Severity = "high"
|
|
SeverityCritical Severity = "critical"
|
|
)
|
|
|
|
// Status reflects the validation state. Static-analysis findings
|
|
// default to "suspected" — they're regex hits without context.
|
|
// Validation (Phase D) promotes to "confirmed" or rejects with reason.
|
|
type Status string
|
|
|
|
const (
|
|
StatusConfirmed Status = "confirmed"
|
|
StatusSuspected Status = "suspected"
|
|
StatusRejected Status = "rejected"
|
|
StatusBlocked Status = "blocked"
|
|
)
|
|
|
|
// Source tracks who produced a finding. Useful in the JSON for
|
|
// downstream consumers that want to sort/filter.
|
|
type Source string
|
|
|
|
const (
|
|
SourceStatic Source = "static"
|
|
SourceLLM Source = "llm"
|
|
SourceValidator Source = "validator"
|
|
)
|
|
|
|
// Finding is the canonical shape per docs/REPORT_SCHEMA.md.
|
|
// IDs are deterministic-from-content (file + line + check) so the
|
|
// same finding across runs produces the same ID — useful for memory
|
|
// dedup later.
|
|
type Finding struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
Severity Severity `json:"severity"`
|
|
Status Status `json:"status"`
|
|
File string `json:"file"`
|
|
LineHint string `json:"line_hint,omitempty"`
|
|
Evidence string `json:"evidence"`
|
|
Reason string `json:"reason"`
|
|
SuggestedFix string `json:"suggested_fix,omitempty"`
|
|
Source Source `json:"source"`
|
|
Confidence float64 `json:"confidence"`
|
|
CheckID string `json:"check_id,omitempty"` // e.g. "static.hardcoded_paths"
|
|
}
|