<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">AI-Native TypeScript — The Guide</title>
  <status stage="spec" state="done"/>
  <p p="1"><fact id="status-line" status="impl/done">**Discipline v0.2 · status: BETA · T2 · TypeScript only (JavaScript gets a separate guide) · supersedes GUIDE-TYPESCRIPT-v0.1**</fact></p>
  <p p="2"><fact id="projection-onto-typescript" status="impl/done">*The projection of the Discipline onto TypeScript.*</fact></p>
  <p p="3"><fact id="GUIDE-COVERS-TYPESCRIPT-AS-A-TYPED-LANGUAGE" status="impl/done">*This guide covers TypeScript as a typed language in its own right — not JavaScript-with-types-bolted-on; the JS guide is separate and will address the untyped substrate.*</fact></p>
  <p p="4"><fact id="READ-THE-T1-CORE-FIRST" status="impl/done">*Read `00-MANIFESTO.xml` and `02-EXECUTABLE-SCAFFOLDS.xml` (the T1 core) first; this guide assumes the central law and the nine scaffold classes.*</fact></p>
  <p p="5"><fact id="A-HUMAN-CAN-READ-AI-NATIVE-TYPESCRIPT" status="spec/done">*A human CAN read and modify AI-Native TypeScript; it may be less comfortable to write by hand than ordinary TypeScript, but it remains ordinary idiomatic TypeScript at the token level.*</fact></p>
  <p p="6"><fact id="what-differs-is-the-envelope-lead" status="impl/done">*What differs is the envelope:*</fact></p>
  <list ordered="false" p="7">
    <item><fact id="ENVELOPE-MAXED-COMPILER-CONFIGURATION" status="impl/done">*the maxed compiler configuration,*</fact></item>
    <item><fact id="ENVELOPE-BRANDED-CONTRACT-BEARING-TYPES" status="impl/done">*branded contract-bearing types,*</fact></item>
    <item><fact id="ENVELOPE-RUNTIME-VALIDATION-AT-THE-ERASURE-BOUNDARY" status="impl/done">*runtime validation at the erasure boundary,*</fact></item>
    <item><fact id="ENVELOPE-EXECUTABLE-SCAFFOLDS" status="impl/done">*executable scaffolds,*</fact></item>
    <item><fact id="ENVELOPE-FAST-PER-CELL-LOOP" status="impl/done">*and a fast per-cell verification loop.*</fact></item>
  </list>
  <p p="8"><fact id="STRUCTURALLY-PARALLEL-TO-THE-RUST-GUIDE" status="impl/done">*Structurally parallel to `rust/GUIDE-AI-NATIVE-RUST.md` so the two projections stay comparable — that comparison is how the language-independent T1 layer gets validated.*</fact></p>
  <p p="9"><fact id="CROSS-REFERENCE-NOTATION" status="impl/done">*Section cross-references to the Rust guide are marked `(≈ Rust §N)`.*</fact></p>
  <p p="10"><fact id="TS-SPECIFIC-NOTATION" status="impl/done">*Where TypeScript has no Rust analogue (the configurable compiler, the erasure boundary, type-level testing), the section is marked `[TS-specific]`; those are the levers and the hazards that make the TypeScript projection heavier on bans and boundary validation than the Rust one, by design (§0).*</fact></p>
  <section id="law" title="0. Why TypeScript is special — and the law applied to TS">
    <quote p="11"><fact id="LAW-IDIOMATIC-INSIDE-ENGINEERED-AROUND" status="impl/done">**Idiomatic inside the file; engineered around the file.** *(≈ Rust §0)*</fact></quote>
    <p p="12"><fact id="TYPESCRIPT-IS-DEEPLY-IN-DISTRIBUTION" status="spec/done">TypeScript is deeply in-distribution (among the most common languages on GitHub), so ordinary typed application code and standard generic APIs are safe to be strict in.</fact></p>
    <p p="13"><fact id="TOOLING-CUTS-THREE-WAYS" status="spec/done">But TypeScript has, arguably, the most powerful *and most tractable* tooling of any mainstream language (its only rival for analyzability is C++ via the clang/LLVM backend), and that cuts three ways for the Discipline — two advantages and one hazard that has no Rust analogue.</fact></p>
    <p p="14"><fact id="ADVANTAGE-1-TCD-EXISTS-FOR-TYPESCRIPT" status="spec/done">**Advantage 1 — generation-time type-constrained decoding EXISTS for TypeScript.** The one result behind much of this work — type-constrained decoding cutting compile errors ~74.8% — was measured *on TypeScript* (Mündler et al., PLDI'25; the only language with a real implementation, R2C-005 / DR1-014). *One of those two evidence ids does not resolve: `R2C-005` is authored (`##FINDING-R2C-005` in the core ATLAS), `DR1-014` is not — the roster runs `DR1-013`, then `DR1-015`, and no document in the tree defines a `DR1-014`. The claim itself stands on the cited paper and on R2C-005; the second id is a dead reference.*</fact></p>
    <p p="15"><fact id="RUST-ORACLE-IS-A-MULTI-YEAR-FUTURE-BET" status="spec/done">For Rust, that oracle is a multi-year future bet (`vibe-tcg` Stage 3).</fact></p>
    <p p="16"><fact id="TYPESCRIPT-COMPILER-AS-ORACLE-IS-AVAILABLE-TODAY" status="spec/done">For TypeScript it is available *today*: the compiler-as-oracle can run **during** generation, not only after.</fact></p>
    <p p="17"><fact id="tooling-story-flipped-in-typescripts-favor" status="spec/done">This flips the tooling story in TypeScript's favor (see §14).</fact></p>
    <p p="18"><fact id="ADVANTAGE-2-MATURE-CODEMOD-ECOSYSTEM" status="spec/done">**Advantage 2 — the most mature codemod/AST ecosystem of any language.** `ts-morph`, the TypeScript Compiler API, `jscodeshift`, and typed ESLint autofix make Classes A (generators), F (structured diagnostics), and especially I (codemods) far more achievable than in Rust — where Class I is [E-hyp] partly *because* the tooling is immature.</fact></p>
    <p p="19"><fact id="SCAFFOLDED-EDIT-OPERATIONS-ARE-NEAR-TERM" status="spec/done">In TypeScript, scaffolded edit operations are a near-term reality, not a research gamble.</fact></p>
    <p p="20"><fact id="HAZARD-TYPES-ARE-ERASED-AND-CAN-BE-LIED-TO" status="spec/done">**The hazard with no Rust analogue — types are erased and can be lied to.** Rust's types are load-bearing at runtime; TypeScript's are **erased**.</fact></p>
    <p p="21"><fact id="COMPILER-BELIEVES-AN-UNCHECKED-ASSERTION" status="spec/done">The compiler believes a `value as Foo` assertion with no runtime check behind it.</fact></p>
    <p p="22"><fact id="TYPE-SYSTEM-IS-A-DEFEATABLE-VERIFIER" status="spec/done">This means TypeScript's type system — unlike Rust's borrow checker — is a verifier you can *defeat by writing the right two words* (`as`, `any`, `!`, `@ts-ignore`).</fact></p>
    <p p="23"><fact id="THE-DEFEATING-WORDS-ARE-STATISTICALLY-COMMON" status="spec/done">For an AI reader this is dangerous precisely because those words are statistically common in training data.</fact></p>
    <p p="24"><fact id="CENTRAL-TYPESCRIPT-SPECIFIC-JOB" status="impl/done">The Discipline's central TypeScript-specific job is therefore to **forbid the moves that defeat the type system** (§8) and to **regenerate trust at runtime boundaries** (§2).</fact></p>
    <p p="25"><fact id="LAW-PROJECTED-ORDINARY-IDIOMATIC-TYPESCRIPT" status="impl/done">**The law, projected.** TypeScript source under this discipline reads as *ordinary idiomatic TypeScript*.</fact></p>
    <p p="26"><fact id="NO-INVENTED-SYNTAX" status="spec/done">No invented syntax — that would incur the out-of-distribution penalty (EsoLang-Bench: 0–11% on unfamiliar surface; in-context learning cannot teach it).</fact></p>
    <p p="27"><fact id="TYPESCRIPT-SECOND-OOD-EDGE-IS-TYPE-LEVEL-METAPROGRAMMING" status="spec/done">But TypeScript has a second OOD edge Rust lacks: its *type-level metaprogramming* (deep conditional types, recursive template-literal types, HKT emulation) is a sparse long tail that models handle far worse.</fact></p>
    <p p="28"><fact id="LAW-CLAUSE-EXPRESSIVENESS-UP-TO-IDIOMATIC" status="impl/done">So the law has a TypeScript-specific clause: **use the type system's expressiveness up to the point where the types stay idiomatic, and not one step beyond.**</fact></p>
    <p p="29"><fact id="TYPE-LEVEL-WIZARDRY-IS-TREATED-LIKE-UNSAFE" status="impl/done">Type-level wizardry is OOD and is treated like `unsafe` — isolated, justified, deviation-marked (§8).</fact></p>
    <p p="30"><fact id="STRICTNESS-LIVES-IN-THE-ENVELOPE-NOT-IN-CLEVER-TYPES" status="impl/done">The strictness we add lives in the *compiler configuration, the runtime boundary, the metadata, and the verification loop* — not in clever types.</fact></p>
    <p p="31"><fact id="TYPESCRIPT-STRICTNESS-IS-CONFIGURABLE" status="impl/done">Unlike Rust, where the borrow/type checker's strictness is fixed and free, in TypeScript that strictness is **configurable**, so the first move of the discipline is to turn it all on (§1).</fact></p>
  </section>
  <section id="compiler-config" title="1. Compiler configuration is discipline (the biggest free lever) `[TS-specific]`">
    <p p="32"><fact id="RUST-STRICTNESS-IS-FIXED" status="spec/done">Rust's strictness is fixed; you get the borrow checker whether you ask or not.</fact></p>
    <p p="33"><fact id="NON-STRICT-CONFIG-GIVES-ALMOST-NO-SAFETY" status="spec/done">TypeScript's strictness is **configurable** — a non-strict config gives "the syntax of static typing with almost none of the safety."</fact></p>
    <p p="34"><fact id="MANDATE-THE-STRICTEST-PRACTICAL-CONFIGURATION" status="impl/done">AI-Native TypeScript therefore **mandates the strictest practical configuration**, because every flag turned on is intent moved from prose into the compiler (A3).</fact></p>
    <p p="35"><fact id="COMPILER-IS-A-FREE-HALLUCINATION-DETECTOR" status="impl/done">The compiler is a free hallucination detector; we give it the maximum to check.</fact></p>
    <p p="36"><fact id="typescript-analogue-of-the-rust-guides-line" status="spec/done">This is the TypeScript analogue of the Rust guide's "the compiler is a free hallucination detector" (Rust §0) — except here we must *opt in* to it, flag by flag.</fact></p>
    <p p="37"><fact id="mandatory-tsconfig-floor-lead" status="impl/done">Mandatory `tsconfig` floor:</fact></p>
    <list ordered="false" p="38">
      <item><fact id="TSCONFIG-STRICT-TRUE" status="impl/done">`"strict": true` — bundles the eight base flags (`strictNullChecks`, `strictFunctionTypes`, `strictBindCallApply`, `strictPropertyInitialization`, `noImplicitAny`, `noImplicitThis`, `alwaysStrict`, `useUnknownInCatchVariables`).</fact></item>
      <item><fact id="TSCONFIG-BEYOND-STRICT" status="impl/done">**Beyond `strict` (NOT included, all mandatory here):** `noUncheckedIndexedAccess` (array/index access yields `T | undefined` — catches a whole class of "it's always there" hallucinations), `exactOptionalPropertyTypes` (distinguishes absent from `undefined`), `noPropertyAccessFromIndexSignature`, `noImplicitOverride`.</fact></item>
      <item><fact id="TSCONFIG-DEFECT-CATCHERS" status="impl/done">**Defect-catchers:** `noUnusedLocals`, `noUnusedParameters`, `noFallthroughCasesInSwitch`, `noImplicitReturns`, `allowUnreachableCode: false`.</fact></item>
      <item><fact id="TSCONFIG-ERASABLE-SYNTAX-ONLY" status="impl/done">**Forward-looking erasure flag:** `erasableSyntaxOnly` — restricts to syntax that erases cleanly (forbids runtime `enum`/`namespace`), keeping TypeScript a thin typed layer over JavaScript. This matters now that the native compiler (TS 7 / "Corsa") and Node's type-stripping treat types as erasable annotations. It is also AI-native: it removes constructs whose runtime behavior diverges from their syntax.</fact></item>
    </list>
    <p p="39"><fact id="TSCONFIG-IS-A-VERSIONED-DISCIPLINE-ARTIFACT" status="impl/done">The `tsconfig` is a **versioned artifact of the discipline** (a card-checked file), not a per-developer preference.</fact></p>
    <p p="40"><fact id="LOOSENING-A-MANDATORY-FLAG-REQUIRES-DEVIATES" status="impl/done">Loosening any mandatory flag requires `deviates` + reason.</fact></p>
    <p p="41"><fact id="RULE-STRICT-FLOOR-IS-SET-BY-CONFIG" status="impl/done">*Rule:* the strict floor is set by config and maxed out; "we use strict TypeScript" while disabling individual flags or bypassing them with `@ts-ignore` is a discipline violation.</fact></p>
  </section>
  <section id="erasure-boundary" title="2. The erasure boundary: regenerate trust at runtime edges `[TS-specific]`">
    <p p="42"><fact id="ERASURE-BOUNDARY-IS-WHERE-GUARANTEES-END" status="spec/done">Because types vanish at runtime, the boundary between the typed interior and the untyped exterior (network, JSON, `process.env`, user input, third-party `any`) is where the type system's guarantees end and a model's false confidence begins.</fact></p>
    <p p="43"><fact id="BOUNDARY-REQUIRES-SINGLE-SOURCE-RUNTIME-VALIDATION" status="impl/done">At that boundary the Discipline requires **runtime validation from a single source that is simultaneously the static type and the runtime checker** — a schema library (Zod, Valibot, ArkType, TypeBox).</fact></p>
    <p p="44"><fact id="ONE-DECLARATION-YIELDS-TYPE-AND-PARSER" status="spec/done">One declaration yields both `type User = z.infer&lt;typeof UserSchema&gt;` and `UserSchema.parse(input)`.</fact></p>
    <p p="45"><fact id="SCHEMA-FUSES-THREE-SCAFFOLDS" status="impl/done">This fuses three scaffolds (A generator + B typed surface + C runnable contract) into one TypeScript-shaped artifact — the densest single move in the projection.</fact></p>
    <p p="46"><fact id="RULE-EXTERNAL-DATA-ENTERS-AS-UNKNOWN" status="impl/done">*Rule:* untyped external data enters as `unknown` (never `any`) and is narrowed only through a runtime validator or an assertion function (§5, §8); a bare `as` on external data is forbidden (§8).</fact></p>
    <p p="47"><fact id="SCHEMA-IS-THE-BOUNDARYS-CONTRACT" status="impl/done">The schema is the boundary's contract; inside the boundary the compiler is trusted, outside it is not.</fact></p>
    <p p="48"><fact id="re-establishing-the-verifiers-guarantee" status="impl/done">This is the TypeScript form of "the compiler is a verifier we maximize" — we re-establish the verifier's guarantee at exactly the points where erasure would otherwise silently void it.</fact></p>
  </section>
  <section id="cells" title="3. Cells, closure, ownership *(≈ Rust §1)*">
    <p p="49"><fact id="cell-is-the-unit-of-modification-lead" status="impl/done">The **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.</fact></p>
    <list ordered="false" p="50">
      <item><fact id="CELL-GRANULARITY" status="impl/done">Granularity: a module (file) or a small directory with a single public entry (`index.ts` as the seam), with promotion criteria to a larger cell when cohesion demands.</fact></item>
      <item><fact id="EXPLICIT-IMPORTS-ONLY" status="impl/done">**Explicit imports only; no barrel-file ambient re-export sprawl** that hides the dependency graph. Cells import seams + core, never sibling cells' internals (R-002).</fact></item>
      <item><fact id="OWNERSHIP-ALIGNS-WITH-FILE-BOUNDARIES" status="impl/done">**Ownership aligns with file boundaries** (R3-013): one cell = one file-set with one public entry. God-modules and giant barrel files serialize the swarm and obscure closure — an anti-pattern. Shared facts go to append-only ledgers, not shared mutable modules.</fact></item>
      <item><fact id="AMBIENT-COUPLING-IS-FORBIDDEN" status="impl/done">Ambient coupling — module-level mutable singletons, global augmentation, ambient `declare global`, config read outside the composition root — breaks closure and is forbidden outside the composition root (R3-001).</fact></item>
    </list>
  </section>
  <section id="surface" title="4. Surface form: naming, position, and the structural-typing trap *(≈ Rust §2)*">
    <list ordered="false" p="51">
      <item><fact id="NAMES-ARE-TOKEN-PROGRAMS" status="impl/done">**Names are token programs** (R3-004, R-020): one name = one referent across the contract surface; no shadowing, no synonym pairs; structural tokens from a closed vocabulary. Length is free; ambiguity is not. (Short closure-local bindings are exempt — scope the rule to contract surfaces.) The computed-name half of R3-004 is enforced on Rust and Go by `cell-name-is-computed`; **TypeScript is outside that rule by record, not by oversight** — a TS cell carries no `seam`/`variant` manifest, so there is nothing to compose, held by the parity law `spec://org.vibevm.ai-native/core-ai-native/00-MANIFESTO#PARITY-GAP-IS-NEVER-SILENT`. The remaining halves (closed vocabulary, one referent, no synonyms) are unbuilt in every projection and have no backlog entry yet.</fact></item>
      <item><fact id="FAMILY-PREFIX-RULE" status="impl/done">**The family-prefix rule (owner policy, 2026-07-07; supersedes the `-typescript` suffix rule).** Every named surface of the TypeScript discipline is language-FIRST: it carries the family stem `typescript-ai-native` as a *prefix*, not a `-typescript` suffix (PROP-028 §2.4). The umbrella binary is the family name itself (`typescript-ai-native`, over `init` / `floor` / …; its crate `typescript-ai-native-cli`); the standalone tools and their crates share `typescript-ai-native-&lt;role&gt;` (`typescript-ai-native-conform`, `typescript-ai-native-specmap`, `typescript-ai-native-tcg`, and the libraries `typescript-ai-native-conform-frontend`, `typescript-ai-native-specmap-scan`, `typescript-ai-native-tcg-bridge`, `typescript-ai-native-extract-bridge`); the server package/crate/binary is `typescript-ai-native-mcp` and the agent-visible server name is the family (`typescript-ai-native`); the skills are `typescript-ai-native-sweep` / `typescript-ai-native-terraform`; the token brief is `typescript-ai-native-tcg.xml` beside `rust-ai-native-tcg.xml`. Language-NEUTRAL artifacts stay outside the stem (the shared engine crates take the core stem `core-ai-native-*`).</fact></item>
      <item><fact id="CONTRACT-FIRST-ORDERING" status="impl/done">**Contract-first ordering within an item** (R3-002): the exported type/signature, then its invariants, then its error contract, then one canonical example precede the implementation. Autoregression makes reading order conditioning order; intent goes first.</fact></item>
      <item><fact id="POSITION-IS-A-RESOURCE" status="impl/done">**Position is a resource** (R3-003): module-level invariants and the public surface live at the top; prefer more, smaller, single-purpose modules over long files at equal token mass. This is now enforced, not promised: alongside the long-standing `file-length` check, **`invariant-comment-position`** fires through the normal gate when a comment whose marker is in the configured vocabulary lands in a file's middle third — line `l` with `lines/3 &lt; l &lt;= 2·lines/3` (integer-divided; for a 120-line file, lines 41–80) — with the remedy move-to-edge-or-split. For `.ts` that gate runs through the `typescript-ai-native-conform-frontend` crate (`typescript/tools/conform-frontend-typescript.xml`) feeding the same language-neutral engine; the marker vocabulary and the file-length floor are root `conform.toml` keys shared with the other stacks — `invariant_comment_markers` (default the five labeled markers `INVARIANT:` / `WARNING:` / `PANICS:` / `MUST:` / `NEVER:` — a marker is a labeled tag, not a bare word, so the colon is the markup signal) and `invariant_comment_min_file_lines` (default 120 — below it the whole file is skipped, a «third» meaning nothing). Test-context markers are out of scope.</fact></item>
      <item><fact id="UNIFORMITY-IS-LOAD-BEARING" status="impl/done">**Uniformity is load-bearing** (R3-006, H6): one idiom per operation. The codebase is the few-shot prompt; a second coexisting idiom becomes false training signal and propagates. Legitimate exceptions are MARKED (`deviates`) so they do not propagate as imitation.</fact></item>
      <item><fact id="STRUCTURAL-TYPING-TRAP" status="impl/done">**The structural-typing trap (TypeScript-specific).** TypeScript is *structurally* typed: two types with the same shape are interchangeable, so a model can silently pass a `UserId` where an `OrderId` is expected if both are `string`. Rust gets nominal safety free via newtypes; **TypeScript must recover it manually through branding**. *Rule:* identifiers and other meaning-bearing primitives crossing a seam are **branded** (`type UserId = string &amp; { readonly __brand: 'UserId' }`, or a branding helper) so the wrong same-shaped value fails `tsc`. This is the single most important TypeScript-specific safety move and is the basis of scaffold card B (§5). It is the manual recovery of the nominal safety Rust's newtypes give for free.</fact></item>
    </list>
  </section>
  <section id="scaffolds" title="5. The nine scaffolds in TypeScript *(≈ Rust §3)*">
    <p p="52"><fact id="scaffold-cards-lead" status="impl/done">Each is a card in this package's `cards/` (the TypeScript projection of the language-neutral scaffold catalog `02-EXECUTABLE-SCAFFOLDS.xml`); here is the TypeScript shape and the rule.</fact></p>
    <list ordered="false" p="53">
      <item><fact id="SCAFFOLD-A-GENERATORS" status="impl/done">**A — Generators / codegen** (`scaffold-a-generators`). `ts-morph` / Compiler API generators; types generated from a single schema source (Zod→`infer`, OpenAPI/GraphQL/Prisma→types); `satisfies` + `as const` for checked literal tables; template-literal types as bounded type-level generation. Committed output is plain idiomatic TS; the generator carries the structural decision. TypeScript's codegen is mature — favor it. *Rule:* where an artifact is mechanically derivable from a smaller spec, ship generator + committed output + determinism check, not hand-maintained output (A3).</fact></item>
      <item><fact id="SCAFFOLD-B-TYPED-SURFACES" status="impl/done">**B — Typed surfaces / branding / typestate** (`scaffold-b-typed-builders`). **Branded types** for nominal safety over structural typing (§4 — the key TS move); discriminated unions; phantom-type-parameter builders for call-order protocols; `satisfies` for exhaustiveness; sealed unions; no boolean/positional argument soups. Make the statistically-likely wrong same-shaped call fail `tsc`, not a runtime assert. *Rule:* seam protocols are encoded in types, not docstrings (R3-008; ~94% of compile errors are type-level).</fact></item>
      <item><fact id="SCAFFOLD-C-RUNNABLE-CONTRACTS" status="impl/done">**C — Runnable contracts** (`scaffold-c-runnable-contracts`). **Assertion functions** with `asserts` predicates (`function assertIsUser(x: unknown): asserts x is User`) — uniquely TypeScript: one function that BOTH checks at runtime AND narrows the static type; `tiny-invariant`; Zod/Valibot schemas as executable contracts at boundaries; invariants restated at use sites (R3-009). *Rule:* every load-bearing invariant is witnessed by a runnable assertion where it is relied upon, not only documented at definition.</fact></item>
      <item><fact id="SCAFFOLD-D-DIFFERENTIAL-ORACLES" status="impl/done">**D — Differential / characterization oracles** (`scaffold-d-differential-oracle`). `fast-check` property-based differential harnesses (old-vs-new); `vitest`/`jest` snapshot tests for opaque legacy behavior (must fail loudly when stale, never auto-update). *Rule:* no replacement of a non-trivial cell merges without a differential or characterization oracle against prior behavior (R-040). The modification-specific safety net (§11).</fact></item>
      <item><fact id="SCAFFOLD-E-PER-CELL-FAST-LOOP" status="impl/done">**E — Per-cell fast loop** (`scaffold-e-fast-loop`). `tsc --noEmit` per project (project references for isolation) + `vitest` for the cell; the native compiler (TS 7 / "Corsa", ~10× faster checking) makes per-cell first-signal sub-second — a strong substrate. The agent loop is edit → `tsc --noEmit -p &lt;cell&gt;` + `vitest run &lt;cell&gt;` → read structured diagnostic → edit; first signal &lt; ~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.</fact></item>
      <item><fact id="SCAFFOLD-F-STRUCTURED-DIAGNOSTICS" status="impl/done">**F — Structured, REQ-citing diagnostics** (`scaffold-f-structured-diagnostics`). The third channel this scaffold promises — a project's own checks whose messages name the violated `spec://` REQ and the fix surface — is BUILT for TypeScript: the flat-config ESLint plugin `@org.vibevm/eslint-plugin-ai-native` (`typescript-ai-native-lang/v1.0.0/tools/eslint-plugin-ai-native/`) ships one rule, `diagnostic-cites-req`, authored through `ESLintUtils.RuleCreator`. Every message the rule emits routes through ONE grammar helper, `src/req-message.ts` (`reqMessage` / `matchesReqGrammar`), which reproduces the engine pair `req_message` / `matches_req_grammar` verbatim — a second spelling of the grammar is exactly the bug this channel exists to prevent, so the rule cannot drift from the engine. Wiring is the project's own config, not a floor step: the demo loads it through `research/ts-demo/eslint.config.js` (plugin key `ai-native`, `"ai-native/diagnostic-cites-req": "error"`); the floor's `eslint .` step is unchanged and picks the plugin up through that config. The Compiler API's own diagnostics are already coded (TS2322 etc.) — wrap them with REQ context, do not replace them. *Rule:* every project-raised check emits "violates REQ &lt;uri&gt;: &lt;why&gt;; fix surface: &lt;where&gt;", never bare free text (R3-011); error text is the agent's percept. Honest limits of this syntactic heuristic, recorded not claimed (the `ts-seam-error-cites-req` precedent — never a silent claim): it sees **string literals only** — concatenation, interpolated template literals, variables, and imported constants are not tracked (no value tracking) and pass silently; an "Error heir" is recognised by the callee NAME ending `Error`/`Exception`, not by walking the class hierarchy — a class `extends Error` under another name is missed, a `FooError` that does NOT extend `Error` is matched (the grammar burden is identical either way); an object literal's `message:` field is seen only when the literal is thrown directly; and `AggregateError`'s second argument, message-wrapping helper functions, and `throw &lt;non-string&gt;` are outside the net. 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`); the asymmetry that TypeScript has this channel built and Rust/Go do not yet, each for a recorded reason, is held by its sibling law (`spec://org.vibevm.ai-native/core-ai-native/00-MANIFESTO#PARITY-GAP-IS-NEVER-SILENT`), with the route recorded as `BACKLOG.md {#b-050}`.</fact></item>
      <item><fact id="SCAFFOLD-G-EXECUTABLE-EXAMPLES" status="impl/done">**G — Executable examples** (`scaffold-g-doctests`). **Twoslash** (type-checks code in documentation — the TypeScript doctest equivalent); `@example` JSDoc blocks validated by tooling; `expectTypeOf`/`tsd` for type-level examples; `examples/` cells built in CI. *Rule:* every public seam carries ≥1 type-checked example of canonical use; an example that lies fails the build; a prose snippet that lies ships (R2C-004, H4).</fact></item>
      <item><fact id="SCAFFOLD-H-LOCAL-SIMULATORS" status="impl/done">**H — Local simulators / reference models** (`scaffold-h-simulators`). In-memory fakes (MSW for network, fake implementations of seams); `.d.ts` declaration files as shape models; runnable reference implementations of protocols/state-machines the reader can step through. *Rule:* subsystems with non-obvious dynamics ship a runnable model or fake, not a prose description (execution-prediction is where weak models are weakest — DR2-019, CRUXEval ~63% even for strong models).</fact></item>
      <item><fact id="SCAFFOLD-I-CODEMODS" status="impl/done">**I — Scaffolded edit operations / codemods** (`scaffold-i-codemods`). `ts-morph` / `jscodeshift` codemods for "add a cell," "register a variant," "rename across the seam"; typed ESLint autofix as constrained one-shot transforms. **TypeScript's biggest scaffold advantage** — mature codemod tooling makes Class I far more achievable here than in Rust. *Rule (provisional, [E-hyp]):* a capability-demanding multi-file edit is offered as one parameterized checked operation. The tooling-immaturity half of Rust's [E-hyp] does not apply (the ecosystem is mature); the *weak-agent-can-parameterize* half remains open — validate in pilot.</fact></item>
    </list>
  </section>
  <section id="errors" title="6. Errors as contract surface (TypeScript has no checked exceptions) *(≈ Rust §4)*">
    <p p="54"><fact id="THROW-IS-UNTYPED" status="spec/done">`throw` in TypeScript is **untyped** — you can throw anything, and the type system is blind to it.</fact></p>
    <p p="55"><fact id="a-thrown-error-is-invisible" status="spec/done">So a thrown error is invisible to a reader and to the compiler.</fact></p>
    <p p="56"><fact id="FAILURE-IS-A-VALUE-ON-THE-CONTRACT-SURFACE" status="impl/done">The Discipline therefore makes failure a **value**, not a throw, on the contract surface: a discriminated union `Result&lt;T, E&gt; = { ok: true; value: T } | { ok: false; error: E }` (or `neverthrow`/`Effect`), with `E` a discriminated union of named error variants carrying `spec://` REQ references.</fact></p>
    <p p="57"><fact id="EXHAUSTIVENESS-OVER-E-IS-ENFORCED" status="impl/done">Exhaustiveness over `E` is enforced by a `satisfies never` / `assertNever` check in the default branch.</fact></p>
    <list ordered="false" p="58">
      <item><fact id="THROW-IS-FOR-UNRECOVERABLE-DEFECTS" status="impl/done">`throw` is reserved for truly unrecoverable defects (the panic analogue), at the binary edge.</fact></item>
      <item><fact id="FALLIBLE-SEAMS-RETURN-RESULT" status="impl/done">Fallible seams return `Result`, never a `Promise&lt;T&gt;` that rejects with an untyped error.</fact></item>
      <item><fact id="TYPESCRIPT-PROJECTION-OF-THISERROR" status="impl/done">This is the TypeScript projection of Rust's "one `thiserror` enum per layer; variants carry REQ edges; panics are defects" — the discriminated-union `E` is the `thiserror` enum, and the untyped `throw` is the panic.</fact></item>
    </list>
    <p p="59"><fact id="RULE-FAILURE-ON-A-SEAM-IS-A-TYPED-VALUE" status="impl/done">*Rule:* failure on a seam is a typed value with REQ-citing variants; the exhaustive `switch` over the error union is checked at compile time (R-010, projected).</fact></p>
    <p p="60"><fact id="TS-SEAM-ERROR-CITES-REQ-IS-BUILT" status="impl/done">*The gate now checks this* — the `ts-seam-error-cites-req` rule flags a discriminated-union error type alias `E` whose variants carry no `spec://` REQ. Honest limits, recorded (never a silent claim): it detects **Form-1** only — a `type` alias whose RHS is a union of object-literal members, each carrying a discriminant property from the closed set `{ kind, tag, _tag }`; the error position is taken from the alias **name** (`*Error` / `E`), NOT from the second argument of `Result&lt;T, E&gt;` (the single-file extractor does not resolve references); and the discriminant set is closed to `{ kind, tag, _tag }`, so a union discriminated any other way is not matched — what the heuristic cannot see is recorded here, not claimed. 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`).</fact></p>
  </section>
  <section id="registry" title="7. Registry, flags &amp; the composition root *(≈ Rust §5)*">
    <p p="61"><fact id="SAME-RULE-AS-RUST-SHARPENED-BY-ERASURE" status="impl/done">The Rust guide forbids `if flag` in domain logic; the same rule holds in TypeScript, and the erasure boundary (§2) sharpens it.</fact></p>
    <p p="62"><fact id="FLAGS-READ-ONCE-AT-THE-COMPOSITION-ROOT" status="impl/done">Flags and external configuration are read **once, at the composition root** (the app/entry cell), narrowed there through a schema (so `process.env` — pure untyped exterior — is validated and typed exactly once), and a **registry** (a typed `as const` map, or a discriminated-union selector) chooses the cell/strategy.</fact></p>
    <p p="63"><fact id="NO-IF-FLAG-IN-DOMAIN-CELLS" status="impl/done">**No `if (flag)` scattered through domain cells** (R-001).</fact></p>
    <p p="64"><fact id="EXPLICIT-SWITCH-BEATS-DYNAMIC-LOOKUP" status="impl/done">An explicit `switch` over a discriminated config union at the composition root, exhaustiveness-checked, beats string-keyed dynamic lookup and module-load side effects — "one switch is the system's table of contents."</fact></p>
    <p p="65"><fact id="two-tiers-lead" status="impl/done">Two tiers, mirroring Rust's cargo-features-vs-runtime-flags split:</fact></p>
    <list ordered="false" p="66">
      <item><fact id="TIER-BUILD-TIME" status="spec/done">**Build-time:** bundler `define` / dead-code elimination / env-gated conditional compilation (code physically absent from the bundle). The TypeScript analogue of cargo features. *Specified, not built: no bundler is configured anywhere in this discipline's reach. `research/ts-demo`, the one TypeScript consumer, has no bundler among its devDependencies (eslint, prettier, typescript, typescript-eslint, `@types/node`) and no build script — its `floor` and `test` scripts run `typescript-ai-native floor` and `node --test`. Nothing in the stack or the host reads a `define` table or performs dead-code elimination, so this tier has never been exercised.*</fact></item>
      <item><fact id="TIER-RUNTIME" status="spec/done">**Runtime:** a registry object selects a cell/implementation at run time (code present, cell chosen). The TypeScript analogue of runtime flags. *Built and instantiated (B-039): `research/ts-demo/src/main.ts` is the composition root — it reads `process.env.TS_DEMO_GREETING` once, narrows it to a typed mode, and dispatches to the `greeting`/`farewell` cells through a typed `as const` registry. The `ts-flag-sites` rule in the conform engine (mounted by the TypeScript gate when `[typescript] composition_root` is set) now polices the root: an env/config read in any scanned file outside it is a finding. The rule's honest limit — it catches the env/config half, not the `if (flag)` half — is recorded at §FLAG-REGISTRY-IS-TYPED-DATA-WITH-PROVENANCE below.*</fact></item>
    </list>
    <p p="67"><fact id="FLAG-REGISTRY-IS-TYPED-DATA-WITH-PROVENANCE" status="impl/plan">The flag/registry is **typed data with provenance, birth, and sunset** — a branded or `as const` table, not stringly-typed ambient lookup, and never a module-level mutable singleton (which would breach §3 closure). *Built (B-039), TS-shaped: the demo registry is `research/ts-demo/src/main.ts` (a typed `as const` dispatch table — the provenance the line normatively asks for), and the `ts-flag-sites` rule in the conform engine polices WHERE the exterior is read — `process.env` / `import.meta.env` reads are legal only in the file named by `[typescript] composition_root`, and any read in a scanned file outside it is a finding. Honest limit: the rule catches the mechanical half (config/env reads outside the root) but NOT the `if (flag)` half — detecting a conditional on a flag needs flag identity, and no flag table flows through the facts yet, so a bare `if (someValue)` in a domain cell is undetected. The Rust-shaped `FlagSites` (R-001, keyed on construction sites) remains Rust-only; this is its TS-native twin keyed on the read sites the `ts-tsc` frontend can actually see.*</fact></p>
    <p p="68"><fact id="RULE-FLAGS-READ-AT-THE-ROOT-AND-DISPATCHED" status="impl/done">*Rule:* flags are read at the composition root and dispatched through a typed registry; `if (flag)` in a domain cell, or reading config outside the root, requires `deviates` + reason.</fact></p>
  </section>
  <section id="bans" title="8. Bans and their escape hatches — the TypeScript `unsafe` set *(≈ Rust §6)*">
    <p p="69"><fact id="BANS-ARE-THE-MOVES-THAT-DEFEAT-THE-TYPE-SYSTEM" status="impl/done">These are the moves that *defeat the erased type system* — the TypeScript analogue of Rust's `unwrap`/inline-asm/`unsafe` ban set.</fact></p>
    <p p="70"><fact id="forbidden-by-default-lead" status="impl/done">Forbidden by default in domain code; legal only with the escape hatch shown and a recorded reason (`deviates`):</fact></p>
    <list ordered="false" p="71">
      <item><fact id="BAN-ANY" status="impl/done">**`any`** — disables checking and **propagates transitively** (one `any` poisons everything it touches). Banned. *Escape hatch:* `unknown` + runtime narrowing; or, at a genuine third-party boundary, a localized `// eslint-disable-next-line @typescript-eslint/no-explicit-any -- reason` confined to one line.</fact></item>
      <item><fact id="BAN-UNCHECKED-AS" status="impl/done">**Unchecked `as` assertions** — the erasure hazard's sharp edge: `data as User` makes the compiler believe a lie. Banned on untrusted/domain data. *Escape hatch:* `as` only *after* a runtime check, or the always-safe `as const`; cross-type assertions require `deviates` + reason. (Note: the common "fix" `key as keyof typeof obj` to silence `noUncheckedIndexedAccess` is exactly this hazard — narrow instead.)</fact></item>
      <item><fact id="BAN-NON-NULL-ASSERTION" status="impl/done">**Non-null assertion `!`** — claims non-null without proof. Banned. *Escape hatch:* narrowing, or an assertion function `function assertDefined&lt;T&gt;(x: T): asserts x is NonNullable&lt;T&gt;`.</fact></item>
      <item><fact id="BAN-TS-IGNORE" status="impl/done">**`@ts-ignore`** — silences the compiler invisibly and stays silent even after the error is gone. Banned outright. *Escape hatch:* `@ts-expect-error -- reason`, which *fails* if the error disappears (it cannot rot silently) — the only acceptable form.</fact></item>
      <item><fact id="BAN-TYPE-LEVEL-METAPROGRAMMING" status="impl/done">**Type-level metaprogramming beyond the idiomatic** (deep recursive/conditional types) — OOD tail (§0). *Escape hatch:* isolate genuinely needed type-level code behind a documented boundary with `deviates` + reason; never spread it through domain types.</fact></item>
      <item><fact id="BAN-RUNTIME-ENUM-AND-NAMESPACE" status="impl/done">**Runtime `enum` and `namespace`** — don't erase cleanly; forbidden under `erasableSyntaxOnly` (§1). *Replacement:* `as const` union objects and ES modules.</fact></item>
    </list>
    <p p="72"><fact id="BAN-WITHOUT-HATCH-IS-A-DISCIPLINE-BUG" status="impl/done">A ban with no escape hatch is a discipline bug; a deviation with no reason is a code bug.</fact></p>
  </section>
  <section id="specmap" title="9. Metadata layer (specmap in TypeScript) *(≈ Rust §7)*">
    <p p="73"><fact id="SPEC-URIS-CARRIED-BY-JSDOC-OR-DECORATORS" status="impl/done">`spec://` URIs carried by JSDoc tags (`/** @implements spec://... */`), TC39 decorators (stage-3 ES decorators) on classes/methods, or a sidecar mapping; `.d.ts` files as a natural meta/shape layer.</fact></p>
    <p p="74"><fact id="EDGE-KINDS-MIRROR-PROP-014" status="impl/done">The edge kinds mirror PROP-014 (`implements | verifies | documents | deviates | informs`, ≤3 edges per item, the specmark budget); two-tier revisions (author-asserted semantic revision + content hash) with **asymmetric invalidation** (spec bump → edges suspect; code change → edges stay valid); a derived deterministic committed index; an orphan ratchet; `deviates` requires a reason.</fact></p>
    <p p="75"><fact id="METADATA-IS-THE-AUTHORED-RETRIEVAL-INDEX" status="impl/done">The metadata is the authored retrieval index (R3-012): stable anchors + a uniform one-line what/why per exported symbol, in a fixed grammar the pager consumes.</fact></p>
    <p p="76"><fact id="prefer-jsdoc-tags-over-decorators" status="impl/done">(Decorators have runtime cost and partial erasure — prefer JSDoc tags for inert metadata to stay erasure-clean under §1.)</fact></p>
  </section>
  <section id="prose" title="10. Prose discipline (the asymmetric hazard) *(≈ Rust §8)*">
    <p p="77"><fact id="WRONG-PROSE-IS-WORSE-THAN-NO-PROSE" status="spec/done">Wrong prose is worse than no prose (R2C-004, H4): a model conditions on in-repo text with high trust, so a lying comment is adversarial input, and the harm exceeds that of absence.</fact></p>
    <p p="78"><fact id="DRIFTED-JSDOC-IS-TRUSTED-OVER-THE-TYPES" status="spec/done">TypeScript-specific sharp edge: a JSDoc `@param`/`@returns` that has drifted from the signature is a lie the model trusts *over* the (correct) types.</fact></p>
    <p p="79"><fact id="RULE-BEHAVIORAL-CLAIMS-ARE-MACHINE-CHECKED" status="impl/done">*Rule:* behavioral claims near code are **machine-checked** — backed by Twoslash/`@example` (type-checked) or `expectTypeOf` (type-level checked) — or **explicitly trust-labeled** (verified / unverified / aspirational); JSDoc that merely restates the types is duplication (a defect) — let the types speak.</fact></p>
    <p p="80"><fact id="MISLEADING-STRINGS-COUNT-TOO" status="impl/done">Misleading `console.log`/error strings count too (the harm is the false claim, not the syntax).</fact></p>
    <p p="81"><fact id="TSDOC-IS-THE-HUMAN-DETAIL-LAYER" status="impl/done">TSDoc remains the human detail layer; duplication with the spec is a spec defect.</fact></p>
  </section>
  <section id="replacement" title="11. Replacement protocol *(≈ Rust §9)*">
    <p p="82"><fact id="REPLACEMENT-SHIPS-A-DIFFERENTIAL-ORACLE" status="impl/done">Replacing a cell ships a **differential oracle** (Class D, §5) against the old cell — `fast-check` feeding identical generated inputs to `old` and `new` and asserting equal outputs — plus the `@verifies spec://…` edge (§9).</fact></p>
    <p p="83"><fact id="CHARACTERIZATION-GOLDENS-PIN-LEGACY-BEHAVIOR" status="impl/done">Characterization goldens (`vitest` snapshots) pin opaque legacy behavior; goldens must fail loudly when stale (run under `--ci`; never `--update` silently auto-rewriting).</fact></p>
    <p p="84"><fact id="CHARACTERIZATION-ENSHRINES-BUGS-TOO" status="impl/done">The characterization variant enshrines current behavior including its bugs — pair it with a spec edge marking which behaviors are intentional vs incidental.</fact></p>
    <p p="85"><fact id="BYTE-FOR-BYTE-THE-RUST-PROTOCOL" status="impl/done">This is byte-for-byte the Rust replacement protocol (R-040) with TypeScript tools; it is the one place the modification-time safety net is mandatory rather than advisory.</fact></p>
  </section>
  <section id="matrices" title="12. Test matrices and type-level testing *(≈ Rust §10 + a TS-unique scaffold)*">
    <p p="86"><fact id="TEST-MATRICES-ARE-DECLARED" status="impl/done">**Test matrices.** Declared test matrices, never an implicit `2^n`.</fact></p>
    <p p="87"><fact id="MATRIX-TOOLING" status="impl/done">`vitest`/`jest` `test.each` / `it.each` over a **named, bounded case table** (`as const` so the table is typed and exhaustiveness is visible); `fast-check` for behavioral surfaces; the differential oracle (§11) covers replacement; per-cell `vitest` runs in the fast loop (§5).</fact></p>
    <p p="88"><fact id="MATRIX-IS-AUTHORED-DATA" status="impl/done">The matrix is authored data, not a combinatorial explosion the reader must hold in their head (R-060, projected).</fact></p>
    <p p="89"><fact id="TYPE-LEVEL-TESTING-IS-TYPESCRIPT-UNIQUE" status="spec/done">**Type-level testing (a TypeScript-unique scaffold).** TypeScript can assert **type relationships at compile time** — a class of runnable contract no mainstream language has so readily, and a place where TypeScript's expressiveness pays the discipline back instead of costing it.</fact></p>
    <p p="90"><fact id="TYPE-LEVEL-TEST-TOOLING" status="impl/done">`expectTypeOf&lt;X&gt;().toEqualTypeOf&lt;Y&gt;()` (vitest), `tsd`'s `expectType`, and `@ts-expect-error` as a negative assertion let you test that a generic, a branded type (§4), or a discriminated union (§6) behaves as intended *before any code runs*.</fact></p>
    <p p="91"><fact id="RULE-PUBLIC-SURFACES-CARRY-TYPE-LEVEL-TESTS" status="impl/done">*Rule:* public generic/branded/union surfaces carry type-level tests asserting their key relationships; these run in the Class E loop (a type-level test that regresses fails `tsc`).</fact></p>
    <p p="92"><fact id="type-level-testing-is-additive-over-rust" status="spec/done">This is Class C/D applied to the types themselves — Rust has no comparable readily-available form, so it is additive over the Rust projection, not a mirror.</fact></p>
  </section>
  <section id="weak-reader" title="13. How a weak reader actually uses this guide *(≈ Rust §11)*">
    <p p="93"><fact id="WEAK-SWARM-DOES-NOT-READ-THIS-GUIDE" status="impl/done">The weak swarm does **not** read this guide.</fact></p>
    <p p="94"><fact id="WEAK-READER-RECEIVES-BAND-3-OPS-PER-EDIT" status="impl/done">It 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).</fact></p>
    <p p="95"><fact id="GUIDE-IS-THE-AUTHORING-AND-REVIEW-ARTIFACT" status="impl/done">This guide and the cards are the authoring/review artifact for the strong author and the human; the runtime surface for the weak reader is "the right TypeScript card's routine + checker, when its trigger fires" — and for `.ts` edits that is a card from *this package's* `cards/`, never the Rust core's.</fact></p>
    <p p="96"><fact id="RAIDS-SWEEP-CROSS-CUTTING-CONCERNS" status="impl/done">Cross-cutting concerns the per-edit loop cannot hold are swept by raids (`03-RAID-PLAYBOOK.xml`).</fact></p>
  </section>
  <section id="tooling" title="14. Tooling roadmap pointer (the tcg line) *(≈ Rust §12)*">
    <p p="97"><fact id="two-tcg-briefs-lead" status="impl/done">The tcg line has TWO briefs, split by where the intervention happens:</fact></p>
    <list ordered="false" p="98">
      <item><fact id="TCG-AGENTIC-BRIEF-SHIPPED" status="impl/done">**[`typescript/tools/vibe-agentic-tcg-ts.xml`](tools/vibe-agentic-tcg-ts.xml) — SHIPPED (the agentic oracle):** a long-lived language-service oracle the agent CONSULTS — validate-an-overlay / scope / type-valid completions / quick info at millisecond latency, discipline-enriched by the same conform engine as the gate — delivered as `tcg_*` MCP tools and one-shot `typescript-ai-native-tcg` CLI forms. Mechanisms: `mechanisms/TCG-ORACLE-v0.1.xml`, `mechanisms/TCG-PROTOCOL-v0.1.xml`. It is the generation-time complement to the post-generation `tsc --noEmit` loop (Class E): the loop stays the GUARANTEE; the oracle removes red iterations before they happen.</fact></item>
      <item><fact id="TCG-TOKEN-LEVEL-BRIEF-VERY-FAR-FUTURE" status="spec/done">**[`typescript/tools/typescript-ai-native-tcg.xml`](tools/typescript-ai-native-tcg.xml) — VERY-FAR-FUTURE (token-level):** logit masking to type-checker-validated, discipline-conformant continuations, by construction. It waits, owner-dispositioned, on an inference substrate (`vibe-llm` is a stub; hosted agent APIs never expose logits) and will reuse the SAME oracle as its completability answer when it comes.</fact></item>
    </list>
    <p p="99"><fact id="TOOLING-ASYMMETRY-STATED-HONESTLY" status="spec/done">**The TypeScript tooling asymmetry, stated honestly.** The PLDI'25 result proves type-constrained decoding works for TypeScript (75.3% (synthesis) / 70.2% (translation) compile-error reduction; ~94% of TS compile errors are type-level) — but its repository is inspiration-only under the clean-room rule (never a code source; the algorithm would be reimplemented from the paper in structurally different code).</fact></p>
    <p p="100"><fact id="TYPESCRIPT-EXPOSES-ITS-CHECKER-PROGRAMMATICALLY" status="spec/done">What makes TypeScript first anyway is the compiler itself: unlike Rust at decode time, TypeScript exposes its checker programmatically (Compiler API / language service), so our oracle stands on the REAL checker rather than a rebuilt subset.</fact></p>
    <p p="101"><fact id="TYPESCRIPT-IS-THE-STRONGEST-NEAR-TERM-PILOT" status="spec/done">Combined with the mature codemod ecosystem (Class I), that makes TypeScript the strongest near-term pilot for the swarm story, second only to where the algorithmic core lives (Rust/vibevm).</fact></p>
    <p p="102"><fact id="COUNTERWEIGHT-DEFAULT-SAFETY-IS-LOWER" status="spec/done">**The honest counterweight.** TypeScript's erasure and structural typing mean its *default* safety is *lower* than Rust's — more must be done manually (branding, runtime validation, banning `as`/`any`) to reach the same floor.</fact></p>
    <p p="103"><fact id="MORE-LEVERAGE-AND-MORE-ROPE" status="spec/done">TypeScript gives more tooling leverage and more expressiveness, but it also gives more rope.</fact></p>
    <p p="104"><fact id="PROJECTION-IS-HEAVIER-ON-BANS-BY-DESIGN" status="impl/done">The Discipline's TypeScript projection is heavier on *bans and boundary validation* (§2, §8) than the Rust projection precisely for this reason — and that asymmetry, not a failure of mirroring, is the genuine T2 content.</fact></p>
    <p p="105"><fact id="STANDING-OPEN-QUESTION" status="spec/done">**The standing open question (shared with Rust).** The 74.8% / type-constrained-decoding result is a *generation*-time result; the Discipline's central unproven bet is whether scaffolds help *comprehension and modification* of in-distribution code, not just generation.</fact></p>
    <p p="106"><fact id="MODIFICATION-SAFETY-IS-STILL-THE-PILOTS-JOB" status="spec/done">A type oracle makes a weak agent *write* well-typed TypeScript (by construction at token level; by cheap consultation agentically); whether it then *modifies* existing TypeScript safely is still the pilot's job — and erasure means well-typed code can still lie at runtime if an `as` slipped through, which is why the §8 ban on `as` matters even with the type oracle on.</fact></p>
    <p p="107"><fact id="AGENTIC-BATTERY-IS-THE-FIRST-MEASUREMENT" status="impl/done">The agentic battery (two arms, weak model, mechanical verification — see the sibling brief's «Staged ambition», `vibe-agentic-tcg-ts.xml` §4) is the first standing measurement of exactly this question.</fact></p>
  </section>
  <section id="wiring" title="15. Wiring a consumer (the shipped toolchain) *(≈ Rust §13)*">
    <p p="108"><fact id="wires-it-in-five-moves-lead" status="impl/done">The stack ships the toolchain as runnable code (PROP-024); a consumer wires it in five moves:</fact></p>
    <list ordered="true" p="109">
      <item><fact id="WIRE-1-INSTALL-THE-STACK" status="impl/done">**Install the stack** — `vibe install` with `stack:org.vibevm.ai-native/typescript-ai-native-lang` in `[requires].packages` materialises the slot under `vibedeps/` (the neutral engines ride along as vendored copies; the slot is its own Cargo workspace and builds standalone).</fact></item>
      <item><fact id="WIRE-2-GET-THE-BINARIES" status="impl/done">**Get the binaries** — `cargo install --path vibedeps/&lt;stack-slot&gt;/crates/typescript-ai-native-cli` (plus `typescript-ai-native-conform` / `typescript-ai-native-specmap` if you want the narrow engines on PATH), or run in place: `cargo run --manifest-path vibedeps/&lt;stack-slot&gt;/Cargo.toml -p typescript-ai-native-cli --bin typescript-ai-native -- &lt;args&gt;`.</fact></item>
      <item><fact id="WIRE-3-PROJECT-TOOLCHAIN" status="impl/done">**Project toolchain** — node ≥ 22.6 (strip-types runs `.ts` directly; `node --test` is the default runner) and `npm install -D typescript prettier eslint typescript-eslint`. The structural gate parses through the PROJECT's own `typescript` — the same install the `tsc` floor step uses, so the gate adds no new dependency.</fact></item>
      <item><fact id="WIRE-4-BOOTSTRAP" status="impl/done">**Bootstrap** — `typescript-ai-native init` writes conform.toml (`[typescript]`: roots, `cells_dir`, seam), specmap.toml (namespace + discovered `[[external_specs]]`), both ratchet baselines, and the BROWNFIELD registries; then `typescript-ai-native specmap` mints the index and `typescript-ai-native floor` runs the seven steps. Adoption on a brownfield tree: the `/typescript-ai-native-terraform` skill.</fact></item>
      <item><fact id="WIRE-5-GENERATION-TIME-ORACLE" status="impl/done">**The generation-time oracle (optional but cheap)** — the stack's 4th binary, `typescript-ai-native-tcg`, answers validate/scope/complete/type over in-memory overlays (§14). One-shot from anywhere: `vibe bin exec typescript-ai-native-tcg -- validate src/cells/&lt;cell&gt;/index.ts --json`. Warm, inside an agent session: the `tcg_*` MCP tools (`vibe mcp serve`; vibevm PROP-026) hold a persistent oracle per language, so consulting the type checker before an edit costs milliseconds. The floor stays the truth; the oracle exists so the floor stays green on the first try.</fact></item>
    </list>
    <p p="110"><fact id="gotchas-the-fresh-walks-caught-lead" status="impl/done">Gotchas the fresh walks caught:</fact></p>
    <list ordered="false" p="111">
      <item><fact id="GOTCHA-WORKSPACE-EXCLUDE-VIBEDEPS" status="impl/done">a repo that also carries Rust keeps `[workspace] exclude = ["vibedeps"]`;</fact></item>
      <item><fact id="GOTCHA-NODE-MODULES-AND-LOCKFILES" status="impl/done">`node_modules/` is gitignored but lockfiles are committed;</fact></item>
      <item><fact id="GOTCHA-EXTRACTOR-REMATERIALISES" status="impl/done">the extractor materialises content-addressed under `target/conform/ts-extract/` — clean builds re-materialise it automatically.</fact></item>
    </list>
  </section>
  <section id="sweep" title="16. Sweep idioms *(≈ Rust §14)*">
    <p p="112"><fact id="sweep-idioms-lead" status="impl/done">The recurring posture is the shipped Sweep Playbook driven by `/typescript-ai-native-sweep`; the TypeScript-specific idioms:</fact></p>
    <list ordered="false" p="113">
      <item><fact id="SWEEP-DANGER-BAND-SPLITS" status="impl/done">**Danger-band splits** keep traceability: the new module gets its own file-level `@scope` (or carries the moved exports' `@implements` tags) so the orphan ratchet never regresses on a refactor.</fact></item>
      <item><fact id="SWEEP-SUPPRESSION-DRAINS" status="impl/done">**Suppression drains**: `@ts-ignore` → `@ts-expect-error -- reason` is always a strict improvement (it fails when the error goes); an unreasoned `@ts-expect-error` in the health census is unrecorded testimony — reason it or fix it.</fact></item>
      <item><fact id="SWEEP-UNSAFE-SET-DRAINS" status="impl/done">**Unsafe-set drains** go type-first: `any` → `unknown` + one narrowing helper reused everywhere (uniformity is load-bearing); a cross-type `as` at an erasure boundary becomes a schema parse; `!` becomes an `asserts` function.</fact></item>
      <item><fact id="SWEEP-FLOOR-DISABLEMENT-IS-DEBT" status="impl/done">**Floor disablement is debt**: every `[[typescript.floor_disable]]` entry prints on every run — re-question the reasons weekly; an empty list is the exit criterion the terraform aims at.</fact></item>
    </list>
  </section>
</spec>
