baseline

package
v0.3.0-alpha.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 23, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package baseline tracks codefit's view of a project's audited surface across scans. The baseline is a committed file (.codefit-baseline) — shared knowledge like .codefit.yaml — that records every item codefit knows about, identified by a content Fingerprint (see findings.Fingerprint), so a re-scan can tell what is new, unchanged (known), changed, or gone.

Safeguard by certainty (PRD RF-08):

  • SURFACE (a question) becomes known automatically once recorded; a re-scan silences it. accept marks it acknowledged (a false positive / accepted debt).
  • DETERMINISTIC (an affirmation, confidence 1.0) is NEVER known automatically: it is shown on every scan until a human accepts it explicitly with a reason. Silencing an affirmation is graver than silencing a question, so it needs the stronger safeguard.
  • AGENT VERDICT (an agent's reasoning about an item, confidence < 1.0) is RECORDED but never ACCEPTS on its own (D1, ADR 0081): it persists in Item.AgentVerdicts, always by:"agent", and leaves the item's safeguard exactly where the two rules above already put it — a surface item still goes known, an affirmation still shows until accepted. Recording moves nothing in either direction; only a human accepts, through the same Accept path as any other item.

codefit never edits code — only this file.

Package baseline implements the adoption baseline (PRD RF-08): a committed snapshot of a project's findings so that, with baseline enabled, codefit reports only new findings while pre-existing debt is recorded (baselined: true) and does not block. This makes adopting codefit on an existing project painless (Scenario B).

Status: BUILT (Fase 1). The snapshot/diff logic and the on-disk format are implemented. The file is named by Name — ".codefit-baseline" at the repo root, a committed plain file, NOT ".codefit/baseline.json" as an earlier draft of this comment claimed.

Index

Constants

View Source
const Name = ".codefit-baseline"

Name is the baseline file, committed at the repo root.

Variables

This section is empty.

Functions

This section is empty.

Types

type Ack

type Ack struct {
	Reason string `yaml:"reason"`
	At     string `yaml:"at"`
	By     Actor  `yaml:"by"` // always "human": codefit never acknowledges on its own
}

Ack records that a human accepted an item (false positive or accepted debt).

type Actor

type Actor string

Actor is who recorded an entry in this file. Exactly two values, and the asymmetry between them IS the safeguard (D4, ADR 0081): a human's record is a DECISION and can silence an item (Ack, AuthzHelper); an agent's is a RECOMMENDATION (AgentVerdict) and never can.

const (
	ActorHuman Actor = "human" // Ack, AuthzHelper — silences
	ActorAgent Actor = "agent" // AgentVerdict only — never silences
)

type AgentVerdict

type AgentVerdict struct {
	Verdict    surface.Verdict   `yaml:"verdict"`
	Reasoning  string            `yaml:"reasoning"`
	Confidence float64           `yaml:"confidence"`
	Severity   findings.Severity `yaml:"severity,omitempty"`
	At         string            `yaml:"at"`
	By         Actor             `yaml:"by"`
}

AgentVerdict is what an AGENT concluded after reasoning over this item's surface (codefit-baseline-record-verdict). Recording one NEVER silences the item (D1) and NEVER overwrites a previous verdict on the same fp — conflicting verdicts are both kept for a human to resolve (D2, see Item.InConflict). By is always ActorAgent, stamped by RecordVerdict itself, never caller-supplied — a claim scoped to THIS type; the human-only claims on Ack.By and AuthzHelper.By are unchanged and still true.

type AuthzHelper added in v0.1.2

type AuthzHelper struct {
	Name     string `yaml:"name"`
	Language string `yaml:"language"`
	Reason   string `yaml:"reason"`
	At       string `yaml:"at"`
	By       Actor  `yaml:"by"` // always "human": codefit never registers on its own
}

AuthzHelper is a project-specific authorization helper the AGENT identified by reasoning over the code and a HUMAN approved registering — so codefit recognizes it on later scans without the agent re-reasoning (it augments the built-in NextAuth-style set per project). It is project knowledge, like an acknowledged item: persisted, committed, recorded by:"human". Registering a helper changes a FACT (known_authz_detected for the authz concern), never a verdict — it clears the AUTHZ gap, never the IDOR/ownership gap (ADR 0013, ADR 0006 amended).

type Baseline

type Baseline struct {
	Version      string        `yaml:"version"`
	Items        []Item        `yaml:"items"`
	AuthzHelpers []AuthzHelper `yaml:"authz_helpers,omitempty"`
	// contains filtered or unexported fields
}

Baseline is the committed set of known items plus the project's registered authz helpers.

func Load

func Load(path string) (*Baseline, error)

Load reads the baseline at path. A missing file is NOT an error: it returns an empty baseline (the first scan creates it).

func (*Baseline) Accept

func (b *Baseline) Accept(fps []string, reason, at string) (accepted []string, err error)

Accept marks the given fingerprints as acknowledged by a human. A reason is mandatory; an unknown fingerprint is an error (nothing is changed). codefit records by:"human" — it never acknowledges on its own.

func (*Baseline) List

func (b *Baseline) List(filter string) ([]Entry, error)

List returns the baseline items as Entries, filtered by state: "" (all), "known" (not acknowledged), or "acknowledged". An unknown filter is an error.

func (Baseline) MarshalYAML

func (b Baseline) MarshalYAML() (interface{}, error)

MarshalYAML encodes the known Baseline fields normally, then re-emits any unknown top-level key this binary preserved from Load (D6-B), sorted for deterministic output.

func (*Baseline) Prune

func (b *Baseline) Prune(fps []string) (pruned []string)

Prune removes the given fingerprints from the baseline (used for gone items the caller has confirmed no longer exist in the code). Returns the removed fps.

func (*Baseline) RecognizedAuthzHelpers added in v0.1.2

func (b *Baseline) RecognizedAuthzHelpers(language string) []string

RecognizedAuthzHelpers returns the names of the helpers registered for a language — the set a scan adds to the built-in authz helpers for that project.

func (*Baseline) RecordVerdict

func (b *Baseline) RecordVerdict(fp, category, file, snippet string, v AgentVerdict) *Item

RecordVerdict appends an agent's reasoning about one item to the baseline, creating the item (fp/category/file/snippet) if this is its first record. It NEVER sets Ack (D1: an agent verdict never silences the item) and NEVER overwrites a previous verdict on the same fp — conflicting verdicts are both kept for a human to resolve (D2, Item.InConflict). By is stamped ActorAgent here, unconditionally, regardless of what the caller passed in v.By — the same handler-assigned discipline Accept and RegisterAuthzHelper already apply to their own by:"human". Reasoning is capped at maxVerdictReasonLen runes, here in core, so every caller is bounded.

func (*Baseline) RegisterAuthzHelper added in v0.1.2

func (b *Baseline) RegisterAuthzHelper(name, language, reason, at string) (added bool, err error)

RegisterAuthzHelper records a project-specific authz helper as recognized, by:"human". A name, language, and reason are mandatory (the reason is the human's justification, as for Accept). Idempotent: registering an already-known (language, name) is a no-op that returns added=false. codefit never registers on its own — the agent proposes, the human decides (the skill enforces it; codefit records the decision).

func (*Baseline) Save

func (b *Baseline) Save(path string) error

Save writes the baseline to path as commented, human-readable YAML.

func (*Baseline) UnmarshalYAML

func (b *Baseline) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML decodes the known Baseline fields normally, then captures any top-level key this binary does not recognize (D6-B) so Save can re-emit it unchanged.

func (*Baseline) UnregisterAuthzHelper added in v0.1.2

func (b *Baseline) UnregisterAuthzHelper(name, language string) bool

UnregisterAuthzHelper removes a registered helper (the reversal of RegisterAuthzHelper — the developer's decision is always reversible). Returns whether a helper was removed.

type Counts

type Counts struct {
	New, Changed, Known, Acknowledged, Gone, AffirmationsShown int
}

Counts is the at-a-glance delta.

type DiffResult

type DiffResult struct {
	State  map[string]State // fp → state, for observed items
	Shown  map[string]bool  // fp → must be shown (not silenced)
	Gone   []Item           // baseline items no longer observed (prune candidates)
	Counts Counts
	Next   *Baseline // the baseline to persist
}

DiffResult is the full comparison of a scan against the previous baseline.

func Diff

func Diff(prev *Baseline, observed []Observed, scanned map[string]bool, files scope.Scope) DiffResult

Diff compares the observed scan against the previous baseline and returns the per-item delta, what must be shown, the gone candidates, and the next baseline to persist. It never silences a deterministic affirmation that has not been acknowledged.

The scope is TWO-DIMENSIONAL, and an item is eligible to be "gone" only when BOTH dimensions admit it:

scanned[item.Category]  AND  files.Includes(item.File)

scanned is the set of Item categories owned by the sensors that RAN this pass. A previous item whose category is NOT in scanned (its sensor did not run) is carried forward UNTOUCHED — absent from the delta, never a gone/prune candidate. This distinguishes "not observed because the sensor did not run" from "not observed because it disappeared", so a single-sensor run cannot corrupt another dimension's state (ADR 0019).

files is the FILE scope of the pass. The category dimension alone does not cover a partial audit: a security finding in a file this pass never opened still belongs to the security category, which DID run, so a category-only guard would see it unobserved-and-in-scope and mark it gone — and codefit-baseline-prune would then delete the audit memory of every file the scan did not look at, silently, in the direction of going blind.

Both dimensions fail safe: an empty scanned and the zero-value scope.Scope each include nothing, so a caller that forgets one under-reports and never prunes. Under-report, never corrupt.

type Entry

type Entry struct {
	Fingerprint string `json:"fingerprint"`
	File        string `json:"file"`
	Category    string `json:"category"`
	State       State  `json:"state"` // known | acknowledged
	Reason      string `json:"reason,omitempty"`
	At          string `json:"at,omitempty"`
	// AgentVerdicts is where the agent reasoning PROSE lives. scan-all's delta
	// names reasoned items without it — 500 runes per verdict would eat the
	// response budget — so this targeted read is the only place the text is
	// reachable. Omitting it here would make the light delta a loss instead of a
	// trade-off.
	AgentVerdicts []EntryVerdict `json:"agent_verdicts,omitempty"`
}

Entry is a read-only projection of a baseline item for codefit-baseline-list: just what the agent needs to reference an item in accept/prune. It omits the snippet on purpose (the agent supplies the reasoning; this keeps the list small).

type EntryVerdict

type EntryVerdict struct {
	Verdict    string  `json:"verdict"`
	Reasoning  string  `json:"reasoning,omitempty"`
	Confidence float64 `json:"confidence"`
	At         string  `json:"at"`
	By         string  `json:"by"`
}

EntryVerdict is the list-time projection of one AgentVerdict. Reasoning is truncated by the same maxReasonLen idiom Ack.Reason already uses here; the FULL text always stays in the committed .codefit-baseline.

type Item

type Item struct {
	FP            string         `yaml:"fp"`
	Category      string         `yaml:"category"`
	File          string         `yaml:"file"`
	Snippet       string         `yaml:"snippet,omitempty"`
	AgentVerdicts []AgentVerdict `yaml:"agent_verdicts,omitempty"`
	Ack           *Ack           `yaml:"acknowledged,omitempty"`
}

Item is one tracked surface item or deterministic finding. Snippet is a human-readable display only; it is never the matched secret (the identity is the content-hashed FP). Ack is non-nil only when the item was accepted. AgentVerdicts is the append-only history of what an agent concluded about this item across audit passes — never trimmed except by ADR 0009's identity reset (a code edit changes FP, which starts a new item with an empty history).

func (Item) InConflict

func (it Item) InConflict() bool

InConflict reports whether this item's agent verdicts disagree: at least one "vulnerable" AND at least one "not_vulnerable" (an "uncertain" verdict participates in neither direction). Derived, never stored — every reader applies its own current rule to the raw facts rather than trusting a flag a different binary version may have written (D2).

type Observed

type Observed struct {
	FP       string
	Category string
	File     string
	Snippet  string
	Affirms  bool
}

Observed is one item seen in the current scan. Affirms is true for a deterministic finding (an affirmation) and false for a surface item (a question).

type State

type State string

State is an item's delta against the previous baseline.

const (
	StateNew     State = "new"
	StateChanged State = "changed"
	StateKnown   State = "known"
	StateAcked   State = "acknowledged"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL