VibeVM
Contents
On this page
en
Publisher
org.vibevm.core
Version
1.0.0latest
Audiences
Reading time
11 min
Rendered
Read aloud
never

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. Gobuild 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). Rustrecord 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. TSrecord 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::TsSeamErrorFact::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 --campaignmerge-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.

For an agent

This page has a machine mirror. The citation carries the version rather than latest, so what an agent quotes does not move under it.

spec://org.vibevm.core/vibevm@1.0.0/design/seam-error-and-assertion-parity

.md.xmlllms.txt