AI-Native Go — The Guide
01Discipline v0.2 · status: BETA · T2 · supersedes the legacy projection GUIDE-GO-v0.1 (which stays, untouched, in flow:org.vibevm.ai-native/core-ai-native/spec/legacy-projections/) · third supported language, after Rust (pilot) and TypeScript
02The projection of the Discipline onto Go.
03Read 00-MANIFESTO.xml and
02-EXECUTABLE-SCAFFOLDS.xml (the T1 core) first; this guide assumes the central law and
the nine scaffold classes.
04Structurally parallel to rust/GUIDE-AI-NATIVE-RUST.md and
typescript/GUIDE-AI-NATIVE-TYPESCRIPT.md — cross-language diffing of the guides is a
feature of the discipline.
05Cross-references are marked (≈ Rust §N) / (≈ TS §N);
sections with no sibling analogue are marked [Go-specific].
06A human CAN read and modify AI-Native Go; it is ordinary idiomatic Go at the token level — arguably the least surprising projection of the three, because Go's own culture already runs half the discipline.
07What differs is the envelope:
- 08closed error sets,
- loud interface conformance,
- owned goroutines,
//spec:traceability,- executable scaffolds,
- and a fast per-cell verification loop.
0. Why Go is special — and the law applied to Go
09Idiomatic inside the file; engineered around the file. (≈ Rust §0, TS §0)
10The typology, one line each:
- 11Rust enforces;
- TypeScript permits but compiles;
- Python trusts;
- C++ demands a subset to survive;
- Go prescribes.
12The language ships with its discipline pre-installed:
- 13gofmt ended the formatting war,
- the compiler rejects unused imports and variables,
- errors are values by culture,
- inheritance does not exist,
internal/is compiler-enforced encapsulation,- and "idiomatic Go" is the strongest single-idiom culture of any mainstream language.
14Go is also massively in-distribution — ordinary Go is among the safest surfaces a model can read or write.
15That prescription cuts three ways for the Discipline:
16Advantage 1 — half the envelope is free. Uniformity (R3-006) is largely enforced upstream: one formatter, one vocabulary of idioms, a stdlib that models have seen millions of times.
17The guide spends almost no budget on style — the language already won those arguments.
18Advantage 2 — verification is the fastest of the three stacks. go build and
per-package go test are famously quick; the Class E loop needs no project-reference
machinery (TS) and no cold target/ pain (Rust).
19go test -json is a native
machine-readable stream; Example functions are compiled AND executed doctests;
go test -fuzz is a built-in differential engine; httptest is a stdlib simulator.
20Go hands the scaffold catalog more standard machinery than either sibling.
21The hazard — prescriptions stop one step short of contract, and expressiveness is the
lowest of the three. Go has no sum types, no exhaustive switch, no typestate culture,
late and deliberately modest generics.
22Where Rust encodes an invariant in a type and TS in a branded union, Go often CANNOT put it in the type system at all — so the Discipline carries proportionally more weight in linter-borne rules, runnable contracts, fuzz oracles, and conventions with checkers.
23And four specific prescriptions stop exactly one step short of contract grade; closing those gaps is this guide's whole job:
- 24Errors are values — but their SETS are open. Culture says return
error; nothing says WHICH errors. The seam's failure set becomes part of the checked contract (§5). - Interface conformance is silent. Structural satisfaction means a cell can drift off its seam without a compile error naming the seam. Conformance is made loud (§2).
- Goroutines are unowned by design.
go f()has no owner, no join handle, no cancellation unless you build them. Ownership is made structural (§5). init()blesses the side-effectful import. The stdlib itself registers drivers at import (database/sql,image/*,_ "net/http/pprof") — which is exactly why cells must ban it explicitly (§2).
25The law, projected. Go source under this discipline reads as ordinary idiomatic Go.
26No invented notation — that would incur the out-of-distribution penalty (EsoLang: 0–11% on unfamiliar surface; in-context learning cannot teach it).
27Go's own OOD tail is
named and quarantined: reflection-driven frameworks, struct-tag DSLs, unsafe, cgo, and
clever channel topologies are the constructs models handle worst and humans debug
longest — they are boundary-only (§7).
28The strictness we add lives in the envelope:
closed error sets, conformance assertions, ownership discipline, //spec: metadata,
linter evidence, and the per-cell loop — never in exotic surface.
1. The prescriptive baseline — take everything the language gives
29req r1 — the toolchain floor below is MUST; policy-gated rows are named as such.
30(≈ TS §1: TS must OPT IN to its compiler's strictness flag by flag; Go must simply not opt OUT of its culture. This section is the free-lever twin.)
- 31Version floor: go 1.24; target the latest stable. Modules with committed
go.sum;GOFLAGS=-mod=readonlyin CI (the lockfile is native — A2 by default).go.workfor multi-module workspaces. - gofmt is non-negotiable and free — the one language where the style war was won upstream; the floor's first step is a formatting check, and it costs the Discipline zero attention budget.
go vetMUST (floor step); staticcheck MUST (MIT; policy-gated floor step — aDISABLED by policyline prints with its reason and is re-questioned weekly);exhaustivelinter (BSD-2) for closed-set switches (§5; policy-gated with the same printed-line rule);govulncheck(BSD-3) in CI, not the floor (it touches the network). golangci-lint is GPL-3.0: never vendored, never linked, never in the floor — at most a personal separate-process dev tool, per the licensing flow.- The race detector gates tests:
go test -raceis the MUST configuration for any package that starts a goroutine; findings are failures, not warnings. - Suppression policy (xfail-strict posture). The blessed forms carry a reason by
construction: staticcheck's
//lint:ignore <Check> <reason>and the exhaustive linter's//exhaustive:ignore <reason>. A bare//nolint(any linter), a reasonless ignore directive, or at.Skipon a known-failing test (§10) is a conform finding. The suppression census only shrinks (BROWNFIELD §4 at the lint level). - Generics: legal and bounded. Type parameters for containers/algorithms in infra packages; domain seams stay interface-based unless a measured hot path says otherwise. No type-parameter theater (R-021) — Go's generics are deliberately modest; code that fights that modesty is OOD.
- Boundary validation (parse, don't validate). JSON decoding is loose by default —
missing fields become zero values silently, unknown fields are ignored. Boundary
decode uses
json.Decoder.DisallowUnknownFieldsplus explicit validation; boundary DTO structs convert explicitly into domain types; absent-vs-zero ambiguity is resolved with pointer fields or a validation layer at the boundary, never guessed in cells. Struct tags live on boundary DTOs only (§7). Specified, not built: nothing enforces this. No conform rule and no floor step inspects boundary decode, andDisallowUnknownFieldsappears in no Go source anywhere in the tree — the rule lives only as prose here, in the core Go projection, and as one inventory item the brownfield skill looks for (go-ai-native-terraform, "loose boundary decoding"). Nor is it demonstrated:research/go-demo, the one Go consumer, decodes no JSON at all, so the rule is untested there rather than broken.
2. Cells, closure, ownership
32req r1 (≈ Rust §1, TS §3)
33The cell is the unit of modification, closed under paging (R3-001): it declares its full semantic dependency set so a pager can assemble sufficient context mechanically.
- 34A cell is a package under
internal/cells/<name>.internal/makes non-module imports a compile error — the cell ring as language physics; the in-module sibling ban (a cell importing a sibling cell, R-002) is checked at T-syn from the import graph. Seams live in a neutral package (internal/seamsby convention; configurable);internal/registryis the only package that imports cell packages (§6). - Import-is-execution, Go edition:
init()and blank imports are banned in cells. So is package-levelvarwith a non-constant initializer. The single carve-out is boundary adapters wrapping stdlib-style driver registration — registration happens there or in the composition root, never as a side effect of importing domain code. - No ambient state. Cells never touch
os.Getenv,time.Now,os.Stdin/Stdout,http.DefaultClient/DefaultServeMux,flag.CommandLine,math/rand's global source, or the globallog/slogdefault. Capabilities are injected at construction — and Go makes this uniquely cheap: the cell declares the narrow interface it needs privately (type clock interface{ Now() time.Time }) and structural typing does the rest. No central capability package, no mocking framework: tests hand in literal fakes (§4-H). context.Contextis the cancellation capability: first parameter of every potentially-blocking seam method, never stored in a struct field (vet-checked).- Exports are the surface. A cell package exports its constructor (
New(...)) and nothing else beyond seam-required types. Exported-but-unreferenced identifiers are findings. - Conformance is made loud — every cell carries the compile-time assertion, and
conform checks its presence (T-syn): the
go-conformance-assertionrule polices the gated cells — a package in[go] gatedthat declares a seam impl must carry itsvar _ seams.<Seam> = (*<Impl>)(nil), and a gated cell missing the assertion is a finding; exempt and ungated cells (the genuinely seamless ones included) are out of scope and are never falsely flagged. The assertion itself is real, idiomatic Go and the pattern below is correct. The parity this rests on — no projection enforces the discipline more weakly than another without a recorded reason — is a discipline law in the manifesto (spec://org.vibevm.ai-native/core-ai-native/00-MANIFESTO#PARITY-ACROSS-PROJECTIONS).
35// internal/cells/batchplanner/planner.go
//
//spec:implements spec://go-demo/PROP-001-reconciler#req-planner-seam r=1
//spec:cell seam=Planner variant=batch replaces=naive flag=planner
package batchplanner
var _ seams.Planner = (*BatchPlanner)(nil) // silent conformance made loud — MUST
func New(store seams.Store, clk clock) *BatchPlanner { /* … */ }
- 36Promotion to a separate module on the usual triggers: heavy optional deps, independent release cadence, ~2 kLoC.
3. Surface form: naming, position, uniformity
37req r1 (≈ Rust §2, TS §4)
- 38Names are token programs (R3-004, R-020). Canonical cell type name is computed
from the manifest:
{Variant}{Seam}→BatchPlanner; the package is the lower-case variant (batchplanner). Go practised this by hand; it is now machine-checked by the SAME rule as Rust —cell-name-is-computed, mounted ingo-ai-native-conform, reads the//spec:cell seam=… variant=…directive (the extract bridge renders it into the engine's one attr shape) and reds a name that is not the composed one. It checks composition only. Length is free; ambiguity is not. (Short closure-local bindings —i,ok,ctx— are idiomatic Go and exempt; the rule scopes to contract surfaces.) - The other halves of R3-004 — one name = one referent across contract surfaces, no synonym pairs or shadowing, and a closed vocabulary of structural tokens — are not built: no such checker or vocabulary exists in the tree (the owner's fork №1 took computed names; the closed-vocabulary variant was not taken), and no backlog entry exists for them yet.
- The family-prefix rule (owner policy; PROP-028 §2.4). Every named surface of the
Go discipline is language-FIRST, carrying the
go-ai-nativestem as a prefix: the umbrella binarygo-ai-native(cratego-ai-native-cli), the standalone toolsgo-ai-native-conform/go-ai-native-specmap/go-ai-native-tcg, the librariesgo-ai-native-conform-frontend/go-ai-native-extract-bridge/go-ai-native-specmap-scan/go-ai-native-tcg-bridge, the server package/binarygo-ai-native-mcp(agent-visible server name: the family,go-ai-native), the skillsgo-ai-native-sweep/go-ai-native-terraform. Language-NEUTRAL artifacts stay outside the stem (the shared engine crates carrycore-ai-native-*). - Contract-first ordering within an item (R3-002): the doc comment states behavior,
invariants, and the error contract; the
Examplefunction shows canonical use; both precede or immediately adjoin the declaration. Autoregression makes reading order conditioning order; intent goes first. - Position is a resource (R3-003): package-level invariants live in the package doc
block (
doc.go) or at file top; safety-critical facts never sit in a file's diluted middle third. Prefer more, smaller, single-purpose files at equal token mass — Go packages are natively multi-file, so splitting costs nothing (§15). Enforced, not promised: alongside the long-standingfile-lengthcheck on the budget,invariant-comment-positionfires through the normal gate when a comment whose marker is in the configured vocabulary lands in a file's middle third — linelwithlines/3 < l <= 2·lines/3(integer-divided; for a 120-line file, lines 41–80) — with the remedy move-to-edge-or-split; the marker vocabulary (invariant_comment_markers, default the five labeled markersINVARIANT:/WARNING:/PANICS:/MUST:/NEVER:— a marker is a labeled tag, not a bare word, so the colon is the markup signal) and the floor (invariant_comment_min_file_lines, default 120 — below it the whole file is skipped) are rootconform.tomlkeys shared across languages. Test-context markers are out of scope. - Uniformity is load-bearing (R3-006, H6) — and Go's culture already enforces most
of it. What remains ours: one idiom per operation within this repository (one way to
construct a cell, one error shape per seam, one fake per capability), and legitimate
exceptions are MARKED (
//spec:deviates … reason="…") so they do not propagate as false training signal.
4. The nine scaffolds in Go
39req r1 (≈ Rust §3, TS §5) — each is a card in this package's cards/; here is the
Go shape and the rule.
- 40A — Generators / codegen (
scaffold-a-generators).go:generateis the culture's own slot — the directive names the emitter next to its output's home;stringer-class tools,text/templateemitters, schema-to-type generation. Committed output is plain idiomatic Go; the generator input is the taggable unit; outputs are excluded from orphan checks. Rule: where an artifact is mechanically derivable from a smaller spec, ship generator + committed output + a CI regenerate-and-diff check, not hand-maintained output (A3). - B — Typed surfaces / defined types (
scaffold-b-typed-builders). Go's defined types are nominal for free —type AccountID stringdoes not interchange withstringor withtype OrderID stringat call sites: the identity-swap failure TS must brand away failsgo buildhere by default. Meaning-bearing primitives crossing a seam are defined types; required-field protocols are constructor-enforced (Newvalidates and is the only path — unexported struct fields make bypassing it a compile error); call-order protocols use staged builders; option lists use functional options. Typestate via phantom type parameters is possible since generics but is NOT idiomatic Go — use it only where a protocol genuinely demands compile-time ordering, and mark it. Rule: seam protocols are encoded in types and constructors, not docstrings; the wrong call failsgo build, not a runtime check (R3-008). - C — Runnable contracts (
scaffold-c-runnable-contracts). Go has nodebug_assert!; the projection is an explicitinvarianthelper (panics — an invariant violation IS the panic case, §5) restated at use sites (R3-009), plustesting/quick/ fuzz properties backing behavioral claims. Rule: every load-bearing invariant is witnessed by a runnable check where it is relied upon, not only documented at definition. - D — Differential / characterization oracles (
scaffold-d-differential-oracle). Native fuzzing is the engine: oneFuzzXxxtarget drives old and new cells through the seam and asserts agreement; the seed corpus lives intestdata/and runs deterministically in CI (go testruns seeds;-fuzzexplores locally). Golden files live intestdata/under the promotion protocol — the conventional-updateflag never runs in CI. Rule: no replacement of a non-trivial cell merges without a differential or characterization oracle against prior behavior (R-040). - E — Per-cell fast loop (
scaffold-e-fast-loop).go test ./internal/cells/<name>/ -raceanswers in seconds with zero setup — the strongest Class E substrate of the three stacks. The agent loop is edit → per-package test → read structured error → edit; first signal < ~60s (R3-007). Rule: whole-repo CI is not an agent loop; the per-cell loop is the substrate that makes every other scaffold's signal fast enough. - F — Structured, REQ-citing diagnostics (
scaffold-f-structured-diagnostics). Two of the three channels are built: a seam's closed error set carries itsSpecfield and rendersviolates REQ <spec-uri>: <why>; fix surface: <where>inError()(§5; the structure + message halves, enforced bygo-seam-error-cites-reqingo-ai-native-conform, B-033), and conform findings ship as SARIF. The grammar is the engine's one renderer/acceptor pair (req_message/matches_req_grammar), so the custom checks that exist already speak it. Not built — the third channel: a customanalysis.Analyzerwhose message names the rule and the remedy. The promise does not name a vehicle ("custom checks emit the same grammar"); the natural carrier is a standaloneanalysis.Analyzermodeled on thestaticcheck/exhaustiveanalyzers the floor already invokes (a singlego installbinary, same shape as those). The promise stands, the build is planned, and the route is recorded:BACKLOG.md {#b-050}(owner ruling 2026-08-04; the Go half rides the same entry as Rust's). Rule: every custom check and every seam error is agent-actionable — REQ URI + fix surface, never bare free text (R3-011). The parity behind it — no projection enforces the discipline more weakly than another without a recorded reason — is a discipline law in the manifesto (spec://org.vibevm.ai-native/core-ai-native/00-MANIFESTO#PARITY-ACROSS-PROJECTIONS); the asymmetry that TypeScript has this channel built and Go does not yet is held by its sibling law (spec://org.vibevm.ai-native/core-ai-native/00-MANIFESTO#PARITY-GAP-IS-NEVER-SILENT), recorded with a reason and a route, not in silence. - G — Executable examples (
scaffold-g-doctests).Examplefunctions are real doctests, and stronger than Rust's:ExampleXxxwith an// Output:comment is compiled AND executed bygo test, its stdout diffed against the comment — a behavioral guarantee, not just compilation. Rule: every public seam item carries ≥1Exampleof canonical construction+use with// Output:where output is deterministic; an example that lies fails the build (R2C-004, H4). - H — Local simulators / reference models (
scaffold-h-simulators). Hand-rolled in-memory fakes are Go's native test culture (small interfaces make them one-screen literals);httptestis a stdlib network simulator; subsystems with non-obvious dynamics (a reconcile loop, a state machine) ship a steppable reference model. Rule: non-obvious dynamics ship a runnable model or fake, not a prose description (DR2-019). - I — Scaffolded edit operations / codemods (
scaffold-i-codemods).gofmt -rfor pattern rewrites;go/ast+go/formatcodemods for structural ones; the shippedgo-ai-native codemod add-cellemits a cell skeleton (package, conformance assertion, directive tags, registry arm, Example stub) as ONE checked operation. Rule (provisional, [E-hyp]): a capability-demanding multi-file edit is offered as one parameterized checked operation; validate weak-agent parameterization in pilot.
5. Errors as contract surface — and goroutines as owned resources
41req r1 (≈ Rust §4, TS §6)
42Go made errors values twenty years before it was cool; the Discipline makes their sets part of the contract:
- 43Each seam owns a closed, enumerated error set:
44// PlanError is the Planner seam's closed failure set.
type PlanErrorCode int
const (
ErrConflict PlanErrorCode = iota + 1 // desired and actual disagree irreconcilably
ErrUnknownKind // a resource kind outside the seam's vocabulary
)
type PlanError struct {
Code PlanErrorCode
Spec string // the violated REQ URI: "spec://go-demo/PROP-001-reconciler#req-plan-total"
Err error // wrapped cause, if any
}
func (e *PlanError) Error() string {
return fmt.Sprintf("plan: %v: violates REQ %s", e.Code, e.Spec)
}
func (e *PlanError) Unwrap() error { return e.Err }
45Consumers use errors.As against the published type and switch on Code; boundary
rendering appends the REQ URI and a fix surface (PROP-014 §2.6; Class F).
- 46Banned at seams: matching on error strings;
fmt.Errorfwithout%w(breaks the chain); anonymouserrors.Newfor expected failures;errorreturns that are sometimes nil-with-meaning. - Exhaustiveness — the deepest gap, carried by a linter and named honestly. Go has
no sum types and no exhaustive
switch; closed sets are const-enums, and theexhaustivelinter supplies what the compiler won't. This is the one Discipline rule in the Go projection enforced entirely by an external evidence provider; the honest degradation is stated rather than papered over. Adefault:arm on a closed-set switch is the graveyard move (it silences the linter) — banned; where a trap arm is genuinely needed it panics, and the linter still checks the named cases. - panic = invariant violation — the analog is native, same word.
recoveris legal only at goroutine/boundary top level (middleware,main), never as control flow in cells; panicking on an expected failure is banned. - Structured concurrency by ownership. Every goroutine a cell starts has an owner:
errgroup.Group(BSD-3) orsync.WaitGroup+ context cancellation; a nakedgowhose goroutine can outlive its cell is banned; channels are owned and closed by their spawner; channel topologies are implementation, never API (§7). The unowned goroutine is Go's unreferencedcreate_task— with no GC to even cancel it. - The release map is free. Every Go binary embeds
runtime/debug.ReadBuildInfo(VCS revision, dirty flag, module versions), readable from the artifact (go version -m). The A1 chain binary → build info → specmap@commit → REQ needs zero extra machinery; the only rule is not to strip what the runtime gave you.
6. Registry, flags & the composition root
47req r1 (≈ Rust §5, TS §7)
48R-001 binding — flag at the seam, never in the veins:
49// internal/registry — the only flag reader and the only package
// permitted to import cell packages.
func Planner(cfg Config, store seams.Store, clk seams.Clock) seams.Planner {
switch cfg.Planner { // provenance: default | env | cli | lockfile
case PlannerBatch:
return batchplanner.New(store, clk)
default:
return naiveplanner.New(store)
}
}
- 50Two tiers, never confused: build tags (
//go:build) answer "is the code in the binary" — the cargo-feature analog, per-file granularity — and are confined to registry/adapter files, never inside cell bodies (T-lex); runtime flags answer "is the cell selected", read once into a config struct inmainand passed down. - Delivery-mode honesty: Go has no credible lazy in-process loading (the
pluginpackage is platform- and version-locked); eager is the only mode; presence is the build tier's job. - No
ServiceLoader-style discovery (§2'sinit()ban already killed it), no reflection-based wiring, no DI frameworks. The registryswitchis the system's table of contents.
7. Bans and their escape hatches — the Go theater list
51req r1 (≈ Rust §6, TS §8)
52Forbidden by default in domain cells; legal only with //spec:deviates <uri> r=<N>
reason="…" and the required machinery.
53These are Go's OOD tail and its action-at-a-distance set:
- 54
init()and blank imports (§2) — the import-time registration culture stops at the boundary ring. - Reflection in domain code (
reflect,Type.Implements, struct-walking) — the second language Go bifurcates into at boundaries (encoding, ORMs) stays there. - Struct-tag DSLs outside boundary DTOs — tags are stringly programs interpreted by reflection at runtime; domain types carry none.
interface{}/anyin domain signatures where a type or a small interface fits.- Channels as API — a seam exposes methods; channels are implementation. Clever fan-in/fan-out topologies as public surface are hidden control flow (R-021).
recoveras control flow; panic-driven non-local exits inside cells.- Package-level mutable state — the module-level singleton in its Go form
(
http.DefaultClientis the stdlib's own disguise). - Behavior-bearing struct embedding — embedding to inherit method sets across domain types is inheritance cosplay; compose via fields and explicit delegation. (Interface embedding in interface declarations is fine — that is composition of contracts.)
unsafeand cgo outside designated boundary files — cells are pure checkable Go.- Method sets split across files to obscure a type; a type's methods live with it.
55A ban with no escape hatch is a discipline bug; a deviation with no reason is a code bug.
8. Metadata layer (specmap in Go)
56req r1 (≈ Rust §7, TS §9)
57Directive comments — a deliberate divergence from doc-comment tags, forced by the
toolchain: since Go 1.19 gofmt reformats doc comments (would re-wrap prose tags) but
preserves //name:value directive lines verbatim, and godoc hides them.
58Go already owns
the cultural slot (//go:generate, //go:embed); the Discipline takes //spec::
59//spec:implements <uri> r=<N> one edge per line; lines repeat
//spec:deviates <uri> r=<N> reason="..." reason mandatory
//spec:verifies <uri> r=<N> above Test/Fuzz/Example functions
//spec:scope <uri> r=<N> in the package doc block (doc.go) —
package-level inheritance
60Edge kinds mirror PROP-014 (implements | verifies | documents | deviates | informs);
≤3 edges per item or split; two-tier revisions (author-asserted r + content hash) with
asymmetric invalidation (spec bump → edges suspect; code change → edges stay valid); a
derived deterministic committed index (specmap.json); an orphan ratchet over exported
identifiers.
61Generated code is excluded; the go:generate input is the taggable unit.
62The trade-off is named honestly: provenance disappears from rendered godoc and lives in
trace/the ledger instead (the deliberate opposite of Java's @Documented choice).
9. Prose discipline (the asymmetric hazard)
63req r1 (≈ Rust §8, TS §10)
64Wrong prose is worse than no prose (R2C-004, H4): models condition on in-repo text with high trust, so a lying comment is adversarial input, and the harm exceeds absence.
65Go-specific sharp edge: godoc comments are the language's celebrated documentation surface — and nothing checks them.
66Rule: behavioral claims near code are
machine-checked — backed by an Example with // Output: (which executes) or a
test — or explicitly trust-labeled (verified / unverified / aspirational).
67A godoc line that merely restates the signature is duplication (a defect); misleading log strings count too (the harm is the false claim, not the syntax).
68Godoc remains the human detail layer; duplication with the spec is a spec defect.
10. Replacement protocol
69req r1 (≈ Rust §9, TS §11)
70Replacing a cell ships a differential oracle (Class D): a fuzz target driving old
and new cells through the seam, asserting agreement modulo a documented divergence list,
//spec:verifies-tagged, run with -race, its seed corpus committed under testdata/.
71Characterization goldens live in testdata/ and follow the promotion protocol — CI
never regenerates; a local update carries a debt/intent reference in the commit body.
72xfail honesty [Go-specific]: Go has no native strict-xfail and this guide bans
t.Skip on known-failing tests (a skip hides both regressions and healings) — known
failures live ONLY in discipline/registry/tests-baseline.json, which carries full
weight here: Go is the one stack of the three without an in-source xfail twin, stated
rather than hidden.
11. Test matrices
73req r1 (≈ Rust §10, TS §12)
74Table-driven tests are Go's native idiom and the Discipline's declared matrix in one
— a named, bounded case slice with t.Run subtests, never an implicit 2^n:
75cases := []struct {
name string
in State
want []Action
}{ /* … the matrix is authored data … */ }
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) { /* … */ })
}
76testing/quick covers simple property surfaces (stdlib; adequate for the demo class);
fuzz targets cover differential and parser-shaped surfaces; the differential oracle
(§10) covers replacement; per-cell tests run in the fast loop.
77Third-party property frameworks are admitted case-by-case under the licensing flow when quick runs out.
12. How a weak reader actually uses this guide
78(≈ Rust §11, TS §13)
79The weak swarm does not read this guide.
80It receives, per edit, the Band-3 ops extract of whichever cards' triggers fire — a small, activation-matched set (lazy-push, R3-014; minimal sufficiency, AGENTbench).
81This guide and the cards are the
authoring/review artifact for the strong author and the human; the runtime surface for a
.go edit is a card from this package's cards/, never another language's.
82Cross-cutting concerns the per-edit loop cannot hold are swept by raids
(03-RAID-PLAYBOOK.xml).
13. Tooling roadmap pointer (the tcg line)
83(≈ Rust §12, TS §14)
84The tcg line has two briefs, split by where the intervention happens:
- 85
go/tools/vibe-agentic-tcg-go.xml— SHIPPED (the agentic oracle): a consultation oracle over the CONSUMER's own gopls — validate an in-memory overlay / in-scope symbols / type-valid completions / quick info at millisecond-class latency, discipline-enriched in-process by the same conform engine as the gate — behind the same language-parameterisedtcg_*MCP tools (language: "go") and one-shot CLI forms. Mechanisms:mechanisms/TCG-ORACLE-GO-v0.1.xml,mechanisms/TCG-PROTOCOL-GO-v0.1.xml. Fidelity, honestly: gopls stands ongo/types— the reference library implementation of the language spec — while the gc compiler runs types2, its deliberately-synchronized twin. The Go oracle therefore sits BETWEEN the TS oracle (which IS tsc's engine) and the Rust one (rust-analyzer is NOT rustc): far tighter than an independent reimplementation, still not the compiler itself. The floor stays the truth. go/tools/go-ai-native-tcg.xml— VERY-FAR-FUTURE (token-level): logit masking to type-valid, discipline-conformant continuations. Owner-dispositioned 2026-07-17: not until an inference substrate exists; the brief is held at stub depth, at parity with the TS stub.
14. Wiring a consumer (the shipped toolchain)
86req r1 (≈ Rust §13, TS §15)
87The stack ships the toolchain as runnable code (PROP-024); a consumer wires it in five moves:
- 88Install the stack —
vibe installwithstack:org.vibevm.ai-native/go-ai-native-langin[requires].packagesmaterialises the slot undervibedeps/(the neutral engines ride along as vendored copies; the slot is its own Cargo workspace and builds standalone). A Rust-hosting consumer keeps[workspace] exclude = ["vibedeps"]. - Get the binaries —
vibe bin buildthenvibe bin exec go-ai-native -- <args>(PROP-025 lockfile dispatch), orcargo install --path vibedeps/<stack-slot>/crates/go-ai-native-cli, or run in place viacargo run --manifest-path vibedeps/<stack-slot>/Cargo.toml -p go-ai-native-cli --bin go-ai-native -- <args>. - Machine prerequisites — go ≥ 1.24 on PATH (or
GOROOT-resolvable) and gopls (go install golang.org/x/tools/gopls@latest): installing this stack obliges the machine to carry both — inside the stack's own suite an absent tool is a recipe-carrying FAILURE, never a skip. staticcheck / exhaustive are optional evidence providers the floor policy names. - Bootstrap —
go-ai-native initwritesconform.toml([go]: roots,cells_dir,seams_pkg,registry_pkg— topology detected fromgo.mod),specmap.toml(namespace + discovered[[external_specs]]), both ratchet baselines, and the BROWNFIELD registries; thengo-ai-native specmapmints the index andgo-ai-native floorruns the seven steps (gofmt → vet → test → staticcheck+ exhaustive → conform → specmap → test-gate). Brownfield adoption: the/go-ai-native-terraformskill. - The generation-time oracle (optional but cheap) — before writing a nontrivial
.goedit, validate the HYPOTHETICAL content:vibe bin exec go-ai-native-tcg -- validate internal/cells/<cell>/<file>.go --content-from - --root .(the edit on stdin; exit 1 = an error-grade diagnostic or a non-baselined finding), or thetcg_validate/tcg_scope/tcg_complete/tcg_typeMCP tools withlanguage: "go". The floor stays the truth; the oracle exists so the floor stays green on the first try.
15. Sweep idioms (Go)
89(≈ Rust §14, TS §16) — the recurring posture is the shipped Sweep Playbook driven by
/go-ai-native-sweep; the Go-specific idioms:
- 90Danger-band splits are the cheapest of the three stacks: a Go package is natively
multi-file — move a cohesive slice of an oversized file into a sibling file of the
SAME package (no module surgery, no re-exports, imports unchanged). The new file
inherits the package's
//spec:scopefromdoc.goautomatically; a file carrying its own//spec:item tags keeps them with the moved items. Measure with the rule (physical lines), not the eye. - The four Example idioms (export doc-example drain): a construct-and-
Error()assert for seam error types (the Class-F message already cites its REQ, so the example doubles as a navigability demo); an encode/decode round-trip for boundary DTO types; a zero-value/enumerator demo for const-enum sets; a canonical construct-and-use for each seam (via the blessedNew). - Suppression drains: a reasonless
//lint:ignore///exhaustive:ignoreis unrecorded testimony — reason it or fix it; at.Skipon a known-failing test moves totests-baseline.json(§10) the day it is found. - Census regressions (gated packages must hold zero):
init_in_cell,ambient_call_in_cell,naked_go_in_cell,error_string_match,seam_error_missing_req— restructure beats testify: encode the invariant in a type or constructor rather than recording an excuse. Where these live in the shipped tooling:go-extractemits the kinds, thego-unsafe-in-domainconform rule reports them — exceptseam_error_missing_req, which since B-033 is owned by the dedicatedgo-seam-error-cites-reqrule (its structure half) — andgo-ai-native healthsummarises them into the snapshot'sban_censusblock. Two names above are the shipped kinds verbatim (error_string_match,seam_error_missing_req); the other three are this guide's cell-scoped reading of kinds the extractor names without the suffix —init_in_cellisinit_decl,ambient_call_in_cellisambient_call,naked_go_in_cellisnaked_go— because the engine expresses "in a cell" as a scope predicate overcells_dirrather than as part of the name. - Flip-only-after-drain: a package enters
[go] gatedonly at zero findings; the collector (go-ai-native health) names promotion candidates and ranks the drain backlog smallest-gap-first; a flip must never widen a baseline.