Skip to content

fix(oracles): working replay -t, one-line gap lines, typed operands, and a two-step not-observed directive - #20

Merged
KyleAMathews merged 3 commits into
mainfrom
overnight/c-directives
Nov 11, 2026
Merged

KyleAMathews merged 3 commits into
mainfrom
overnight/c-directives

Conversation

@KyleAMathews

Copy link
Copy Markdown
Contributor

Summary

This PR makes four fixes to the oracle-gaps output, and an extended oracle drives each one. One fixes the F22 directive. The others are #12 leftovers: the baseline replay command, one-line gap lines, and typed operands.

Changes

  • F22 directive. A not-observed survivor had an infection, but no recorded observation changed. The records cannot separate an unobserved change from a forced branch that matched the original (klona's M6). The directive now has two steps: "Observe the value this code changes in <test>, and assert on it. Where the mutated code computes the same result as the original, add a history where it computes something different."
  • Replay command. The baseline printed -t "<a > b > test>" in JSON quotes. Vitest 4 joins names with a space, so -t "t0 > t0" selected nothing. Regex syntax in a name broke the pattern, and $ or a backtick broke the shell. A load failure printed -t undefined. Now the pattern holds the suite and test names, regex-escaped and joined with (?: | > ) for Vitest 4 and 5. It has anchors and POSIX single quotes. A load failure replays the whole file with no -t.
  • Gap lines. The output collapses whitespace in mutant code and authored intents, and cuts them at 60 code points. results.json keeps the full text.
  • Typed operands. The capture records each comparison operand as a typed span [kind, text, digest]. A string past 40 characters keeps its first 37 and an 8-hex SHA-1 digest. A non-primitive keeps only its type. classify.mjs prints each operand as a code span. Before, 1 and "1", 0 and -0, 1n and 1, and long strings with one prefix printed alike. Also, "or?" read as an exit.

The oracles

The classify oracle (oracle-gaps.report-classify) gets three laws.

  • Law 7 adds the F22 sentence and the operand law. Each not-infected message names, in order, the operand pairs that the model saw. No text stands for two values that the model tells apart. The model now counts a non-primitive operand as a change, as the capture does.
  • Law 8 is the one-line rule. Each gap line shows the shortened change as two code spans, and the results keep the full text.
  • Law 9 is the baseline. Each file line is pass, or fail with a replay command. A small POSIX word reader splits the command and refuses expansions. The command adds -t <pattern> only when a test failed. Under both Vitest joins, the pattern must select exactly the failing test.

The grammar adds these inputs:

  • Operands: -0, numeric strings, "NaN", "1n", undefined, null, NaN, bigints, booleans, objects, or?, and two long strings with one prefix.
  • Mutant code of 60 and 61 characters, multi-line code, and backticks.
  • Authored mutants, new to the oracle, with varied owners, intents, authors, and find.
  • Names with (a|b), $HOME, it's, q"t, [t0]+, ^x$, a.b, and a backslash. A name can end with another name.

The end-to-end fixture puts the failing test in the suite broken (b.*) $x it's, next to a top-level fixed seed 999. The driver runs the printed replay in a real sh and observes which tests ran.

Evidence

  • Law: classify laws 7, 8, and 9, and end-to-end law 3. Authority: the maintainer's findings F22 and feat(oracles): survivor classes with directive messages; short, streamed gap output #12 (2026-11-10), @vitest/runner 4.1 and the Vitest rerun command, and POSIX.1-2017 sections 2.2 and 2.6.
  • Reach (classify, fixed seed 20261105): baseline failing test 58, load failure 35, regex-syntax suite 37, contained name 8. Gap cut at 60: 45. Multi-line code: 26. Conflated operands: 9. Authored: not-observed 6, not-judged 9, killed 6, does-not-apply 33, unowned 62. End to end, a constructed history reaches refused brokenOwner.
  • RED (classify, each law without its fix):
    • Operands: names no readable operand pairs, owed 1
    • F22: (not-observed) has message "…", which is not its directive
    • Gap line: which does not show its change on one line, shortened to 60 characters
    • Baseline: the replay pattern "t0 > t0" … runs tests [] when Vitest joins names with " "
  • RED (end to end, parent): The replay of broken (b.*) $x it's > fixed seed 999 ran [].
  • GREEN: 4 oracle files passed 31249 tests. The end-to-end fixed seed passed in 208 s.
  • Mutants: each fails both classify campaigns.
    • Operands: unquoted strings, -0 as 0, no digest.
    • Gap line: a cut at 61, an unshortened intent.
    • Baseline: no start anchor, no end anchor, the Vitest 5 join only, no regex escapes, JSON quotes, and -t '' on a load failure.
    • Review round: a bigint with N, undefined as void.
  • Limits:
    • The driver encodes operands with a copy of the capture's shown. No law judges that encoding.
    • A 32-bit digest separates long strings, and no symbol operands occur.
    • Names hold no backtick and no >, and they are distinct in a file.
    • The end-to-end replay runs one fixture under Vitest 4 only.
    • The output does not shorten the author.
    • Only the single-file runner path (unit()) records names for the baseline.

Review round 1

Each fix first extended the classify oracle, which failed on the round-0 code.

  • Control characters escaped. A newline in a test name broke baseline lines. Control characters now print as \uXXXX, which still selects the same test in a pattern.
  • Code-point cuts. The cuts counted UTF-16 units and could split a surrogate pair. Now they count code points.
  • Law 7 against the model's rendering. Each operand must equal the model's rendering (operandOf), not only differ from the others.
  • Authored intents as code spans. A plain intent such as "null or undefined?" read as an exit.
  • Limits added for symbols and the batch path.

GREEN after the round: 31249 tests passed, and the end-to-end seed passed in 209 s.

Decisions for the maintainer

  • F22 wording. The maintainer's text offered a choice with or, which the no-exit law forbids. So the directive has two steps. It says "mutated code" because the class also covers comparisons and authored mutants.
  • The L? exemption. The exit check now reads L? as a placeholder for a gap with no line. It is safe because it matches only L? between spaces. Any other ? still counts as an exit.

Changeset

.changeset/gap-report-output-fixes.md (patch, @tanstack/oracles).

This pull request and its description were written by Isaac.

KyleAMathews and others added 3 commits November 11, 2026 00:09
…lines, typed operands, F22's not-observed directive

- The baseline's replay -t pattern is the test's suite and own names,
  regex-escaped, joined for Vitest 4 and 5, anchored, and single-quoted;
  a file with no failing test replays whole. Classify law 9 checks it
  over generated names; the end-to-end oracle runs the printed command.
- A gap line's code and intent collapse whitespace and cut at 60
  characters; results.json keeps the full text (classify law 8, with
  authored mutants now generated).
- not-infected operands print as typed code spans, never two values
  alike (classify law 7).
- not-observed also directs a history where the mutated code computes
  something different (F22).

Co-authored-by: Isaac <no-reply@databricks.com>
…erand texts, intents as code

- Control characters in a test's name or failure print as \\uXXXX escapes
  in the baseline (where the replay pattern still selects the test) and in
  messages; classify law 9 owes one-line baseline lines.
- The gap line's and the capture's cuts count code points, so an
  astral-plane character is never split.
- Classify law 7 owes each operand text equal to the model's own
  rendering, not only distinct texts.
- An authored intent prints as a code span, so its words are not read as
  the report's.

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

changeset-bot Bot commented Nov 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 138c63e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@tanstack/oracles Patch

Not sure what this means? Click here to learn what changesets are.

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

@coderabbitai

coderabbitai Bot commented Nov 11, 2026

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a3aa284a-1d95-4194-be5e-d2d11f78d045
  • 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

@pkg-pr-new

pkg-pr-new Bot commented Nov 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/TanStack/oracles/@tanstack/eslint-plugin-oracles@20
npm i https://pkg.pr.new/TanStack/oracles/@tanstack/oracles@20

commit: 138c63e

@KyleAMathews
KyleAMathews merged commit 114bdfb into main Nov 11, 2026
8 checks passed
@KyleAMathews
KyleAMathews deleted the overnight/c-directives branch November 11, 2026 08:47
KyleAMathews added a commit that referenced this pull request Nov 11, 2026
…le format, and no listener warning with many contexts (#26)

* feat(oracles): --config selects the Vitest config; .mts wrappers; listener accounting per warm context

- --config <file>, relative to --package, selects the package's Vitest
  config; the baseline names the config loaded, or says it found none; a
  --config that is not a file of the package refuses the run (F12).
- The runner's wrapper configs are .mts, so Vite loads them and the
  package's config as ES modules in a package of any module type (F13).
- The process's listener limit grows by one per open warm context and
  shrinks when it closes, so eleven or more contexts print no
  MaxListenersExceededWarning (F15).
- The end-to-end oracle generates config place, module type, a
  top-level-await config, and eleven contexts; the static oracle generates
  a missing or directory --config.

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

* fix(oracles): a failing owner's replay names --config; bound e2e shrinking

- A failing owner's replay command names the --config file the run was
  given, so it runs the failing test under that config even when Vitest
  would discover another one (F12 with #20's replay law).
- The end-to-end oracle writes a discovered config that includes no test
  beside every config that only --config names, and a constructed history
  replays a failing owner there.
- The end-to-end oracle's counterexamples shrink through at most six
  histories, so a campaign reports its first law verdict within its 900 s
  limit instead of a timeout.
- The four config states were listed twice in the required states.

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

* fix(oracles): wrapper format follows the package config; config line once loaded

- The runner's wrapper config has the module format that Vite gives the
  package's own config: .mts for an ES module config, .cts for a CommonJS
  one, so a top-level await and require both load as under Vitest.
- The run names its config once its contexts loaded it, so a refusal by
  the analysis or the baseline names it too.
- A context that fails to open gives back its listener allowance, and one
  whose standalone or init step rejects is closed.
- The end-to-end oracle generates config extensions .ts, .mts, .cts, .js,
  .mjs, and .cjs in either module type, CommonJS configs that call require
  and require.resolve, a law 9 edit that switches --config, and owes the
  config line on every run whose config loaded.

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

---------

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