quality

package
v0.181.0 Latest Latest
Warning

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

Go to latest
Published: Oct 2, 2026 License: Apache-2.0 Imports: 34 Imported by: 0

Documentation

Overview

This file backs task-21's static check (spec/plans/coverage-to-100 README.md, and this repository's own AGENTS.md:108-112): "Name tests after the behaviour they verify and assert an observable outcome, never a filler coverage:ignore-style marker or a name that reflects a coverage campaign instead of behaviour (zz_cov_*, dqcov, tailcov-style names are forbidden)." A 2026-09-25 rename campaign (cov-rename-tests) fixed every violation a same-day batch of coordinator briefs had just added and swept every _test.go file this detector still matched on main into testdata/campaign_test_names.pending -- the same shrink-only discipline task-24's unit_tier.pending and task-8's exec_sites.pending already use, reusing their exact committed file format and this package's own parser for it (execsites.go's own comment names the same convention).

The check flags, in every `_test.go` file anywhere in the module, two lineages of campaign token: the long-lived "cov" family several earlier coverage campaigns left on main, and the rwi/pkp/pk0/cgx/pr9 family the 2026-09-25 coordinator briefs used for one day before the same-day rename campaign fixed every occurrence it had just added (997a4201). Both are guarded, not just the one still visible on main at seed time: an unguarded, already-renamed-away pattern is exactly the gap a future coordinator brief could walk straight back through by reusing one of these tokens tomorrow.

  • a file name (basename, not the full path) containing "zz_", starting "cov_", or containing "_cov_", "tailcov" or "dqcov" (the "cov" family), or containing "_rwi<digits>_", "_pkp<digits>_", "_pk0_" (no trailing digits -- "pk0" is already a complete token), "_cgx<digits>_"/"_cgxc<digits>_", or starting or containing "_pr9_" (the rwi/pkp/pk0/cgx/pr9 family) -- every fragment token-bounded by a leading/trailing "_" (or the start of the name for a leading token) so an ordinary word that merely contains the letters -- "pkg", "network", "coverage" -- can never match;
  • a `Test*` function name starting CwCov, TailCov, DqCov or Zz (case-sensitive, immediately after "Test", followed by an uppercase letter, a digit, or the end of the name -- so TestCoverageXxx, whose "Cov" is followed by lowercase "erage", is never mistaken for the campaign token TestCov never actually names on main), or starting Rwi/RWI/Pkp/Pk0/Cgx (case variants main's own violations actually use) immediately followed by a digit -- Cgx's own campaign token is always spelled with a further lowercase "c" before the digit (Cgxc1/2/3), so that form is matched explicitly rather than by a generic uppercase-or-digit boundary the literal "c" would fail.

Both lineages come from what main and this exact rename campaign actually contain, not an exhaustive theoretical list of every token a campaign could invent; a genuinely new token still needs this detector extended by hand, the same way AGENTS.md:108-112's rule itself would need updating.

This file backs spec/plans/coverage-to-100 task-10: the static check that keeps a direct time.Sleep/time.Now/time.After/time.NewTimer/time.Tick call out of a retry, timeout or backoff loop.

"Retry, timeout or backoff code path" is defined mechanically here, not by judgement: it is exactly the named list below, ClockSeamSites -- one entry per (file, function) that owned a direct time.Sleep/time.Now call controlling a retry loop, a lock-wait deadline, or a poll-until-ready wait before task-10 gave it a clock/sleep seam (a function parameter or struct field, defaulting to the real time.Now/time.Sleep/time.After/ time.NewTimer/time.Tick, that a test replaces with a fake so the wait never happens in real time). A function on this list must never again call any of those five directly -- every wait it makes must go through its own seam. This mirrors task-24's unit-tier pending list (internal/quality/unittier.go): a named, reviewed surface, not an open-ended repository-wide scan, so a legitimate, unrelated `time.Sleep`/`time.Now` elsewhere (a heartbeat ticker, a one-off pause, or the single place each seam's own default is seeded, e.g. `Sleep: time.Sleep` in a DefaultXxxDeps/New constructor) is never a false positive.

Add an entry here, in the same reviewed PR, whenever a new retry/timeout/ backoff loop is written anywhere in this repository and given a seam the same way; FindClockSeamViolations then holds it to the same zero-direct- calls rule from that point on. Removing an entry is a mechanical no-op once its function is deleted. A site naming a function FindClockSeamViolations cannot locate is itself an error (a stale or mistyped entry), not a silent pass.

Package quality runs read-only coverage and verification checks for a local repository fleet. It deliberately reports every selected repository instead of stopping at the first failure, so people and AI agents can act on one complete index.

This file backs task-8's mechanical check (spec/plans/coverage-to-100 task-8, verifies #4): non-test Go code must reach an external program through internal/runner or internal/gitcli, not directly, so unit tests can substitute their fakes.

The check flags, in every non-test `.go` file outside internal/runner, internal/gitcli and internal/process (internal/process joins the allow-list as the runner's base, per task-8's own text) and outside the fd-inheriting secure git helpers named in execSiteAllowedFunctionNames:

  • a direct exec.Command, exec.CommandContext, os.StartProcess or syscall.Exec call;
  • a literal "git" argv[0] passed to exec.Command, exec.CommandContext, process.CommandContext or process.CommandContextInteractive;
  • a call to one of the named git helpers in ExecSiteGitHelperNames.

internal/quality/testdata/exec_sites.pending lists every file this detector still matches, following the exact same rules as task-24's unit_tier.pending: one line per file with its match count and owning task, a local exact-equality guard (TestExecSitesPendingDoesNotRegress), and a cross-PR ratchet on the list's grand total (ciaudit.CompareExecSitesPendingTotal, wired into `wb ci audit --target` through ciaudit.CompareAgainstTarget) that must not rise against the base branch's copy unless another entry shrinks by at least as much.

This file backs TestNoInlineWriteSequencesOutsideFilewrite (spec/plans/ coverage-to-100 task-9): the mechanical check that a temp-file write -> sync -> chmod -> close -> publish (rename or link) sequence is implemented in exactly one place, internal/filewrite, and nowhere else.

The check is call-based, not a co-occurrence heuristic: a function is a violation if its body directly calls one of a fixed set of publish or create primitives:

  • publish, always banned: os.Rename, os.Link, syscall.Rename, syscall.Renameat, syscall.Link, the fd-relative unix.Rename/ Renameat/Renameat2/RenameatxNp/Link/Linkat family, the repo-local renameNoReplace helper, or a package-level alias of os.Link/os.Rename.
  • create, always banned regardless of whether the same function goes on to write content: os.CreateTemp, ioutil.TempFile, os.Create. A round-2 review of task-9 PR-1 found these three reserve or open a file unconditionally -- unlike os.OpenFile/unix.Openat, they cannot be used for a lock-only open, so gating them behind a content-write check let a real write escape through a package-level seam function (internal/nodeidentity/nodeidentity.go:writeNodeIDTempFile).
  • create, banned only when the same function also writes content: os.OpenFile or unix.Openat carrying an O_CREAT-family flag. This gate stays narrow because both are legitimately used for a lock-file open (O_CREAT|O_EXCL followed only by Fchmod/Flock, never a content write) that internal/filewrite has nothing to replace.
  • os.WriteFile alone is not banned; it is only a violation together with one of the publish primitives above in the same function, since a bare os.WriteFile is an ordinary overwrite, not a temp-file publish.

This replaced an earlier create-and-rename-pair heuristic that missed every os.*-based site (the dominant shape in this repository), every renameNoReplace call and every package-level rename/link alias, and that could never match os.OpenFile at all because it looked for the identifier O_CREAT while the os package spells its flag O_CREATE.

A violation's key is "relative/path.go:FuncName", or "relative/path.go:ReceiverType.FuncName" for a method -- the receiver type disambiguates two methods that share a name on different receivers in the same file (internal/streams/events.go has both (*FileEventLog).Append, a real O_APPEND write, and (DiscardEvents).Append, a no-op stub that is never flagged).

Two named allow-lists carry the sites this detector finds but task-9's PR series has not folded into internal/filewrite yet:

  • PendingMigrationExemptions: real write-then-publish (or write-once, or create-only-scratch) sequences still implemented inline, each naming the PR that will migrate it. The last PR in the series empties this map, turning the guard below into a zero-exception gate. Per a round-2 review decision, this includes every ephemeral/scratch CreateTemp site (a name reserved and freed, or a file written and used once by a single subprocess, never durably read back): the plan the file's own package doc for internal/filewrite states the Verifies goal as "zero direct temp-file write/sync/chmod/close/ rename sequences outside the new package", with no carve-out for scratch files, so these migrate through internal/filewrite's CreateScratch helper (landed in task-9 PR-9) rather than staying permanently exempt.
  • NotAFileWritePublishExemptions: sites this detector's necessarily conservative rules flag, but that are not a temp-file write-and- publish sequence at all -- a queue-state move, an archive/quarantine move, a directory move, an append-only log write, or the renameNoReplace primitive's own OS-specific implementation. These never migrate to internal/filewrite, because there is nothing here for it to replace. This list holds only move-only renames, append-only log writes, and the renameNoReplace OS wrappers -- never a create-temp-file site, since every one of those is either a real write (pending migration) or a scratch file (also pending, per the policy above).

TestEveryFilewriteBoundaryExemptionMatchesALiveViolation asserts every entry in both maps still names a real, currently-detected site, so a stale or padded entry is caught immediately and the allow-lists can only shrink as sites genuinely migrate. TestNotAFileWritePublishExemptionsNeverAlsoCreateAndWriteContent asserts no NotAFileWritePublishExemptions entry -- exempted for a rename/move/ append reason -- also independently creates a file via a gated OpenFile/Openat-with-create-flag call, an os.WriteFile/ioutil.WriteFile call, or an unconditionally-banned create primitive, and writes content to it; a round-2 review found internal/locallink/execports.go's Link function misclassified this way (exempted as "renames ... into place", when it also does two real O_CREATE|O_EXCL content writes before that rename), and a round-3 review found the same true of internal/lifecyclehooks/queue.go's Dispatcher.quarantineFile (renames the quarantined file, then os.WriteFile's a ".reason.txt" sidecar of its own). TestNotAFileWritePublishExemptionsAreRenameOnlyOrAppendOnlyNeverBoth asserts every remaining entry is exactly one of the list's two legitimate shapes -- a pure rename/move (calls a publish primitive, writes no content of its own) or a pure append-only log (opens O_APPEND and writes, calls no publish primitive) -- never neither and never both; a function doing both at once (rename plus an independent append-write) would otherwise slip past the create-and-write check above, since that check only looks for a *gated* create primitive and O_APPEND opens are deliberately excluded from it.

Package quality's parallel-baseline logic backs two things that must never drift apart: TestParallelBaselineDoesNotRegress (the CI guard) and cmd/parallelbaseline (the tool a human runs to regenerate the committed baseline after a deliberate, reviewed decision to add a new serial test). Both call the exported functions in this file so there is exactly one implementation of "what counts as serial" and "what counts as a baseline key".

This file backs the unit tier / e2e tier split (spec/plans/coverage-to-100 task-24): the static check that keeps a process-starting or real-git test out of the default `go test ./...` tier unless it is named on one of two committed lists.

Two lists, two different jobs:

  • internal/quality/testdata/unit_tier.pending names legacy _test.go files that still start a real process or shell out to real git, each with the exact match count this file's detector finds today and the task that will convert or move it. TestUnitTierPendingDoesNotRegress (in this package) fails when a file's live match count exceeds its committed entry -- a fresh violation must update the list in the same reviewed PR, never silently grow past what was recorded. Separately, the CI ratchet (ciaudit.CompareUnitTierPendingTotal, wired into `wb ci audit --target`) fails when the list's grand total rises against the base branch's committed copy, unless the same PR shrank other entries by at least as much.
  • internal/quality/testdata/unit_tier.allow names files that legitimately re-run the test binary itself (Go's helper-process pattern, `exec.Command(os.Args[0], ...)`) rather than a real external program. These are permanent, reviewed exceptions: a file listed here is not required to also appear on the pending list, and task-20 does not require this list to be empty.

The detector is call-based, over go/ast, not a text/regexp scan (task-24's Rework note: "Prefer go/ast over regex where it's cheap"), except for the one pattern that is inherently textual: the helper-process re-exec marker environment variable (GO_WANT_HELPER_PROCESS and this repository's GO_WANT_HELPER_PROCESS_OBSERVE variant), which shows up as a string literal value, not a call shape.

A default-tier test file is any `_test.go` file whose own build constraint does not require the `e2e` tag (go/build/constraint decides this the same way `go build` would, rather than a substring match on the `//go:build` line). An e2e-tagged file is out of scope for this detector entirely: task-24's Rework note is explicit that "[t]he e2e build tag on test files ... only selects a test tier."

This file backs task-25 (spec/plans/coverage-to-100/README.md, "Coverage worklists"): it turns a measured Go coverage profile into the deterministic unit list a coverage-to-100 lane's brief carries instead of exploration. The coordinator regenerates the list from the latest cov/integration profile before cutting new lane briefs, so the same profile must always produce the same units in the same order.

Index

Constants

View Source
const (
	// ReasonChangedStatementUncovered is a statement the diff itself adds or
	// modifies, found via GitChangedLines.
	ReasonChangedStatementUncovered = "added or changed statement is not covered by a test"
	// ReasonNewlyUncoveredAtBase is a statement the diff does not touch at
	// all, found only because the package's uncovered count rose (review
	// B2): it was covered when baseline was measured and is not now.
	ReasonNewlyUncoveredAtBase = "newly uncovered (was covered at base)"
)

Ratchet finding/warning reasons (review-696 non-blocking #4): a genuinely added or changed line and a pre-existing statement whose *coverage* changed are different situations and must read differently, since the first names something the diff shows and the second does not.

View Source
const (
	MaxRatchetToleranceStatements = 5
	MaxRatchetToleranceFunctions  = 5
	MaxRatchetToleranceEntries    = 3
)

Hard caps on the tolerance policy. The tolerance is a stopgap for a handful of timing-dependent branches (spec/plans/coverage-to-100/README.md task-3 (b3)); a repository that needs more than this has a coverage problem a tolerance must not hide.

View Source
const DefaultDeadcodeBaseline = ".wb/deadcode-baseline.txt"

DefaultDeadcodeBaseline is the repository-relative baseline path. It sits beside .wb/quality.yaml because it is repository-owned policy, reviewed in the pull request that changes it, not machine state.

View Source
const NativeGoTestSelector = "^Test(E2E|Contract)"

NativeGoTestSelector is shared by coverage execution and the static guard.

Variables

View Source
var ClockSeamSites = []ClockSeamSite{
	{File: "internal/remotestate/gitrepo/clonelock.go", Func: "acquireCloneLock"},
	{File: "internal/remotestate/gitrepo/provider.go", Func: "Fetch"},
	{File: "internal/gitops/gitops.go", Func: "pull"},
	{File: "internal/agents/owner.go", Func: "StopRun"},
	{File: "internal/agents/owner.go", Func: "waitForProcessExit"},
	{File: "internal/orchestrate/pr_create.go", Func: "pinPullRequestViewToHead"},
	{File: "internal/orchestrate/worktree_merge_ack.go", Func: "closeSupersededWorktreeMergePullRequest"},
	{File: "internal/orchestrate/worktree_merge_ack.go", Func: "ensurePreparedWorktreeMergeRebatch"},
	{File: "internal/worktrees/repository_registration_lock.go", Func: "acquireRepositoryRegistrationLock"},
	{File: "cmd/wb/daemon_process_darwin.go", Func: "startDaemonProcessInjected"},
	{File: "cmd/wb/daemon_process_darwin.go", Func: "awaitLaunchdReady"},

	{File: "cmd/wb/daemon.go", Func: "stateLock"},
}

ClockSeamSites is the named surface task-10 built while giving each of these functions a clock/sleep seam. See the package doc comment above for what belongs here and when to add to it.

View Source
var DefaultDeadcodePlatforms = []string{"linux", "darwin", "windows"}

DefaultDeadcodePlatforms is the supported GOOS set the gate analyses. A function is reported only when it is unreachable on every entry, so the verdict does not depend on which of them the gate happens to run on.

View Source
var DefaultDeadcodeTool = []string{"go", "run", deadcodeToolPackage}

DefaultDeadcodeTool pins the analyzer the way .wb/quality.yaml pins golangci-lint: an unpinned analyzer silently changes the gate's verdict between runs, which is the one thing a ratchet must never do.

View Source
var ExecSiteGitHelperNames = map[string]bool{
	"runGit": true, "gitOutput": true, "gitRawOutput": true,
	"runGitIn": true, "runGitWithFilesystemCapability": true,
	"gitWithExtraFiles": true,
}

ExecSiteGitHelperNames is task-8's starting list of named git-helper functions this repository's production code calls without themselves literally spelling "git" at the call site -- the same starting list task-24's static check names for test files ("starting with runGit, gitOutput, gitRawOutput, runGitIn, runGitWithFilesystemCapability and gitWithExtraFiles"), since these same helper names are used from both test and production code across this repository.

View Source
var NotAFileWritePublishExemptions = map[string]string{
	"internal/lifecyclehooks/queue.go:Dispatcher.recoverRunning":       "renames a queue job's state directory back to pending on recovery; not a file write",
	"internal/lifecyclehooks/queue.go:Dispatcher.claimBatchWithUnlock": "renames a queue job's state directory to claim it; not a file write",
	"internal/streams/store.go:Store.archiveLocked":                    "renames a stream's directory into an archive location; not a file write",
	"internal/locallink/execports.go:ExecNode.unlinkWithObservations":  "renames an existing backup directory back into place; not a temp-file write",
	"internal/locallink/execports.go:renameInstalledPackageForLink":    "moves the existing installed package aside; not a temp-file write or content publication",
	"cmd/wb/daemon_file_bridge.go:daemonFileBridgeServer.quarantine":   "renames a request file into a quarantine directory; not a write publish",

	"internal/hooks/rename_noreplace_darwin.go:renameNoReplace": "OS-specific renameNoReplace syscall wrapper, not a write sequence",
	"internal/hooks/rename_noreplace_linux.go:renameNoReplace":  "OS-specific renameNoReplace syscall wrapper, not a write sequence",

	"internal/agentguard/gh.go:recordGhPrMergeOverride": "O_APPEND log write, not a create/publish sequence",
	"internal/runlog/runlog.go:appendInjected":          "O_APPEND log write (flock-guarded), not a create/publish sequence",
}

NotAFileWritePublishExemptions lists "relative/path.go:FuncName" (or "relative/path.go:ReceiverType.FuncName" for a method) sites this detector's conservative call-based rules flag, but that are not a temp-file write-and-publish sequence: a queue-state move, an archive or quarantine move, a directory or lock move, an append-only log write, or the renameNoReplace primitive's own OS-specific implementation (which internal/filewrite does not yet own -- see LinkNoReplace's doc comment). None of these migrates to internal/filewrite, because there is no write sequence here for it to replace. Per a round-2 review decision, this list holds only move-only renames, append-only logs, and the renameNoReplace OS wrappers -- a create-temp-file site never belongs here, even a scratch one; see PendingMigrationExemptions' Category D/E. TestNotAFileWritePublishExemptionsNeverAlsoCreateAndWriteContent enforces that no entry below also independently creates and writes a file.

View Source
var ParallelGuardExcludedDirs = []string{"cmd/wb", "hub", "internal/runqueue"}

ParallelGuardExcludedDirs are the subtrees sneat-dev/wb#623's test-speed sweep did not touch, because other agent lanes were actively editing their test files at the same time (cmd/wb is #623 step 3; hub and internal/runqueue belong to other in-flight lanes). Once those get their own pass this list should shrink, and eventually disappear.

View Source
var PendingMigrationExemptions = map[string]string{

	"internal/execfile/execfile.go:WriteExecutableFile": "PR-10 (deferred from PR-8): misc-atomic-writers -- path-based CreateTemp+chmod+Rename, no sync; the tempExecutableFile interface seam and syscall.ForkLock.RLock discipline need a dedicated migration pass, not a careless one alongside PR-8's other 23 sites",
}

PendingMigrationExemptions lists "relative/path.go:FuncName" (or "relative/path.go:ReceiverType.FuncName" for a method) sites that implement a real temp-file write-then-publish sequence, write-once sequence, or scratch/name-reservation create inline, not yet routed through internal/filewrite. Every entry names the task-9 PR that will migrate it; that PR removes the entry in the same commit it lands.

View Source
var UnitTierGitHelperNames = map[string]bool{

	"runGit":                         true,
	"gitOutput":                      true,
	"gitRawOutput":                   true,
	"runGitIn":                       true,
	"runGitWithFilesystemCapability": true,
	"gitWithExtraFiles":              true,

	"gitRaw":                         true,
	"gitWithEnvironment":             true,
	"gitTopLevel":                    true,
	"gitPathExistsAtHEAD":            true,
	"gitPathUnchangedFromHEAD":       true,
	"ShowFile":                       true,
	"OriginAddress":                  true,
	"OriginSlug":                     true,
	"GitMergeBase":                   true,
	"GitTopLevel":                    true,
	"GitTouchedFiles":                true,
	"ComputeBaselineAtRef":           true,
	"resolveRefSHA":                  true,
	"ConfigureGitAutoMaintenanceOff": true,
	"commitPatchIDs":                 true,
	"isAncestor":                     true,
	"localBranchExists":              true,
	"atomicLocalBranchRename":        true,
	"mergeResultTree":                true,
	"GitBytes":                       true,
	"GitObjectSHA":                   true,

	"git": true, "gitIn": true, "gitFixture": true, "gitPorcelain": true,
	"gitRefExists": true, "gitStatus": true, "gitTest": true,
	"gitTestOutput": true, "gitTestRun": true, "gitTestRunEnv": true,
	"journeyGit": true, "journeyGitOutput": true, "lgCovRunGit": true,
	"publicationGit": true, "pushTierGit": true, "remoteGit": true,
	"runAbsorbedConflictGit": true, "runCLIWorktreeGit": true,
	"runCampaignGit": true, "runDependencyGit": true, "runEngineGit": true,
	"runFixtureGit": true, "runGitTestOutput": true, "runGuardTestGit": true,
	"runModuleArchiveGit": true, "runQualityGit": true, "runStreamGit": true,
	"runTestGit": true, "runUpgradeGit": true, "scratchGit": true,
	"slCovGit": true, "targetGit": true, "wtLifeCovGit": true,
	"cwDepsGit": true, "gcGit": true, "hkCovGitRepository": true,
	"initGitRepository": true, "initLifecycleGitRepository": true,
	"initTestRepository": true, "agentGuardGit": true,

	"wtLifeCovRunSecureHelper": true, "wtLifeCovRunSecureHelperInvocation": true,

	"InitBareRemoteForTest": true,

	"runCommand":    true,
	"installFakeGH": true,
}

UnitTierGitHelperNames is the maintained set of unqualified call names task-24's detector treats as "a named git helper call": a same-package function, production or test-local, whose own body shells out to the real git executable. A test file that calls one of these carries no exec.Command/exec.CommandContext literal of its own, so UnitTierPatternExecStart cannot see it -- only a name-based check can.

Every name below was found in this repository on 2026-09-25 by grepping every function whose body directly invokes exec.Command/exec.CommandContext with a literal "git" argv[0] (production helpers), plus every _test.go helper conventionally named after the same shape. Later leaf-package entries also include wrappers that reach real Git through gitcli. Task-24's Note is that "the check keeps the full list" -- add a name here, with a short comment naming where it is defined, whenever a new one is found; removing a name is a mechanical no-op once its only caller is gone.

Functions

func CampaignTestNamesPendingTotal added in v0.172.0

func CampaignTestNamesPendingTotal(entries map[string]UnitTierPendingEntry) int

CampaignTestNamesPendingTotal sums every entry's count.

func CountCampaignTestNameMatchesByFile added in v0.172.0

func CountCampaignTestNameMatchesByFile(matches []CampaignTestNameMatch) map[string]int

CountCampaignTestNameMatchesByFile aggregates matches per file: the file name itself (if it violates) counts as one, and every violating Test function inside it adds one more -- the same per-file "how many things would a reviewer have to rename" count task-24's and task-8's own detectors report.

func CountExecSiteMatchesByFile added in v0.172.0

func CountExecSiteMatchesByFile(matches []ExecSiteMatch) map[string]int

CountExecSiteMatchesByFile aggregates matches per file.

func CountUnitTierMatchesByFile added in v0.170.0

func CountUnitTierMatchesByFile(matches []UnitTierMatch) map[string]int

CountUnitTierMatchesByFile aggregates matches into a per-file total count, the shape the pending list and its guard compare against.

func EvaluateRatchet added in v0.164.0

func EvaluateRatchet(blocks []CoverageBlock, changed ChangedLines, touchedFiles map[string]bool, lineOffsets map[string]FileLineOffsets, baseline PackageBaseline, modulePath string, tolerances RatchetTolerances, changedOwners ...[]string) ([]PackageRatchet, []RatchetWarning)

EvaluateRatchet applies the per-change coverage ratchet (spec/plans/coverage-to-100/README.md task-3, founder decisions 11 and 12): a package the PR changes fails when its uncovered-statement count rises against baseline, or when a changed, non-moved line is uncovered anywhere. A package the PR does not change only ever warns on a count rise — touchedFiles (repository-relative paths, including files the diff only deletes lines from, deletes entirely, or a rename's old AND new path) decides package ownership; a changed package with no baseline entry at all is treated as a baseline of 0 (review-696 blocking #2: the merge-base measurement covers every package that existed then, so a missing entry means the package did not exist, not that it is exempt).

Attributing a count-only rise to an exact statement (uncoveredBlockKey against baseline.UncoveredBlocks) can land on a block inside a file the PR itself touched: editing a file shifts every later line's position, so the baseline's raw stored position there does not directly compare. Set lineOffsets (from GitLineOffsets) maps each baseline block's stored line through that file's own diff hunks to its current line first: a current block landing on that mapped line is the same pre-existing statement, just shifted, not new (review-696 non-blocking #3) — pass nil to skip this mapping entirely, which means no touched-file block can be matched to a shifted baseline position, so every uncovered block in a touched file is reported as attributable (the original, pre-5a7d0df6 behavior, before the blanket touched-file skip existed — this is the LEAST conservative option, not a conservative one).

tolerances (task-3 (b3), from LoadRatchetTolerances on the head checkout) loosens only the count rule, only for the changed packages it names, and only for statements inside the functions an entry lists, on lines the change did not add, modify or move (lineOffsets supplies the moved lines that changed leaves out); see toleratedStatements. A package that passes this way has Rose false and carries Tolerance and Tolerated so the caller can warn about it. Pass nil for the strict ratchet.

func ExecSitesPendingTotal added in v0.172.0

func ExecSitesPendingTotal(entries map[string]UnitTierPendingEntry) int

ExecSitesPendingTotal sums every entry's count.

func ExistingCoveragePackages

func ExistingCoveragePackages(root string, patterns []string) ([]string, error)

ExistingCoveragePackages resolves a logical selection at one revision. A new or deleted package contributes no statements at the revision where absent.

func FindNativeTestSelectionProblems

func FindNativeTestSelectionProblems(root string) ([]string, error)

FindNativeTestSelectionProblems rejects silently unselected native tests. There are no pending counts or file-wide helper allowances.

func FormatCampaignTestNamesPending added in v0.172.0

func FormatCampaignTestNamesPending(entries map[string]UnitTierPendingEntry) string

FormatCampaignTestNamesPending renders entries back into campaign_test_names.pending's file format, sorted by path, under campaignTestNamesPendingHeader.

func FormatDeadcodeBaseline added in v0.137.0

func FormatDeadcodeBaseline(findings []DeadcodeFinding) string

FormatDeadcodeBaseline renders findings as a baseline file. Entries are sorted and one per line so that a diff of this file reviews as a list of mechanisms that lost or gained a caller.

func FormatExecSitesPending added in v0.172.0

func FormatExecSitesPending(entries map[string]UnitTierPendingEntry) string

FormatExecSitesPending renders entries back into exec_sites.pending's file format, sorted by path, under execSitesPendingHeader.

func FormatParallelBaseline added in v0.164.8

func FormatParallelBaseline(entries []ParallelBaselineEntry) string

FormatParallelBaseline renders entries as the committed file format: sorted by key, tab-separated key and reason, one per line.

func FormatUnitTierPending added in v0.170.0

func FormatUnitTierPending(entries map[string]UnitTierPendingEntry) string

FormatUnitTierPending renders entries as the committed file format: a header comment, then one sorted, tab-separated line per entry.

func GitLineOffsets added in v0.164.0

func GitLineOffsets(ctx context.Context, repoRoot, mergeBase string) (map[string]FileLineOffsets, error)

GitLineOffsets computes FileLineOffsets for every file a diff against mergeBase touches (review-696 non-blocking #3). --no-renames matches GitTouchedFiles: a rename is a plain delete-then-add pair, so its old path's hunks (an entire "delete everything") never falsely offset the new path's line numbers.

func GitMergeBase added in v0.164.7

func GitMergeBase(ctx context.Context, repoRoot, target string) (string, error)

GitMergeBase resolves the merge-base commit of HEAD and target inside repoRoot. It is the base resolution `wb coverage --changed --target` and `wb run --changed --target` both use, so the two never disagree about which commit a diff is measured against.

func GitTopLevel added in v0.164.7

func GitTopLevel(ctx context.Context, dir string) (string, error)

GitTopLevel resolves the repository's top-level working-tree directory containing dir. Every path GitTouchedFiles/GitChangedLines/GitLineOffsets report is relative to this directory, never to whatever directory the caller happened to invoke Git from — callers that need those paths relative to a different directory (a nested Go module root, or the caller's own working directory) must rebase them explicitly; see ChangedPackages for that rebasing.

func GitTouchedFiles added in v0.164.0

func GitTouchedFiles(ctx context.Context, repoRoot, mergeBase string) (map[string]bool, error)

GitTouchedFiles reports every repository-relative file path a diff touches against mergeBase — added, modified, deleted, or renamed — independent of whether the diff added any line at all. A pure deletion (for example removing a test function) never appears in ChangedLines (it added no line), but it must still count as "the PR changed this package" (founder decision 2026-09-23, review B1): the caller uses this, not ChangedLines, to decide per-package ratchet ownership.

func LoadDeadcodeBaseline added in v0.137.0

func LoadDeadcodeBaseline(path string) (entries map[string]bool, missing bool, err error)

LoadDeadcodeBaseline reads a baseline file. A missing file is not an error: it reports every finding as new, which is what a repository adopting the gate should see before it records its starting point.

func PackageOf added in v0.164.0

func PackageOf(file, modulePath string) string

PackageOf maps a coverage profile's module-qualified file path (for example "github.com/sneat-dev/wb/internal/quality/ratchet.go") to the package directory relative to the module root ("internal/quality"). modulePath is the module declaration from go.mod (for example "github.com/sneat-dev/wb"); the module root package itself maps to ".".

func PackageUncoveredCounts added in v0.164.0

func PackageUncoveredCounts(blocks []CoverageBlock, modulePath string) map[string]int

PackageUncoveredCounts sums the uncovered statement count per package.

func ParallelGuardModuleRoot added in v0.164.8

func ParallelGuardModuleRoot() (string, error)

ParallelGuardModuleRoot walks up from the calling file to the nearest go.mod.

func ParseCampaignTestNamesPending added in v0.172.0

func ParseCampaignTestNamesPending(path string) (map[string]UnitTierPendingEntry, error)

ParseCampaignTestNamesPending parses testdata/campaign_test_names.pending.

func ParseCampaignTestNamesPendingBytes added in v0.172.0

func ParseCampaignTestNamesPendingBytes(data []byte, sourceName string) (map[string]UnitTierPendingEntry, error)

ParseCampaignTestNamesPendingBytes parses campaign_test_names.pending content already read into memory (for example, a fetched target branch's copy).

func ParseExecSitesPending added in v0.172.0

func ParseExecSitesPending(path string) (map[string]UnitTierPendingEntry, error)

ParseExecSitesPending parses testdata/exec_sites.pending.

func ParseExecSitesPendingBytes added in v0.172.0

func ParseExecSitesPendingBytes(data []byte, sourceName string) (map[string]UnitTierPendingEntry, error)

ParseExecSitesPendingBytes parses exec_sites.pending content already read into memory (for example, a fetched target branch's copy).

func ParseParallelBaseline added in v0.164.8

func ParseParallelBaseline(path string) (map[string]string, error)

ParseParallelBaseline reads the baseline file, keyed as "<key>\t<reason>" per line. Every entry must carry a non-empty reason; ParseParallelBaseline returns an error naming every entry that does not (callers surface all of them at once rather than failing on the first).

func ParseUnitTierAllow added in v0.170.0

func ParseUnitTierAllow(path string) (map[string]string, error)

ParseUnitTierAllow reads the committed allow list at path: one "<path>\t<reason>" line per permanently exempt helper-process test file. It shares ParallelBaseline's file format and validation (a non-empty reason on every entry) rather than reimplementing the same parser for a second committed key-tab-reason list.

func ParseUnitTierPending added in v0.170.0

func ParseUnitTierPending(path string) (map[string]UnitTierPendingEntry, error)

ParseUnitTierPending reads the committed pending list at path.

func ParseUnitTierPendingBytes added in v0.170.0

func ParseUnitTierPendingBytes(data []byte, sourceName string) (map[string]UnitTierPendingEntry, error)

ParseUnitTierPendingBytes parses pending-list content already in memory (for example the output of `git show <target>:<path>`, which ciaudit.CompareUnitTierPendingTotal reads without ever writing a temp file). sourceName is used only to build a readable error message.

func ReadModulePath added in v0.164.0

func ReadModulePath(moduleRoot string) (string, error)

func SaveValidationCache added in v0.98.3

func SaveValidationCache(cacheRoot string, key ValidationCacheKey, report VerificationReport) error

SaveValidationCache writes terminal evidence atomically. Failed writes are returned to the caller; a cache failure never changes validation semantics.

func ScanExecWriteFileCallSites added in v0.166.0

func ScanExecWriteFileCallSites(root string) ([]string, error)

ScanExecWriteFileCallSites walks every .go file under root (skipping .git/node_modules/vendor/dot-directories and execWriteFileGuardExcludedDirs) and reports one "file:line" entry for each call site it can statically prove writes -- or later renders executable -- a file at its final path without going through testenv.WriteExecutableFile. It flags four shapes:

  1. os.WriteFile / ioutil.WriteFile / os.OpenFile with a mode argument that resolves to an executable literal: a bare integer literal, an os.FileMode(literal) conversion, or a local variable/parameter this scan can trace back to one of those within the same function or (for a parameter forwarded straight into the write) at the call site that supplies it.
  2. os.WriteFile / ioutil.WriteFile followed, later in the same function, by os.Chmod or os.Fchmod on a matching path expression to an executable literal mode -- the write's own mode does not matter, since opening a writable fd at the final path is what races a concurrent fork, regardless of what the file's mode is at that moment (golang/go#22315; task-21, #739).

A call site that computes its mode in a way this scan cannot trace (for example, a mode read from a tar header or other runtime value) is not flagged: it is not something a static scan can classify, and forcing every dynamic-mode writer through testenv.WriteExecutableFile is out of scope for this guard. testenv.WriteExecutableFile closes the race window by writing to a temporary sibling file and renaming it into place under a process-wide fork guard; every fake-executable writer this scan can prove unsafe must use it instead.

func SingleWorkerNodeEnv added in v0.88.0

func SingleWorkerNodeEnv() []string

SingleWorkerNodeEnv is the environment a single-worker Node run must carry. It is exported so a caller that composes its own command still states the same environment the profile does.

func SortVerificationReports

func SortVerificationReports(reports []VerificationReport)

SortVerificationReports orders reports for deterministic output.

func UnitTierPendingTotal added in v0.170.0

func UnitTierPendingTotal(entries map[string]UnitTierPendingEntry) int

UnitTierPendingTotal sums every entry's count.

func ValidateBaseline added in v0.164.0

func ValidateBaseline(baseline PackageBaseline, expectedSHA string) error

ValidateBaseline reports whether baseline is usable against expectedSHA. A wrong schema version, an empty package map, or (when expectedSHA is non-empty) a SHA that does not match expectedSHA each make the baseline unusable: EvaluateRatchet treats a package missing from Packages as having no baseline and passes the count rule for it by design, so a baseline that silently lost its contents (an empty `{}` artifact, a schema drift, or one published for the wrong commit) would otherwise disable the per-package count rule for every package without failing anything (spec/plans/coverage-to-100/README.md task-3(b)). Callers must treat a non-nil error as "this baseline cannot be trusted", not "no baseline available" — the caller falls back to measuring the merge base directly, or fails loudly, either way never using the untrusted baseline as-is.

func ValidateGoCoveragePackagePatterns added in v0.174.0

func ValidateGoCoveragePackagePatterns(patterns []string) error

ValidateGoCoveragePackagePatterns rejects values that `go test` could interpret as flags instead of the package patterns callers intend to scope.

func ValidateNativeWorkflowSelector

func ValidateNativeWorkflowSelector(data []byte) error

ValidateNativeWorkflowSelector checks executable run steps, not comments or workflow metadata, against the selector used by native coverage execution.

func ValidationCacheDir added in v0.98.3

func ValidationCacheDir(root string) string

ValidationCacheDir is kept in one place so all merge baseline callers share the same private WB state and tests can replace it without touching a user repository.

func WriteBaseline added in v0.164.0

func WriteBaseline(path string, baseline PackageBaseline) error

WriteBaseline writes baseline as deterministic, indented JSON.

func WriteCoverageSummary added in v0.171.0

func WriteCoverageSummary(path string, summary CoverageSummary) error

WriteCoverageSummary writes summary as deterministic, indented JSON.

func WriteDeadcodeBaseline added in v0.137.0

func WriteDeadcodeBaseline(path string, findings []DeadcodeFinding) error

WriteDeadcodeBaseline records findings as the new tolerated set.

Types

type CampaignTestNameKind added in v0.172.0

type CampaignTestNameKind string

CampaignTestNameKind names which half of a _test.go file FindCampaignTestNameMatches flagged: the file's own name, or one of its Test function names.

const (
	// CampaignTestNameKindFile is the file's own basename.
	CampaignTestNameKindFile CampaignTestNameKind = "file-name"
	// CampaignTestNameKindFunc is one Test* function declared in the file.
	CampaignTestNameKindFunc CampaignTestNameKind = "func-name"
)

type CampaignTestNameMatch added in v0.172.0

type CampaignTestNameMatch struct {
	File string
	Line int
	Kind CampaignTestNameKind
	Name string
}

CampaignTestNameMatch is one occurrence FindCampaignTestNameMatches reports: either the file itself (Line 1, Name the basename) or one Test function whose name carries a campaign token (Line the func's own declaration line, Name the function name).

func FindCampaignTestNameMatches added in v0.172.0

func FindCampaignTestNameMatches(root string) ([]CampaignTestNameMatch, error)

FindCampaignTestNameMatches walks root and reports, in every `_test.go` file anywhere in the module (unlike task-24's unit-tier detector, this naming rule is not tier-specific: an e2e-tagged file is named after its behaviour exactly the same as a default-tier one), every file name and every Test function name that carries a forbidden campaign-naming token. Results are sorted by file, then line, then name.

func (CampaignTestNameMatch) String added in v0.172.0

func (m CampaignTestNameMatch) String() string

type ChangedLines added in v0.164.0

type ChangedLines map[string]map[int]bool

ChangedLines is the set of new-file line numbers a diff added or modified against a merge base, excluding lines git identifies as moved-but-unmodified (spec/plans/coverage-to-100/README.md task-3(a)). Keys are file paths relative to the repository root, matching `git diff`'s `b/<path>` spelling.

func GitChangedLines added in v0.164.0

func GitChangedLines(ctx context.Context, repoRoot, mergeBase string) (ChangedLines, error)

GitChangedLines computes ChangedLines for repoRoot against mergeBase, running `git diff --merge-base <mergeBase> -U0 --color-moved=plain` with explicit color assignments so moved lines are distinguishable from plain additions regardless of the caller's git config.

func (ChangedLines) Contains added in v0.164.0

func (c ChangedLines) Contains(file string, line int) bool

Contains reports whether line in file was added or changed (not moved).

type ChangedPackagesResult added in v0.164.7

type ChangedPackagesResult struct {
	// Target is the branch or ref the caller asked to diff against.
	Target string
	// MergeBase is the resolved merge-base commit of HEAD and Target.
	MergeBase string
	// Packages is the sorted, deduplicated list of `go test`/`go vet`-ready
	// package patterns the diff touches ("." for workingDir's own module
	// root, "./internal/foo" or "../sibling" otherwise, always relative to
	// workingDir). A directory outside the Go module that contains
	// workingDir, a directory belonging to a DIFFERENT Go module nested
	// inside that module (its own go.mod below workingDir's module root —
	// a tools/, examples/, or <product>/backend-style subtree), a directory
	// the diff empties out entirely (fully deleted or moved away), and a
	// directory the go tool itself would never build (no buildable *.go
	// file left in it, a "testdata"/"vendor" directory, or a "_"/"."-prefixed
	// path segment) are never included. A directory whose only *.go files
	// are excluded by build constraints on the current host (an
	// architecture- or OS-specific file that does not match GOOS/GOARCH
	// here) is not detected as such and may still be included — that would
	// need actually loading the build graph, which this function
	// deliberately does not do.
	Packages []string
}

ChangedPackagesResult is the outcome of computing which Go packages a local diff touched against a resolved merge base.

func ChangedPackages added in v0.164.7

func ChangedPackages(ctx context.Context, workingDir, target string) (ChangedPackagesResult, error)

ChangedPackages computes the Go packages a local diff against target touches, scoped to the Go module that contains workingDir (the nearest go.mod at or above workingDir, up to the repository root) and expressed as patterns relative to workingDir itself — exactly what a human typing `go test ./...` from that directory would need, whether workingDir is a repository's top level or a nested module root such as "<product>/backend" (the fleet's common layout).

It captures staged changes, unstaged changes, and already-committed changes since the merge base, all in one pass (spec/plans/coverage-to-100/README.md task-19, issue #570). This promotes the pre-commit hook template's shell mapping (internal/hooks/config.go, BuiltinGoPreCommit) into a first-class, tested Go function `wb run --changed` calls.

The diff itself is computed the same way GitTouchedFiles' underlying `git diff --merge-base <mergeBase>` call already does for `wb coverage --changed`: with no --cached, `git diff <ref>` compares ref to the CURRENT WORKTREE, which is the index (staged changes) and the on-disk files (unstaged changes) together — already committed changes since the merge base are naturally included too, since they are already part of that worktree state relative to the older merge-base ref. One git invocation therefore captures all three kinds of local change; no separate --cached pass is needed. Git always reports these paths relative to the repository's top level, never relative to workingDir, which is why this function resolves that top level itself (GitTopLevel) instead of treating workingDir as if it already were that root.

Untracked files (never added to Git at all) are not included: `git diff` itself never reports them, staged, unstaged, or committed.

Renames count both their old and new path (GitTouchedFiles uses --no-renames for exactly this reason: with rename detection on, git prints only the destination path and silently drops the source). Files that do not end in ".go" are ignored; a "_test.go" change counts like any other Go file. The module root package maps to ".".

type Check

type Check string

Check selects a conventional verification class.

const (
	CheckLint  Check = "lint"
	CheckTest  Check = "test"
	CheckBuild Check = "build"
	CheckSpec  Check = "spec"
)

func ParseChecks

func ParseChecks(value string) ([]Check, error)

ParseChecks validates the explicit --checks list. A missing list defaults to the conventional lint, test, build sequence.

type ClockSeamMatch added in v0.172.0

type ClockSeamMatch struct {
	// File is the path relative to root, slash-separated.
	File string
	// Line is the match's line number.
	Line int
	// Func is the enclosing function's name (the ClockSeamSite.Func that
	// found it).
	Func string
	// Pattern names which time-package call matched.
	Pattern ClockSeamPattern
}

ClockSeamMatch is one direct, banned time-package call found inside one ClockSeamSite's function body.

func FindClockSeamViolations added in v0.172.0

func FindClockSeamViolations(root string) ([]ClockSeamMatch, error)

FindClockSeamViolations parses every file ClockSeamSites names (relative to root) and reports every direct time.Sleep/time.Now/time.After/ time.NewTimer/time.Tick call found inside each named function's body. It returns an error, rather than zero matches, when a named function cannot be found in its file at all -- a stale or mistyped ClockSeamSites entry must fail loudly, never silently pass as clean.

func (ClockSeamMatch) String added in v0.172.0

func (m ClockSeamMatch) String() string

type ClockSeamPattern added in v0.172.0

type ClockSeamPattern string

ClockSeamPattern names one banned direct time-package call shape.

const (
	ClockSeamPatternSleep    ClockSeamPattern = "time.Sleep"
	ClockSeamPatternNow      ClockSeamPattern = "time.Now"
	ClockSeamPatternAfter    ClockSeamPattern = "time.After"
	ClockSeamPatternNewTimer ClockSeamPattern = "time.NewTimer"
	ClockSeamPatternTick     ClockSeamPattern = "time.Tick"
)

type ClockSeamSite added in v0.172.0

type ClockSeamSite struct {
	File string
	Func string
}

ClockSeamSite names one retry/timeout/backoff function this detector guards: File is relative to the module root, slash-separated; Func is the name of the function or method declared in it (a method's receiver is ignored -- every entry below names a function whose name is unique within its own file, the same pragmatic stance task-24's detector takes rather than resolving full method sets).

type CoverageBlock added in v0.164.0

type CoverageBlock struct {
	File       string
	StartLine  int
	StartCol   int
	EndLine    int
	EndCol     int
	Statements int
	Count      int
}

CoverageBlock is one statement-range entry from a Go coverage profile (`go test -coverprofile`). Count is the number of times the profiled binary executed every statement in the block; Count == 0 means the block is uncovered.

func ParseCoverageProfile added in v0.164.0

func ParseCoverageProfile(profilePath string) ([]CoverageBlock, error)

ParseCoverageProfile reads a Go coverage profile (`mode: ...` header followed by `file:startLine.startCol,endLine.endCol numStmt count` rows) into unique source blocks, preserving line ranges for callers that need more than profileTotals' aggregate. Repeated blocks from instrumented test binaries combine execution counts according to the profile mode.

type CoverageDiagnostic added in v0.67.9

type CoverageDiagnostic struct {
	Manifest string `yaml:"manifest" json:"manifest"`
	SHA256   string `yaml:"sha256" json:"sha256"`
}

CoverageDiagnostic points at the private manifest containing lossless raw output for failed coverage jobs.

type CoverageDiagnosticFile added in v0.67.9

type CoverageDiagnosticFile struct {
	Label         string `yaml:"label" json:"label"`
	Path          string `yaml:"path" json:"path"`
	Bytes         int    `yaml:"bytes" json:"bytes"`
	SHA256        string `yaml:"sha256" json:"sha256"`
	ElapsedNS     int64  `yaml:"elapsed_ns,omitempty" json:"elapsed_ns,omitempty"`
	TimeoutSource string `yaml:"timeout_source,omitempty" json:"timeout_source,omitempty"`
}

type CoverageDiagnosticManifest added in v0.67.9

type CoverageDiagnosticManifest struct {
	SchemaVersion int    `yaml:"schema_version" json:"schema_version"`
	Repository    string `yaml:"repository" json:"repository"`
	Module        string `yaml:"module" json:"module"`
	// Ambient names the machine-state signals present in the gate's own
	// environment and in the ancestors of TMPDIR and Module when the shard
	// failures below were recorded. Empty when none were observed.
	Ambient envguard.AmbientInputs   `yaml:"ambient,omitempty" json:"ambient,omitempty"`
	Files   []CoverageDiagnosticFile `yaml:"files" json:"files"`
}

CoverageDiagnosticManifest is intentionally separate from CoverageReport: it contains unbounded command output and therefore stays in the private report root rather than crossing the bounded hook/session boundary.

type CoverageReport

type CoverageReport struct {
	SchemaVersion int                  `yaml:"schema_version" json:"schema_version"`
	Repositories  []RepositoryCoverage `yaml:"repositories" json:"repositories"`
	Statements    int                  `yaml:"statements" json:"statements"`
	Covered       int                  `yaml:"covered" json:"covered"`
	Percentage    float64              `yaml:"percentage" json:"percentage"`
}

CoverageReport is a deterministic, machine-readable coverage index.

func NewCoverageReport

func NewCoverageReport(repositories []RepositoryCoverage) CoverageReport

NewCoverageReport aggregates reports in deterministic repository order.

type CoverageScopeIdentity

type CoverageScopeIdentity struct {
	HeadSHA     string `json:"head_sha"`
	BaseSHA     string `json:"base_sha"`
	IncludeE2E  bool   `json:"include_e2e"`
	BuildSHA256 string `json:"build_sha256"`
}

CoverageScopeIdentity records revision and effective build provenance. The environment is hashed so build flags containing private values are not logged.

type CoverageScopePackage

type CoverageScopePackage struct {
	Pattern         string
	ImportPath      string
	Imports         []string
	TestImports     []string
	XTestImports    []string
	EmbedFiles      []string
	TestEmbedFiles  []string
	XTestEmbedFiles []string
}

CoverageScopePackage describes one module-local package from go list. Pattern is module-relative ("." or "./internal/example"). Supply both revisions and both build-tag tiers: test imports are part of the graph.

type CoverageSelection

type CoverageSelection struct {
	Packages        []string               `json:"packages"`
	ChangedPackages []string               `json:"changed_packages"`
	Full            bool                   `json:"full"`
	Reason          string                 `json:"reason"`
	Identity        *CoverageScopeIdentity `json:"identity,omitempty"`
}

CoverageSelection is a logical scope shared by baseline and head. Packages absent from one revision have no statements there; callers resolve existence separately without replacing an empty selection with ./....

func AffectedCoverageScope

func AffectedCoverageScope(ctx context.Context, repo, mergeBase string, touched map[string]bool, includeE2E bool) (CoverageSelection, error)

AffectedCoverageScope reads both revision graphs before selecting one logical comparison scope. Graph failures fail validation, never silently skip tests.

func PlanCoverageScope

func PlanCoverageScope(touched []string, graphs ...[]CoverageScopePackage) CoverageSelection

PlanCoverageScope selects changed packages and their transitive dependents. Tests and instrumentation use this same set, preserving cross-package hits. Package-owned assets, fixtures and generated files use their nearest package ancestor. Shared build inputs and unowned inputs conservatively select all.

type CoverageSummary added in v0.171.0

type CoverageSummary struct {
	SchemaVersion  int                       `json:"schema_version"`
	Repository     string                    `json:"repository,omitempty"`
	SHA            string                    `json:"sha,omitempty"`
	Ref            string                    `json:"ref,omitempty"`
	WorkflowRunID  int64                     `json:"workflow_run_id,omitempty"`
	WorkflowRunURL string                    `json:"workflow_run_url,omitempty"`
	ReportedAt     time.Time                 `json:"reported_at"`
	Status         Status                    `json:"status"`
	Statements     int                       `json:"statements"`
	Covered        int                       `json:"covered"`
	Percentage     float64                   `json:"percentage"`
	Modules        []ModuleCoverageSummary   `json:"modules,omitempty"`
	Packages       map[string]PackageSummary `json:"packages,omitempty"`
}

CoverageSummary is the deterministic JSON artifact published by CI coverage runs.

func ReadCoverageSummary added in v0.171.0

func ReadCoverageSummary(path string) (CoverageSummary, error)

ReadCoverageSummary reads a CoverageSummary JSON file.

func SummaryFromProfile added in v0.171.0

func SummaryFromProfile(blocks []CoverageBlock, modulePath string, meta CoverageSummaryMeta) CoverageSummary

SummaryFromProfile builds a CoverageSummary from parsed coverage blocks.

type CoverageSummaryMeta added in v0.171.0

type CoverageSummaryMeta struct {
	Repository     string
	SHA            string
	Ref            string
	WorkflowRunID  int64
	WorkflowRunURL string
	ReportedAt     time.Time
	Status         Status
}

CoverageSummaryMeta holds build metadata injected into the summary.

type DeadcodeFailureEvidence added in v0.172.0

type DeadcodeFailureEvidence struct {
	Count      int      `yaml:"count" json:"count"`
	Identities []string `yaml:"identities,omitempty" json:"identities,omitempty"`
	Complete   bool     `yaml:"complete" json:"complete"`
}

DeadcodeFailureEvidence is the complete set of newly unreachable functions from a failed `go run ./cmd/wb deadcode` check. Count is independently declared by the command; Complete is false when its output could not be verified. The ordinary Detail remains bounded for human-facing reports.

func (*DeadcodeFailureEvidence) Valid added in v0.172.0

func (e *DeadcodeFailureEvidence) Valid() bool

Valid also checks evidence after a receipt has been deserialized; a stored count/list mismatch or duplicate must not authorize a baseline match.

type DeadcodeFinding added in v0.137.0

type DeadcodeFinding struct {
	// Identity is the baseline key: import path + "." + function name. It
	// deliberately excludes the source position, so moving a function or
	// editing the lines above it does not invalidate the baseline and does not
	// silently re-admit a genuinely new finding.
	Identity string `yaml:"identity" json:"identity"`
	Package  string `yaml:"package" json:"package"`
	Function string `yaml:"function" json:"function"`
	File     string `yaml:"file,omitempty" json:"file,omitempty"`
	Line     int    `yaml:"line,omitempty" json:"line,omitempty"`
}

DeadcodeFinding is one unreachable function.

type DeadcodeOptions added in v0.137.0

type DeadcodeOptions struct {
	// Patterns are the main packages to analyze. deadcode only starts from
	// executables, so a pattern matching no main package reports nothing.
	Patterns []string
	// BaselinePath is relative to the repository root when not absolute.
	BaselinePath string
	// Tool overrides the analyzer invocation. When set, the analyzer runs once
	// per Platforms entry, or once with the host environment when Platforms is
	// empty. When nil, the pinned analyzer is installed and run once per
	// platform; Platforms empty then means DefaultDeadcodePlatforms.
	Tool []string
	// Platforms lists the GOOS values to analyse. A function is reported only
	// when it is unreachable on all of them.
	Platforms []string
	// ToolDirectory is the parent directory the analyzer is installed under;
	// empty means the operating system's temporary directory.
	ToolDirectory string
	// Runner starts the analyzer and the go tool; nil uses the real runner.
	Runner runner.Runner
	// GoCommand is the go tool used to install the pinned analyzer; empty
	// means "go".
	GoCommand string
	// Filter is deadcode's -filter regular expression. Empty keeps deadcode's
	// own default, which reports the module of the first listed package.
	Filter string
	// IncludeGenerated reports dead functions in generated files too. Off by
	// default: generated code is not hand-wired, so its reachability is the
	// generator's contract, not this repository's.
	IncludeGenerated bool
	// Timeout bounds the analyzer. Zero disables the bound.
	Timeout time.Duration
}

DeadcodeOptions configures one reachability run.

type DeadcodeReport added in v0.137.0

type DeadcodeReport struct {
	// Platforms lists the GOOS values analysed; Findings, New and Fixed refer
	// to functions unreachable on all of them. Empty when one unscoped run was
	// made with an explicit analyzer.
	Platforms []string `yaml:"platforms,omitempty" json:"platforms,omitempty"`
	// Findings is every unreachable function found, baselined or not.
	Findings []DeadcodeFinding `yaml:"findings" json:"findings"`
	// New is the gate: findings absent from the baseline. Non-empty fails.
	New []DeadcodeFinding `yaml:"new,omitempty" json:"new,omitempty"`
	// Fixed lists baseline entries that are now reachable or gone. They never
	// fail the gate; they are what the baseline should shed.
	Fixed []string `yaml:"fixed,omitempty" json:"fixed,omitempty"`
	// BaselinePath is the file consulted, empty when none was configured.
	BaselinePath string `yaml:"baseline_path,omitempty" json:"baseline_path,omitempty"`
	// BaselineMissing distinguishes "no baseline file yet" from "empty
	// baseline". The first is a repository that has not adopted the gate; the
	// second is a repository that has adopted it and is clean.
	BaselineMissing bool `yaml:"baseline_missing,omitempty" json:"baseline_missing,omitempty"`
}

DeadcodeReport is the verdict of one run.

func Deadcode added in v0.137.0

func Deadcode(ctx context.Context, repositoryPath string, options DeadcodeOptions) (DeadcodeReport, error)

Deadcode runs the reachability analysis in repositoryPath and compares it against the configured baseline.

type ExecSiteMatch added in v0.172.0

type ExecSiteMatch struct {
	File    string
	Line    int
	Pattern ExecSitePattern
	Detail  string
}

ExecSiteMatch is one occurrence FindExecSiteMatches reports.

func FindExecSiteMatches added in v0.172.0

func FindExecSiteMatches(root string) ([]ExecSiteMatch, error)

FindExecSiteMatches walks root and reports every occurrence, in every non-test `.go` file outside execSiteAllowedDirs, of a pattern task-8's check bans. Results are sorted by file, then line.

func (ExecSiteMatch) String added in v0.172.0

func (m ExecSiteMatch) String() string

type ExecSitePattern added in v0.172.0

type ExecSitePattern string

ExecSitePattern names one direct-process escape shape execSites' detector counts.

const (
	// ExecSitePatternDirectExec is a direct exec.Command, exec.CommandContext,
	// os.StartProcess or syscall.Exec call.
	ExecSitePatternDirectExec ExecSitePattern = "direct-exec"
	// ExecSitePatternGitLiteral is a literal "git" argv[0] passed to
	// exec.Command, exec.CommandContext, process.CommandContext or
	// process.CommandContextInteractive.
	ExecSitePatternGitLiteral ExecSitePattern = "git-literal"
	// ExecSitePatternGitHelper is a call to one of ExecSiteGitHelperNames.
	ExecSitePatternGitHelper ExecSitePattern = "git-helper-call"
)

type FileLineOffsets added in v0.164.0

type FileLineOffsets struct {
	// contains filtered or unexported fields
}

FileLineOffsets maps one file's merge-base (old) line numbers to its current (new) line numbers, built from that file's own unified-diff hunks. EvaluateRatchet uses it (review-696 non-blocking #3) to find the current position of a baseline-recorded statement whose file was edited elsewhere, instead of treating every uncovered block in a touched file as unattributable.

func (FileLineOffsets) Added

func (offsets FileLineOffsets) Added(line int) bool

Added reports whether the diff added line to the file, counting lines git would colour as moved. GitChangedLines deliberately leaves moved lines out (the moved-code rule), which is right for "must this statement be covered" and wrong for "did this change leave this statement alone": text that matches a removed line elsewhere is still a statement this change put here.

func (FileLineOffsets) Map added in v0.164.0

func (offsets FileLineOffsets) Map(oldLine int) (newLine int, ok bool)

Map translates a merge-base line to its current line. ok is false when oldLine falls inside a hunk's old range: the diff itself touched that exact line, so there is no single current line to point to for it — the direct changed-line rule (GitChangedLines) already covers whatever replaced it.

type InlineWriteSequenceViolation added in v0.165.0

type InlineWriteSequenceViolation struct {
	// File is the path relative to root, slash-separated.
	File string
	// Func is the offending function's name, or "ReceiverType.Name" for a
	// method.
	Func string
	// Line is the function declaration's line number, for a human
	// reading the failure to jump straight to it.
	Line int
}

InlineWriteSequenceViolation names one function outside internal/filewrite whose body directly calls a publish or create primitive spec/plans/coverage-to-100 task-9 consolidates into internal/filewrite, and is not exempted by either allow-list passed to FindInlineWriteSequences.

func FindInlineWriteSequences added in v0.165.0

func FindInlineWriteSequences(root string, pendingMigration, notAFileWritePublish map[string]string) ([]InlineWriteSequenceViolation, error)

FindInlineWriteSequences walks root (a module root, typically ParallelGuardModuleRoot's result) and reports every non-test Go function outside internal/filewrite and internal/unixcompat whose body directly calls a publish primitive (os.Rename, os.Link, syscall.Rename, syscall.Renameat, syscall.Link, the fd-relative unix.Rename/Renameat/ Renameat2/RenameatxNp/Link/Linkat family, the repo-local renameNoReplace helper, or a package-level alias of os.Link/os.Rename), a create primitive banned unconditionally (os.CreateTemp, ioutil.TempFile, os.Create), a create primitive banned only alongside a content write (os.OpenFile or unix.Openat carrying an O_CREAT-family flag), or os.WriteFile together with one of the publish primitives above in the same function -- skipping any file:func listed in pendingMigration or notAFileWritePublish. Callers pass PendingMigrationExemptions and NotAFileWritePublishExemptions for the real guard; a test may pass its own maps (or nil) to exercise the detector without touching package state, which keeps every test in this file parallel-safe.

func (InlineWriteSequenceViolation) String added in v0.165.0

type ModuleCoverage

type ModuleCoverage struct {
	Path       string  `yaml:"path" json:"path"`
	Statements int     `yaml:"statements" json:"statements"`
	Covered    int     `yaml:"covered" json:"covered"`
	Percentage float64 `yaml:"percentage" json:"percentage"`
	Attempts   int     `yaml:"attempts,omitempty" json:"attempts,omitempty"`
}

ModuleCoverage records the statement totals from one Go module's generated coverage profile.

type ModuleCoverageSummary added in v0.171.0

type ModuleCoverageSummary struct {
	Path       string  `json:"path"`
	Statements int     `json:"statements"`
	Covered    int     `json:"covered"`
	Percentage float64 `json:"percentage"`
}

ModuleCoverageSummary records statements and coverage for a single Go module.

type PackageBaseline added in v0.164.0

type PackageBaseline struct {
	SchemaVersion   int                         `json:"schema_version"`
	SHA             string                      `json:"sha,omitempty"`
	IncludeE2E      bool                        `json:"include_e2e,omitempty"`
	Packages        map[string]int              `json:"packages"`
	UncoveredBlocks map[string][]UncoveredBlock `json:"uncovered_blocks,omitempty"`
	// RedBase is set when ComputeBaselineAtRef measured a ref whose own
	// tests were failing; see RedBaseline for what that does to the counts.
	RedBase *RedBaseline `json:"red_base,omitempty"`
}

PackageBaseline is the per-package uncovered-statement baseline the ratchet compares against. It has no committed file of its own: go-ci's coverage job publishes it as a build artifact on every push to the default branch (spec/plans/coverage-to-100/README.md task-3(b)). Packages holds each package's uncovered statement count for the rise check; UncoveredBlocks holds the exact uncovered statement ranges behind that count, so a rise can be attributed to specific newly-uncovered statements instead of only reported as a number.

func BaselineFromProfile added in v0.164.0

func BaselineFromProfile(blocks []CoverageBlock, modulePath, sha string) PackageBaseline

BaselineFromProfile builds a PackageBaseline from a measured coverage profile, for publishing as the baseline artifact.

func ComputeBaselineAtRef added in v0.164.0

func ComputeBaselineAtRef(ctx context.Context, repoRoot, ref string, timeout time.Duration, options RunOptions) (PackageBaseline, error)

ComputeBaselineAtRef checks out ref into a throwaway git worktree and measures its per-package uncovered-statement counts, for the fallback path when no published baseline artifact exists yet (spec/plans/coverage-to-100/README.md task-3(b)). It is bounded by timeout so a missing artifact cannot make every PR pay for an open-ended run. options carries the same Retry/CoverageDiagnosticsDir a normal `wb coverage` run uses; RepositoryRunOptions is applied to the checked-out worktree so the merge base is measured through the identical .wb/quality.yaml-aware sharded, retried CoverWithOptions runner the head measurement uses (review item 5/non-blocking #1), not a bare `go test`.

A ref whose tests fail is still measured, because a base that is red can only be repaired through a pull request this ratchet has to judge: the profile every failing test binary still wrote is used, and the returned baseline names the failed tests in RedBase. Everything else stays fail closed with the same errors as before: a build or setup failure, a test binary that died before writing coverage, a timeout and a missing or unreadable profile. No package is ever given a baseline it was not measured for, so a package absent from the profile is judged by EvaluateRatchet's existing strictest rule (a changed package counts from 0).

func LoadBaseline added in v0.164.0

func LoadBaseline(path string) (PackageBaseline, error)

LoadBaseline reads a PackageBaseline written by WriteBaseline. A missing file is reported as os.ErrNotExist so callers can distinguish "no baseline available yet" from a malformed one.

type PackageRatchet added in v0.164.0

type PackageRatchet struct {
	Package               string
	Uncovered             int
	BaselineUncovered     int
	HasBaseline           bool
	Rose                  bool
	Changed               bool // true when the PR itself touches a file (including _test.go) in this package
	NewlyUncoveredChanged []RatchetFinding
	Pass                  bool
	// Tolerance and Tolerated are set only when the package passed because
	// of its configured RatchetTolerance: Tolerance is the configured
	// statement allowance and Tolerated the statements it let through.
	Tolerance int                  `yaml:"tolerance,omitempty" json:"tolerance,omitempty"`
	Tolerated []ToleratedStatement `yaml:"tolerated,omitempty" json:"tolerated,omitempty"`
}

PackageRatchet is one package's ratchet verdict.

type PackageSummary added in v0.171.0

type PackageSummary struct {
	Statements int     `json:"statements"`
	Covered    int     `json:"covered"`
	Percentage float64 `json:"percentage"`
}

PackageSummary records statements and coverage for a single Go package.

type ParallelBaselineEntry added in v0.164.8

type ParallelBaselineEntry struct {
	Key    string
	Reason string
}

ParallelBaselineEntry is one committed line: a serial test or subtest, keyed by package directory + test name + subtest path (never by file:line, which shifts on every unrelated edit), with a mandatory reason.

func ScanSerialTests added in v0.164.8

func ScanSerialTests(root string) (serial []ParallelBaselineEntry, bareNolint []string, err error)

ScanSerialTests walks every _test.go file under root (skipping ParallelGuardExcludedDirs) and returns one entry per serial Test function or t.Run subtest, at any nesting depth, with an automatically classified reason. It also returns the set of nolint-without-a-reason sites, which the guard treats as offenders in their own right (S2/B2: a bare `//nolint:paralleltest` is no longer accepted).

type Progress added in v0.50.0

type Progress struct {
	Repository string
	Language   string
	Module     string
	Check      Check
	Command    string
	Detail     string
	State      ProgressState
	Status     Status
	Attempts   int
	Completed  int
	Total      int
}

Progress describes one external check or a completed repository. Repository is filled by the fleet runner, which owns cross-repository scheduling.

type ProgressState added in v0.50.0

type ProgressState string

ProgressState identifies a visible quality-work transition.

const (
	ProgressStarted             ProgressState = "started"
	ProgressRetrying            ProgressState = "retrying"
	ProgressCompleted           ProgressState = "completed"
	ProgressRepositoryCompleted ProgressState = "repository_completed"
)

type RatchetFinding added in v0.164.0

type RatchetFinding struct {
	File   string
	Line   int
	Reason string
}

RatchetFinding names one newly uncovered statement that fails the ratchet.

type RatchetTolerance

type RatchetTolerance struct {
	// Statements is how many untouched statements may be newly uncovered
	// against the merge base before the package fails.
	Statements int
	// Reason is the configured justification, repeated in every warning and
	// report entry that uses the tolerance.
	Reason string
	// Functions are the only declarations a tolerated statement may be in.
	Functions []ToleratedFunction
}

RatchetTolerance is one package's explicitly configured allowance for statements that are covered or not depending on timing.

type RatchetTolerances

type RatchetTolerances map[string]RatchetTolerance

RatchetTolerances maps a package directory relative to the module root (the spelling PackageOf returns, for example "internal/orchestrate") to its tolerance. A package without an entry is held to the strict ratchet.

func LoadRatchetTolerances

func LoadRatchetTolerances(root string) (RatchetTolerances, error)

LoadRatchetTolerances reads root's .wb/coverage-ratchet.yaml. root must be the checkout being judged (the pull request's head), never the merge-base checkout: the tolerance is policy of the change under review, and its functions are resolved against the source being measured. A missing file means no tolerance. Anything malformed fails closed: more than MaxRatchetToleranceEntries entries; a package that is not a clean, module-relative directory spelled exactly as on disk, or is repeated; a statement count that is not a plain decimal integer from 1 to MaxRatchetToleranceStatements; no reason; and a functions list that is empty, longer than MaxRatchetToleranceFunctions, repeats itself, or names a function the head checkout does not declare.

type RatchetWarning added in v0.164.0

type RatchetWarning struct {
	Package string `json:"package"`
	File    string `json:"file"`
	Line    int    `json:"line"`
	Reason  string `json:"reason"`
}

RatchetWarning names one newly uncovered statement in a package the PR did not itself change (review B1, founder decision 2026-09-23: "only packages the PR changes" are hard-gated on their uncovered count; every other package's count rise is reported, never failed on).

type RedBaseline

type RedBaseline struct {
	SHA         string   `yaml:"sha" json:"sha"`
	FailedTests []string `yaml:"failed_tests" json:"failed_tests"`
}

RedBaseline records that a per-change ratchet measured its merge base while tests were failing there. A baseline that carries it is usable, but its counts are an upper bound: a statement only a failed test reaches may be recorded as uncovered, so the count-rise rule is looser by that margin for the packages named in FailedTests. The changed-statement rule is unaffected.

type RepositoryCoverage

type RepositoryCoverage struct {
	Repository string              `yaml:"repository" json:"repository"`
	Path       string              `yaml:"path" json:"path"`
	Status     Status              `yaml:"status" json:"status"`
	Modules    []ModuleCoverage    `yaml:"modules,omitempty" json:"modules,omitempty"`
	Statements int                 `yaml:"statements" json:"statements"`
	Covered    int                 `yaml:"covered" json:"covered"`
	Percentage float64             `yaml:"percentage" json:"percentage"`
	Error      string              `yaml:"error,omitempty" json:"error,omitempty"`
	Diagnostic *CoverageDiagnostic `yaml:"diagnostic,omitempty" json:"diagnostic,omitempty"`
}

RepositoryCoverage records aggregate Go coverage for one repository.

func CoverWithOptions

func CoverWithOptions(ctx context.Context, repository, path string, options RunOptions) RepositoryCoverage

CoverWithOptions measures coverage with a deadline and retries for each Go module's test command.

type RunOptions

type RunOptions struct {
	Timeout time.Duration
	Retry   int
	// CheckTimeout bounds one logical verification check, including all of its
	// command attempts and any process-isolated Go shards. Zero leaves the
	// existing per-command Timeout behavior unchanged.
	CheckTimeout time.Duration
	// ShardAttemptTimeout bounds one process-isolated Go test shard attempt.
	// Zero retains Timeout as the shard-attempt bound when Timeout is set.
	ShardAttemptTimeout time.Duration
	// GoTestShards runs each explicitly named Go package in this many
	// process-isolated shards. It is opt-in because TestMain and process-global
	// fixtures run once per shard; callers must name packages whose contract
	// permits that isolation. Discovery invokes TestMain once before each shard
	// process invokes it again.
	GoTestShards int
	// GoShardPackages are module-relative package patterns such as
	// ./internal/worktrees. Selected packages not named here still run exactly once.
	GoShardPackages []string
	// GoTestPackages limits coverage to these module-relative Go package
	// patterns. An empty slice retains the default whole-module ./... scope.
	GoTestPackages []string
	// ExplicitGoTestSharding records that the caller selected GoTestShards and
	// GoShardPackages on the command line. Repository policy remains validated
	// and supplies lint commands, but cannot silently broaden this selection.
	ExplicitGoTestSharding bool
	// GoLintCommands replaces the default `go vet ./...` lint step with the
	// repository-owned argv sequences from .wb/quality.yaml. Structured argv
	// keeps exact tool pins reproducible without invoking a shell.
	GoLintCommands [][]string
	// PriorNodeInstallReport permits a later phase over the same repository
	// path to reuse only successful locked Node installs from an earlier phase.
	// A missing or failed install still runs before the later checks.
	PriorNodeInstallReport *VerificationReport
	// CoverageProfile retains the exact merged Go profile for one module.
	// Fleet and multi-module adapters reject it rather than inventing names.
	CoverageProfile string
	// IncludeE2E merges a separately measured native tier into default coverage.
	IncludeE2E bool

	// CoverageDiagnosticsDir retains raw output from failed process-isolated
	// coverage jobs beside the durable coverage report. The human-facing error
	// remains bounded; this private artifact is the lossless recovery path.
	CoverageDiagnosticsDir string
	// CoverageDiagnosticsRepository identifies the owning repository in the
	// private manifest when a fleet runner executes several repositories.
	CoverageDiagnosticsRepository string
	// SingleWorker constrains every check to one worker, so a verification
	// run cannot exceed the workstation's concurrency cap on its own. Go tests
	// gain `-p 1` and never `-race`; package-script Node runs gain
	// `--parallel=1` and `--maxWorkers=1`, while mixed Nx target runs gain
	// only Nx's executor-neutral `--parallel=1`. The Nx daemon and cache are
	// disabled in either case.
	//
	// Serialization is deliberately *not* a substitute for per-file
	// isolation: nothing here relaxes an isolation flag, because a serialized
	// leak is worse than a flake — it is reproducible and misattributed.
	SingleWorker bool
	// Env is appended to each check's environment as KEY=VALUE entries. It is
	// how a caller states the environment a run must carry (GOWORK=off,
	// NX_DAEMON=false) rather than leaving it to the shell that invoked wb.
	Env []string
	// Progress receives lifecycle events for external checks. Callers may use it
	// for terminal diagnostics; reports remain the authoritative output.
	Progress func(Progress)
	// contains filtered or unexported fields
}

RunOptions bounds a single external command and retries only failed attempts. Zero Timeout disables the per-command deadline.

func RepositoryRunOptions added in v0.67.1

func RepositoryRunOptions(root string, base RunOptions) (RunOptions, error)

RepositoryRunOptions applies an explicit repository-owned quality policy to one validation run. Absence is the portable default; malformed or ambiguous policy fails closed rather than silently falling back to a slower or weaker command.

func SelectedCoverageOptions

func SelectedCoverageOptions(options RunOptions, patterns []string) RunOptions

SelectedCoverageOptions keeps repository shard policy within a selected set. The policy is loaded and validated before this operation.

type Status

type Status string

Status is the outcome of a repository or a discrete verification command.

const (
	StatusPassed  Status = "passed"
	StatusFailed  Status = "failed"
	StatusSkipped Status = "skipped"
)

type ToleratedFunction

type ToleratedFunction struct {
	// File is the repository-relative path of the file declaring it.
	File string
	// Name is the declared name, "Func" or "Type.Method".
	Name string
	// StartLine and EndLine bound the declaration in the head file.
	StartLine, EndLine int
}

ToleratedFunction is one function or method a tolerance entry names, resolved against the head checkout's source.

type ToleratedStatement

type ToleratedStatement struct {
	File     string `yaml:"file" json:"file"`
	Line     int    `yaml:"line" json:"line"`
	Function string `yaml:"function" json:"function"`
	Reason   string `yaml:"reason" json:"reason"`
}

ToleratedStatement names one statement EvaluateRatchet let through under a package's RatchetTolerance.

type UncoveredBlock added in v0.164.0

type UncoveredBlock struct {
	File      string `json:"file"`
	StartLine int    `json:"start_line"`
	StartCol  int    `json:"start_col"`
	EndLine   int    `json:"end_line"`
	EndCol    int    `json:"end_col"`
}

UncoveredBlock names one uncovered statement range in the baseline, keyed the same way a Go coverage profile line names it, so a later EvaluateRatchet run can tell which of a package's currently-uncovered blocks are new against the baseline and which already existed there (spec/plans/coverage-to-100/README.md task-3, review item B2: a count-only failure must still name file:line).

type UnitTierMatch added in v0.170.0

type UnitTierMatch struct {
	// File is the path relative to root, slash-separated.
	File string
	// Line is the match's line number.
	Line int
	// Pattern names which shape matched.
	Pattern UnitTierPattern
	// Detail is a short human-readable identifier for the match (the
	// selector or identifier name), for a diagnostic message.
	Detail string
	// SelfReexec is set only for UnitTierPatternExecStart: it reports
	// whether the program argument (the exec.Command/os.StartProcess
	// argument that names the executable to run) is exactly the expression
	// os.Args[0] -- Go's own helper-process pattern, re-running the test
	// binary itself, rather than a real external program such as git.
	// TestUnitTierAllowListEntriesAreGenuineHelperProcessReexec (review
	// note #764 B1) requires this on every exec-start match in an
	// allow-listed file.
	SelfReexec bool
}

UnitTierMatch is one occurrence of a banned pattern in one default-tier test file.

func FindUnitTierMatches added in v0.170.0

func FindUnitTierMatches(root string) ([]UnitTierMatch, error)

FindUnitTierMatches walks root and reports every occurrence, in every default-tier _test.go file (one whose own build constraint does not require the e2e tag), of a pattern task-24's unit tier bans. Results are sorted by file, then line.

func (UnitTierMatch) String added in v0.170.0

func (m UnitTierMatch) String() string

type UnitTierPattern added in v0.170.0

type UnitTierPattern string

UnitTierPattern names one process/real-git escape shape the unit-tier detector counts.

const (
	// UnitTierPatternExecStart is a direct exec.Command, exec.CommandContext
	// or os.StartProcess call.
	UnitTierPatternExecStart UnitTierPattern = "exec-start"
	// UnitTierPatternWriteExecutable is a call to
	// testenv.WriteExecutableFile, which writes a fake executable a test
	// then runs on PATH.
	UnitTierPatternWriteExecutable UnitTierPattern = "write-executable-file"
	// UnitTierPatternSetenvPath is t.Setenv("PATH", ...): the shape that
	// installs a fake executable on PATH for a subprocess to find.
	UnitTierPatternSetenvPath UnitTierPattern = "setenv-path"
	// UnitTierPatternAllowRealProcess is a call to
	// runnertest.AllowRealProcess, task-8's own escape hatch for a unit test
	// that must start a real process. Only a file on the pending list or
	// the allow list may call it (task-24's Runtime guard section).
	UnitTierPatternAllowRealProcess UnitTierPattern = "allow-real-process"
	// UnitTierPatternGitHelper is an unqualified call to one of
	// UnitTierGitHelperNames: a same-package helper (production or
	// test-local) that shells out to the real git executable itself, so a
	// test file that only calls it carries no exec.Command literal of its
	// own for this detector to see directly.
	UnitTierPatternGitHelper UnitTierPattern = "git-helper-call"
	// UnitTierPatternHelperProcessEnv is a string literal naming the
	// helper-process re-exec environment variable (GO_WANT_HELPER_PROCESS
	// or this repository's GO_WANT_HELPER_PROCESS_OBSERVE variant). It is
	// how the re-exec pattern's own child process finds out it should run
	// as the helper rather than the ordinary test suite, so it is expected,
	// alongside a genuine self-reexec exec-start match, in a file on
	// unit_tier.allow -- TestUnitTierAllowListEntriesAreGenuineHelperProcessReexec
	// permits it there. Outside the allow list it is unreviewed (review
	// note #764 N1/N2) and stays subject to the ordinary pending-count rule
	// like any other match.
	UnitTierPatternHelperProcessEnv UnitTierPattern = "helper-process-env"
)

type UnitTierPendingEntry added in v0.170.0

type UnitTierPendingEntry struct {
	File  string
	Count int
	Owner string
}

UnitTierPendingEntry is one committed line of unit_tier.pending: a default-tier test file that still trips the unit-tier detector, its exact match count as of the commit that added or last updated the entry, and the task that owns converting, moving, or deleting it.

type ValidationCacheKey added in v0.98.3

type ValidationCacheKey struct {
	Repository       string   `json:"repository"`
	TargetRevision   string   `json:"target_revision"`
	Checks           []Check  `json:"checks"`
	QualityConfigSHA string   `json:"quality_config_sha"`
	WBRevision       string   `json:"wb_revision"`
	GoToolchain      string   `json:"go_toolchain"`
	ModuleFiles      []string `json:"module_files"`
	// ValidatorSHAs binds cached evidence to the executable bytes that produced
	// it. In particular, SpecScore's rules can change between installed
	// versions while the repository and WB revision remain identical.
	ValidatorSHAs       map[string]string `json:"validator_shas,omitempty"`
	Timeout             time.Duration     `json:"timeout"`
	Retry               int               `json:"retry"`
	CheckTimeout        time.Duration     `json:"check_timeout"`
	ShardAttemptTimeout time.Duration     `json:"shard_attempt_timeout"`
}

ValidationCacheKey identifies the exact inputs that make a verification report reusable. Checks remain ordered because the order is part of the command contract and can affect the resulting evidence.

func NewValidationCacheKey added in v0.98.3

func NewValidationCacheKey(repository, targetRevision, root, wbRevision string, checks []Check, validatorSHAs map[string]string, options RunOptions) (ValidationCacheKey, error)

NewValidationCacheKey fingerprints repository-local policy, module manifests, and the executable digests used by external validators. The caller supplies the exact target revision, WB revision, and effective command limits, and passes nil validatorSHAs when no external validator participates.

One constructor rather than two: the original signature was kept alongside a WithValidators variant that delegated to it, and `wb deadcode` immediately reported the original as unreachable once the only caller moved. A dead wrapper beside a live near-identical function is a reliable way to have the wrong one called later.

type VerificationEntry

type VerificationEntry struct {
	Language string `yaml:"language" json:"language"`
	Module   string `yaml:"module,omitempty" json:"module,omitempty"`
	Check    Check  `yaml:"check" json:"check"`
	Command  string `yaml:"command,omitempty" json:"command,omitempty"`
	Status   Status `yaml:"status" json:"status"`
	Detail   string `yaml:"detail,omitempty" json:"detail,omitempty"`
	// Deadcode retains complete machine-comparable findings separately from
	// the bounded human diagnostic. A non-nil incomplete value fails closed.
	Deadcode *DeadcodeFailureEvidence `yaml:"deadcode,omitempty" json:"deadcode,omitempty"`
	Attempts int                      `yaml:"attempts,omitempty" json:"attempts,omitempty"`
}

VerificationEntry is one command WB attempted or intentionally skipped.

type VerificationReport

type VerificationReport struct {
	Repository string `yaml:"repository" json:"repository"`
	Path       string `yaml:"path" json:"path"`
	// Revision and WorkspaceClean are populated by the WB command adapter
	// around the complete verification run. They let a downstream receipt bind
	// successful mechanisms to the exact clean Git tree they exercised.
	Revision       string              `yaml:"revision,omitempty" json:"revision,omitempty"`
	WorkspaceClean bool                `yaml:"workspace_clean,omitempty" json:"workspace_clean,omitempty"`
	Status         Status              `yaml:"status" json:"status"`
	Results        []VerificationEntry `yaml:"results" json:"results"`
}

VerificationReport records all conventional checks applicable to a repository. Unsupported stacks and missing optional Node scripts are skipped rather than treated as failures.

func LoadValidationCache added in v0.98.3

func LoadValidationCache(cacheRoot string, key ValidationCacheKey) (VerificationReport, bool, error)

LoadValidationCache returns only an intact terminal report with an exact key. Any malformed, stale, or otherwise incomplete record is a cache miss.

func VerifyWithOptions

func VerifyWithOptions(ctx context.Context, repository, path string, checks []Check, options RunOptions) VerificationReport

VerifyWithOptions runs the requested checks with per-command reliability controls. The returned report includes every attempted, skipped, passed, or failed command.

type Worklist added in v0.172.0

type Worklist struct {
	UnitSize                 int            `json:"unit_size"`
	TotalUncoveredStatements int            `json:"total_uncovered_statements"`
	Units                    []WorklistUnit `json:"units"`
}

Worklist is the deterministic grouping BuildWorklist produces from one coverage profile.

func BuildWorklist added in v0.172.0

func BuildWorklist(blocks []CoverageBlock, modulePath, moduleRoot string, unitSize int) (Worklist, error)

BuildWorklist reads every uncovered block in blocks (Count == 0), maps each one to its enclosing top-level function by parsing the module source under moduleRoot with go/ast, and groups them into units of about unitSize statements: a function's blocks are never split across units, and consecutive functions from the same file stay in the same unit while the running total allows it. The result is deterministic for a given profile and module tree: same input, same units, same order, every uncovered block in exactly one unit.

type WorklistBlock added in v0.172.0

type WorklistBlock struct {
	File       string `json:"file"`
	StartLine  int    `json:"start_line"`
	StartCol   int    `json:"start_col"`
	EndLine    int    `json:"end_line"`
	EndCol     int    `json:"end_col"`
	Statements int    `json:"statements"`
	Function   string `json:"function"`
}

WorklistBlock is one uncovered statement range from a coverage profile, attributed to its enclosing top-level function declaration. Function is empty when no top-level func/method declaration in the file contains the block (for example a package-level var initializer that calls a function): the block still gets its own singleton group, keyed by file.

type WorklistUnit added in v0.172.0

type WorklistUnit struct {
	Index          int             `json:"index"`
	Statements     int             `json:"statements"`
	Files          []string        `json:"files"`
	Blocks         []WorklistBlock `json:"blocks"`
	SharesFileWith []int           `json:"shares_file_with,omitempty"`
}

WorklistUnit is one group of uncovered blocks, sized to about the unitSize BuildWorklist was called with, that keeps whole functions (and, where the running total allows it, whole files) together. SharesFileWith names every other unit that also holds a block from one of Files, sorted and deduplicated, so the coordinator never schedules two lanes that would edit the same file at the same time.

Directories

Path Synopsis
cmd
parallelbaseline command
Command parallelbaseline is the single source of truth for internal/quality/testdata/paralleltest_baseline.txt.
Command parallelbaseline is the single source of truth for internal/quality/testdata/paralleltest_baseline.txt.

Jump to

Keyboard shortcuts

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