staticcheck

package
v0.0.0-...-c9e24ca Latest Latest
Warning

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

Go to latest
Published: Jun 29, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package staticcheck holds the build-time, analyzer-enforced members of the design-invariant framework. Its first (and currently only) member is the single-writer-state analyzer: the static-analysis form of CLAUDE.md's "State mutation is single-writer" rule.

The runtime invariants framework (internal/invariants) cannot catch the single-writer rule — its violation shape is "an unlocked write to d.state", which manifests only as a data race, not as state divergence observable at snapshot time. So instead of a Check that walks a State snapshot, this package ships a golang.org/x/tools/go/analysis.Analyzer that walks internal/daemon at build time and asserts every direct assignment to a field of d.state lives under a d.stateMu write-lock.

The analyzer is invoked two ways:

  • As an explicit gate in scripts/pre-push-gates.sh via the cmd/singlewriterstate standalone binary (singlechecker), so a diagnostic fails the push gate on every cycle.
  • Through analysistest in single_writer_test.go against the fixtures under testdata/src/.

A thin Invariant-compatible shim (singleWriterStateInvariant) self- registers into internal/invariants' STATIC registry at init so the coverage gate can enumerate "single-writer-state" alongside the runtime invariants without the runtime sweep ever calling its no-op Check.

Index

Constants

This section is empty.

Variables

View Source
var Analyzer = &analysis.Analyzer{
	Name: "singlewriterstate",
	Doc: "single-writer-state: every direct assignment to a field of d.state must be " +
		"preceded by a d.stateMu.Lock() in the enclosing scope (or d.stateMu.RLock() " +
		"inside Snapshot). Matches the canonical <x>.state.<Field> LHS only; indirect " +
		"writes through a pointer alias and writes routed through a helper are known " +
		"false-negatives. Suppress with a '// invariants:single-writer-state ok' comment " +
		"on the offending line or the line above; each suppression must be reviewed in " +
		"its introducing PR (phase doc § 7 R-6), and documenting the rationale in a " +
		"same-line trailing comment after the marker is a soft expectation (tolerated, " +
		"not parse-enforced).",
	Run: run,
}

Analyzer is the singlewriterstate static analyzer. It reports a diagnostic for every direct assignment to a field of d.state that is not preceded — in the assignment's enclosing function or a lexically- containing scope — by a d.stateMu.Lock() (write-lock) call, or, only inside a method named Snapshot, by a d.stateMu.RLock() call.

