GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||
GeezerVison is showing github.com — feat: make oracleProperty the only campaign API and lint the older path by KyleAMathews · Pull Request #4 · TanStack/oracles Conversation
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
| Name | Type |
|---|---|
| @tanstack/eslint-plugin-oracles | Patch |
| @tanstack/oracles | Patch |
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
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…st; report invalid entries
R4-7: an `fc` imported from @fast-check/vitest runs campaigns too. The rule
counted only fast-check bindings, so `fc.assert` through that import was not
reported.
R4-8: the rule cannot see the base commit, so it cannot stop a baseline from
growing. Its header and changeset now say so, and a project enforces shrink
only in its own diff check. Entries the rule can never judge are reported as
`invalidEntry`: a file outside the oracle-file glob, or a framework
implementation module.
Also: the legacy-name import check stays after the APIs are removed, so a
project that still vendors them sees the reports (header note). The
`imported.name ?? imported.value` pair is one helper (importedName).
Law: a generated-history campaign in an oracle file runs through
oracleProperty, whatever fast-check binding it takes; a baseline entry is
judged only in an oracle file that is not an implementation module
(maintainer decision, 2026-11-09).
Reach: oracle-property-only oracle; the new `vitest` alias and `invalid`
dimension are generated; the invalid state is entered by a constructed
history ("an entry the rule cannot judge"), and the vitest form by the
generated alias.
RED: R4-7: with the vitest alias in the grammar, the counterexample
{"alias":"vitest", sites: [fc.assert]} fails against the rule that accepted
only fast-check (1 of 4 tests failed). R4-8: with the invalid dimension and
no rule support, 2 tests fail (counterexample: invalid "outside").
GREEN: the oracle passes 4 of 4 after each change. Plugin suite: see the
pull request for the full CI set.
Mutant: accept only fast-check: 1 test fails. Never report an out-of-glob
entry: "Failed Tests 2". Never report an implementation-module entry: not
rerun separately; the invalid dimension's implementation case is generated
in the same oracle, so it is part of the same kill.
Limits: the rule sees one file, not the base commit: additions are not
stopped. An entry for a deleted file is not reported. Aliases and helpers
are not followed.
Co-authored-by: Isaac <[email protected]>
…unexport oracleCampaignSeed
R4-10 (and S1): two fixed histories read `replay requested` twice, so they
did not pit a second reader against the selection. The second reads are now
`run config replays` ("a reconfiguration that would change a read selection")
and `replay witness attaches` ("a replay set after configuration"). Both
readers return the replay selection, so the law is the same. Coverage change:
these two histories now exercise the run-configuration and witness readers
instead of repeating the first one.
S5: oracleCampaignSeed has only the internal caller in oracle-config.ts, so it
is no longer exported; the package API snapshot drops it.
S9: the config-oracle header's uneven lines are reflowed. No content change.
Law: a configuration decides every oracle read; the replay selection is the
one the readers agree on (oracle-config.ts; maintainer decision, 2026-11-08).
Reach: config-oracle's declared states unchanged (the model's reached function
reads the steps, and the two histories still enter their states).
RED: no RED is claimed: the duplicate reads were a coverage gap, not a wrong
answer. The counterpart is the mutant below.
GREEN: packages/oracles config and package tests: 33 of 33 pass after the
change, and the config oracle passes 11 of 11.
Mutant: the run-configuration reader made to return false: the config oracle
fails 1 of 11 tests.
Limits: the edited histories cover two readers; the other readers keep the
coverage they had. Unexporting oracleCampaignSeed is a breaking change for
a consumer that imported it; no consumer in this repository does.
Co-authored-by: Isaac <[email protected]>
…ument the rule R4-9: the packages are at 0.0.0 and nothing is released, so the removal of createOracleReach and runOracleCampaign needs no changeset: the framework's add changeset simply never had them. The separate minor changesets are deleted. The rule is folded into the plugin's add changeset, a patch, so the first release is 0.0.x as intended. The changeset now says the rule cannot stop a baseline from growing. README: a section for oracle/oracle-property-only: what it reports, the exemptions, the legacyCampaigns setting with an example, and the entry checks (no reason, stale, and invalid entries). Law: documentation of an existing law; no behaviour change. Reach: n/a (documentation). RED/GREEN: prettier --check on README and .changeset passes. Mutant: n/a. Limits: the README describes the rule as it is; the entry checks are the ones in the rule's header and oracle. Co-authored-by: Isaac <[email protected]>
… read them
The part-reach split named its five files and its support module without
"oracle", so recommended config (**/*oracle*), oracle/no-unit-test,
pure-model, replayable-seed, and oracle-property-only skipped them. Rename
them to *-oracle.property.test.js and part-reach-oracle-support.js.
The rules then reported 22 incomplete oracleProperty calls: each file passed
familyOptions(...) to oracleProperty, which hides the check from the rule.
Each call now passes `{ ...familyOptions({...}), check: checkPaths }`, so the
check is visible in the file and the family options are unchanged.
The receiving-linter property passes checkPaths explicitly.
Simplifications folded in: the REACH_ORACLE_DEBUG console block is removed;
withForms is one export beside BASE; usePartReachPaths registers the
receiving paths' setup and teardown once per file.
Law: unchanged (the same reach relation and check; see PART_REACH_AUTHORITY).
Reach: unchanged: 42 declared states, each gated by the family that enters it.
RED: npx eslint --no-fix on the renamed files (before this commit's inline
edit): 22 errors, oracle/no-unit-test "does not pass an object literal with
a check" in forms, helpers, modules, families, and the receiving linter.
GREEN: npx eslint --no-fix packages/eslint-plugin-oracles/tests/part-reach-*.js
reports 0 problems. vitest tests/part-reach: 145 of 145 pass (5 files, about
3m12s on 2 workers).
Mutant: the calibrations of every property stay (a dropped report and a
spurious report on each receiving path), so the check still rejects the
wrong observations.
Limits: the run-budget check (check-oracle-run-counts) is part of TanStack DB,
not this repository, so it is not run here; this repository has no
equivalent.
Co-authored-by: Isaac <[email protected]>
There was an error while loading. Please reload this page.
commit: |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
… not sampling A constructed history must shrink through the generated input. The constructions were rejection samplers: they hashed the generated skeleton into a seed, discarded it, and drew up to 3000 fresh skeletons with fc.sample until one entered the state. The output did not depend on the generated input except through the hash, a failed draw threw only after 3000 builds, and every construction built 3000 skeletons, so the suite took about 3m12s. Each state now has an explicit construction, a factory of the features that gate it. It splices the fragments that enter the state into the generated skeleton, in the generated shape (formIndex, frameworkOptions, import forms), and keeps the rest. The fragments are the fixtures that the support module already states, and the framework checks every `enters` at run time. The hook helper allows a minute, since the receiving-path setup can exceed the default ten seconds on a loaded machine. The companion-edit state is still recorded by statesOf in this commit; the edit-law change follows in the next commit. Law: unchanged. Each declared state stays gated by a constructed history under the features of its family; the reach relation and the check are the same. Reach: 42 gated states, each with a construction: 300 of 300 generated skeletons enter each state under its family's features, and every built history is generable (programSkeleton.canShrinkWithoutContext), checked with a standalone script before the suite ran. RED: at d4f1988 the construction was constructedFor, which returned a skeleton drawn from fc.sample(programSkeleton, { seed, numRuns: 3000 }) and ignored its generated input except through the seed. The suite took 3m12s on 2 workers. GREEN: npx vitest --run --maxWorkers=2 tests/part-reach: 145 of 145 pass in 43 s. npx eslint --no-fix on the part-reach files: 0 problems. Mutant: the check is unchanged and still rejects the dropped and spurious reports of every property (the calibrations). Limits: a construction enters its state for every sample checked; a family whose features cannot enter a state fails its construction loudly. The builder fragments are fixed shapes, so the generated skeleton shrinks around them rather than through them. Co-authored-by: Isaac <[email protected]>
…second lint Three fixes to the part-reach laws, each with its RED first. R4-4: the oracle-properties family ran 30 runs, but the original campaign ran 200 (the campaign call in 471edd0). It is restored to 200. Every other family's budget was compared with the original and matches: 400 for both cycle families, 200 for layouts and namespace imports, 300 for drivers and JavaScript companions, 30 elsewhere, and the laws' 4, 3000, BASE_RUNS, and 40. R4-5: editCheck passed when the second lint's observation was missing, though the model owed it. RED: a calibration that drops the `after` observation was added first, and with the old check it failed ("the second lint is not recorded" was not rejected), as the calibration requires. Fixed: a missing observation differs from the owed reports and fails the check. The law's arbitrary is again the dependency filter, so every drawn program has a companion to edit: only programs with a dependency are drawn. R4-6: statesOf recorded companion-edited-between-lints for any program with a dependency, at e382e7b (part-reach-fixtures.js:1573), so a family that never edits claimed the state. The state is removed from statesOf. The companion-edit law records it through `reached(plan, trace)`, from the `after` observation, so a state is claimed only when a second lint ran. Law: the edit law is unchanged in its statement (a companion edited between two lints gives the reports of a fresh process). The check now owes the second lint whenever the plan has a dependency. Reach: the edit state is recorded only from the trace. Gated states: 42, as before, each with a construction. RED: (a) the old editCheck, restored temporarily, fails the calibration "the second lint is not recorded" (1 of 1 failed); (b) e382e7b:1573 claims the edit state for any dependency; (c) the oracle-properties budget at 471edd0 is 200, at e07674a it was 30. GREEN: the new check rejects the dropped second lint (the calibration passes). vitest tests/part-reach: 146 of 146 pass; the whole plugin suite: 4285 of 4285 (13 files). eslint --no-fix on the part-reach files: 0 problems. Mutant: the driver that skips the edit (rewriteCompanion removed) is rejected on both the fixed and random companion-edit campaigns, with an `after` violation (2 failed). Limits: the reach claim is taken from the trace the driver records; a driver that edits but records no `after` observation is caught by the check, not by the reach claim. The run-budget check is part of TanStack DB, not this repository. Co-authored-by: Isaac <[email protected]>
…acle file Q-8: probe-form-grammar.js holds the grammar, MODEL, and predictReports that two oracles share. Its name had no `oracle`, so the oracle rules, the run-budget check, and the recommended config's file glob never read it. It is renamed probe-form-oracle-grammar.js, and its two importers follow. The rules report nothing on it, so there is no suppression and no rule change. Law: unchanged (the probe form, oracle/probe-form). Reach: unchanged. RED: the parent's name is outside the oracle-file glob, so the oracle rules never linted it (the glob check reads the basename). GREEN: npx eslint --no-fix on the renamed grammar and both importers: 0 problems. The probe-form oracle passes. Mutant: n/a (rename only). Limits: none beyond the existing ones. Co-authored-by: Isaac <[email protected]>
…at once; cover @fast-check/vitest
Q-1: a malformed legacyCampaigns entry (not an object with a string file, or
a reason that is not a string) crashed every oracle file with a TypeError.
The rule now validates the settings when it is created and throws one clear
message per bad entry, so the run stops with that message.
Q-3: an entry the rule cannot judge (a file outside the oracle-file glob, or
an implementation module) was reported once per linted file. It is now a
configuration error, validated at creation, so it stops the run once rather
than repeating per file. Decision: these are configuration errors, not
lint reports.
Q-4: the law statement names the configuration errors and @fast-check/vitest.
Q-5: a declared state and a constructed history for the @fast-check/vitest
path. Dropping that source fails the constructed history deterministically.
Law: a generated-history campaign in an oracle file runs through oracleProperty,
whatever fast-check binding takes it; a baseline entry the rule cannot judge
stops the run before any file is judged (maintainer decision, 2026-11-09).
Reach: the vitest state (declared; constructed history "a campaign through
@fast-check/vitest"), the refused state (constructed "an entry outside the
oracle glob"), and the malformed state (constructed "a malformed entry").
RED: with the outcome model, the oracle failed 3 of 5 tests before the rule
change (counterexample: outsideGlob entry, which the rule reported instead
of refusing; and the calibration found no clean configuration history).
GREEN: 5 of 5 after the change.
Mutants:
- no malformed check at all (the four conditions removed): 2 tests fail,
counterexample a bare-string entry.
- a single condition removed (the object check only): the file check still
catches it, and all 5 pass. This partial mutant is not a kill, which is
why the full mutant is the one recorded.
- @fast-check/vitest dropped from the sources: 2 tests fail, counterexample
alias vitest with a campaign through the alias.
- implementation-module validation removed: 2 tests fail.
Limits: the configuration errors are thrown from rule creation; ESLint then
stops the run. A throw at creation is not reported per file by the rule
itself, so the once-per-run behaviour depends on ESLint stopping on a rule
exception. A stale entry for a deleted or renamed file is not reported.
Co-authored-by: Isaac <[email protected]>
… stop the run Q-9: an entry for a deleted or renamed oracle file is never reported, because no lint run sees that file, and the rule cannot check existence soundly: a settings path can be a suffix of the repository path, so a check from the lint root would report entries that exist. The README and the plugin changeset now say so, and the limit is in the rule's header and oracle. Q-1/Q-3: a malformed or unjudgeable entry is a configuration error that stops the run (ESLint reports "Error while loading rule" with the message; verified with the ESLint API on a bare-string entry). The README and changeset describe that instead of a per-file report. Law: documentation of the behaviour in the previous commit. Reach: n/a. RED/GREEN: prettier --check on README and the changeset passes; the stop behaviour was checked directly with ESLint's lintFiles. Mutant: n/a. Limits: the rule sees one file, so it cannot stop a baseline from growing. Co-authored-by: Isaac <[email protected]>
…nd keep the rest of the input
Round-2 review Q-2 (maintainer direction: reach keeps randomness). The
constructions replaced whole fixtures: 31 of the 42 replaced the generated
registration, module, or companions with a constant, so the part that
enters a state did not vary with the input, and shrinking could not move it.
Each construction is now a list of writes to its gating fields (a dotted
path into the generated skeleton, and the value that gates the state). The
generated registrations, modules, and companions are kept, and a write that
creates a missing element uses its generated-shape default. The neutral
module fields and slots that a state does not use are gated too, as the
fixtures left them; the registrar call is gated when a construction imports
by index.
Law: a constructed history changes only its gated fields; outside them it
equals the generated skeleton (lint.part-reach.constructions, new). Each
state's `enters` is still checked by its family's constructed history.
Reach: distinct constructed outputs over 300 skeletons (fixed seed 2234),
per construction, the registration (oracle.tests[0]), the module, and the
companions. RED (before) -> GREEN (after), distinct counts; entering is the
number of samples in which the state is entered:
export-star-cycle tests0 1 -> 261; module 1 -> 300; companions 65 -> 218; entering 300 -> 300
named-reexport-cycle tests0 1 -> 261; module 1 -> 300; companions 65 -> 183; entering 300 -> 300
javascript-companion-import-reaches-part tests0 1 -> 145; companions 126 -> 216; entering 185 -> 300
mutual-recursion-reaches-no-part tests0 1 -> 261; module 1 -> 293; entering 300 -> 300
companion-edited-between-lints tests0 1 -> 145; companions 65 -> 216; entering 0 -> 300 (dependencyOfReached; statesOf cannot see it)
form-each, form-call-body, form-member-body, form-for, form-options,
let-assigned-driver, named-constant-arbitrary, imported-predicate,
predicate-ignores-input, oracle-named-helper, prefixed-oracle-helper,
caller-passed-body-helper, caller-body-wrapper, oracle-property-*
tests0 1 -> 261; entering 300 -> 300
The other constructions: each changes a field that gates the state; every
one has tests0, module, or companions varying in every sample (see the
table in the pull request).
RED: the mutant that builds form-each by replacing the generated oracle.tests[0]
with a constant fails the new law (fixed and random campaigns), so the law
rejects the fixture style the RED table measures.
GREEN: part-reach tests pass (150 of 150, six files) with the new builders.
Mutant: the same mutant gives an empty gate (whole element), and the law's
gate-shape observation (a gate that names a whole element) rejects it. The
first form of the law let it through; the gate-shape observation was added
after that mutant passed.
Limits: the law checks the non-gated fields; each construction's entering is
checked by its family's constructed history. Measured over 300 skeletons
under the ALL features; the families use their own features, which the
family runs check.
Co-authored-by: Isaac <[email protected]>
…e the support module's status; fix JSDoc and dead imports Round-2 review items Q-6, Q-7, Q-10. Q-6: familyOptions no longer returns `check`: each oracle file passes `check: checkPaths` at its call site, so the check is one visible source. The rule reads the literal at the call site. (No change to no-unit-test.) Q-7: the support module's header says its name contains `oracle` (it does) and that it declares no oracleProperty and registers no test: its properties are owned by the oracle files that import it. Q-10: the lintedOnItsOwn JSDoc was attached to withForms; it now sits on lintedOnItsOwn, and withForms keeps its own. The laws file's unused imports setupReceivingPaths and teardownReceivingPaths are removed. Law: unchanged behaviour. Each oracle file's check is its own call site. Reach: unchanged (no state or construction changed here). RED: the old familyOptions returned a check that no call site used, so the call sites' own `check: checkPaths` replaced it. Nothing failed; the duplicate was the defect (review Q-6). GREEN: eslint --no-fix on the part-reach files: 0 problems; part-reach tests pass (150 of 150, six files). Mutant: removing `check: checkPaths` from one call site makes that file's oracleProperty fail (no check): the rule no-unit-test reports the call. Limits: checks are per-file call sites; a future call site with no check is reported by no-unit-test, not by this file. Co-authored-by: Isaac <[email protected]>
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.