The gate gains seam-error and conformance-assertion parity across languages
01Companion to: BACKLOG.md B-033 (closed by f882cd46) (the dedicated Go seam-error rule + its message half + the TS twin), B-030 (closed by 1ef63a37) (conformance-assertion presence — build Go, survey Rust/TS), B-049 (closed by e4314e83) ([rust] floor_disable); the fork it discharges is TOOLING-MAP.md §5 №9 (the parity-principle home, taken). Evidence, measured before any build: e11-r1-seam-errors-census.md (the seam-error paradigm, two halves) and e11-r2-assertions-census.md (the assertion idiom, Rust/TS survey). The prior batch's design is gate-parity-config.xml — this one builds on its symmetric per-language surface. Non-normative; the PROPs and the backlog rulings win.
1. The measured basis
02Seam errors — one paradigm, three states (census R1). The Rust
paradigm is one fact (Fact::ErrorVariant, facts.rs:66-73) carrying both the
Display message and the owning-enum enum_attrs, and two rules each gating a
different field: ErrorMessageCitesReq (diagnostics.rs:229-282, fires when the
Display text carries no spec://) and ErrorEnumCitesReq (:308-366, fires when
the enum carries no #[spec(...)]). Go has only the structure half — the
seam_error_missing_req finding-kind INSIDE the go-unsafe-in-domain umbrella
(rules/go.rs:145-149), emitted by go-extract when a *Error type owning an
Error() method has no Spec field (extract.go:519-535); no rule id of its
own, and the message half (does Error() render the REQ?) is checked by nobody
because go-extract never reads an Error() body (census R1 Q2). TS has
neither half — no error fact, no error rule; the extractor emits nothing carrying
union shape, variant members, or a spec:// reference on an error type (R1 Q4),
though the guide promises «E a discriminated union of named error variants
carrying spec:// REQ references» (GUIDE-AI-NATIVE-TYPESCRIPT.xml:152,159).
03Conformance assertions — Go idiom live, gate blind (census
R2). The Go idiom var _ seams.X = (*Impl)(nil) is live (four demo sites, the
guide's own — MUST example at GUIDE-AI-NATIVE-GO.xml:201) and the guide
PROMISES «conform checks its presence (T-syn)» while self-annotating that promise
as not-yet-built (→ B-030). But go-extract actively discards the assertion:
the ValueSpec branch skips every _-named var (extract.go:461-463,
«conformance assertions et al.»), so no fact reaches the engine. Rust has no
var _ analogue rule — cargo check at the use site IS the assertion
(GUIDE-AI-NATIVE-RUST.xml:68), and the guide makes no promise that a gate checks
a written assertion (R2 Q3). TS promises branded seams / satisfies never /
type-level tests (GUIDE-AI-NATIVE-TYPESCRIPT.xml:130,154,237); the gate checks
none and the extractor emits no fact for any (R2 Q4).
04The floor asymmetry (B-049, parity loop row 13). Go and TS
consumers disable a floor step with a recorded reason (GoConfig/TsConfig
floor_disable, enforced with a loud print + hard-fail on an unknown step); the
Rust floor (rust-ai-native-cli/src/floor.rs:46-141) runs every step
unconditionally and RustConfig has no such field — the loop's one asymmetry
pointing the wrong way.
05The wire every new signal rides (census R1 Q5, R2 Q2). The
ts_env_read pathway (B-039) is the proven four-hop template:
extractor emit → bridge RawFact arm → engine Fact → rule match → driver mount.
Adding a Fact variant bumps the frontend version and retires cache slots
(facts.rs:5-8) AND is a cross-package ripple (batch-1 lesson, §8 sixth paid
fact); adding a Kind VALUE to the existing GoUnsafe fact is neither.
2. The boss decisions (no owner fork inside this batch)
06No map fork opens here. The two nearest owner forks are taken (№2 gate units, №9 parity home). Every choice below is a boss design decision on measured fact, not an owner decision — recorded so the workers elaborate, never redraw. Should elaboration surface a genuine owner fork, it stops for the owner one at a time (the standing rule); none is expected.
07One Go rule, both halves, per-half fingerprints. The Go doc
promises a single named rule — «seam-error-cites-req — a seam's closed error set
carries its REQ URI» (conform-frontend-go.xml:41). Go's idiom is one struct type
with two obligations (carry the spec:// URI as a Spec field; render it in
Error()), so the projection is one rule go-seam-error-cites-req, not two.
Rust's two-rule split is an artifact of its two-field fact, not a strength Go
lacks: one Go rule checking both halves is not weaker than two Rust rules checking
one half each (the parity test is strength, not id count — §4). The baseline
granularity Rust's two ids give is preserved by two distinct fingerprints off
the one rule (…-structure|… and …-message|…), so the ratchet still tightens
each half independently and SARIF still separates them.
08The TS twin builds now, conservatively, with its limit
recorded. The parity principle (being lifted this batch) forbids leaving TS
weaker without a recorded reason, and «TS has nothing» is not a reason — it is the
gap. So ts-seam-error-cites-req is built now. Detection is the honest-minimal
form (the batch-1 ts-flag-sites precedent: build the detectable core, record the
undetectable remainder as a documented limit, never a silent claim). The exact
discriminated-union-error heuristic is a measured refinement point (§3.3).
09B-030's survey verdicts. Go — build the presence
rule; the written var _ assertion is the one seam-conformance signal that can
drift, so a presence check earns its keep (owner ruling 2.2a). Rust — record
the reason, do not build: the compiler at the use site is the assertion
(GUIDE-AI-NATIVE-RUST.xml:68); the guide promises no gate-checked written
assertion, so there is no promise-without-check to close — a genuine recorded
reason, not a refusal. TS — record and route: the guide's promise that
public branded/union surfaces carry type-level tests (:237) IS a
promise-without-check, but its build (detecting expectTypeOf/tsd/
@ts-expect-error/satisfies never presence) is a distinct rule over a distinct
surface from the Go var _ scan; it is named as parity debt carried by the B-035
loop, not silently dropped and not crammed into this batch (BUILD-FIRST is
honoured by a named carrier, not by same-batch delivery).
10The fact plan (ripple-minimising). The Go message half rides a
new GoUnsafe KIND seam_error_message_no_req — no new Fact variant, no ripple.
The Go assertion signal needs seam+impl names the GoUnsafe {kind, line} fact
cannot carry, and overloading the ban-census go_unsafe with a POSITIVE signal is
semantically wrong — so a new Fact::GoConformance variant. The TS seam-error
signal needs union/citation shape no existing TS fact carries — a new
Fact::TsSeamError variant. Two new variants → two ripples; the engine-spine
worker greps the whole tree and budgets exhaustive-match arms in every frontend
(§5, S1).
3. The design past the decisions (boss-settled, worker-elaborated)
3.1 B-033 Go — go-seam-error-cites-req
11Structure half — promote, don't rebuild. The
seam_error_missing_req go_unsafe fact already flows (extractor unchanged for
this half). Build a dedicated rule GoSeamErrorCitesReq (rules/go.rs) that
matches Fact::GoUnsafe { kind: "seam_error_missing_req", .. } and emits under
go-seam-error-cites-req with fingerprint go-seam-error-cites-req-structure|{file}|{line};
remove the seam_error_missing_req arm from GoUnsafeInDomain (:145-149) so
the kind is owned by exactly one rule. Уточни (worker): the exact current arm
lines and the deviation-honour / !in_test guards to carry across verbatim
(rules/go.rs:96-98, :145). Проверь: the seam_error_missing_req kind is
listed in the engine kinds docstring (facts.rs:119-128) and stays.
12Message half — the new go-extract input. go-extract gains
the ability to read an Error() method body's rendered text and emit
GoUnsafe { kind: "seam_error_message_no_req", line } when the type owns an
Error() whose format/return strings carry no spec:// substring — the direct Go
analogue of Rust's message.contains("spec://") gate (diagnostics.rs:260). The
new dedicated rule consumes this kind too, fingerprint
go-seam-error-cites-req-message|{file}|{line}. Измерь и подставь (worker): the
minimal AST reach to get Error() string literals — today errorMethodOwners
(extract.go:499-515) reads only the receiver, never the body; the body walk must
collect string-literal operands (fmt.Sprintf template, returned string
constants) and test for spec://. Уточни: fire on the *Error-owning-Error()
type at the type-decl line (the same anchor the structure half uses), so a type
missing BOTH halves reports two findings at one site, distinct fingerprints. Проверь:
the clean live demo (research/go-demo/internal/seams/errors.go:35-40, renders
violates REQ %s) stays green and the dirty fixture
(test/fixtures/dirty/internal/cells/plan/plan.go:22, renders plan: %d) goes
red on the message half.
3.2 B-033 TS — ts-seam-error-cites-req
13The new signal. ts-extract emits a ts_seam_error record for
a discriminated-union error type alias, carrying: the alias symbol, whether it
cites a spec:// REQ (via a JSDoc @implements/@documents marker on the alias
OR a spec:// substring in a variant member), and the line. The bridge lowers it
to Fact::TsSeamError { symbol, cites_req, line, in_test }; the rule
TsSeamErrorCitesReq fires when !cites_req, fingerprint
ts-seam-error-cites-req|{file}|{symbol}.
14The detection heuristic — measured, conservative (refinement
point). Измерь и реши (worker), recorded in the report's Decisions: what makes
a type alias «an error union E» in the ts-extract AST. The conservative default
to measure against research/ts-demo and the guide's canonical form
(GUIDE-AI-NATIVE-TYPESCRIPT.xml:152,157,159): a type alias whose RHS is a union
(ts.UnionTypeNode) of object-literal members each carrying a discriminant
property (kind/tag/_tag), where the alias participates in an error position
(named *Error/E, or the second type argument of a Result<T, E>). Pick the
tightest form that matches the guide idiom and does not false-positive on
non-error unions; whatever the heuristic cannot see is recorded as a documented
limit in the guide, never silently claimed (the ts-flag-sites if(flag)
precedent). Проверь: ts-demo gains one citing error union (green) and a dirty
fixture carries a non-citing one (red).
3.3 B-030 Go — go-conformance-assertion
15The extractor stops discarding. go-extract recognises
var _ <seam> = (*<Impl>)(nil) in the ValueSpec branch BEFORE the _-skip
(extract.go:461-463) and emits a conformance-assertion record carrying the seam
interface name, the impl type name, and the line. Проверь (worker) — the
near-misses the pattern must NOT match: var _ = New and var _ *Type
(codemod.rs:61,63) are not conformance assertions — the match requires the exact
= (*Ident)(nil) RHS shape.
16The rule fires on absence (the cell-has-oracle shape).
GoConformanceAssertion keys on the cell set (existing cell/Item facts under
cells_dir) and the new Fact::GoConformance facts, and fires for a cell that
declares an impl of a seam with no matching assertion — the same absence-check
shape as CellHasOracle (structure.rs:148-180). Реши при постройке (worker,
recorded): the precise «a cell owes an assertion» predicate (every exported cell
type implementing a seam, or the cell's registered impl) — measure what the cell
facts already carry and pick the predicate the demo satisfies. Mounted conditional
on cells_dir (the GoCellIsolation template, go driver lib.rs:56-58), so a
project without cells never runs it; findings land soft through the ratchet
baseline until the tree is clean (##B030-FORM).
17The survey verdicts land as recorded reasons. Per
#dec-b030-verdicts: the Rust reason (compiler-is-the-assertion) and the TS
routed-build are written into the parity table's assertion row (B-035 loop) and
the guides' honest self-annotations — not left as silent asymmetries.
3.4 B-049 — [rust] floor_disable
18Mirror the Go/TS mechanic exactly. RustConfig gains
floor_disable (the uniform section shape already reserves the slot —
gate-parity-config.xml#fork-shape); rust-ai-native-cli/src/floor.rs reads it and
disables named steps with the twins' enforcement — a loud print of every
disablement and a hard-fail on an unknown step name. Проверь (worker): the step
names match the Rust floor's actual steps (floor.rs:46-141); an unknown name
fails loudly; a disabled step prints and is skipped. Disjoint from every other
slice in this batch (own files) — its own lane.
4. The parity-principle lift (boss contract diff, fork №9)
19The home, ruled. Map fork №9 (2026-08-04): «Ядро дисциплины» — the
language-neutral guiding layer of core-ai-native, manifesto level, one home, the
stacks cite. The carrier is 00-MANIFESTO.xml
§4 (where the strictness lives), a boss-authored clause set the language guides
cite.
20The principle (owner verbatim, 2026-08-02, B-035 anchor):
«Мы по условию идеи не должны делать поддержку других языков … хуже, чем это
сделано для Rust. А по факту мы почему-то начинаем ослаблять правила без видимой
причины». Lifted to a discipline law: no language projection enforces the
discipline more weakly than another; where a projection genuinely lacks an idiom's
analogue, the gap is recorded with its reason — never left silent. It is the
projection-level twin of ##BAN-WITHOUT-HATCH-IS-A-BUG: an unexplained asymmetry
between projections is a bug in the discipline exactly as a reasonless deviation is
a bug in the code. The pilot (Rust) is the current reference bar, not a permanent
privilege; Python inherits the law on arrival.
21The stacks cite, they do not restate. Each language guide adds
one citation to the new manifesto anchor beside its own conformance section (Go
##CONFORMANCE-IS-MADE-LOUD, TS ##RULE-FAILURE-ON-A-SEAM-IS-A-TYPED-VALUE, Rust
its scaffold-F row), so the principle has one home and N pointers — the
gate-parity-config home-and-pointers pattern.
5. The build cut
22S1 — engine spine (one thread, cargo-heavy): in canonical
core-ai-native/v0.8.0 only — facts.rs (Fact::GoConformance, Fact::TsSeamError,
the new seam_error_message_no_req kind documented in the kinds docstring);
rules/go.rs (GoSeamErrorCitesReq consuming both Go kinds with per-half
fingerprints, GoConformanceAssertion; the seam_error_missing_req arm removed
from GoUnsafeInDomain); rules/typescript.rs (TsSeamErrorCitesReq);
rules/mod.rs re-exports; engine unit tests feeding the new facts; the ripple —
grep the whole tree for exhaustive Fact matches and add arms for the two new
variants in every frontend (the Rust FE total sort, health census, any consumer).
Self-verify: canonical engine check + test + clippy -D warnings + wc -l ≤ 600
per changed .rs (split rules/go.rs along seams if it crosses the budget). One
thread because facts.rs/mod.rs are shared and the ripple crosses packages.
23S2a ∥ S2b — extractors + bridges (two disjoint lanes, after S1 lands +
sync-engines): S2a (Go): extract.go reads Error() bodies (emit
seam_error_message_no_req) and recognises var _ Seam = (*Impl)(nil) before the
_-skip (emit the conformance record); go-bridge gains the RawFact arm →
Fact::GoConformance (the message half rides the existing go_unsafe mapping —
verify the kind flows). S2b (TS): extract.ts detects the error union (§3.2
heuristic) and emits ts_seam_error; ts-bridge gains RawFact::TsSeamError →
Fact::TsSeamError. Disjoint files (go- vs ts-) → parallel. Self-verify: each
extractor's own go test / node --test + the bridge crate's cargo check/test.
24S3 — driver mounts + B-049 (parallel, disjoint): Go driver
build_rules mounts GoSeamErrorCitesReq (always) + GoConformanceAssertion
(conditional on cells_dir); TS driver mounts TsSeamErrorCitesReq; B-049 (its
own lane, may run as early as alongside S1 — disjoint from facts.rs/rules):
RustConfig.floor_disable + rust floor enforcement. Self-verify: each driver
crate's check/test/clippy; a live demo exhibit at real exit.
25S4 — docs + demo + fixtures + citations (doc lane, after the rules are
real): the Go guide's ##RULE-SEAM-ERROR-CONTRACT and ##CONFORMANCE-IS-MADE-LOUD
self-annotations die (the rule and the message half are built; the assertion
presence is checked); the TS guide's «Specified, not built» seam-error note dies
and its type-level-test routed-build is named honestly; the parity-principle
citation lands in all three guides (#lift-citation); demo/fixtures gain the
citing and non-citing exhibits for each new rule (red exhibit per new rule).
26The boss tail per slice: review by WORKER-REPORT (existence part
of the set-compare), cargo xtask sync-engines from the host root whenever a
package crate changed, cargo fmt --all + fmt per package manifest, vibe install
rematerialise after canonical package edits, cargo clean -p before diagnosing any
stale-fingerprint build, panel bare with the tail read on an untouched tree,
commits per Rules 1–4, meta.md per worker. After the batch: the B-035 loop pass
№2 re-cuts the parity table, and the F-185 family re-judgement drains through
vibe progress mirror --campaign → merge-verdicts.py → seal (never chained;
seal takes explicit paths).
6. Acceptance
27Measured, not narrated: (1) go-seam-error-cites-req is a
distinct rule id emitting two fingerprints — a dirty seam error red on both halves,
the clean demo green — exhibited; (2) ts-seam-error-cites-req reds a non-citing
error union and greens a citing one on the demo, its limit documented — exhibited;
(3) go-conformance-assertion reds a cell missing var _ Seam = (*Impl)(nil) and
ignores the var _ = New near-miss — exhibited; (4) the Rust floor disables a named
step with a loud print and hard-fails an unknown one — exhibited; (5) the parity
principle reads once in the manifesto and is cited by three guides; (6) the panel
green with the tail read; (7) the B-035 loop table shows no language cell weaker
than Rust without a recorded reason, and F-185's family re-judgement rides the
landing.