Scope and known false-negatives (the conservative first cut described in the issue Notes): the analyzer matches ONLY the canonical LHS shape <x>.state.<Field> — a selector whose middle component is a field named "state" whose type is a named type called "State" (the type guard keeps d.state (*store.State) in scope while excluding look-alikes like a Poller's p.state (*pollerState) guarded by a different mutex). It deliberately does NOT chase:

  • Indirect writes through a pointer alias: `s := &d.state; s.X = 1` (LHS `s.X` does not name `state`), nor `(*State).Field` writes on a receiver bound to the State value directly.
  • Map / slice element writes: `d.state.Issues[k] = v` (LHS is an IndexExpr, not a whole-field replacement) — those mutate through an already-allocated header and are a different, lower-risk shape.
  • Writes routed through a helper function that the locked caller invokes (no inter-procedural lock tracking).

False-negatives are the dangerous failure mode (an unlocked write that escapes detection), so the matcher errs toward the common, highest- signal case and documents the gaps here rather than reporting on shapes it cannot reason about soundly. A follow-on issue can widen coverage.

Test files (*_test.go) are skipped: test setup legitimately seeds d.state directly without locks (no concurrency at setup time), so gating them would be all false positives.

Suppression: a "// invariants:single-writer-state ok" comment on the offending line or the line immediately above suppresses the diagnostic. Each suppression is expected to carry a trailing rationale and to be reviewed in its introducing PR (phase doc § 7 R-6).

View Source
var BareCloneMutationHygieneAnalyzer = &analysis.Analyzer{
	Name: "barecloneMutationhygiene",
	Doc: "bare-clone-mutation-hygiene: MergeDefaultIntoPlanBranch / " +
		"SquashChildIntoPlanBranch MUST clear any stale bare-clone config.lock before mutating " +
		"the bare clone. The analyzer asserts each target function reaches clearStaleBareCloneLocks " +
		"through either a direct call or the acquirePlanBranchMutationAndCleanLocks shim. A target " +
		"function reaching it through neither returns a diagnostic at the function declaration.",
	Run: runBareCloneMutationHygiene,
}

BareCloneMutationHygieneAnalyzer is the singleton static analyzer for the bare-clone-mutation-hygiene design rule. It walks each top-level function declaration in internal/github/; when the function name is in bareCloneMutationHygieneTargetFunctions and the function body reaches clearStaleBareCloneLocks through NEITHER a direct call NOR the acquirePlanBranchMutationAndCleanLocks wrapper, the analyzer reports a diagnostic at the function declaration's position.

View Source
var ClassifierSourcedRoutingAnalyzer = &analysis.Analyzer{
	Name: "classifiersourcedrouting",
	Doc: "classifier-sourced-routing: the three PER-FILE / PER-REQUIREMENT consumers of language routing " +
		"(generateTraceabilityMatrix; RunForRequirement on structuralRequirementExecutor; Run on " +
		"PropTestStubVerifier) MUST source their language from the per-file classifier " +
		"(config.LanguageForPath) and the embedded language profiles, never a single project-wide " +
		"ProjectLanguage read. The analyzer reports a .ProjectLanguage selector read inside any of the " +
		"three named consumers' bodies. The shared verifierLanguageProfile (type/benchmark fall-through) " +
		"and the generatePropTestStubUnion stub-union generator are OUT of scope by not being named " +
		"consumers. Suppress a reviewed exception with a '// invariants:classifier-sourced-routing ok' " +
		"comment (plus a one-line rationale) on the offending line or the line above.",
	Run: runClassifierSourcedRouting,
}

ClassifierSourcedRoutingAnalyzer is the singleton static analyzer for the classifier-sourced-routing design rule. It walks each top-level function declaration in any in-scope file, and for the three named per-file consumers reports every `.ProjectLanguage` selector read in the function body unless suppressed.

View Source
var DeclaredDepsDispatchGateAnalyzer = &analysis.Analyzer{
	Name: "declareddepsdispatchgate",
	Doc: "declared-deps-dispatch-gate: the dispatch/readiness gates " +
		"allDepsSatisfied (internal/schedule/depgraph.go) and hasUnsatisfiedDep " +
		"(internal/daemon/supervisor_planning.go) MUST evaluate the DECLARED dependency set " +
		"only — DeclaredDependsOn(), never the union iss.DependsOn nor the reconciler-derived " +
		"iss.DerivedDependsOn. Reconciler-derived footprint edges are observability-only and " +
		"never gate dispatch; reading them re-tangles cross-plan derived edges into dispatch " +
		"ordering. Reachability / cycle-detection consumers (Graph.Build etc.) legitimately " +
		"read the union and are out of scope. Suppress with a " +
		"'// invariants:declared-deps-dispatch-gate ok' comment on the offending line or the " +
		"line above; each suppression must be reviewed in its introducing PR.",
	Run: runDeclaredDepsDispatchGate,
}

DeclaredDepsDispatchGateAnalyzer is the singleton static analyzer for the declared-deps-dispatch-gate design rule (spec R9). It walks each top-level function declaration in any non-test file; when a function in declaredDepsDispatchGateTargetFunctions reads a forbidden dependency-set field directly (iss.DependsOn / iss.DerivedDependsOn), the analyzer reports a diagnostic at the offending selector position.

View Source
var DiscoveryDefensiveHelperActivatedAnalyzer = &analysis.Analyzer{
	Name: "discoverydefensivehelperactivated",
	Doc: "discovery-defensive-helper-activated: the boot-recovery helper " +
		"MaybeRouteImplementingWithoutDiscovery MUST be called from at least one site in the " +
		"package that declares it (in production, internal/daemon). The analyzer walks the " +
		"non-test files of each package; if the package declares the helper but never calls it, " +
		"the defensive boot-recovery routing path is dead code and the analyzer reports a " +
		"package-level diagnostic naming the helper. A package that does not declare the helper " +
		"is out of scope.",
	Run: runDiscoveryDefensiveHelperActivated,
}

DiscoveryDefensiveHelperActivatedAnalyzer is the singleton static analyzer for the discovery-defensive-helper-activated design rule. For each analyzed package it asserts that, if the package declares MaybeRouteImplementingWithoutDiscovery in a non-test file, at least one non-test file in the same package calls it; otherwise it reports a package-level diagnostic naming the helper. A package that does not declare the helper is out of scope (no diagnostic).

View Source
var DispatchRoleNameCoverageAnalyzer = &analysis.Analyzer{
	Name: "dispatchrolenamecoverage",
	Doc: "dispatch-role-name-coverage: the supervisor's implementer-family and reviewer-family " +
		"(IssueState → role-name) dispatch maps MUST be exhaustive over the documented phased " +
		"states. The implementer-family map must contain discovering + implementing; the " +
		"reviewer-family map must contain review_discovering + review_judging. The legacy " +
		"in_review entry is NOT required (it falls back to the base \"reviewer\" role). A " +
		"missing entry is reported at the map literal's position; the failure it forecloses is " +
		"a future state-machine addition that forgets a dispatch-map entry and fails at runtime " +
		"instead of at build time.",
	Run: runDispatchRoleNameCoverage,
}

DispatchRoleNameCoverageAnalyzer is the static analyzer for the dispatch-role-name-coverage design rule. It walks each top-level `var` declaration; for every value that is a `map[sm.IssueState]string` composite literal whose var name classifies it into a role family, it asserts the literal contains every state key the family requires and reports a diagnostic at the literal's position naming each missing state.

View Source
var DispatchViaClaimChokepointAnalyzer = &analysis.Analyzer{
	Name: "dispatchviaclaimchokepoint",
	Doc: "dispatch-via-claim-chokepoint: every role-session open MUST route through the single " +
		"claimDispatch chokepoint (internal/daemon/claim_dispatch.go), so the durable sessions " +
		"ledger and the refractory predicate are consulted before openSession spawns. A direct " +
		"openSession call outside claimDispatch, anywhere under internal/daemon/, bypasses the " +
		"session-dedup guard and is flagged. Suppress with a " +
		"'// invariants:dispatch-via-claim-chokepoint ok' comment on the offending line or the " +
		"line above; each suppression must be reviewed in its introducing PR.",
	Run: runDispatchViaClaimChokepoint,
}

DispatchViaClaimChokepointAnalyzer is the singleton static analyzer for the dispatch-via-claim-chokepoint design rule. It walks each top-level function declaration in any in-scope file; for every function NOT named claimDispatch it reports a diagnostic at each openSession call — the shape of a reintroduced session open that bypasses the dispatch chokepoint.

View Source
var EpisodeIsolatedPlanBranchMutationAnalyzer = &analysis.Analyzer{
	Name: "episodeisolatedplanbranchmutation",
	Doc: "episode-isolated-plan-branch-mutation: a plan-branch mutation episode " +
		"(SquashChildIntoPlanBranch / cpbRunGateAndPush / cpbAcquireRecheckPush / " +
		"MergeDefaultIntoPlanBranch / ResetPlanBranchToMain) MUST stay on a detached HEAD and push an explicit " +
		"committed SHA. Flags (a) a `git checkout -B <planBranch>` call (literal args " +
		"contain both \"checkout\" and \"-B\") that cuts a shared local refs/heads/<planBranch> " +
		"ref, and (b) a symbolic `HEAD:refs/heads/...` push refspec that resolves through that " +
		"shared ref — reintroducing the SOR-2878 lost-update class. Suppress with a " +
		"'// invariants:episode-isolated-plan-branch-mutation ok' comment on the offending line " +
		"or the line above; each suppression must be reviewed in its introducing PR.",
	Run: runEpisodeIsolatedPlanBranchMutation,
}

EpisodeIsolatedPlanBranchMutationAnalyzer is the singleton static analyzer for the episode-isolated-plan-branch-mutation design rule. It walks each top-level function declaration whose name is in the target set and reports a diagnostic on (a) any `git checkout -B` call (a runGitIn-style call whose literal args include both "checkout" and "-B") and (b) any symbolic-HEAD push (a literal-string arg whose value begins with "HEAD:refs/heads/").

View Source
var FeedbackConcernPRPostChokepointAnalyzer = &analysis.Analyzer{
	Name: "feedbackconcernprpostchokepoint",
	Doc: "feedback-concern-pr-post-chokepoint: every daemon-side write of a refer-back concern to a PR MUST " +
		"route through the postReviewerConcerns chokepoint (which invokes the d.cfg.ReviewerConcernPoster " +
		"hook) — never a direct ReviewerConcernPoster invocation outside it. The chokepoint groups concerns " +
		"by resolved URL, diff-splits them, and audits the write in one place; any direct hook call elsewhere " +
		"re-opens the scattered-feedback-write failure class and prompt-engineers the post back outside the " +
		"deterministic poster. A nil-check (`if d.cfg.ReviewerConcernPoster == nil`) is a binary expression, " +
		"not a call, and is out of scope. Suppress a reviewed exception with a " +
		"'// invariants:feedback-concern-pr-post-chokepoint ok' comment on the offending line or the line above.",
	Run: runFeedbackConcernPRPostChokepoint,
}

FeedbackConcernPRPostChokepointAnalyzer is the singleton static analyzer for the feedback-concern-pr-post-chokepoint design rule. It walks every non-test file's top-level function declarations; for each function OTHER than postReviewerConcerns it reports every call whose Fun trailing identifier is ReviewerConcernPoster, unless the node carries a reviewed suppression comment.

View Source
var GateHarnessTimeoutAuthorityAnalyzer = &analysis.Analyzer{
	Name: "gateharnesstimeoutauthority",
	Doc: "gate-harness-timeout-authority: the gate's effective harness timeout on the Go gate " +
		"path MUST be sourced from the daemon resolver (github.ResolveGateHarnessTimeout, backed " +
		"by daemon config / the embedded language profile), never from a worktree CI file (a " +
		"`.github/workflows/`-shaped path, which only reaches a plan branch on main-merge and so " +
		"lags on propagation) nor from a hardcoded `-timeout=` flag injected outside the resolver. " +
		"The analyzer reports any call argument whose string literal carries \".github/workflows/\" " +
		"or has the \"-timeout=\" prefix. Suppress a reviewed non-timeout use (e.g. reading the CI " +
		"workflow for the preserved test selection) with a " +
		"'// invariants:gate-harness-timeout-authority ok' comment on the offending line or the " +
		"line above.",
	Run: runGateHarnessTimeoutAuthority,
}

GateHarnessTimeoutAuthorityAnalyzer is the singleton static analyzer for the gate-harness-timeout-authority design rule. It walks every non-test file in scope and reports each string-literal call argument (recursively, across format strings and concatenation) whose value carries a `.github/workflows/` CI-file path or a `-timeout=` flag, unless suppressed.

View Source
var GateRuntimeViaChokepointAnalyzer = &analysis.Analyzer{
	Name: "gateruntimeviachokepoint",
	Doc: "gate-runtime-via-chokepoint: gate subprocesses MUST be spawned through the configured " +
		"gate-runtime layer (gateruntime.GateRuntime.Command on the daemon side, github.GateRunner.Command " +
		"on the CIPB side), never via a direct host exec. A reintroduced direct exec.Command or " +
		"exec.CommandContext inside one of the gate-execution functions — PrePushGateVerifier.Run, " +
		"PropTestStubVerifier.Run, runToolOverPkgDirs, cpbRunGateAndPush, MergeDefaultIntoPlanBranch — " +
		"silently bypasses the runtime layer and is flagged. The sanctioned Command chokepoint methods are " +
		"skipped by name; utility spawns in non-enumerated functions are out of scope. Suppress with a " +
		"'// invariants:gate-runtime-via-chokepoint ok' comment on the offending line or the line above; " +
		"each suppression must be reviewed in its introducing PR.",
	Run: runGateRuntimeViaChokepoint,
}

GateRuntimeViaChokepointAnalyzer is the singleton static analyzer for the gate-runtime-via-chokepoint design rule. It walks each top-level function declaration in any in-scope file; for every gate-execution function NOT named Command it reports a diagnostic at each exec.Command / exec.CommandContext call — the shape of a reintroduced direct gate-script spawn.

View Source
var HarnessMutatorMainLoopAffinityAnalyzer = &analysis.Analyzer{
	Name: "harnessmutatormainloopaffinity",
	Doc: "harness-mutator-main-loop-affinity: a daemon test function MUST NOT call a main-loop-only " +
		"apply* state mutator (applyOperatorCreateIssue / applyIssueTransition / applyPlanTransition / " +
		"applyMutationAtomically / applyIssueTransitionsBatch / applyOperatorIssueTransition / " +
		"terminateSession / attachIssueSession / clearIssueSessionID) from the test goroutine while a " +
		"live daemon main loop is running. The single-writer invariant makes those chokepoints safe to " +
		"call only on d.Run's goroutine; a test that both starts a live daemon (runDaemon / a spawned " +
		"d.Run) and calls one of them races on d.state, which -race flags intermittently. The analyzer " +
		"is function-scoped and identifies test functions by their *testing.T parameter (not the " +
		"_test.go filename). Suppress a verified-safe co-occurrence with a " +
		"'// invariants:harness-mutator-main-loop-affinity ok' comment (plus a one-line rationale) on " +
		"the offending mutator-call line or the line above.",
	Run: runHarnessMutatorMainLoopAffinity,
}

HarnessMutatorMainLoopAffinityAnalyzer is the singleton static analyzer for the harness-mutator-main-loop-affinity design rule. It walks each top-level function declaration in any in-scope file; for every function identified as a test function (by its *testing.T parameter) whose body BOTH starts a live daemon AND calls a curated main-loop-only mutator, it reports a diagnostic at the mutator call.

View Source
var InFlightStatesPolicyCoverageAnalyzer = &analysis.Analyzer{
	Name: "inflightstatespolicycoverage",
	Doc: "in-flight-states-policy-coverage: a switch `case` clause MUST NOT hand-roll an " +
		"enumeration of sm.IssueState values whose set exactly matches a registered policy " +
		"predicate's domain; call the predicate instead. The seeded policies are " +
		"in-flight-for-pr-polling (sm.IsInFlightForPRPolling) over its 7-state domain and " +
		"in-flight-impl (sm.IsInFlightImplState) over its 7-state domain. A " +
		"case enumerating >=3 sm.IssueStateX selector constants whose set equals a policy " +
		"domain exactly is reported at the case position; the failure it forecloses is a " +
		"hand-rolled enumeration drifting behind the predicate when a new state joins the " +
		"policy (the github-prs poller drift that wedged review_judging issues).",
	Run: runInFlightStatesPolicyCoverage,
}

InFlightStatesPolicyCoverageAnalyzer is the static analyzer for the in-flight-states-policy-coverage design rule. It walks every switch statement; for each `case` clause that enumerates >=3 sm.IssueStateX selector constants whose set equals a registered policy's Domain exactly, it reports a diagnostic at the case position instructing the developer to call the policy predicate instead of re-enumerating the domain in place.

View Source
var IssuestoreSourceOfTruthAnalyzer = &analysis.Analyzer{
	Name: "issuestoresourceoftruth",
	Doc: "issuestore-source-of-truth: no code path writes a plan archive under " +

		".sorcerer/plans/ — plan content lives in the SQLite issuestore. The analyzer " +
		"scans Go string literals for the forbidden archive-path substring. Suppress with " +
		"a '// invariants:issuestore-source-of-truth ok' comment on the offending line or " +
		"the line above; each suppression must be reviewed in its introducing PR.",
	Run: runIssuestoreSourceOfTruth,
}

IssuestoreSourceOfTruthAnalyzer is the singleton static analyzer for the issuestore-source-of-truth design rule. It walks every string literal in non-test files; any literal whose value contains forbiddenPlanArchiveSubstring gets a diagnostic at the literal's position.

View Source
var LandingGateFreshUncachedAnalyzer = &analysis.Analyzer{
	Name: "landinggatefreshuncached",
	Doc: "landing-gate-fresh-uncached: the fresh pre-MergeSet landing gate " +
		"(RunPlanLandingGate, internal/github/plan_landing_gate.go) verifies the exact tree landing " +
		"on main and MUST never consult the gate-verdict cache (spec SPEC-SOR-3035-v2 R7/R13). A " +
		"reintroduced selection of the gateVerdictCache field inside RunPlanLandingGate — a field " +
		"read or a Lookup / RecordPass call on it — re-opens the un-gated-tree-lands-on-main hole the " +
		"landing gate closes and is flagged. The intermediate plan-branch seams' legitimate cache " +
		"consults live in other functions and are out of scope. Suppress with a " +
		"'// invariants:landing-gate-fresh-uncached ok' comment on the offending line or the line " +
		"above; each suppression must be reviewed in its introducing PR.",
	Run: runLandingGateFreshUncached,
}

LandingGateFreshUncachedAnalyzer is the singleton static analyzer for the landing-gate-fresh-uncached design rule. It walks each top-level function declaration in any in-scope file; inside RunPlanLandingGate it reports a diagnostic at every selection of the gateVerdictCache field — the shape of a reintroduced cache consult in the landing-gate path.

View Source
var LiveLoopPerturbableAssertionAnalyzer = &analysis.Analyzer{
	Name: "liveloopperturbableassertion",
	Doc: "live-loop-perturbable-assertion: a daemon test function MUST NOT make a loop-perturbable " +
		"exact-state assertion (an exact `len(<ident>) != / == <int>` count on a store-fetched slice) " +
		"while a live daemon run loop is running. The daemon's reconcile/persist passes append " +
		"history/issue/event rows during the run, racing the exact count, which -race flags " +
		"intermittently. Every operator under test is synchronous and needs no live loop, so the fix is " +
		"to drop the runDaemon / spawned d.Run start (or quiesce the loop / scope the assertion to a " +
		"loop-invariant). The analyzer is function-scoped and identifies test functions by their " +
		"*testing.T parameter (not the _test.go filename); it is the READ/ASSERT-axis complement of " +
		"harness-mutator-main-loop-affinity (the WRITE axis). Suppress a verified-safe assertion with a " +
		"'// invariants:live-loop-perturbable-assertion ok' comment (plus a one-line rationale) on the " +
		"offending assertion line or the line above.",
	Run: runLiveLoopPerturbableAssertion,
}

LiveLoopPerturbableAssertionAnalyzer is the singleton static analyzer for the live-loop-perturbable-assertion design rule. It walks each top-level function declaration in any in-scope file; for every function identified as a test function (by its *testing.T parameter) whose body BOTH starts a live daemon AND makes a loop-perturbable exact-count assertion, it reports a diagnostic at the assertion.

View Source
var NoAmbientTimeAnalyzer = &analysis.Analyzer{
	Name: "noambienttime",
	Doc: "no-ambient-time: ambient stdlib time.* scheduling calls (time.Sleep, " +
		"time.After, time.Tick, time.NewTicker, time.NewTimer, time.AfterFunc) are " +
		"forbidden outside the internal/clock package — drive time through the injected " +
		"clock.Clock so tests stay hermetic and deterministic under load (spec " +
		"SPEC-SOR-3238 R6/R7/R8). A time.Now() timestamp read is permitted. Pre-existing " +
		"sites are grandfathered via the embedded no_ambient_time_allowlist.txt so the " +
		"build is green from the first commit (R8); a new off-allowlist site is diagnosed " +
		"and fails the landing gate (R7). Suppress a reviewed exception with a " +
		"'// invariants:no-ambient-time ok' comment on the offending line or the line above.",
	Run: runNoAmbientTime,
}

NoAmbientTimeAnalyzer is the singleton static analyzer for the no-ambient-time design rule. It walks every call expression in every in-scope file (production AND test); a time.{Sleep,After,Tick,NewTicker, NewTimer,AfterFunc} call outside internal/clock that is neither suppressed nor in an allowlisted file is reported.

View Source
var NoBareAutonomousCreateAnalyzer = &analysis.Analyzer{
	Name: "nobareautonomouscreate",
	Doc: "no-bare-autonomous-create: every autonomous (daemon-internal) issue-create MUST route through " +
		"the CreateAutonomousIssue dedupe chokepoint — never a bare applyOperatorCreateIssue persist call " +
		"outside the blessed set (the MutationCreate handler, the plan-child materializer, and the " +
		"per-incident sweep filers). The chokepoint runs the dedupe gate (recording dedupe_check_ran) and " +
		"suppresses a duplicate; any bare call re-opens the gate-bypass class. Suppress a reviewed exception " +
		"with a '// invariants:no-bare-autonomous-create ok' comment on the offending line or the line above.",
	Run: runNoBareAutonomousCreate,
}

NoBareAutonomousCreateAnalyzer is the singleton static analyzer for the no-bare-autonomous-create design rule. It walks every non-test file's top- level function declarations; for each function OUTSIDE the blessed set it reports every call to applyOperatorCreateIssue, unless the call carries a reviewed suppression comment.

View Source
var NoBareHumanBlockAnalyzer = &analysis.Analyzer{
	Name: "nobarehumanblock",
	Doc: "no-bare-human-block: every transition into blocked_user or plan_blocked MUST route through " +
		"the escalateHumanBlock chokepoint (via escalateSubject) — never a bare IssueTransitionEffects{To: " +
		"...IssueStateBlockedUser} / PlanTransitionEffects{To: ...PlanStateBlocked} composite literal or a " +
		"bare `<x>.State = ...IssueStateBlockedUser` / `<x>.PlanState = ...PlanStateBlocked` assignment " +
		"outside the chokepoint. The chokepoint classifies the disposition through its default-autonomous " +
		"router + denylist + sustained-failure backstop and audits it in one place; any bare site re-opens " +
		"the scattered-dead-end failure class. Suppress a reviewed exception with a " +
		"'// invariants:no-bare-human-block ok' comment on the offending line or the line above.",
	Run: runNoBareHumanBlock,
}

NoBareHumanBlockAnalyzer is the singleton static analyzer for the no-bare-human-block design rule. It walks every non-test file's top- level function declarations; for each function OTHER than escalateHumanBlock it reports every IssueTransitionEffects / PlanTransitionEffects composite literal carrying a human-block To value, and every bare `.State` / `.PlanState` human-block assignment, unless the node carries a reviewed suppression comment.

View Source
var NoBareStateWriteAnalyzer = &analysis.Analyzer{
	Name: "nobarestatewrite",
	Doc: "no-bare-state-write: every write that can change a state-bearing column " +
		"(issues.state / issues.plan_state / issues.session_id) MUST route through a blessed " +
		"SM chokepoint (applyIssueTransition and its effects / persistTransitionHistory / " +
		"mirrorIssue / storeRowToSMIssue / applyMutationAtomically / terminateSession / " +
		"attachIssueSession / clearIssueSessionID) — never a bare `<x>.State` / `<x>.PlanState` " +
		"/ `<x>.SessionID` assignment on an *sm.Issue or a direct SaveIssue / SetIssueSessionID " +
		"/ ClearIssueSessionID / ForceUnTerminate call outside one. The chokepoints enforce the " +
		"persist-before-apply + version-guard discipline and audit the change in one place; any " +
		"bare site can clobber a state-bearing column unguarded. Suppress a reviewed exception " +
		"with a '// invariants:no-bare-state-write ok' comment on the offending line or the line " +
		"above.",
	Run: runNoBareStateWrite,
}

NoBareStateWriteAnalyzer is the singleton static analyzer for the no-bare-state-write design rule. It walks every non-test file (outside the two primitive-owner packages — internal/issuestore, which owns the write-primitive implementations, and internal/sm, which owns the in- memory SM transition primitives); for each function OTHER than a blessed chokepoint it reports every bare `<x>.State` / `<x>.PlanState` / `<x>.SessionID` assignment on an *sm.Issue and every direct SaveIssue / SetIssueSessionID / ClearIssueSessionID / ForceUnTerminate call, unless the node carries a reviewed suppression comment.

View Source
var NoForcePushAnalyzer = &analysis.Analyzer{
	Name: "noforcepush",
	Doc: "no-force-push: MergeDefaultIntoPlanBranch MUST use a regular " +
		"`git push` — never --force, never --force-with-lease. Reverting to a force-style push " +
		"reopens the CIPB Phase C conflict-loop class. Matches `--force` and " +
		"`--force-with-lease[=...]` literal-string args inside a runGitIn call whose argument " +
		"list also contains \"push\". Suppress with a '// invariants:no-force-push ok' comment " +
		"on the offending line or the line above; each suppression must be reviewed in its " +
		"introducing PR.",
	Run: runNoForcePush,
}

NoForcePushAnalyzer is the singletons static analyzer for the no-force-push design rule. It walks each top-level function declaration in any file whose `package github` declaration matches the target (internal/github/) package; when a function in noForcePushTargetFunctions invokes a "push" git subprocess whose argument list contains "--force" or any "--force-with-lease[=...]" form, the analyzer reports a diagnostic at the offending argument position.

View Source
var NoLeakingTestTempdirAnalyzer = &analysis.Analyzer{
	Name: "noleakingtesttempdir",
	Doc: "no-leaking-test-tempdir: an os.MkdirTemp(\"\", …) call in test or test-support code MUST be " +
		"effectively cleaned — the temp root directory it creates is NOT auto-removed by the testing " +
		"framework (unlike t.TempDir()). The analyzer flags two leak shapes: (1) no cleanup at all, and " +
		"(2) a deferred os.RemoveAll / t.Cleanup bypassed by an os.Exit in the same function (the TestMain " +
		"leak class). A direct os.RemoveAll before os.Exit is effective and is not flagged. Scope is " +
		"_test.go files plus test-support helper packages whose name contains \"test\"; production " +
		"os.MkdirTemp sites and non-empty-first-arg calls are out of scope. Pre-existing sites are " +
		"grandfathered via the embedded no_leaking_test_tempdir_allowlist.txt (expected empty). Suppress a " +
		"reviewed exception with a '// invariants:no-leaking-test-tempdir ok' comment on the offending " +
		"line or the line above.",
	Run: runNoLeakingTestTempdir,
}

NoLeakingTestTempdirAnalyzer is the singleton static analyzer for the no-leaking-test-tempdir design rule. It walks each top-level function declaration in every in-scope file; an os.MkdirTemp("", …) call whose own function-body scope lacks effective cleanup (or whose deferred cleanup is bypassed by os.Exit) that is neither suppressed nor in an allowlisted file is reported.

View Source
var NoMainLoopBlockingCallAnalyzer = &analysis.Analyzer{
	Name: "nomainloopblockingcall",
	Doc: "no-main-loop-blocking-call: a main-loop handler (one of the functions dispatched " +
		"directly from d.handle, internal/daemon/daemon.go) MUST NOT make a subprocess or " +
		"network-client invocation directly on the main goroutine — a blocking git/gh/network " +
		"call stalls the daemon's single-writer loop. The analyzer reports every direct Config " +
		"function-field call `<recv>.cfg.<Field>(…)` inside a curated handler; the blessed shape " +
		"captures the field then calls it inside a spawned goroutine that posts results back via " +
		"d.Submit. Suppress a deliberately-cheap on-main call with a " +
		"'// invariants:no-main-loop-blocking-call ok' comment (plus a one-line rationale) on the " +
		"offending line or the line above.",
	Run: runNoMainLoopBlockingCall,
}

NoMainLoopBlockingCallAnalyzer is the singleton static analyzer for the no-main-loop-blocking-call design rule. It walks each top-level function declaration in any in-scope file; for every function whose name is in the curated d.handle dispatch-target set it reports a diagnostic at each `<recv>.cfg.<Field>(…)` call — a subprocess/network-shaped Config function-field invocation made directly on the main goroutine.

View Source
var NoTimeBasedCacheRefreshAnalyzer = &analysis.Analyzer{
	Name: "notimebasedcacherefresh",
	Doc: "no-time-based-cache-refresh: SPA-facing endpoints, issue-creation responses, and " +
		"audit-event displays MUST surface mutations within seconds via SSE push or " +
		"per-request synchronous probe — never a time.NewTicker on an operator-facing cache. " +
		"Suppress with a '// invariants:no-time-based-cache-refresh ok' comment on the " +
		"offending line or the line above; each suppression must be reviewed in its " +
		"introducing PR and carry a rationale referencing the CLAUDE.md operator-tolerance " +
		"carve-out it documents.",
	Run: runNoTimeBasedCacheRefresh,
}

NoTimeBasedCacheRefreshAnalyzer is the singleton static analyzer for the no-time-based-cache-refresh design rule. It walks every call expression in non-test files; when the call's function position is `time.NewTicker(...)` and no suppression marker covers the line, the analyzer reports a diagnostic.

View Source
var OneLivenessTrackerAnalyzer = &analysis.Analyzer{
	Name: "onelivenesstracker",
	Doc: "one-liveness-tracker-per-subprocess: each dispatched claude subprocess has exactly " +
		"one liveness.Tracker driven by one tick goroutine. The analyzer asserts every " +
		"per-dispatch function constructs AT MOST ONE Tracker via liveness.New(...); a " +
		"function with multiple construction calls reports a diagnostic at every " +
		"construction site after the first.",
	Run: runOneLivenessTracker,
}

OneLivenessTrackerAnalyzer is the singleton static analyzer for the one-liveness-tracker-per-subprocess design rule. It walks every top-level function declaration in non-test files and counts calls to the canonical Tracker constructor (`liveness.New(...)` selector shape OR a bare `New(...)` inside the liveness package itself). A function whose body contains MORE THAN ONE construction call gets a diagnostic at the second-and-later construction sites — the canonical dispatch shape is exactly one Tracker per dispatch path.

View Source
var OperatorEntryOrchestrationAnalyzer = &analysis.Analyzer{
	Name: "operatorentryorch",
	Doc: "operator-entry-orchestration: operator-driven transitions MUST run the full entry " +
		"orchestration a normal daemon-driven entry into the target state runs (establishing the " +
		"state's preconditions + side-effects) or refuse — they never bare-set the issue's State / " +
		"PlanState field. The analyzer reports any `<expr>.State = ...` / `<expr>.PlanState = ...` " +
		"assignment inside a function whose name starts with applyOperator / ApplyOperator. Suppress " +
		"a reviewed bare-set (e.g. a fresh issue mint with no prior state to transition from) with a " +
		"'// invariants:operator-entry-orchestration ok' comment on the offending line or the line above.",
	Run: runOperatorEntryOrchestration,
}

OperatorEntryOrchestrationAnalyzer is the singleton static analyzer for the operator-entry-orchestration design rule. It walks every non-test file's top-level function declarations; for each function whose name starts with `applyOperator` / `ApplyOperator`, it reports every assignment statement whose left-hand side is a selector expression ending in `.State` or `.PlanState`, unless the assignment carries a reviewed suppression comment.

View Source
var OriginHeadResolutionAnalyzer = &analysis.Analyzer{
	Name: "originheadresolution",
	Doc: "origin-head-resolution: default-branch / cited-file resolution MUST go through the " +
		"centralized config-sourced chokepoint (config.DefaultBranch), never the set-once " +
		"`refs/remotes/origin/HEAD` symbolic ref (which `git fetch` never advances and which " +
		"can be stale or unset, making a cat-file probe fail for every path and falsely report " +
		"every cited file as absent). The analyzer reports any call argument whose string " +
		"literal carries \"refs/remotes/origin/HEAD\". Suppress a reviewed non-resolution use " +
		"(e.g. raw-clone pristinity) with a '// invariants:origin-head-resolution ok' comment " +
		"on the offending line or the line above.",
	Run: runOriginHeadResolution,
}

OriginHeadResolutionAnalyzer is the singleton static analyzer for the origin-head-resolution design rule. It walks every non-test file and reports each string-literal call argument (recursively, across string concatenation and format strings) whose value carries the `refs/remotes/origin/HEAD` ref, unless suppressed.

View Source
var PlanBranchMatrixVerifyAnalyzer = &analysis.Analyzer{
	Name: "planbranchmatrixverify",
	Doc: "plan-branch-matrix-verify: every enumerated plan-branch mutation chokepoint " +
		"(SquashChildIntoPlanBranch / cpbDoSquashAndCommit / cpbRunGateAndPush / " +
		"cpbAcquireRecheckPush / MergeDefaultIntoPlanBranch) MUST run the canonical " +
		"tracematrix.Verify against its staged tree before its push, so a published plan-branch " +
		"tip verifies against itself and CI's identical tracematrix verify passes by construction. " +
		"Flags a target function whose body contains no tracematrix.Verify call. A function that " +
		"delegates the staged-tree verify to another target function suppresses with a " +
		"'// invariants:plan-branch-matrix-verify ok' comment on the func line or the line above; " +
		"each suppression must be reviewed in its introducing PR.",
	Run: runPlanBranchMatrixVerify,
}

PlanBranchMatrixVerifyAnalyzer is the singleton static analyzer for the plan-branch-matrix-verify design rule. It walks each top-level function declaration whose name is in the target set and reports a diagnostic on any such function whose body contains no tracematrix.Verify call and carries no reviewed suppression marker.

View Source
var PlanBranchMutexAnalyzer = &analysis.Analyzer{
	Name: "planbranchmutex",
	Doc: "plan-branch-mutation-mutex: MergeDefaultIntoPlanBranch / " +
		"SquashChildIntoPlanBranch MUST acquire the per-(repoSlug, planBranch) " +
		"planBranchMutationMu before any bare-clone mutation. The analyzer asserts each " +
		"target function's body contains a call to acquirePlanBranchMutation, " +
		"AcquirePlanBranchMutation, acquirePlanBranchMutationAndCleanLocks, or a direct " +
		"planBranchMutationMu.<...>.Lock() chain. " +
		"Missing acquire calls return a diagnostic at the function declaration.",
	Run: runPlanBranchMutex,
}

PlanBranchMutexAnalyzer is the singleton static analyzer for the plan-branch-mutation-mutex design rule. It walks each top-level function declaration in internal/github/; when the function name is in planBranchMutexTargetFunctions and the function body does NOT contain a recognized mutex-acquire call, the analyzer reports a diagnostic at the function declaration's position.

View Source
var PlanStructuralMembershipAnalyzer = &analysis.Analyzer{
	Name: "planstructuralmembership",
	Doc: "plan-structural-membership: every plan-structural question — leaf / sibling / chain / " +
		"terminal-gate / duplicate-flag / completion — MUST be answered from plan membership (the " +
		"issue_materialized_children junction, via planChain / planLeaf / planSiblings / planKeyFor in " +
		"plan_membership.go) and NEVER from dependency-graph reachability. Two shapes are flagged inside " +
		"internal/daemon/: (1) a CALL to a reachability primitive (transitivelyDependsOn / chainClosure) " +
		"outside the primitive's own implementation; (2) a raw READ of the DerivedDependsOn field — the " +
		"cross-plan footprint-overlap carrier — outside its lifecycle owners (sweepFootprintDepReconciler, " +
		"smIssueToStoreRow, storeRowToSMIssue). Answering a membership question from the DependsOn " +
		"reachability union, or from the DerivedDependsOn subset directly, lets a cross-plan derived " +
		"footprint edge contaminate one plan's structure (the SOR-2279 R2 class). A blanket raw-DependsOn " +
		"field-read detector is intentionally omitted: DependsOn is the scheduler's global input, read " +
		"legitimately in dozens of places, so flagging it would be pure noise. A genuinely-global dispatch- " +
		"ordering / reachability / cycle-detection read, or a reviewed non-structural DerivedDependsOn read " +
		"(declaredOnly subtraction / persistence / display), is permitted only with a reviewed " +
		"`// invariants:plan-structural-membership ok` suppression on the offending line or the line above.",
	Run: runPlanStructuralMembership,
}

PlanStructuralMembershipAnalyzer is the singleton static analyzer for the plan-structural-membership design rule. It walks each top-level function declaration in any in-scope file; for every function NOT named transitivelyDependsOn / chainClosure it reports a diagnostic at each call to a graph-reachability primitive (transitivelyDependsOn / chainClosure) — the shape of a plan-structural question answered from dependency-graph reachability instead of plan membership.

View Source
var ProductSelfBoundaryAnalyzer = &analysis.Analyzer{
	Name: "productselfboundary",
	Doc: "product-self-boundary: a PRODUCT-PATH Go site (internal/daemon, internal/github, " +
		"internal/gateruntime, internal/spec/proptestbackend) MUST NOT assume a single project " +
		"language/toolchain/identity nor reach into the sorcerer source tree; every language-bound " +
		"operation routes per-file through config.LanguageForPath. The analyzer reports a " +
		"readGoModModulePath go.mod read, an os.Getenv/os.LookupEnv read of \"SORCERER_REPO\", a " +
		"self-asset name literal in a call argument, a language-name string literal equal to any " +
		"embedded-profile language name anywhere in the AST (the forbidden set DERIVED per pass from " +
		"langprofile.AllLanguages() so a new profile auto-extends it with no analyzer edit, typescript " +
		"included), a switch/case dispatching on a language name, a composite literal ([]string / " +
		"map[string]...) enumerating two or more embedded-profile language names (the set detector that " +
		"keeps the hardcoded language SET from reappearing), " +
		"a bare .ProjectLanguage selector read (a d.cfg.ProjectLanguage field read or a " +
		"config.ProjectLanguage(...) call) — the last flags regardless of any preceding Go gate; route " +
		"it per-file through config.LanguageForPath instead — and a string literal equal to a " +
		"profile-derived artifact token (a generated-stub basename, a build/gate detection marker like " +
		"go.mod, or a prop-test helper-symbol pattern), the forbidden set DERIVED from langprofile.All() " +
		"+ langprofile.AllBuildSystems() so a new language profile auto-extends it with no analyzer edit. " +
		"Language knowledge must live in langprofile " +
		"profiles (the named-strategy registry), not product-path code. Self-path / dev-tool / codegen " +
		"programs and the langprofile registry are out of scope by living outside the scoped dirs. " +
		"Suppress a reviewed single-language use with a '// invariants:product-self-boundary ok' comment " +
		"(plus a one-line rationale) on the offending line or the line above.",
	Run: runProductSelfBoundary,
}

ProductSelfBoundaryAnalyzer is the singleton static analyzer for the product-self-boundary design rule. It walks each top-level function declaration in any in-scope file and reports every product-path self-assumption (an ungated go.mod read, a $SORCERER_REPO env read, or a self-asset name literal) unless suppressed.

View Source
var ProviderIDCoverageAnalyzer = &analysis.Analyzer{
	Name: "provideridcoverage",
	Doc: "provider-id-coverage: the agentcli provider registry " +
		"(providerRegistrations) MUST cover every required ProviderID — claude (phase 0) and codex " +
		"(phase 1). A missing entry is reported at the registry literal's position; the failure it " +
		"forecloses is a new provider added to the codebase without a registry entry, which would " +
		"fail at runtime with \"no provider for id\" (or be silently omitted from the doctor / " +
		"credential-pool wiring) instead of at build time.",
	Run: runProviderIDCoverage,
}

ProviderIDCoverageAnalyzer is the static analyzer for the provider-id-coverage design rule. It walks each top-level `var` declaration; for the `providerRegistrations` value (a `map[ProviderID]providerEntry` composite literal) it asserts the literal contains every required ProviderID key and reports a diagnostic at the literal's position naming each missing provider.

View Source
var PushRetryRoutingAnalyzer = &analysis.Analyzer{
	Name: "pushretryrouting",
	Doc: "push-retry-routing: every daemon-side gh-push result-handler seam routes its auth/transient " +
		"classify-and-retry through the shared withPushRetry / classifyPushFailure seam " +
		"(internal/daemon/push_retry.go) rather than open-coding gh.IsAuthFailure / " +
		"gh.IsNetworkTransient classification inline. A function other than the shared classifier that " +
		"calls IsAuthFailure / IsNetworkTransient is a duplicated retry seam and returns a diagnostic " +
		"at the offending call.",
	Run: runPushRetryRouting,
}

PushRetryRoutingAnalyzer is the singleton static analyzer for the push-retry-routing design rule. It walks each top-level function declaration; when a function NOT in pushRetryRoutingAllowedFunctions calls one of the shared classifiers (IsAuthFailure / IsNetworkTransient), the analyzer reports a diagnostic at the offending call position.

View Source
var RemoteTrackingFetchHygieneAnalyzer = &analysis.Analyzer{
	Name: "remotetrackingfetchhygiene",
	Doc: "remote-tracking-fetch-hygiene: every forced remote-tracking bare-clone fetch " +
		"(a refspec writing refs/remotes/origin/<branch>) MUST be routed through the " +
		"FetchRemoteTrackingForced helper, which serializes on the per-bare-clone mutex and " +
		"runs the bounded ref-lock-recovery retry. The analyzer reports any fetch call whose " +
		"argument list contains the \":refs/remotes/origin/\" destination discriminator when " +
		"that call is NOT lexically inside the FetchRemoteTrackingForced definition. The " +
		"EnsureBareClone local-heads fetch (refs/heads destination) and the bare " +
		"refs/remotes/origin/<branch> worktree-carve / merge refs (no leading colon) are not " +
		"flagged.",
	Run: runRemoteTrackingFetchHygiene,
}

RemoteTrackingFetchHygieneAnalyzer is the singleton static analyzer for the remote-tracking-fetch-hygiene design rule. It walks each top-level function declaration in any non-test file; when a function OTHER than FetchRemoteTrackingForced invokes a "fetch" git subprocess whose argument list (recursively, across string concatenation and format strings) contains a literal writing an origin remote-tracking ref, the analyzer reports a diagnostic at the call expression's position.

View Source
var RoleDispatchViaRuntimeAnalyzer = &analysis.Analyzer{
	Name: "roledispatchviaruntime",
	Doc: "role-dispatch-via-runtime: role dispatches MUST run through the configured " +
		"agentcli.RuntimeRunner (the Command method, implemented by NativeRunner and " +
		"ContainerRunner). A reintroduced direct claude-binary spawn — exec.Command or " +
		"exec.CommandContext on a non-literal binary argument outside a RuntimeRunner.Command " +
		"implementation, anywhere under internal/agentcli/ — silently bypasses the runtime " +
		"layer and is flagged. Hardcoded-literal utility spawns (podman, du, git) are not " +
		"flagged. Suppress with a '// invariants:role-dispatch-via-runtime ok' comment on the " +
		"offending line or the line above; each suppression must be reviewed in its introducing PR.",
	Run: runRoleDispatchViaRuntime,
}

RoleDispatchViaRuntimeAnalyzer is the singleton static analyzer for the role-dispatch-via-runtime design rule. It walks each top-level function declaration in any in-scope file; for every function NOT named Command it reports a diagnostic at each exec.Command / exec.CommandContext call whose binary-name argument is not a string literal — the shape of a reintroduced direct claude-binary spawn.

View Source
var ScopedAmendmentMarkerAnalyzer = &analysis.Analyzer{
	Name: "scopedamendmentmarker",
	Doc: "scoped-amendment-marker: applyRolePromptEdit MUST call enforcePlannerScope " +
		"before writing the planner spec — the scope-enforcement helper restricts edits to " +
		"the SCOPED_AMENDABLE marker regions. The analyzer asserts the target function's " +
		"body still contains the guard call; deleting it re-opens the planner-spec drift " +
		"class.",
	Run: runScopedAmendmentMarker,
}

ScopedAmendmentMarkerAnalyzer is the singleton static analyzer for the scoped-amendment-marker design rule. It walks every top-level function declaration in non-test files; when the function name is applyRolePromptEdit and the body does NOT contain a call to enforcePlannerScope, the analyzer reports a diagnostic at the function declaration's position.

View Source
var SpecApprovedContentImmutabilityAnalyzer = &analysis.Analyzer{
	Name: "specapprovedcontentimmutability",
	Doc: "spec-approved-content-immutability: the specs_immutable_after_approval trigger MUST live " +
		"in an internal/issuestore migration step (it blocks in-place UPDATE of body_yaml / " +
		"smt_lib_text on an approved spec), and no production code under internal/daemon/ or " +
		"internal/spec/patcher/ may open-code a raw `UPDATE specs SET body_yaml` / " +
		"`UPDATE specs SET smt_lib_text` — the canonical mutation path is the patcher creating a " +
		"NEW specs row. Suppress a reviewed exception with a " +
		"'// invariants:spec-approved-content-immutability ok' comment on the offending line or " +
		"the line above.",
	Run: runSpecApprovedContentImmutability,
}

SpecApprovedContentImmutabilityAnalyzer is the singleton static analyzer for the spec-approved-content-immutability design rule. Per package it runs whichever half(ves) its import path is in scope for:

  • migration package (path suffix internal/issuestore): asserts the specs_immutable_after_approval trigger statement is present in some non-test migration step; reports one diagnostic at the package clause when absent.
  • daemon / patcher production packages: reports a diagnostic at every non-test string literal that open-codes a raw `UPDATE specs SET body_yaml` / `UPDATE specs SET smt_lib_text`, honoring the suppression marker.
View Source
var SubmitResultContractRequiredAnalyzer = &analysis.Analyzer{
	Name: submitResultContractRequiredAnalyzerName,
	Doc: "submit-result-contract-required: the deny-by-default submit_result contract layer. " +
		"Every runner.Run dispatch (internal/role/dispatcher.go) MUST pass the role as a string " +
		"literal (rule a), and every literal role dispatched in a package that also declares the " +
		"SubmitResultContracts registry MUST appear there as a submitting contract or an explicit " +
		"NoSubmit negative (rule b). A non-literal role argument or an unregistered role is a build " +
		"failure. Scope is internal/role/ + internal/agentcli/; the analyzer runs per-package so " +
		"rule (b) is exercised only where the registry and the call sites coexist (the fixture). " +
		"Suppress with a '// invariants:submit-result-contract-required ok' comment on the offending " +
		"line or the line above; each suppression must be reviewed in its introducing PR.",
	Run: runSubmitResultContractRequired,
}

SubmitResultContractRequiredAnalyzer is the singleton static analyzer for the submit-result-contract-required design rule. Phase 1 collects the SubmitResultContracts registry's covered roles from the in-scope package; Phase 2 reports every in-scope runner.Run call whose role argument is not a string literal (rule a) or — when the registry is visible in the same package — whose literal role is absent from the registry (rule b).

View Source
var SubmitResultDispatchRoutingAnalyzer = &analysis.Analyzer{
	Name: submitResultDispatchRoutingAnalyzerName,
	Doc: "submit-result-dispatch-routing: the build-time backstop for the SPEC-SOR-2785 dispatch-routing " +
		"contract over internal/role/dispatch_contract.go and internal/agentcli/submit_result_typed_schema.go. " +
		"Rule (a) / R2: flags a strings.HasSuffix / strings.HasPrefix call whose match string is a terminal-marker " +
		"literal (ends in `_OK` or `_FAILED`) — typed-result extraction routed on the stdout terminal marker rather " +
		"than the resolved dispatch contract. Rule (b) / R5: flags a dispatchContracts entry missing a `requiredMarker` " +
		"key, or a non-NoSubmit SubmitResultContracts entry missing a `RequiredMarker` key. Suppress with a " +
		"'// invariants:submit-result-dispatch-routing ok' comment on the offending line or the line above; each " +
		"suppression must be reviewed in its introducing PR.",
	Run: runSubmitResultDispatchRouting,
}

SubmitResultDispatchRoutingAnalyzer is the singleton static analyzer for the submit-result-dispatch-routing design rule. Within either seam file it reports (a) a strings.HasSuffix / strings.HasPrefix call whose match literal is a terminal-marker prefix — typed-result extraction routed on the stdout marker — and (b) a dispatch-contract registry entry that omits its RequiredMarker declaration.

View Source
var SubmitResultNoGenericSchemaAnalyzer = &analysis.Analyzer{
	Name: "submitresultnogenericschema",
	Doc: "submit-result-no-generic-schema: the default-inversion submit_result contract layer. " +
		"Once every submitting role is typed, the permissive open-object schema genericInputSchema() " +
		"is reachable only through the single registry-derivation chokepoint toolDescriptor " +
		"(internal/agentcli/submit_result_mcp.go). Any call to genericInputSchema() outside " +
		"toolDescriptor, anywhere under internal/agentcli/, silently reintroduces the generic " +
		"schema and is flagged. Suppress with a '// invariants:submit-result-no-generic-schema ok' " +
		"comment on the offending line or the line above; each suppression must be reviewed in its " +
		"introducing PR.",
	Run: runSubmitResultNoGenericSchema,
}

SubmitResultNoGenericSchemaAnalyzer is the singleton static analyzer for the submit-result-no-generic-schema design rule. It walks each top-level function declaration in any in-scope file; for every function NOT named toolDescriptor it reports a diagnostic at each call to genericInputSchema() — the shape of a reintroduced off-chokepoint generic-schema fallback.

View Source
var SubmitResultSchemaCompletenessAnalyzer = &analysis.Analyzer{
	Name: submitResultSchemaAnalyzerName,
	Doc: "submit-result-schema-completeness: every TYPED submit_result input schema (a builder " +
		"returning a map with a literal `properties` block) must declare each field in the " +
		"TypedSchemaDispatches required-field union — a typed `properties` block makes the agent " +
		"drop any envelope field it omits (the #1037 marker regression). Generic open-object schemas " +
		"(no `properties` key) and a `properties` whose value is a variable/call are never flagged. " +
		"The analyzer activates only on the package declaring the TypedSchemaDispatches registry; " +
		"every other package is silently skipped.",
	Run: runSubmitResultSchemaCompleteness,
}

SubmitResultSchemaCompletenessAnalyzer is the singleton static analyzer for the submit-result-schema-completeness design rule. It activates only on a package declaring the TypedSchemaDispatches registry; there it reports every typed submit_result schema (a builder returning a map with a literal `properties` block) whose block omits a field in the registry's required-field union.

View Source
var SubmitResultSingleValidatorAnalyzer = &analysis.Analyzer{
	Name: "submitresultsinglevalidator",
	Doc: "submit-result-single-validator: the anti-split-brain submit_result contract layer. " +
		"Both the in-conversation boundary validator (internal/agentcli/submit_result.go) and the " +
		"post-exit parser (internal/role/dispatcher.go) must resolve through the single contract lookup — " +
		"LookupValidator / defaultValidatorMap on the boundary, lookupDispatchContract / dispatchContracts " +
		"on the dispatcher — never naming a role.Parse* function directly. Any direct role.Parse* selector " +
		"or bare Parse* ident call in either seam file is flagged so the two validators can never drift into " +
		"a split-brain. Suppress with a '// invariants:submit-result-single-validator ok' comment on the " +
		"offending line or the line above; each suppression must be reviewed in its introducing PR.",
	Run: runSubmitResultSingleValidator,
}

SubmitResultSingleValidatorAnalyzer is the singleton static analyzer for the submit-result-single-validator design rule. It walks every CallExpr in the two seam files and reports a diagnostic at each direct role.Parse* selector (Rule 1) or bare Parse* ident call (Rule 2) — the shape of a second validator drifting away from the single contract lookup.

View Source
var WorkPreservationAnalyzer = &analysis.Analyzer{
	Name: "workpreservation",
	Doc: "work-preservation: every destructive abandon-with-cleanup transition (an " +
		"IssueTransitionEffects composite literal carrying both To: <...>.IssueStateAbandoned " +
		"AND CleanWorktree: true) MUST route through the abandonWithCleanup guarded helper — " +
		"either constructed inside abandonWithCleanup itself or passed as a direct argument to " +
		"a abandonWithCleanup(...) call. The guard refuses to silently discard a reviewer-" +
		"approved PR set; any bypass re-opens the work-destroying-transition failure class. " +
		"Non-destructive abandons (no CleanWorktree: true) are out of scope.",
	Run: runWorkPreservation,
}

WorkPreservationAnalyzer is the singleton static analyzer for the work-preservation design rule. It walks every non-test file's top- level function declarations; for each composite literal of type IssueTransitionEffects whose key/value list contains BOTH `To: <...>.IssueStateAbandoned` AND `CleanWorktree: true`, it reports a diagnostic unless the composite literal is allowed by one of two structural exemptions:

  • The enclosing function declaration's name is abandonWithCleanup (the guard itself is allowed to construct or forward these).
  • The composite literal is a direct argument to a call whose trailing function-name identifier is abandonWithCleanup (the canonical pattern at the surviving call sites: a raw call constructs the effects inline and hands them to the guard).

Anywhere else, a diagnostic names the offending site and points at the guard.

View Source
var WorktreeCreateTeardownPairingAnalyzer = &analysis.Analyzer{
	Name: "worktreecreateteardownpairing",
	Doc: "worktree-create-teardown-pairing: every ephemeral-worktree creation site " +
		"(a `git worktree add` immediately followed by `git worktree lock`) MUST register a " +
		"paired deferred teardown closure (unlock → remove → prune) in the same function. " +
		"The analyzer flags a function that carves+locks an ephemeral worktree (via runGitIn) " +
		"but defines no such teardown closure, reporting a diagnostic at the function " +
		"declaration. It is the build-time complement to the runtime " +
		"worktree-no-leaked-locked-ephemeral leak detector.",
	Run: runWorktreeCreateTeardownPairing,
}

WorktreeCreateTeardownPairingAnalyzer is the singleton static analyzer for the worktree-create-teardown-pairing design rule. It walks each top-level function declaration; when the function body runs BOTH a `runGitIn(..., "worktree", "add", ...)` call and a `runGitIn(..., "worktree", "lock", ...)` call (an ephemeral worktree creation site) but defines NO teardown closure (an ast.FuncLit that runs both a `worktree unlock` and a `worktree prune` via runGitIn), the analyzer reports a diagnostic at the function declaration's position. Test files (_test.go) are skipped.

View Source
var WorktreeOwnershipExclusiveAnalyzer = &analysis.Analyzer{
	Name: "worktreeownershipexclusive",
	Doc: "worktree-ownership-exclusive: every keyed per-issue / per-role / per-plan-child worktree " +
		"directory under .sorcerer/worktrees or .sorcerer/role-worktrees MUST be built through a " +
		"canonical helper in internal/github/worktree.go (WorktreeDir, RoleWorktreeDir, " +
		"PlanBranchWorktreeDir, PlanFixWorktreeDir, BareCloneDir, and the wrapper-dir peers) rather " +
		"than a hand-concatenated filepath.Join, so two execution contexts can never collide on a " +
		"hand-built path. The analyzer flags a filepath.Join that reconstructs a keyed worktree path " +
		"by hand, reporting a diagnostic at the call. Ephemeral os.MkdirTemp temp dirs are an " +
		"explicit carve-out (owned by the runtime worktree-no-leaked-locked-ephemeral invariant).",
	Run: runWorktreeOwnershipExclusive,
}

WorktreeOwnershipExclusiveAnalyzer is the singleton static analyzer for the worktree-ownership-exclusive design rule. It walks every file outside the canonical helper file and outside _test.go files; when a filepath.Join call reconstructs a keyed .sorcerer/worktrees or .sorcerer/role-worktrees path by hand (the ".sorcerer" + "worktrees" /"role-worktrees" literal pair with a further keyed segment after the worktrees literal), the analyzer reports a diagnostic at the call's position.

Functions

func ProductSelfBoundaryFileInScope

func ProductSelfBoundaryFileInScope(fname string) bool

ProductSelfBoundaryFileInScope reports whether fname (an absolute path from pass.Fset.Position) lives under one of the analyzer's target directories. Out-of-scope files are skipped silently. Exported so the spec R4 property test can exercise the directory-scope predicate directly (an out-of-product path — e.g. a cmd/ site — must return false).

Types

This section is empty.

Directories

Path Synopsis
cmd
invariantanalyzers command
Command invariantanalyzers is the standalone multichecker driver for the static analyzers landed by the invariants migration:
Command invariantanalyzers is the standalone multichecker driver for the static analyzers landed by the invariants migration:
singlewriterstate command
Command singlewriterstate is the standalone driver for the single-writer-state static analyzer.
Command singlewriterstate is the standalone driver for the single-writer-state static analyzer.

Jump to

Keyboard shortcuts

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