Skip to content

fix(oracle-gaps): infect nullish ?. receivers and classify swallowed throws - #60

Draft
KyleAMathews wants to merge 5 commits into
mainfrom
fix/gap-infection-completion
Draft

KyleAMathews wants to merge 5 commits into
mainfrom
fix/gap-infection-completion

Conversation

@KyleAMathews

@KyleAMathews KyleAMathews commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The gap CLI skipped a mutant of an optional read (?.) as "changes nothing" and reported it not-distinguished in 0 s, although the mutant throws wherever the receiver is nullish. The capture never recorded that completion change, so check.mjs changesNothing took the skip path. Reported on quick-lru peek (this.#node(key)?.value).

This PR: (1) makes the capture infect a ?. site whose receiver is nullish, (2) adds a swallowed-throw survivor class for a mutant whose owner test caught the thrown error and went on (no skip, no accept-as-equivalent exit), and (3) extends the e2e oracle with the witnesses and reach states that show both.

Decisions

Register entries (~/.cache/oracle-grammar/decisions-register.md) this change touches:

  • P3 (what a kill is): swallowed-throw and crashed are gaps, never kills. A bare throw stays crashed.
  • P4 (reach keeps randomness): the new states are declared on the constructed unit fixed seed 20261105: every outcome class; the random seeds are unchanged.
  • P5 (every survivor is a gap): swallowed-throw has one directive that offers no exit ("observe the completion of that read, its value or its error"). "Unchanged" means an equal completion (value or thrown error): the capture now infects a nullish ?. receiver, so the mutant runs.
  • P9 (oracle-first): RED and GREEN are in the Evidence block; the swallowed RED is the oracle-only commit 2a343bc.
  • P10 (one diagnostic per failure): an open defect on the stdout line count is recorded under Evidence, not fixed here.
  • P12 (CI budget): the new witnesses add CLI runs to the constructed unit; CI timings are reported on this PR.
  • Generator rule (C, 2026-11-13): the new witness options (absent, caught) are fixed witness fields, not generator draws. No fc arbitrary changes, so no existing seed's history changes.
  • Process (M, 2026-11-13): the oracle-only commit went to CI, not the local lock.

Evidence

  • Law: A mutant is judged without a run only when every owner's unmutated run completes its site as the original does (same value, or same thrown error). The capture must infect every site whose mutant would change that completion. Authority: the gap CLI's soundness contract, "types and value capture never skip or dead-mark a mutant that changes behavior" (maintainer decision cited in the lane brief). A survivor whose owner test threw at the site and passed is swallowed-throw: it is never skipped and has no accept-as-equivalent exit.
  • Reach: the e2e unit fixed seed 20261105: every outcome class declares the reach states a plain read of an absent object crashed, a plain read of a null object crashed, and a plain read whose throw the owner swallowed. Witnesses: w_absent, w_absentNull, w_swallow.
  • RED:
    • Peek, unchanged CLI, quick-lru copy with ?. restored (--only index.js:M66): not-distinguished L119 index.js:M66 ?. → ., 1 gap, 0 killed, 0 s. Local log.
    • E2e, unchanged production, unit above: w_absent not-distinguished, owed crashed. Local log.
    • E2e, swallowed witness: CI run at the oracle-only commit 2a343bc (link below once it runs).
  • GREEN: e2e unit above passes with the chain() fix (commit 53966e9). Local log. CI at the production commit: pending.
  • Mutant: hostile mutants are planned and run locally, not pushed: (a) today's capture (no infection on nullish), (b) an undefined-only infection (misses the null witness), (c) a classifier that labels swallowed-throw as not-distinguished. Verdicts: pending.
  • Open issue found while measuring: on the oracle-edited tree, the same unit failed once on the stdout greppable stream law ("125 gap lines for 126 gaps") for a generated history. Replays of that history on this branch and on clean origin/main are being run to tell whether the bug predates this PR. Verdict: pending. If it reproduces on main, it goes to its own PR.
  • Limits: the swallowed class is recorded for any site whose active mutant threw at a nullish receiver; today only ?. sites can throw under a mutant, so it is ?. in practice, by construction. The fixed witnesses are one caught read each (undefined and null receivers), not generated histories. The quick-lru peek mutant is reported from its driver's observed error; a bare throw without observation is crashed, not a kill. Full gap-oracle run and the pr-shards and e2e-shards checks are not complete locally; CI runs them.

This pull request and its description were written by Isaac.

KyleAMathews and others added 3 commits November 13, 2026 07:23
A plain read in place of ?. changes its completion (a TypeError where the
original returned undefined), but the capture never recorded it, so the
mutant was skipped as unchanged and reported not-distinguished in 0 s.

Law: a mutant is judged without a run only when every owner's unmutated run
completes its site as the original does. Witnesses w_absent and w_absentNull
(undefined and null receivers) declare the crashed reach states.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
The model gets a caught witness (w_swallow): its owner catches the TypeError a
mutated ?. throws and writes nothing, so the test passes. Law: a survivor of an
optional-chain site whose owner test threw at the site is swallowed-throw (never
a skip, never an exit). Reach state: a plain read whose throw the owner swallowed.

Oracle-only commit; production follows.

Co-authored-by: Isaac <no-reply@databricks.com>
@coderabbitai

coderabbitai Bot commented Nov 13, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@changeset-bot

changeset-bot Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: f9bad06

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

KyleAMathews and others added 2 commits November 13, 2026 11:19
…ixture contains

A caught optional read is rendered without its out.push, so it has no
delete-call site on that push. The model still emitted one, expecting a gap
the CLI cannot produce (126 expected, 125 printed), and every static
enumeration unit with a caught witness failed and shrank for 41 minutes in
CI (gap report oracles 2/3).

This corrects the model's internal consistency to its own rendered fixture.
It is not a model change toward production output: no expected class or
outcome changed, only the set of sites the fixture contains.

Co-authored-by: Isaac <no-reply@databricks.com>
…ment

The CLI anchors the site in the statement that holds it, which for a caught
read is its own expression statement (void oN ?. v ;), not the try line. The
model named the try line, so the static generated units failed on the key.
This changes only the model's rendered anchor text, to match the fixture it
renders; no expected class or outcome changed.

Co-authored-by: Isaac <no-reply@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant