Documentation
¶
Overview ¶
Package check holds the check verb's body and the verb-level check-rule helpers that need git access. The pure-tree rules live in internal/check; this package composes them with history walks (runTestsMetricsCheck, runProvenanceCheck) and renders the final output envelope.
Index ¶
- func NewCmd() *cobra.Command
- func ParseUntrailedCommits(s string) []check.UntrailedCommit
- func ReadUntrailedCommits(ctx context.Context, root, rangeArg string) ([]check.UntrailedCommit, error)
- func ResolveUntrailedRange(ctx context.Context, root, since string) (string, *check.Finding, error)
- func Run(root, format string, pretty bool, since string, shapeOnly, fast, verbose bool, ...) int
- func RunGitConfigCheck(ctx context.Context, root string) []check.Finding
- func RunProvenanceCheck(ctx context.Context, root string, t *tree.Tree, since string, ...) ([]check.Finding, error)
- func RunTestsMetricsCheck(ctx context.Context, root string, t *tree.Tree, require bool) ([]check.Finding, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewCmd ¶
NewCmd builds `aiwf check`: validate the consumer repo's planning state. Read-only; produces no commit. The pre-push git hook runs this verb — its findings + exit code are the framework's authoritative correctness gate.
func ParseUntrailedCommits ¶
func ParseUntrailedCommits(s string) []check.UntrailedCommit
ParseUntrailedCommits unpacks the multi-record stream produced by ReadUntrailedCommits. The format is:
<RS>{SHA}<US>{parent SHAs, space-separated}<US>{subject}<US>{trailers}<US>
{file1}
{file2}
...
<RS>{SHA}<US>...
Parents, trailers, and file lists are all whitespace- or newline- delimited. Subject is the commit's first line, used for the squash-merge specialization (G31); parent SHAs feed the merge- commit carveout (G-0231 item 3). Empty input (no unpushed commits) returns nil.
func ReadUntrailedCommits ¶
func ReadUntrailedCommits(ctx context.Context, root, rangeArg string) ([]check.UntrailedCommit, error)
ReadUntrailedCommits returns the commits in rangeArg (e.g. `@{u}..HEAD`, or `<sha>..HEAD` from --since) along with their trailer set and the relative paths each commit touched.
The range is supplied by the caller (ResolveUntrailedRange); ReadUntrailedCommits is purely the git-log invocation + parsing. An empty range (HEAD == @{u}) returns no commits, no findings.
`-m --first-parent` walks the integration-branch view (G32): merge commits surface their introduced changes (against their first parent) so the audit pass sees entity-file paths brought in by `git merge`, while feature-branch commits not on first-parent ancestry are correctly excluded (those are the feature branch's own warning scope, not the integration branch's). Without `-m` the default is "show no diff for merge commits," which silently bypassed the audit for merges that absorbed entity-file changes from a feature branch.
G-0231 item 3 shifts where the merge-vs-direct-edit decision lives: the reader still emits the data (the merge commit's touched paths, its parent SHAs), and RunUntrailedAudit decides to SKIP ordinary `--no-ff` merges based on len(ParentSHAs) > 1 + non-squash subject. The reader stays dumb; the rule decides. Squash-merge commits keep firing because GitHub strips trailers and the squash IS the only audit-trail event on the integration branch. See `internal/check/provenance.go` RunUntrailedAudit for the carveout's predicate and rationale.
func ResolveUntrailedRange ¶
ResolveUntrailedRange picks the `git log` range for the step-7b untrailered-entity audit. Three branches:
- since != "" — the operator's explicit choice wins. Validates the ref shape via `git rev-parse --verify`; an unrecognized ref returns a usage-error advisory finding so the audit is still skipped (rather than failing the whole check verb).
- else, an upstream is configured — return `@{u}..HEAD`.
- else — return ("", advisory) so the caller skips the scan and surfaces the undefined-scope warning.
func Run ¶
func Run(root, format string, pretty bool, since string, shapeOnly, fast, verbose bool, registeredVerbs map[string]struct{}) int
Run is the check verb's body. Loads the tree, runs every rule (pure-tree + provenance + tests-metrics + contracts + tree discipline), applies aiwf.yaml-driven severity bumps, renders the findings in the chosen format, and returns the exit code.
func RunGitConfigCheck ¶ added in v0.9.0
RunGitConfigCheck verifies that the local repo's `core.worktree` configuration, if set, resolves to the directory `aiwf` is operating in (the resolved root). A mismatch means every subsequent git operation from this directory is silently redirected against a different working tree — git reports no error, `git status` shows the wrong worktree's files, and `aiwf check` itself loads the wrong tree. The failure is invisible without inspection; this rule is the chokepoint that catches it. G-0155.
Returns no findings in three healthy cases:
- core.worktree unset (the normal state — `git config --get` exits 1)
- core.worktree set but resolves to the directory aiwf was invoked from (linked worktrees typically have this set to their own path; that's legitimate)
- The root or configured path can't be made absolute (don't fire a noisy finding on path-resolution edge cases)
Fires SeverityError otherwise — the misdirection corrupts every subsequent aiwf verb's view of the tree, so the push must block.
func RunProvenanceCheck ¶
func RunProvenanceCheck(ctx context.Context, root string, t *tree.Tree, since string, registeredVerbs map[string]struct{}, ackedSHAs map[string]bool, ackedSHAEntities map[string]map[string]bool, postCutoffSHAs map[string]bool) ([]check.Finding, error)
RunProvenanceCheck walks every commit reachable from HEAD that carries any `aiwf-*` trailer and runs the I2.5 standing rules against the result. It also runs the step-7b untrailered-entity- commit warning, scoped per the rules in ResolveUntrailedRange:
- --since <ref> on the verb wins.
- Otherwise `@{u}..HEAD` when an upstream is configured.
- Otherwise the audit is SKIPPED with a single `provenance-untrailered-scope-undefined` advisory; the fallback used to be "all of HEAD," which on long-lived branches floods with warnings against commits already merged in from trunk. See issue #5 sub-item 2.
Returns a single concatenated finding slice; transport errors propagate.
Why grep on `^aiwf-` for the standing rules: every rule is keyed on at least one aiwf trailer (actor, principal, scope-ends, etc.). Untrailered commits are handled by the separate step-7b audit pass, which uses a different filter (range scoped per ResolveUntrailedRange, no trailer grep).
M-0159/AC-3: ackedSHAs is the gather-layer-computed map of retroactively-acknowledged commit SHAs (via check.WalkAcknowledgedSHAs called once at check.go::Run). Passed through to three rules that consume it from this gather (check.RunIsolationEscape, check.RunTrailerVerbUnknown, check.RunIDRenameUntrailered — the third added at M-0160/AC-4); the fourth consumer (check.FSMHistoryConsistent) is called directly from check.go::Run with the same map.
G-0218 Patch 2: postCutoffSHAs is the gather-layer-computed map of commit SHAs that descend from check.HookInstallSHA (via check.WalkPostCutoffSHAs called once at check.go::Run). Mirrors the ackedSHAs pattern — single-compute, cascading pass-through. The map drives the trailer-verb-unknown rule's severity decision (post-cutoff → SeverityError; pre-cutoff or nil-map fallback → SeverityWarning per the G-0150 baseline). Threaded as a parameter rather than computed inside this function so seam tests can pin the rule's severity transition against fixture cutoffs (the production HookInstallSHA points at a specific main-branch commit that fresh-fixture repos don't carry).
func RunTestsMetricsCheck ¶
func RunTestsMetricsCheck(ctx context.Context, root string, t *tree.Tree, require bool) ([]check.Finding, error)
RunTestsMetricsCheck emits an `acs-tdd-tests-missing` warning for every AC at `tdd_phase: done` under a `tdd: required` milestone whose `aiwf history` carries no `aiwf-tests:` trailer on any commit. Gated on require: when false (the default), returns nil without walking history — the trailer is informational metadata and absence is not a finding.
Why the check lives here rather than in package check: the rule requires git access (a history walk per qualifying AC) which the pure-tree check.Run intentionally does not have. Composing this pass in the check verb's package keeps the rule's runtime cost scoped to invocations that opt in via aiwf.yaml.
Types ¶
This section is empty.