Skip to content

ci: add a non-blocking Windows job for the oracle framework and gap CLI - #58

Draft
KyleAMathews wants to merge 9 commits into
mainfrom
ci/windows
Draft

KyleAMathews wants to merge 9 commits into
mainfrom
ci/windows

Conversation

@KyleAMathews

Copy link
Copy Markdown
Contributor

Summary

Adds two non-blocking Windows jobs, so we can see what breaks on Windows. Nothing in this repo has run on Windows before, and a user has reported path problems. This PR changes CI only. It fixes no failures.

  • windows-unit (windows-latest): framework unit tests, eslint plugin tests, and the gap CLI's fast oracles (static, classify, probe-form, mutant-validity).
  • windows-gap-cli (windows-latest): a tiny fixture package, written at run time and not committed, run through the gap CLI in the default shell (PowerShell), then through --daemon and --stop-daemon, then one fixed-seed unit of the end-to-end oracle.

Both jobs are continue-on-error: true with a 25-minute timeout-minutes backstop, and each step has continue-on-error: true, so a later step runs after an earlier failure. Neither job is in preview's needs, and neither is a required check.

Notes

  • Each step has continue-on-error so one failure does not hide the next. The diagnostic steps are marked as diagnostic in the workflow comments.
  • The fixture oracle is the smallest oracleProperty I could write. It only exists to make the CLI's end-to-end path run.

This pull request and its description were written by Isaac.

The framework, the eslint plugin, and the gap CLI have never run on
Windows, and users report path problems there. Two diagnostic jobs run on
windows-latest: the unit suites (framework, eslint plugin, gap fast
oracles) and the gap CLI end to end (a fixture package written at run
time, the plain and daemon paths, and one fixed-seed e2e unit). Both are
continue-on-error and each step continues on error, so the first failure
does not hide later ones. Neither is a required check or a dependency of
preview.

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

changeset-bot Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 00456e7

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

@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

@pkg-pr-new

pkg-pr-new Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 72b9495

KyleAMathews and others added 8 commits November 13, 2026 09:02
Diagnostic only, not a fix. The first run showed the gap fast suites and the
fixed-seed end-to-end unit hang on windows-latest (cancelled at the job
timeout, with no output after the static oracle and the e2e calibrations
started). The fast suites now run one file per step with a step timeout and
verbose output for the static oracle, so the hang is located. The fixture
gets the package.json it was missing (the CLI reported ENOENT for it). The
job timeouts are raised to 45 minutes so the split steps can finish.

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

Diagnostic only. Adds a bash replay of the first failing static unit (its
verdict is not printed by the run), a run of the fixture with the discovered
config instead of --config, and a dump of the gap CLI's error.log files from
the OS temp directory, which the daemon run's failure points to.

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

Forward slashes at entry, native only at the file system. Paths enter the
CLI as argv, as Vite and Vitest report them, and as realpath returns them;
comparisons and keys use one spelling (oracle-gaps/paths.mjs).

- The config wrapper imports the config by a POSIX specifier. A backslash
  in an ES module specifier is a character, so every run with a config
  was refused on Windows (check.mjs, wrapper).
- Mutant copies are keyed and served in forward slashes, as Vite resolves
  and Vitest reports them. The copy map was keyed by native paths, so the
  copies were never served on Windows.
- Module IDs are kept by isAbsolute, not by a leading slash: a Windows ID
  is `C:/...`.
- The package root, the located packages, and the source names use the
  native real path on both sides (realPathOf). The JavaScript realpath
  kept 8.3 short names such as RUNNER~1 and refused every owns entry.
- The daemon listens on a named pipe on win32 (no socket file to
  remove), keys by the same real path as the CLI, and its timeout names
  the end of its log.
- A package with no package.json is refused, not an internal error.
- Replay and rerun lines print PowerShell and cmd forms on Windows; the
  POSIX form is unchanged.

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

- npm is an npm.cmd shim on Windows; spawnSync runs it through a shell
  there (package.test.ts, shipped-citations.test.js).
- The probe-form oracle's model decides production by a directory named
  src, split on either separator, not by a substring with `/`. Production
  was right; the model was wrong on Windows.
- The owns test uses the native real path, as the CLI does.

Co-authored-by: Isaac <no-reply@databricks.com>
The diagnostic steps are gone. The Windows jobs mirror the Linux shards:
the unit suites in one job, the static gap oracle and the fixed-seed
end-to-end oracle in three shards each (pr-shards.mjs), and the gap CLI on
a fixture, including the discovered config and the daemon. Each job has a
15-minute backstop. The jobs are still continue-on-error until every one
is green; that line is removed then.

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

The owners and the instrumenter named files with the platform's
separators, and TypeScript matches a file's name as given, so on Windows
the owner map keyed `src\x.js` while the sources were `src/x.js`, and
CommonJS sites lost their functions. The compiler now gets forward-slash
names, and owner keys are forward-slash (schemata.mjs, owners.mjs,
analysis.mjs).

A path's drive letter is capitalised in the one spelling (paths.mjs), so a
drive's case never decides a path.

New oracle: gap-report-path-spelling (a metamorphic check). Law 1: the
instrumenter gives the same mutant ids for a source under any spelling of
its path. Law 2: relativeWithin answers from the segments alone.

Evidence block
- Law: a path's separators and a drive letter's case do not change what the
  gap CLI decides (paths.mjs, Windows support, 2026-11-13).
- Reach: 200 generated histories (fixed seed 20261113 and random), over four
  module forms, drives in both cases, mixed separators, short and spaced
  names. Reach is not declared (states: []); the histories are not
  measured as reaching a state.
- RED: on the parent commit (72b9495), the Windows jobs of
  #58 failed: the config wrapper
  import (check.mjs), the copy map, the owner keys (owners.mjs), and the
  8.3 short names. On Linux the enumeration law does NOT reproduce the
  Windows failure: the instrumenter gave the same ids on the parent. The
  Windows failure is a platform path.relative difference, which Linux
  cannot produce. The RED for those classes is the Windows CI run.
- GREEN: the Windows jobs (see the PR). Local, on macOS: the new oracle 5
  of 5, the framework 114 of 114, the eslint plugin 7335 of 7335.
- Mutant: relativeWithin as it was before (raw string comparison) fails the
  relation checkpoint; dropping the drive capitalisation fails it too. Both
  run on the parent tree with the oracle and both fail (exit 1).
- Limits: no declared reach; Law 1 uses the forward-slash spelling as its
  reference, so it claims only that the spelling changes nothing; owners,
  realpath, and OS short names are judged by the Windows end-to-end run,
  not by this oracle.

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

- P10: the Windows CLI runs assert the done line on both streams, and that
  it matches the exit code (scripts/windows-witness.mjs done).
- A package with no package.json is refused with exit 2 and a done line
  that names it (Windows witness).
- One early stop: SIGINT once the CLI prints its first line; the run must
  end with the stop's done line on both streams, or with no output (#57).
- Per-shell replay (framework, accepted by the coordinator): a failing
  property's PowerShell and cmd lines each reproduce the failure in their
  own shell. The POSIX line is run in PowerShell and must not reproduce (the
  RED). A run that printed only the POSIX line fails here (the mutant).
- The tsc link lookup in package.test.ts reads npm's Windows shim, not a
  symlink.
- The eslint plugin suite runs even when the framework suite fails.
- Job timeouts are 20 minutes, as high backstops (2026-11-12).

Co-authored-by: Isaac <no-reply@databricks.com>
…ch packages have a manifest

Windows CI failed the classify oracle's baseline law: the CLI prints a
PowerShell and a cmd replay line there, and the law read only the POSIX
`replay:` line (Difference: "the replay of tests/f0.test.ts is undefined").
The law is unchanged: each replay line the platform prints must read as
`vitest run <file> -t <pattern>` in its own shell, and the owed test is the
one it selects. On win32 the law owes both per-shell lines; elsewhere the
POSIX line (replayLinesOf, powerShellWords, cmdWords).

The static oracle's scratch packages had no package.json, which the CLI now
refuses (args.mjs). Each fixture now writes a minimal manifest; its content
and its histories are unchanged.

Evidence block
- Law: the replay line of each shell reads as the owed command (Law 9,
  baseline; the CLI's replay lines, stream.mjs).
- Reach: the existing classify histories (276 tests); no new histories.
- RED: Windows run 43478073715, classify shard 3 (baseline law, 11
  violations) and the static shard 1 refusal (the missing manifest).
- GREEN: local POSIX classify 276 of 276. The win32 branch runs in the
  Windows job (see the PR).
- Mutant: not run; the win32 branch is exercised only by the Windows job.
- Limits: the win32 branch is checked on Windows only, not by the oracle's
  own generated histories.

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