Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ codeguard rules
codeguard profiles
codeguard explain security.hardcoded-credential
codeguard baseline -config codeguard.yaml -output codeguard-baseline.json
codeguard baseline audit -config codeguard.yaml -format json
codeguard baseline prune -config codeguard.yaml -check
codeguard baseline policy -config codeguard.yaml -compare-baseline /tmp/base-baseline.json
```

`codeguard rules` prints each rule's level, execution model, language coverage, section, and title. `codeguard explain <rule-id>` includes the same metadata for a single rule.
Expand Down Expand Up @@ -150,6 +153,42 @@ When a scan fails:
- section names such as `Design Patterns`, `Security`, or `Code Quality` tell you what kind of action is expected.
- rule IDs are stable handles for waivers, baselines, dashboards, and agent workflows.

### Baseline governance

Baseline creation accepts all findings visible in that scan; it is not a cleanup
operation. Use `baseline audit` to classify an existing baseline without adding
findings, and `baseline prune -check` in CI to detect stale, invalid, or duplicate
entries. After review, `baseline prune -write` atomically removes stale entries;
`-output <path>` writes a candidate instead of replacing the source.

An entry remains active when its exact fingerprint, line-shift-resilient context
fingerprint, or path-insensitive content fingerprint matches a current finding.
Identical snippets can legitimately collide on context or content fingerprints.
Audits report those collisions and preserve every matching entry; pruning does
not impose one-to-one matching or change scan suppression behavior.

Opt-in governance rejects suppression growth and selected new rule families:

```yaml
baseline:
path: codeguard-baseline.json
governance:
max_entries: 9771
forbid_growth: true
require_no_stale_entries: true
prohibited_new_rule_prefixes: [security., defensive., error.]
sample_limit: 3
ownership:
- pattern: "services/**"
owner: services
```

`baseline policy -compare-baseline` compares exact entries with a trusted base
branch baseline. Existing prohibited-family debt remains allowed; only additions
violate that policy. Use `scan -include-suppressed -format json` when a consumer
needs individual baseline, waiver, and inline suppression records. Default scan
output remains unchanged.

## SDK

Import the SDK from `github.com/devr-tools/codeguard/pkg/codeguard`.
Expand Down
23 changes: 23 additions & 0 deletions docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,29 @@ This page lists the current `codeguard` feature surface and the main config entr
- verified auto-fix through SDK and CLI
- hook-pack examples for Claude Code and Cursor

## Baseline governance

- `codeguard baseline` creates a new accepted-debt snapshot.
- `codeguard baseline audit` classifies existing entries as active through an
exact, context, or path-insensitive content fingerprint, or as stale/invalid.
- `codeguard baseline prune -check` provides a non-mutating CI gate;
`-write` atomically removes only stale entries, and `-output` creates a
reviewable candidate file.
- `codeguard baseline policy -compare-baseline <path>` rejects configured net
growth, maximum-entry violations, and newly baselined prohibited rule
families while allowing existing approved debt.
- Audit reports group active debt by rule, ownership area, and risk family and
provide deterministic evidence samples with confidence/language counts.
- Context/content collisions from identical snippets are reported and
preserved. Governance never forces one-to-one matching or changes v1.7.3
suppression semantics.
- `codeguard scan -include-suppressed -format json` emits individual baseline,
waiver, and inline suppression records when explicitly requested; default
reports remain unchanged.

See [Production rollout](production.md) for configuration, safe CI usage,
review workflow, and exit-code behavior.

## External report ingestion

CodeGuard can import findings from scanners that have already run. It does not
Expand Down
18 changes: 18 additions & 0 deletions docs/production.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,24 @@ In production, `codeguard` should do three things well:
codeguard baseline -config codeguard.yaml -output codeguard-baseline.json
```

Creating a baseline accepts the scan's current findings. It must not be used
as a substitute for pruning. Audit and validate an existing baseline without
accepting new findings:

```bash
codeguard baseline audit -config codeguard.yaml -format json
codeguard baseline prune -config codeguard.yaml -check
codeguard baseline prune -config codeguard.yaml -write -output /tmp/candidate-baseline.json
codeguard baseline policy -config codeguard.yaml -compare-baseline /tmp/base-baseline.json
```

Audit exits nonzero for scan/load failures. Prune check exits nonzero for
stale, invalid, or duplicate entries and never writes. Prune write removes
only stale entries, preserves fingerprint collisions, and refuses invalid
entries unless `-allow-invalid-entries` is explicitly supplied. Policy exits
nonzero for configured growth, maximum-entry, or prohibited-addition
violations.

Then reference it from config so new regressions still fail while existing debt
stays visible but suppressed.

Expand Down
114 changes: 114 additions & 0 deletions docs/superpowers/plans/2026-08-29-baseline-governance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Baseline Governance Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Add safe baseline auditing, pruning, suppression-level JSON reporting, governance policy enforcement, ownership/risk summaries, and deterministic false-positive review samples.

**Architecture:** The runner will optionally retain suppressed findings with structured suppression metadata while preserving existing report defaults. Focused baseline-governance files in the existing `internal/cli` package will compare an existing baseline with a suppression-free full scan, classify entries through exact, context, or content fingerprints, report collisions without changing v1.7.3 suppression semantics, prune only stale entries, and compare baselines for policy enforcement without adding a new dependency on the central core package. The CLI will retain the existing `codeguard baseline` creation command while adding `audit`, `prune`, and `policy` subcommands.

**Tech Stack:** Go 1.23+, standard-library JSON/file APIs, existing CodeGuard runner/config/report packages.

