audit-go-test
Go test-evidence audit methodology — judges the Go tests in scope against the product-tree and Go-specific evidence properties.
- License 许可
- MIT
- 最近更新
- 2026-11-12
- Stars
- ★ 1
- Forks
- 1
01 前言 Front Matter
- name
- audit-go-test
- description
- Go test-evidence audit methodology — judges the Go tests in scope against the product-tree and Go-specific evidence properties.
- allowed-tools
- Read, Grep, Glob, Bash(git diff:*), {{! tool('use_skill') !}}
03 SKILL.md 正文
<objective> A verdict on Go test evidence — APPROVED, or REJECTED with each finding naming the assertion or evidence artifact, the failed evidence property, and the evidence gap. </objective>
<constraints>
This audit is read-only. Produce a verdict over test evidence; never edit tests, production code, specs, fixtures, harnesses, generators, or project configuration.
</constraints>
<audit_workflow>
<prerequisites>
{!% require_skill 'go:go-code-standards' %!}
{!% require_skill 'go:go-test-standards' %!}
{!% require_skill 'product-tree:audit-tests' %!}
{!% require_skill 'product-tree:test' %!}
Read local overlay files — each routes skill behavior to the product's governing specs and decisions; overlays supplement skills and do not supersede them:
Read spx/local/go.md and spx/local/go-tests.md when they exist; otherwise apply the loaded skills only.
Use skill product-tree:contextualize on the spec node under audit — <PRODUCT_TREE_CONTEXT> marker must be present before Gate 1.
This audit runs no deterministic verification — no gofmt, go vet, go test, go test -cover, or any other project command. Spend the whole audit reading the evidence chain.
</prerequisites>
<audit_scope>
Begin with the current governing spec and its current evidence links. A deleted Go test or test-infrastructure path belongs to this audit only when a current [test] assertion still links it or a current linked test still imports it. When the current spec carries no [test] link to the deleted path and no current evidence chain references it, classify the retired path as outside current Go test-evidence scope and return NOT_APPLICABLE for that path. Never demand restoration of deterministic evidence solely because the base revision or changeset deletion names the retired path. When a current [test] assertion still links a missing path, report missing evidence against that current assertion.
Use read-only git diff only when the supplied changeset scope requires confirming whether an evidence path was deleted. Run no other shell command from this concern skill.
</audit_scope>
<structural_reading> Before judging evidence, read the in-scope test files for structural defects — by reading, never by running the project's gate. These are reading observations folded into Gate 1, not a separate deterministic gate:
- Filename policy — each file MUST match
<subject>.<evidence>.<level>[.<runner>]_test.go(<evidence>∈ scenario/mapping/conformance/property/compliance,<level>∈ l1/l2/l3). The project's validation owns this convention; note a mismatch as afilename_policyfinding carrying propertyalignmentfrom the base/audit-testsenum — a filename that misdeclares its evidence type or level misaligns the file with the assertion it claims to evidence — and do not re-validate it. - Build constraint — an
l2orl3file whose first line is not the matching//go:build l2or//go:build l3constraint runs in the default lane against infrastructure it declares absent there; note it as afilename_policyfinding carrying propertyalignment. - Test-file bindings — apply the base
/audit-testssemantic binding screen before coupling. A:=,var,const, table-row literal, closure parameter, or property-generated parameter is valid when it only receives an actual result, source-owned contract, generated value, harness observation, callback input, resource handle, or fixture path and introduces no data or policy. Emit a finding carrying propertydeclarationsand the base/audit-testsrule label the choice matches —test-owned configurationfor runner settings, seed policy, retries, setup policy, or lifecycle policy, andtest-owned datafor hand-picked data, boundary bags, expected outputs, fixture contents, generator domains, or a table of author-invented rows presented as a mapping. Keep the two labels distinct. Keep every predicate andtesting.Tfailure call in the linked test function or subtest; a binding, closure, ort.Helper()-marked function that moves a predicate or failure call out carries propertypredicate-ownership, ruleassertion-seam, remediation targettest-file. - Source-file reads — a test that reads production
.gofiles (os.ReadFile,embedof a source path,go/parserover production code) asserts on source text, not behavior → prose-coupling REJECT in Gate 1 stepfour_properties. Inert fixture data is read by path frominternal/testinfra/fixtures/testdata/; co-locatedspx/.../tests/remains the home of typed assertion files. When a loaded overlay points to a governing product spec or decision that explicitly amends this contract, follow that declaration; the overlay does not redefine fixture placement itself. - Disabled evidence — a bare
t.Skip()(no reason), skip-by-early-return,t.SkipNow(), orpanic("TODO")in a test body provides no evidence → REJECT in Gate 1 carrying propertycoveragefrom the base/audit-testsenum, since execution never reaches the assertion-relevant path. A reasonedt.Skip("...")is acceptable in an.l3_test.gofile only when a loaded product spec or decision declares that credentialed Level 3 lane and the suite declares that evidence optional; a missing mandatory dependency fails throught.Fatal, so a skip on it rejects. Outside.l3_test.go, reasoned skip is misplaced. - Generated mock signal —
gomock,mockery,moq,mock.Mock, or a reassigned package-level function variable in a test is read and judged in Gate 1 stepcontrolled_implementationsagainst/testStage 5 exceptions.
</structural_reading>
<gate_1_assertion> Entry point is the spec, not the test file.
For each assertion in the spec's Assertions section, execute steps 1-8 in order. First step failure rejects that assertion and moves to the next assertion.
<step name="challenge"> Challenge the assertion:
- Does the assertion derive from an ancestor PDR or ADR claim in
<PRODUCT_TREE_CONTEXT>, or is it floating? - Is the assertion type correct for the claim?
- Does it overlap with another assertion in the same node or parent?
Record challenge findings and continue unless the assertion type is invalid. A challenge finding carries property alignment from the base /audit-tests enum — the claim itself is malformed or misaligned with its governing decision.
</step>
<step name="scope"> Decompose the assertion text into testable clauses.
Example:
| Assertion | Clauses |
|---|---|
| "MUST exit 0 with no stdout for invalid hook JSON" | (1) invalid JSON input, (2) exit 0, (3) empty stdout |
The linked tests must exercise every clause with an assertion. A single assertion for a multi-clause claim is a scope finding carrying property coverage from the base /audit-tests enum — clauses of the claim go unexercised.
</step>
<step name="evidence"> Match the Go evidence method to the assertion type:
| Type | Required Go evidence | Reject if |
|---|---|---|
| Scenario | concrete inputs through the governed function, package, or binary | only existence or truthiness is checked |
| Mapping | table-driven t.Run cases iterating a source-owned enumeration with at least two members |
one example stands in for a mapping |
| Conformance | parser, schema, protocol harness, CLI contract, or toolchain oracle for compile-time contracts | manual shape checks replace the validator |
| Property | rapid through the property harness with meaningful generators and invariants |
examples are wrapped in property syntax |
| Compliance | violating fixture or analyzer harness for a current [test] link |
no violating input or rule oracle exists |
For property tests, inspect the generator domain. rapid.Just, one-value ranges, or tiny enumerations reduce the property to examples unless the spec explicitly declares a finite set.
An assertion tagged [audit:{rule-slug}], or the pathless [audit] that the foundation admits for a toolchain without slug support, carries no assertion type and is outside Go test-evidence scope. Skip it rather than treating the marker as test evidence.
</step>
<step name="controlled_implementations">
Judge controlled implementations against /test exceptions:
| Exception | Legitimate Go pattern |
|---|---|
| 1. Failure modes | interface implementation returning deterministic errors |
| 2. Interaction protocols | recording implementation capturing calls |
| 3. Time/concurrency | injected clock, deterministic channels, synctest where available |
| 4. Safety | recording or no-op implementation preserving the seam |
| 5. Combinatorial cost | configurable in-memory implementation with real-shaped behavior |
| 6. Observability | capture implementation for slog handlers, events, or serialized output |
| 7. Contract probes | httptest stub validated against the same contract schema |
Generated mock frameworks, reassigned package-level function variables, or stubs that bypass the governed seam reject the assertion unless a Stage 5 exception applies and the real interface or protocol remains intact. Such a rejection carries property falsifiability from the base /audit-tests enum — a severed seam means no production mutation can break the test.
</step>
<step name="oracle"> Identify the source of every expected value.
Reject with an oracle finding carrying property oracle-independence and remediation target independent-oracle from the base /audit-tests enum when the expected value is derived from the package under test. This is distinct from falsifiability: an expected result computed by the same path that produces the actual result passes even when both are wrong. Proceed when the expected value comes from an independent source: the spec, an exported constant owned by a different package, an external protocol/schema, a fixture transcript, or a value hand-computed in the test.
</step>
<step name="harness_chain"> Trace every test-infrastructure import:
- imports from
<module>/internal/testinfra/harnesses,<module>/internal/testinfra/generators, and<module>/internal/testinfra/fixtures— the canonical home per the product'stest-infrastructurePDR - non-canonical legacy locations that must be flagged as misplaced infrastructure: an in-package
testutilortesthelperspackage, anexport_test.gothat hands a harness or fixture to a test, atestdata/directory outsideinternal/testinfra/fixtures/, or atests/subdirectory carrying non-test Go files - local functions inside
spx/.../tests/— these are misplaced infrastructure when they own setup, reusable cases, fixture handling, generator selection, harness behavior, diagnostics, or source vocabulary - binary harnesses that build or resolve the product binary and hand it to
os/exec
Open each harness. If the harness replaces the governed package instead of exercising it, reject with a harness_chain finding. Trace imports until the chain terminates at production code, fixture data, or framework/library code. If a harness lives in a non-canonical legacy location, surface an extraction_target finding pointing at internal/testinfra/.
</step>
<step name="four_properties"> Apply the Go supplements:
- Coupling: classified from the full
<supplement property="coupling">taxonomy below — every category it names, never a subset - Falsifiability: concrete mutation named for every codebase path or binary contract
- Alignment: every assertion clause maps to exercised test behavior
- Coverage: read whether the test drives execution into the governed source path; no coverage tool is run
First property failure rejects the assertion. </step>
<step name="coverage">
Establish coverage by reading, never by running go test -cover or any other coverage tool. This audit runs no deterministic verification.
Trace, by reading, whether the test drives execution into the governed source path:
- Read the governed source the assertion names and identify the assertion-relevant functions, branches, and lines.
- Read the test and follow what it calls into that source — directly, through a harness, or through the harness-provided binary for a binary contract.
- Judge whether the test's execution reaches the assertion-relevant path.
A test that compiles against the governed package but never drives execution into the assertion-relevant path → REJECT with coverage; name the path the test fails to reach, traced from the code. When the assertion-relevant path is trivially total, annotate saturated.
</step>
Gate 1 status:
- PASS if every assertion verdict is PASS.
- FAIL if any assertion verdict is REJECT.
</gate_1_assertion>
<gate_2_architectural> Runs only if Gate 1 is PASS. Scan in-scope tests for repeated setup patterns that belong in shared test infrastructure.
Trigger: two or more in-scope tests share any of these patterns:
- identical product-binary build or resolution setup
- repeated hook JSON builders
- repeated transcript fixture writers
- repeated tempdir/home-directory scaffolding beyond a bare
t.TempDir() - repeated stdout/stderr/exit-code comparison functions
- repeated
slogor debug capture setup
Each finding names the pattern, lists at least two occurrences with file and line, and proposes the canonical home under internal/testinfra/ — harnesses for shared resource mediators, generators for input factories, or fixtures for fixture-resolving code.
Gate 2 status:
- PASS if no repeated setup pattern appears in two or more in-scope tests.
- FAIL if any repeated setup pattern appears in two or more in-scope tests.
</gate_2_architectural>
<go_supplements> Applied during Gate 1.
<supplement property="coupling">
This supplement specializes each category of the coupling taxonomy /audit-tests owns to Go paths. Classify from the table below rather than a subset of it; every category the canonical taxonomy names appears here, so a category missing from this table would silently narrow the verdict.
| Category | Definition | Verdict |
|---|---|---|
| Direct | Test calls the governed Go function, type, package, or binary | Proceed |
| Indirect | Test calls test infrastructure that calls the governed path | Proceed after harness tracing |
| Transitive | Test calls a public consumer of the governed path | Proceed if the level matches |
| Laundered indirect | Calls an internal/testinfra package that exists only to expose hardcoded values back to the test |
REJECT — laundering |
| False | Test imports the package but never calls assertion-relevant symbols | REJECT |
| Partial | Test calls the right package with wrong inputs or wrong path | REJECT |
| None | Test imports only testing and third-party modules, with zero product-package coupling |
REJECT — tautology |
| Severed | Test or harness replaces the governed behavior with a mock, fake, generated mock, reassigned function variable, or bypassing stub | REJECT — coupling severed |
| Prose-coupling | Reads an authored prose/doc body and asserts its content, including through a harness constant or an infrastructure reader | REJECT — couples to authored text, not behavior |
Framework/library imports such as testing, context, os/exec, net/http/httptest, pgregory.net/rapid, and github.com/google/go-cmp/cmp do not count as coupling by themselves. A harness-provided product binary run through os/exec counts as coupling to the named binary contract. The Prose-coupling row is the table-side form of the source-file read that <structural_reading> screens for; both reach the same REJECT.
</supplement>
<supplement property="falsifiability"> For each codebase path, name a concrete mutation that would fail the test.
Example:
Package: internal/install
Mutation: Install writes block hook entries under PreToolUse instead of Stop
Impact: install-tooling scenario test comparing settings JSON fails
Reject when no mutation can be named, when generated mocks replace the governed behavior, or when golden files only capture hand-built fixtures. </supplement>
<supplement property="alignment"> Alignment passes when every assertion clause is exercised by at least one assertion and the test's evidence method matches the assertion type.
Reject when the test covers a nearby behavior, collapses clauses, uses one example for a mapping, or tests runtime behavior for a compile-time contract. </supplement>
<supplement property="coverage">
Coverage passes when reading the test against the governed source shows the test drives execution into the assertion-relevant path, or that path is trivially total (saturated) and the other three properties pass. No coverage tool is run — this audit establishes coverage by reading.
Coverage notes do not rescue missing coupling, falsifiability, or alignment. </supplement>
</go_supplements>
</audit_workflow>
<verdict_format>
This skill composes the base /audit-tests verdict: the row names (gate-1-assertion, gate-2-architectural) and the JSON schema are defined in its <verdict_format> and are not redefined here. This skill contributes Go-specific finding detail into those rows. The audit emits no gate-0-deterministic row — it runs no deterministic verification; the structural reading observations from <structural_reading> are folded into the Gate 1 (gate-1-assertion) findings. Gate 2 extraction target: a package under internal/testinfra/, e.g. internal/testinfra/harnesses, internal/testinfra/generators, or internal/testinfra/fixtures — never an in-package testutil or a testdata/ directory outside the fixtures package, which are legacy non-canonical locations.
When <audit_scope> finds that a retired path has no current [test] assertion or current evidence-chain owner, emit this alternate concern result instead of the inherited rows:
{
"status": "NOT_APPLICABLE",
"subjects": ["<retired-repository-relative-path>"],
"explanation": "No current [test] assertion or evidence chain references the retired path."
}
Emit this shape only when every supplied subject is outside current Go test-evidence scope. A current broken [test] link remains applicable and produces the inherited REJECTED verdict.
</verdict_format>
<success_criteria>
The Go test verdict is sound when:
- Every applicable rule was judged: each in-scope assertion received every Gate 1 step and the
<structural_reading>observations (filename, build constraint, source-reads, disabled evidence, mock signals); Gate 2 was judged when Gate 1 passed and omitted only when Gate 1 rejected the evidence. - Every deleted Go test or test-infrastructure path was classified from current spec links and current evidence chains, with retired evidence returned as
NOT_APPLICABLEand current broken[test]links reported as missing evidence. - Applicable scope states an overall
APPROVED/REJECTEDwith no assertion left unevaluated; a composition-only retired-path scope emits the definedNOT_APPLICABLEresult. - Each
REJECTfinding is falsifiable: it names the assertion or evidence artifact, the failed property, the gate and step, and how the test could pass while the assertion is unfulfilled. - The same test node yields the same verdict regardless of run order (reproducible).
</success_criteria>
04 同仓库更多 Skills
plugin
暂无简介
sanitize-powerpoint
ALWAYS invoke this skill when sanitizing, cleaning up, auditing, or aligning a PowerPoint (.pptx) deck — slide-master and layout structure, layout type attributes, stray fonts, non-theme colors, or layout naming. NEVER hand-edit pptx XML without this skill.
draw-excalidraw
ALWAYS invoke this skill when creating Excalidraw diagrams, visualizing workflows, architectures, or concepts. NEVER generate Excalidraw JSON without this skill.
typescript-test-standards
TypeScript test standards enforced across all skills. Loaded by other skills, not invoked directly.
typescript-code-standards
TypeScript code standards enforced across all skills. Loaded by other skills, not invoked directly.
typescript-architecture-standards
TypeScript ADR conventions enforced across architect and auditor skills. Loaded by other skills, not invoked directly.