<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">CARD: scaffold-d-differential-oracle — Differential / Characterization Oracle (TypeScript)</title>
  <status stage="spec" state="done"/>
  <p p="1"><fact id="status-line" status="impl/done">**Discipline v0.2 · BETA · T2 · TypeScript**</fact></p>
  <p p="2"><fact id="reference-instance-note" status="impl/done">*Reference instance of the AI-Native Pattern Card format, TypeScript projection.*</fact></p>
  <p p="3"><fact id="demonstrates-all-three-bands" status="impl/done">*Demonstrates all three bands, especially the operational Band 3.*</fact></p>
  <p p="4"><fact id="card-is-beta" status="impl/done">*This card is itself BETA (its checker is specified but not yet implemented — there is no TypeScript pilot codebase yet).*</fact></p>
  <section id="band-one-identity" title="Band 1 — Identity &amp; Recognition">
    <p p="5"><fact id="CLASSIFICATION" status="impl/done">**Classification:** layer = E (Verification coupling); mechanism = scaffold class D.</fact></p>
    <p p="6"><fact id="INTENT" status="impl/done">**Intent:** When code is replaced or refactored, pin its observable behavior with a runnable check that compares the new implementation against the old one (differential) or against a captured baseline (characterization), so that a reader — especially a weak one — can change code freely and receive a pass/fail signal on whether behavior moved.</fact></p>
    <p p="7"><fact id="ALSO-KNOWN-AS" status="spec/done">**Also Known As:** golden test; snapshot test; characterization test (Feathers); approval test; back-to-back test; differential testing; `fast-check` model-based / property-based test.</fact></p>
    <p p="8"><fact id="applicability-recognition-lead" status="impl/done">**Applicability / Recognition:** Apply when ANY of these signals are present —</fact></p>
    <list ordered="false" p="9">
      <item><fact id="SIGNAL-CELL-IS-BEING-REPLACED" status="impl/done">a cell is being *replaced* or its internals *rewritten* while its contract is meant to stay fixed (the replacement protocol, R-040, guide §11);</fact></item>
      <item><fact id="SIGNAL-LEGACY-BEHAVIOR-IS-UNDERSTOOD-BY-NOBODY" status="impl/done">legacy behavior exists that nobody fully understands but must be preserved (no spec, only observed behavior);</fact></item>
      <item><fact id="SIGNAL-REFACTOR-SPANS-MULTIPLE-FILES" status="impl/done">a refactor spans multiple files and the reader cannot prove by inspection that behavior is unchanged;</fact></item>
      <item><fact id="SIGNAL-WEAK-AGENT-NEEDS-A-SAFETY-NET" status="impl/done">a weak agent is assigned a modification task and needs a safety net it cannot derive itself.</fact></item>
    </list>
    <p p="10"><fact id="DETECTOR-SEED" status="impl/done">*Detector seed:* a diff that modifies the body of an item carrying `@implements spec://…` (or its sidecar edge) without a corresponding oracle artifact in the cell's test module → recognition fires.</fact></p>
  </section>
  <section id="band-two-justification" title="Band 2 — Justification &amp; Tradeoffs">
    <p p="11"><fact id="MOTIVATION" status="spec/done">**Motivation:** A Qwen-32B-class agent is asked to optimize a parser cell authored by Opus. It rewrites the hot loop. By inspection, neither the agent nor a fast human reviewer can be sure the 200-line change preserved behavior across edge cases. With a differential oracle — `fast-check` feeding identical generated inputs to `oldParse` and `newParse` and asserting equal outputs — the agent gets an immediate, mechanical verdict: behavior held, or here is a minimized (shrunk) counterexample. The expensive cognition ("what are all the edge cases?") was materialized once, by the author, as a runnable harness; the weak agent consumes the verdict instead of re-deriving the edge-case analysis.</fact></p>
    <p p="12"><fact id="structure-and-participants-lead" status="impl/done">**Structure &amp; Participants:**</fact></p>
    <list ordered="false" p="13">
      <item><fact id="PARTICIPANT-SUBJECT-OLD" status="impl/done">*Subject-old* — the prior implementation (kept temporarily as `oldParse`, or captured as `vitest` snapshots).</fact></item>
      <item><fact id="PARTICIPANT-SUBJECT-NEW" status="impl/done">*Subject-new* — the replacement.</fact></item>
      <item><fact id="PARTICIPANT-INPUT-SOURCE" status="impl/done">*Input source* — a `fast-check` arbitrary, a recorded production-input set, or a snapshot corpus.</fact></item>
      <item><fact id="PARTICIPANT-COMPARATOR" status="impl/done">*Comparator* — the equality/equivalence predicate (deep-equal, or domain-specific tolerance).</fact></item>
      <item><fact id="PARTICIPANT-ORACLE-HARNESS" status="impl/done">*Oracle harness* — the runnable `vitest`/`fast-check` test binding these, living in the cell's test module.</fact></item>
    </list>
    <p p="14"><fact id="COLLABORATIONS" status="impl/done">**Collaborations:** Pairs with Class B (branded/typed surfaces shrink the input space the oracle must cover) and Class C (contracts define what "equivalent" means). Consumes Class E (the per-cell fast loop runs the oracle). Emits Class F diagnostics (a failure cites the violated REQ + the minimized counterexample). In a raid (§3 of the format), this card is the *differential-safety* gate that every behavior-changing card application must pass.</fact></p>
    <p p="15"><fact id="goals-and-non-goals-lead" status="impl/done">**Goals / Non-Goals:**</fact></p>
    <list ordered="false" p="16">
      <item><fact id="GOALS" status="impl/done">*Goals:* detect unintended behavior change during replacement/refactor; give weak readers a modification safety net; make "behavior preserved" a machine fact, not a claim.</fact></item>
      <item><fact id="NON-GOALS" status="impl/done">*Non-Goals:* NOT a correctness proof (it checks new-vs-old agreement, so it inherits any bug the old code had); NOT a substitute for the spec (it pins behavior, it does not justify it); NOT for greenfield code with no prior behavior to differ against.</fact></item>
    </list>
    <p p="17"><fact id="consequences-lead" status="impl/done">**Consequences:**</fact></p>
    <list ordered="false" p="18">
      <item><fact id="CONSEQUENCE-REFACTORING-BECOMES-SAFE" status="spec/done">(+) The reader can refactor aggressively; the net catches behavior drift mechanically.</fact></item>
      <item><fact id="CONSEQUENCE-IMPLEMENTATION-AND-CONTRACT-VARY-INDEPENDENTLY" status="spec/done">(+) Decouples "change the implementation" from "preserve the contract" — they vary independently.</fact></item>
      <item><fact id="CONSEQUENCE-ARBITRARY-AND-COMPARATOR-COST-EFFORT" status="spec/done">(−) Cost: authoring the `fast-check` arbitrary and comparator; maintaining snapshots (which can rot — they must fail loudly when stale, run under `--ci`, never `--update` auto-rewriting silently).</fact></item>
      <item><fact id="CONSEQUENCE-CHARACTERIZATION-ENSHRINES-CURRENT-BEHAVIOR" status="spec/done">(−) Characterization variant *enshrines current behavior including its bugs* — must be paired with a spec edge that says which behaviors are intentional vs incidental.</fact></item>
    </list>
    <p p="19"><fact id="alternatives-lead" status="impl/done">**Alternatives:**</fact></p>
    <list ordered="false" p="20">
      <item><fact id="ALTERNATIVE-FORMAL-PROOF" status="spec/done">*Full formal proof:* in Rust this is the Kani/Creusot option; **TypeScript has no comparable mainstream formal-verification tool**, so the differential/property oracle carries proportionally more of the modification-safety load here — a genuine TS-vs-Rust asymmetry, not a gap in this card.</fact></item>
      <item><fact id="ALTERNATIVE-MANUAL-REVIEW" status="spec/done">*Manual review:* the status quo; fails exactly where we need it (large multi-file edits, weak readers).</fact></item>
      <item><fact id="ALTERNATIVE-FRESH-UNIT-TESTS" status="spec/done">*Unit tests written fresh:* test what the author thought to test; the differential oracle tests behavior the author never enumerated. Prefer differential when preserving opaque legacy behavior.</fact></item>
    </list>
    <p p="21"><fact id="risks-and-assumptions-lead" status="impl/done">**Risks &amp; Assumptions:**</fact></p>
    <list ordered="false" p="22">
      <item><fact id="RISK-OLD-IMPLEMENTATION-IS-AVAILABLE" status="spec/done">Assumes the old implementation is available or its behavior is capturable (as a snapshot).</fact></item>
      <item><fact id="RISK-INPUTS-ARE-GENERATABLE-WITH-COVERAGE" status="spec/done">Assumes inputs are *generatable* with enough coverage; a weak `fast-check` arbitrary gives false confidence.</fact></item>
      <item><fact id="RISK-SUNSET" status="spec/done">*Sunset condition:* if generation-time tools (`typescript-ai-native-tcg`, renamed from `vibe-tcg-ts` by the family-prefix policy) plus full contracts ever make behavior-preservation statically provable for a class of cells, the differential oracle becomes redundant for that class and retires there. The condition is not met today: the binary of that name ships the *consultation* oracle (relay plus one-shot validate/scope/complete/type), while the token-level generation tier it turns on is still spec-stage in this stack's own tool brief.</fact></item>
      <item><fact id="RISK-TRANSFER" status="spec/done">Transfer risk: the value of executable scaffolds for *modification* (vs generation) is [E-mid], not yet measured on a TypeScript codebase — this card is a prime pilot validation target on the forthcoming VibeVM TypeScript surface.</fact></item>
    </list>
    <p p="23"><fact id="EVIDENCE-AND-TRANSFER-STRENGTH" status="spec/done">**Evidence &amp; Transfer-strength:** findings R-040 (replacement protocol, production), R2C-008 (executable scaffolds transformative for weak agents, benchmark), Feathers characterization method (production). Evidence class: production + benchmark. Transfer tag: **[E-mid]** (executable-scaffold value shown for generation; modification transfer to be validated in the TypeScript pilot).</fact></p>
  </section>
  <section id="band-three-operation" title="Band 3 — Operation">
    <p p="24"><fact id="TRIGGER" status="impl/done">**Trigger:** WHEN a diff modifies the body of an item bearing `@implements spec://…`, OR a cell is marked for replacement, OR a refactor touches &gt; 1 file in a cell whose contract is unchanged — THEN apply this card before merge.</fact></p>
    <p p="25"><fact id="MODE" status="impl/done">**Mode:** gate (runs at the cell's verification gate, not per keystroke).</fact></p>
    <p p="26"><fact id="routine-lead" status="impl/done">**Routine** (≤7 steps, each verifiable):</fact></p>
    <list ordered="true" p="27">
      <item><fact id="ROUTINE-IDENTIFY-THE-BEHAVIORAL-SURFACE" status="impl/done">Identify the behavioral surface to preserve (the seam's public functions).</fact></item>
      <item><fact id="ROUTINE-KEEP-OLD-REACHABLE" status="impl/done">Keep `old` reachable (rename to `oldParse`, or capture `vitest` snapshots from it on a fixed input set).</fact></item>
      <item><fact id="ROUTINE-WRITE-THE-ARBITRARY" status="impl/done">Write/extend a `fast-check` arbitrary generating representative inputs for that surface.</fact></item>
      <item><fact id="ROUTINE-BIND-OLD-VS-NEW" status="impl/done">Bind `old` vs `new` (or `snapshot` vs `new`) under an equality/equivalence comparator.</fact></item>
      <item><fact id="ROUTINE-RUN-IN-THE-LOOP" status="impl/done">Run under the per-cell loop; on a shrunk counterexample, fix `new` (NOT the oracle) until green.</fact></item>
      <item><fact id="ROUTINE-REMOVE-OLD-ONCE-GREEN" status="impl/done">Once green, remove `old` (or commit the snapshots) and leave the oracle in the test module.</fact></item>
      <item><fact id="ROUTINE-CITE-THE-ORACLE" status="impl/done">Cite the oracle from the replacement's `@verifies spec://…` edge.</fact></item>
    </list>
    <p p="28"><fact id="CHECKER" status="spec/done">**Checker:** `@typescript-eslint`/conform rule `replacement-has-oracle` — flags any modification of an `@implements`-bearing item body whose cell lacks a differential/characterization test referencing it. Backed by `vitest run &lt;cell&gt;` running the `fast-check`/snapshot oracle. *(Status: specified, NOT yet implemented → this card is BETA.)*</fact></p>
    <p p="29"><fact id="RAID-ROLE" status="impl/done">**Raid role:** layer = *behavior-preserving* phase (runs in any raid that rewrites implementations); order = applied AS A GATE around every other behavior-changing card (no ordering dependency of its own, but nothing that changes behavior may merge in a raid without it); batch = per-cell.</fact></p>
    <p p="30"><fact id="BUDGET" status="impl/done">**Budget:** competes with few rules (it is gate-time, not inline, so it does not crowd the edit-time active set); first-signal latency = one per-cell `fast-check` run (target &lt; 60s; tune the run count / `numRuns` to stay in budget).</fact></p>
  </section>
</spec>