**Spec:** User-approved baseline-governance prompt in the 2026-08-29 conversation, corrected to preserve many-to-many context/content fingerprint semantics.

## Global Constraints

- Existing baseline files and scan behavior remain compatible; governance is opt-in.
- Audit and prune run full scans with the configured baseline disabled and never add current findings.
- An entry is active if any exact, context, or content fingerprint matches a current finding.
- Collisions are reported and preserved; matching is not forced one-to-one.
- `prune --check` never writes; `prune --write` atomically removes only stale entries and refuses invalid entries unless explicitly overridden.
- JSON, text, SARIF, GitHub, and CycloneDX defaults remain unchanged unless suppressed findings are explicitly requested.
- Governance output and deterministic samples use stable ordering.

---

### Task 1: Structured suppression reporting

**Files:**
- Modify: `internal/codeguard/core/report_types.go`
- Modify: `internal/codeguard/core/diff_types.go`
- Modify: `internal/codeguard/runner/support/context.go`
- Modify: `internal/codeguard/runner/support/suppressions.go`
- Modify: `internal/codeguard/runner/support/findings_section.go`
- Modify: `internal/codeguard/runner/runner.go`
- Modify: `internal/cli/scan_flags.go`
- Test: `tests/checks/suppressed_findings_test.go`
- Test: `tests/cli/scan_suppressed_test.go`

**Interfaces:**
- Produces: `Suppression{Kind, Match, BaselineFingerprint}`, `Report.SuppressedFindings`, and `ScanOptions.IncludeSuppressed`.
- Preserves: existing emitted `SectionResult.Findings`, summary counts, and default JSON shape.

- [ ] Write a runner test proving baseline exact/context/content, waiver, and inline suppressions are individually distinguishable and reconcile with summary/rule statistics.
- [ ] Run the focused test and verify it fails because suppressed records are absent.
- [ ] Add structured suppression matching and opt-in collection with no default-output change.
- [ ] Run the focused runner tests and verify they pass.
- [ ] Write and fail a CLI test for `scan -include-suppressed -format json`.
- [ ] Wire the flag through scan options and verify the CLI test passes.

### Task 2: Deterministic baseline audit and pruning engine

**Files:**
- Create: `internal/cli/baseline_audit.go`
- Create: `internal/cli/baseline_io.go`
- Test: `internal/cli/baseline_audit_test.go`
- Test: `internal/cli/baseline_io_test.go`

**Interfaces:**
- Consumes: `core.BaselineFile` and current `[]core.Finding`.
- Produces: `AuditResult` with active-exact/context/content, stale, invalid, duplicate, collision, rule, owner, risk, language, confidence, and deterministic sample data.
- Produces: `Prune(source, output string, audit AuditResult, allowInvalid bool) error` using atomic replacement.

- [ ] Write table-driven failing tests for exact/context/content activation, moved findings, duplicate snippets, collisions, invalid entries, stable ordering, ownership/risk grouping, and deterministic samples.
- [ ] Implement the smallest audit engine that passes those tests while preserving all collision-matched entries.
- [ ] Write failing filesystem tests for check-mode immutability, stale-only pruning, output candidates, malformed JSON, and failed atomic replacement preserving the source.
- [ ] Implement strict loading and atomic deterministic writing, then run all baseline package tests.

### Task 3: Governance configuration and policy comparison

**Files:**
- Modify: `internal/codeguard/core/config_types.go`
- Modify: `internal/codeguard/config/validate.go`
- Create: `internal/cli/baseline_policy.go`
- Test: `internal/cli/baseline_policy_test.go`
- Test: `internal/codeguard/config/baseline_governance_test.go`

**Interfaces:**
- Produces: opt-in `baseline.governance` fields for limits, stale checks, prohibited prefixes, ownership mappings, and sample limits.
- Produces: deterministic `ComparePolicy(current, comparison, governance)` with exact additions/removals and violations.

- [ ] Write failing tests for invalid limits/mappings/prefixes and valid omitted governance.
- [ ] Add config types and validation, then verify config tests pass.
- [ ] Write failing policy tests for growth, prohibited high-risk additions, allowed existing debt, and deterministic diffs.
- [ ] Implement policy comparison and verify baseline package tests pass.

### Task 4: Baseline audit, prune, and policy CLI

**Files:**
- Modify: `internal/cli/commands.go`
- Create: `internal/cli/baseline.go`
- Test: `tests/cli/baseline_governance_test.go`

**Interfaces:**
- Produces: `codeguard baseline audit`, `baseline prune --check|--write`, and `baseline policy -compare-baseline`.
- Preserves: legacy `codeguard baseline -config ... -output ...` creation.

- [ ] Write failing end-to-end CLI tests for audit text/JSON, prune check/write/output, invalid refusal/override, policy failures, and legacy creation.
- [ ] Add subcommand parsing and a shared full-scan-with-baseline-disabled path.
- [ ] Render stable text/JSON, enforce exit codes, and verify all CLI tests pass.

### Task 5: Documentation, compatibility, and version evidence

**Files:**
- Modify: `README.md`
- Modify: `docs/production.md`
- Modify: `docs/features.md`
- Test: `tests/cli/version_test.go`

**Interfaces:**
- Documents command distinctions, matching semantics, collision behavior, CI usage, review workflow, configuration, and exit codes.

- [ ] Add a failing version test covering linker/build-info precedence and JSON report agreement with `codeguard version`.
- [ ] Fix version plumbing only if the test demonstrates a defect.
- [ ] Document create/audit/check/write/policy workflows and compatible suppression semantics.
- [ ] Run formatting, focused tests, full tests, vet/lint targets, and review the complete diff against every specification requirement.
Loading
Loading