Repository navigation
feat(oracle-gaps): write the stream to <out>/stream.log and name it in the first line - #57
Open
KyleAMathews wants to merge 19 commits into
Open
KyleAMathews wants to merge 19 commits into
KyleAMathews wants to merge 19 commits into
Conversation
The maintainer's decision of 2026-11-12: an agent that runs a check in the background learns where to read its stream from the run itself. A run that starts a check names `<out>/stream.log` in its first line on both streams (`oracle-gaps: note log <path>`), and that file holds the stderr's lines, in order, cold, through the daemon, and after a stop or an abort. The driver records each run's first lines and whether its log equals its stderr; two calibrations give a log that misses a line and a naming line after another line. Co-authored-by: Isaac <no-reply@databricks.com>
…og first The maintainer's decision of 2026-11-12 names the stream log first in every run that starts a check, refusals in it included. The refusal law (#46) owed stdout = the done line alone; it now owes [note log, done line] when the check started, and [done line] for a refusal of the run's arguments, which comes before any check (outsideSource, and the static oracle's argument refusals). Law 15's log checks apply to runs that start a check. Co-authored-by: Isaac <no-reply@databricks.com>
…irst A run that starts a check creates `<out>/stream.log`, writes `oracle-gaps: note log <path>` as its first line on both streams, and writes every stderr line to the log too: the cold check's lines, a daemon reply's stderr, an internal error's or refusal's ending, the completed done line, and the supervisor's own done line for a stopped or crashed run. Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
🦋 Changeset detectedLatest commit: 7db86c5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
commit: |
…nd run on a live --out The supervisor opens <out>/stream.log and writes the note before it spawns the child; it resolves --out once and passes it to the child and to the daemon request; it tees the child's stderr, V8 lines included, to the log. A run whose log cannot be opened is refused before any check (exit 2, one done line), and a second run on a live output directory is refused without writing into it (maintainer decision, 2026-11-13). Oracle: out-mode (explicit or default) and log-blocked and overlap histories, with the law that a completed run's results.json sits beside its stream log and that a refused run writes nothing into a live directory. Stop histories use the stop-only witness. Co-authored-by: Isaac <no-reply@databricks.com>
…le fixes Oracle changes: out-mode, stop-only and stop-at-spawn dimensions appended to the history grammar (earlier fields unchanged on the sampled histories); the five new states as own-history states; overlap generated only for an explicit out, a live first run, and a fault-free history; the overlap wait ends on the first run's exit; constructed fault histories reset the end-to-end dimensions their generated base may draw. CLI: pre-restructure index.mjs from 5a92a3e. Co-authored-by: Isaac <no-reply@databricks.com>
…un.pid on exit A run claims its output directory with run.pid: a temp file that already holds the pid, linked to run.pid (fails if it exists), so two starts cannot both claim. The claim is released on every exit but SIGKILL. A claim whose pid is gone is taken over; a live one refuses the second run and names the pid. Oracle: the spawn-delay law (outcome a or b, judged by the started marker, added with the next commit), the overlap hold guard (a test-only hook), the stop history that waits for the CLI to start, and the appended history fields. Co-authored-by: Isaac <no-reply@databricks.com>
… loads The CLI's first project statement is now the handler install, so a stop that arrives during the loads is kept and acted on once the note is written. The single run path (P4) is in the same file; the static-import variant with the same handlers passed the default-out units, so the dynamic loads are not the cause of any batch failure (review of #57). A test-only marker, ORACLE_GAPS_TEST_STARTED, is written as the first project statement so the oracle can tell a stop before the CLI started (no output is allowed) from one during its loads (the full output is required). Co-authored-by: Isaac <no-reply@databricks.com>
KyleAMathews
added a commit
that referenced
this pull request
Nov 13, 2026
… 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>
KyleAMathews
added a commit
that referenced
this pull request
Nov 13, 2026
… forward-slash done lines - Stop (#57, all-or-nothing) on the unsupervised win32 path: a stop of a run that has started now writes its `oracle-gaps: done stopped (<signal>)` line on both streams and exits 128 + signal, as the supervisor does. A stop before the run starts still prints nothing (index.mjs, runStarted). - Test-only stop hook: when the file ORACLE_GAPS_TEST_STOP names appears, the CLI takes the same stop as a SIGINT (index.mjs). The Windows stop witness uses it (a non-console parent cannot deliver Ctrl+C there; child.kill on win32 is TerminateProcess, which is a SIGKILL-like limit, so no line is owed). - Static oracle: the `unknown` long-argument case uses 30,000 characters on win32. Windows caps a command line at 32,767 characters; a longer one never starts (status null). Narrowing, recorded in the PR: the POSIX runs keep 100,000. - e2e and static model: the expected done line's report path is forward-slash (inline in the model; the e2e corruption check likewise). - The diagnostic Get-Content line is removed. Evidence block - Law: the all-or-nothing stop law (#57) on every platform; keys and report paths forward-slash (register: Windows paths; stop window on every platform). - Reach: the existing static and e2e histories; the stop witness is one run. - RED: run 43498457502, stop witness `stop was not all-or-nothing (signal SIGINT, exit null)`; static `with unknown arguments, the refusal exited null`; e2e `the last stdout line is ... report D:/...`, not `...\out\summary.md`. - GREEN: pending the next Windows run. Local: the CLI lints and loads; the stop witness is queued on the e2e lock for a fixture run. - Mutant: pending (the replay witness, on a throwaway branch). - Limits: OS delivery of Ctrl+C is not exercised on Windows; TerminateProcess is treated like SIGKILL; the win32 argv cap narrows the long-argument case. Co-authored-by: Isaac <no-reply@databricks.com>
…rawn 0-150 ms otherwise The constructed stop history waits for the started marker (ORACLE_GAPS_TEST_STARTED) and then signals at once, so the signal lands in the CLI's loads on every machine. Generated histories keep the drawn 0-150 ms delay and signal (SIGINT or SIGTERM). Verified: the real CLI passes; the late-handler mutant (handlers after the project loads) is rejected with started-but-no-output. Co-authored-by: Isaac <no-reply@databricks.com>
A refusal of the arguments comes before any check, so its output is its done line alone, through the daemon as in a cold run. The cold stream check, the daemon stream check, and the daemon refusal's note now share owesNote(expected), instead of the daemon path applying the note requirement to every refusal. Verified: the outsideSource unit passes on the CLI; the mutant that requires a note for argument refusals fails it. Co-authored-by: Isaac <no-reply@databricks.com>
The started marker (ORACLE_GAPS_TEST_STARTED) is written after the stop handlers are installed, so a marker means the CLI can handle a stop. A test-only pause after the marker (ORACLE_GAPS_TEST_PAUSE_AFTER_STARTED, ms) widens the window for the spawn-stop witness: with the marker before the handlers, a stop during the pause ended the CLI with a marker and no output (0 of 20 passes); with the fixed order, 40 of 40 pass. Co-authored-by: Isaac <no-reply@databricks.com>
…ults.json's state A stale run.pid is taken over only by the racer that creates run.pid.takeover (a directory only one racer can make), and only after it re-reads the stale pid under the mutex. Two concurrent starts against a stale claim now yield exactly one claim (witness: 5 of 5 trials, one claimant each; the mutant without the mutex and the re-read yields two in 5 of 5). A test-only pause (ORACLE_GAPS_TEST_PAUSE_AT, inert unless set) widens the window. The results-beside-log message names the directory and whether results.json is missing, unparseable or read (batch 3, issue #76). Co-authored-by: Isaac <no-reply@databricks.com>
KyleAMathews
added a commit
that referenced
this pull request
Nov 14, 2026
…e path rule (#58) * ci: add a non-blocking Windows job for the oracle framework and gap CLI 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> * ci(windows): diagnostic split of the fast suites, fixture package.json 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> * ci(windows): diagnostic replay, error-log dump, and discovered-config 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> * fix(oracle-gaps): one path rule for Windows, and shell-aware replay lines 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> * test: portable npm spawns, a segment rule for production files, native 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> * ci(windows): sharded Windows jobs in place of the diagnostic ones 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> * fix(oracle-gaps): give TypeScript and the owner map one spelling of a 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> * ci(windows): P10 done-line, refusal, early-stop, and per-shell replay 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> * fix(oracle-gaps): oracles read the platform's replay lines, and scratch 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> * fix(windows): forward-slash report paths, cmd quotes, six shards, and shipped citations Run 43483101749 (Windows, the first with the witnesses) showed: - The CLI printed `report <pkg>\out\summary.md` and `tests\a.test.ts` in the done line and in the heartbeat. Report paths and display paths are now forward-slash (posix, check.mjs, ending.mjs), as the register's keys rule requires; the file system still gets native paths. - The classify oracle's cmd reader rejected `\"` inside a double-quoted argument, which Node's argument parser reads as a quote. It now reads it so. - The static and classify oracles' second scratch package had no manifest. - Shipped citations joined paths with backslashes, and npm names files with forward slashes. The comparison now uses forward slashes. - The refusal witness searches both streams (a refusal prints to stderr). - The static and fixed-seed e2e took 3 to 6 times their Linux time on Windows, and the Linux shards hit the limit. Windows runs six shards of each (pr-shards.mjs `oracle-gaps-static-windows`, `oracle-gaps-fixed-seed-windows`, checked by `pr-shards.mjs check`: each test in exactly one shard). The classify, probe-form, mutant-validity, and path-spelling oracles run in their own job. Evidence block - Law: report and display paths are forward-slash; a cmd line reads its quoted quotes as Node does (register: deterministic replay; the CLI's keys rule). - Reach: the existing e2e and static histories, unchanged. - RED: run 43483101749, which printed backslash report paths and failed classify on `\"`. - GREEN: pending the next Windows run; local POSIX suites pass (classify 276, shipped citations 2). - Mutant: not run for this commit. - Limits: the Windows e2e and static shard timings are measured on the next run before the budget claim (P12) is made. Co-authored-by: Isaac <no-reply@databricks.com> * fix(oracle-gaps): keys and report paths are forward-slash in the CLI and its models Run 43493431349 (Windows) failed the static and e2e oracles on report paths: the done line names its report in forward slashes (the register's Windows paths rule), but the model built the expected line from the native output directory, and the declared oracle files were keyed by native relative paths (`tests\a.test.ts`), so a heartbeat's file was not an owner. - analysis.mjs, check.mjs: declared oracle files and copies are keyed by their forward-slash relative path (relativeWithin). - gap-report-model-oracle.mjs: the model's expected done line is forward-slash (inline, the model does not import production). - shipped-citations.test.js: the rejection test's strings are forward-slash. Evidence block - Law: keys and report paths use forward slashes on every OS (register, Windows paths, #58); filesystem calls get native paths. - Reach: the existing static and e2e histories; no new histories. - RED: run 43493431349: static 40 refusal-ending violations, e2e 17 baseline lead, 12 report-shaped ending, 4 streaming, 3 greppable stream. - GREEN: pending the next Windows run. Local POSIX: shipped citations 2 of 2, CLI lints clean; the Linux keys are unchanged. - Mutant: not run. - Limits: the Windows e2e and static timings are measured on the next run. Co-authored-by: Isaac <no-reply@databricks.com> * ci(windows): the replay witness runs after a failed stop witness The early-stop step failed on Windows (SIGINT ends the process through TerminateProcess, so the CLI's stop handler never runs; the run ended with a null exit code after its done line), which skipped the replay witness behind it. The replay witness now runs regardless, so each witness reports. Co-authored-by: Isaac <no-reply@databricks.com> * ci(windows): print the replay output the witness reads (diagnostic) The replay witness found no per-shell lines in the fixture's failing output. This prints the first lines of that output in the same step, so the next run shows what vitest printed. Diagnostic, to be removed with the witness fix. Co-authored-by: Isaac <no-reply@databricks.com> * ci(windows): the replay fixture declares its fixed seed The replay fixture failed to load (TypeError reading fixedSeeds[0]), so the witness saw no failure. It now declares fixedSeeds: [1]. Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): the stop law on win32, the stop hook, the argv cap, and forward-slash done lines - Stop (#57, all-or-nothing) on the unsupervised win32 path: a stop of a run that has started now writes its `oracle-gaps: done stopped (<signal>)` line on both streams and exits 128 + signal, as the supervisor does. A stop before the run starts still prints nothing (index.mjs, runStarted). - Test-only stop hook: when the file ORACLE_GAPS_TEST_STOP names appears, the CLI takes the same stop as a SIGINT (index.mjs). The Windows stop witness uses it (a non-console parent cannot deliver Ctrl+C there; child.kill on win32 is TerminateProcess, which is a SIGKILL-like limit, so no line is owed). - Static oracle: the `unknown` long-argument case uses 30,000 characters on win32. Windows caps a command line at 32,767 characters; a longer one never starts (status null). Narrowing, recorded in the PR: the POSIX runs keep 100,000. - e2e and static model: the expected done line's report path is forward-slash (inline in the model; the e2e corruption check likewise). - The diagnostic Get-Content line is removed. Evidence block - Law: the all-or-nothing stop law (#57) on every platform; keys and report paths forward-slash (register: Windows paths; stop window on every platform). - Reach: the existing static and e2e histories; the stop witness is one run. - RED: run 43498457502, stop witness `stop was not all-or-nothing (signal SIGINT, exit null)`; static `with unknown arguments, the refusal exited null`; e2e `the last stdout line is ... report D:/...`, not `...\out\summary.md`. - GREEN: pending the next Windows run. Local: the CLI lints and loads; the stop witness is queued on the e2e lock for a fixture run. - Mutant: pending (the replay witness, on a throwaway branch). - Limits: OS delivery of Ctrl+C is not exercised on Windows; TerminateProcess is treated like SIGKILL; the win32 argv cap narrows the long-argument case. Co-authored-by: Isaac <no-reply@databricks.com> * fix(oracle-gaps): the temporary directory's real path for state, socket, and logs The default output directory is under the OS temporary directory, which on windows-latest is `C:\Users\RUNNER~1\...` (an 8.3 short name). The model's expected done line names the package by its real path, so the report path never matched (e2e: `the last stdout line is ... report C:/Users/RUNNER~1/...`). The temporary directory is now taken by its real path (realPathOf) for the state directory, the socket, and the error log. Evidence block - Law: keys and report paths use one spelling; a real path on both sides (register: Windows paths; the realpath rule). - Reach: the existing e2e histories (the done-line law). - RED: e2e run 43515364499, done line with RUNNER~1 vs the package path. - GREEN: pending the next Windows run. - Mutant: pending; the replay witness mutant runs on the throwaway PR. - Limits: the stdout gap-count mismatch (`2 gap lines for 0 gaps`) and the cold internal error in the incremental law are not yet explained. Co-authored-by: Isaac <no-reply@databricks.com> * fix(oracle-gaps): the e2e fixture's temporary directory by its native real path The e2e oracle realpaths the OS temporary directory with the JavaScript realpath, which keeps the 8.3 name (C:\Users\RUNNER~1). The CLI prints the native real path, so the expected report line never matched. Use realpathSync.native, as the CLI does. Evidence block - Law: one real path on both sides (the realpath rule; Windows paths). - Reach: the existing e2e histories. - RED: run 43515364499 and ee1a5fd: the done line names RUNNER~1. - GREEN: pending the next Windows run. - Limits: the static `output namespace` violations (82 in the last run) are not yet traced. Co-authored-by: Isaac <no-reply@databricks.com> * ci(windows): split the blocking Windows jobs from the non-blocking ones; fix the tsc lookup type - Blocking now: the Windows unit suites, the classify, probe-form, mutant-validity, and path-spelling job, and the gap CLI fixture job with its witnesses (done line, refusal, stop, replay). Their continue-on-error is removed. - Non-blocking, stated in the workflow: the Windows static and e2e jobs, which fail on Windows (tracked in the follow-up PR's body by class). - Linux `Test` failed the typecheck on package.test.ts (the tsc lookup's optional capture). Fixed; tsc --noEmit passes locally. Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): stop witness, replay quoting by the shells' grammar, and review items F1-F8 Review of #58 at ebc39e6 (NOT READY). This commit fixes: - F1 (stop never stops): the witness's stop file is absolute (the CLI's cwd is the package), a stop requires the stopped line on both streams with exit 130, and the stop lands 400 ms after the run starts (the fixture's output is written in one burst near its end, so the first output line is no clock). - F2/F3 (replay quoting): PowerShell reads U+2018 to U+201B as quotes, so every such character is doubled inside single quotes. cmd toggles quoting on every `"` and expands `%`; a name with either has no cmd form, and its cmd line says `use the PowerShell line for this name` (stream.mjs, src/oracle-property.ts). The classify oracle reads each shell's line by that shell's grammar (the PowerShell quote set; cmd's quote toggling, `^`, and `%`), checks the win32 printer on every host, and generates adversarial names (curly quotes, `& | < > ( ) ^ % !`, quotes, backslashes), drawn as the last field of the test record (the fixed seeds' later draws shift; recorded here). - F(f) (POSIX hook): the test-only stop hook lives in the supervisor and goes through its stop, which forwards to the child; a hooked stop gives `done stopped (SIGINT)`, exit 130 (local run: outcome (a)). Unsupervised runs keep the hook in the process. - F5: posix() acts only on win32; on POSIX a backslash is a name's character. - F6: check.mjs realpath of workspace links, report.mjs results path, and ending.mjs error log path are forward-slash and use the native real path. - F7: the blocking Windows jobs are in preview's needs. - F8: the non-blocking jobs point at #72. - The Windows replay witness runs each printed PowerShell line and its cmd line, for two fixtures with hostile names (curly quote and metacharacters; a double quote and `%`). Evidence block - Law: the printed replay line replays in the shell it names (register: deterministic replay across shells; each printed line must replay on Windows); a hooked stop is a stopped line with exit 130 (register: stop window on every platform). - Reach: the classify oracle's 276 generated histories (new adversarial name dimension, drawn last); the Windows replay fixtures; one stop per run. - RED: the parent printer (ebc39e6, with only the platform parameter added) fails the new classify oracle on two names: `"vitest run tests/f0.test.ts -t '^’ t0$'"` (the PowerShell line ends its quote at U+2019) and the cmd line for `q"t` (`which the shell does not read as plain words`). Run locally, exit 1. - GREEN: classify 276/276 on Linux (current code); POSIX stop witness outcome (a), exit 130 (local, under the e2e lock). Windows: pending CI on this head. - Mutant: the parent printer is the mutant (the curly-quote and cmd forms before this commit); the RED run above is its rejection. - Limits: - the stop timing (400 ms after spawn) is an assumption about the fixture's length; a run that ends first is reported as a failure, not passed; - cmd's `!` is literal (delayed expansion off), an assumption; - the classify fixed seeds' later draws shift (the new field is drawn last); - the win32 argv cap, the pipe name's machine scope, the POSIX state paths moving to the temporary directory's real path (an older daemon is found only after its idle timeout), and the unsupervised win32 process-tree exemption (#74) are recorded in the PR body. Co-authored-by: Isaac <no-reply@databricks.com> * fix(oracle-gaps): path-spelling oracle generates win32 separators and drives only on win32 The Linux run of 50b4ab5 failed gap-report-path-spelling: posix() acts only on win32 (review F5), so on POSIX a backslash is a name's character and a drive letter's case is a different name. The oracle now generates backslash joints and mixed drive letters only on win32; on POSIX it generates `/` joints and `C`. This narrows the law on POSIX (recorded): the POSIX law is the forward-slash spelling, and the separator and drive-case laws are judged on win32 (the Windows classify job runs the oracle there). Evidence block - Law: a path's separators and a drive's case change nothing the gap CLI decides on win32; on POSIX they are name characters (paths.mjs, F5). - Reach: the same 200 histories, with the separator and drive alphabets by platform. - RED: Linux shard 3 of 50b4ab5: "observed value differs" on the path-spelling oracle (2 of 5 tests). - GREEN: local POSIX 5/5. - Mutant: the win32 mutants run in the Windows classify job; not re-run on POSIX. - Limits: on POSIX the separator and drive laws are not generated. Co-authored-by: Isaac <no-reply@databricks.com> * fix(oracle-gaps): event-triggered stop, derived hostile names, and the POSIX F5 witness Coordinator rulings, applied: 1. Stop trigger: an event, not a clock. The witness writes the stop file on the CLI's first stderr line. Measured (2026-11-14): on a pipe the CLI streams its progress on stderr and prints the done summary (stdout) only at the end, so stdout is no start marker. No stream.log exists on this branch; the stderr line is the event. The 400 ms timer is gone. 2. Classify generator: the hostile names are derived from the test's own fields (HOSTILE[(ms+ti) % 7] for one test in four), not drawn. A drawn field would shift every later draw of the fixed seeds. Proof: `git diff origin/main` on the classify oracle changes no `fc.` line (zero), so the generator is unchanged. 3. Path spelling on POSIX: the oracle generates backslash joints and `x:` drives on every platform. The model splits the spelled strings per platform (win32: both separators, case-insensitive drive; POSIX: `/` only, a backslash is a name's character). On POSIX a disk witness creates the backslash name and asserts it exists, realPathOf keeps it native, and posix() leaves it unchanged (F5). This removes the earlier POSIX narrowing. Evidence block - Law: the stop is delivered at a run event and ends stopped (register: stop window on every platform); a backslash name on POSIX is kept native (review F5). - Reach: the path-spelling oracle's 200 histories, now with backslash and `x:` names on POSIX (disk-backed); the classify oracle's existing histories, with hostile names on one test in four. - RED: ebc39e6 with this oracle: 2 of 5 tests fail, "the observed value differs from the owed value" (the relation and disk checks). - GREEN: POSIX local 5/5 (path-spelling); stop witness local POSIX outcome (a), exit 130 (event trigger). Windows: pending CI on this head. - Mutant: the parent (ebc39e6) is the mutant for F5 (posix() rewrites backslashes on POSIX); its RED is above. - Limits: the stdout summary arrives only at the end on pipes (a finding, not a fix here); the stop trigger assumes the CLI prints a stderr line before its work completes (measured on the fixture only). Co-authored-by: Isaac <no-reply@databricks.com> * fix(oracle-gaps): constructed tests keep their names (classify reach) The derived hostile names reached constructed tests too (ms 0 at index 0), which broke the name-relationship reach of two constructed histories ("a failing baseline test whose name another test's contains" and "... ends another test's"). A hostile name now applies to generated tests only (ms >= 1). Evidence block - Law: the constructed histories reach their declared states (the oracle's own reach rule). - RED: de8a373 run: "constructed history ... did not enter a baseline test whose name another test's contains" (Linux shard 3 and the Windows classify job). - GREEN: local classify 276/276. - Mutant: not run. - Limits: as recorded in the previous commit. Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): Rerun cmd lines, ! as no-form, separators by platform, prefix rule, witness Round-2 review of #58 (NOT READY). Items addressed: 1. Rerun (cmd) fell back on win32 every time: an absent command was passed as undefined and read as "no cmd form". An absent command is now nothing; only a value that cannot be represented has no form (oracle-property.ts commandOf). The witness runs the Rerun lines (as `vitest run` plus the line) in pwsh, Windows PowerShell 5.1, and cmd. 2. `!` is in the cmd no-form set (framework and printer; DelayedExpansion expands it silently). The classify oracle's fallback test follows. 3. The path-spelling generator's original drive and joint domains are restored (the win32 form at b904d57); the POSIX spelling's backslash names and `x:` drives are an appended `wide` record, used on POSIX only. 4. The witness header, the stop failure text, and the replay comments describe the code (event trigger on the first stderr line; the no-form set). 5. isOutside, the owners' node_modules split, and the capture-setup machinery regex split on `\` only on win32; on POSIX a backslash is a name's character. 6. (see 4) 7. Windows PowerShell 5.1 (`powershell.exe`) runs each PowerShell line, as well as pwsh. 8. configureOracles rejects an envPrefix that is not `[A-Z][A-Z0-9_]*`, with a message (the prefix is printed in replay lines). The unit test follows. Evidence block - Law: the printed command replays in the shell it names, or says it has no form (register: deterministic replay across shells); a Rerun line replays too; `!` is a no-form character (coordinator ruling); a POSIX backslash is a name's character (register: Windows paths, as amended). - Reach: the same histories (the win32 domains are unchanged; POSIX uses the appended wide record). - RED (item 1): round-2 review: plain Rerun lines printed "use the PowerShell line" on win32. - GREEN: classify 276/276, path-spelling 5/5, framework 114/114 (locally, POSIX); Windows: CI on this head. - Mutant: the round-2 Rerun behaviour is the mutant (rerunOf passed an absent command as no form). - Limits: U+2019 is not reached by the seeds in the path-spelling or replay histories; the hostile names are exercised by the witness's fixture names. Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): the witness feeds PowerShell its line on stdin, not as an argument Run 43548823073 (head 2b7b7f3): the Windows CLI job failed on Windows PowerShell 5.1 ("Replay 3 did not reproduce in powershell", a parse exception on the fixture with a double-quoted name). The witness passed the line as a -Command argument, so Node's argument quoting turned the double quote into \" and 5.1 does not read that as an escape. A typed line never passes through an argv: the witness now pipes the line to `-Command -` on stdin, for pwsh and powershell.exe alike. Evidence block - Law: each printed line replays in the shell it names, as a user types it (the register's per-shell rule). - RED: run 43548823073, witness step: "Replay 3 did not reproduce in powershell" (the Windows PowerShell 5.1 parse exception). - GREEN: pending the next Windows run. - Mutant: the argument passing is the mutant (the run above). - Limits: a cmd line is still passed verbatim as an argument (cmd has no stdin command mode here). Co-authored-by: Isaac <no-reply@databricks.com> * diagnostic: the replay witness reports the shell's own error for a line that does not reproduce Run 43551132190 (abc8b45): "Replay 3 did not reproduce in powershell" with no reason. The failure now carries the shell's exit code and output, so the Windows PowerShell 5.1 error for the double-quoted name is visible. Diagnostic; the witness's pass and fail rules are unchanged. Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): the -t argument never carries a shell-hostile character (option c) PowerShell 5.1 passes an embedded double quote in a native .cmd argument wrongly (run 43553461458: a `"`-named fixture selected no test, exit 0). The coordinator's ruling (option c): `-t` is a coarse regular-expression filter, and the exact test is carried by ORACLE_UNIT where a line sets it. - The `-t` pattern (CLI baseline and framework Rerun) replaces each character a shell reads unsafely (`"`, `%`, `!`, the curly quotes) with `.`: still anchored, only slightly broader. - Framework environment values: PowerShell (5.1 and 7) doubles the single and curly quotes, which works for any name; cmd's `set "NAME=value"` tolerates a double quote, and `%` and `!` have no cmd form (environment values only). - Classify oracle: a CLI line has no environment values, so a cmd fallback line is a breach; the -t argument must carry no shell-hostile character. - Witness: each PowerShell Replay line's ORACLE_UNIT and ORACLE_PROPERTY decode to the printed text (round-trip), in addition to the reproduction in pwsh, Windows PowerShell 5.1, and cmd. Evidence block - Law: a printed command replays exactly the unit it names, in each shell (register: deterministic replay across shells; the coordinator's option c). - Reach: the classify oracle's 276 histories (the adversarial names, derived); the Windows fixtures (`’`, `"`, `%`). - RED: run 43553461458: "Replay 3 did not reproduce in powershell", exit 0, PowerShell 5.1 with an embedded double quote in the -t argument. - GREEN: classify 276/276 and framework 114/114 locally (POSIX); the Windows witness runs on this head. - Mutant: the pre-fix pattern (a raw double quote in -t) is the mutant; the RED above is its rejection. - Limits: the -t pattern is slightly broader for names with a hostile character (the wildcard may select a test whose name differs in that position, which the classify oracle's names cannot produce). Co-authored-by: Isaac <no-reply@databricks.com> * Revert "diagnostic: the replay witness reports the shell's own error for a line that does not reproduce" This reverts commit 69c82eb. * fix(windows): cmd env rule, exact witness matching, set-line readers, fixtures (round-3 review) - F1: a cmd environment value containing `"`, `%`, or `!` has no form (the register's rule); `set "VAR=value" &&` is only emitted for a plain value (oracle-property.ts commandOf). Fixtures: one with a curly-quote property and no `"%!` (a cmd set line runs); one with a single `"` in its property (its cmd line points to PowerShell). - F2: the PowerShell decoder's offset is the value's own position, and decoded values are compared exactly with a failing unit's property and unit, as vitest prints them (`FAIL <file> > <property> > <unit>`). cmd `set` lines decode too and must agree with the PowerShell line. - F3 (partial): Rerun lines carry no ORACLE_UNIT: the framework reads ORACLE_UNIT only for a random unit during a path replay, so a fixed-seed Rerun cannot be selected exactly. Reported to the coordinator. - F6: the path-spelling comment states what it means (no history to keep). - F7: the classify readers reject `!` and judge `set … &&` prefixes; the fallback is allowed wherever the printer uses it (a file path with a hostile character). - F9: control characters in rerunPatternOf are escaped as stream.mjs does (by code point, not a control-character regex). - The witness fails when a failing unit prints no per-shell line (FAIL lines are counted per unit). Evidence block - Law: a printed command replays the failing unit it names, in each shell (register: deterministic replay across shells; the set rule). - Reach: the classify oracle's 276 histories; the Windows fixtures. - RED: run 43555531142 and the coordinator's round-3 review at ae44184 (a `"` in a set value broke `&&`). - GREEN: classify 276/276, framework 114/114, locally (POSIX). Windows: this head. - Mutant: the pre-fix env rule (a `"` in a set value) is the mutant. - Limits: Rerun lines are not exact (see F3). Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): the replay witness counts each printed line once, and runs on the package's PATH Run 43561333340 (9698922), Windows CLI job: "2 random units failed, but 4 Replay lines printed" (vitest repeats a failing unit's error text, so its replay lines repeat), and every line failed with "'vitest' is not recognized" (the rewritten runIn dropped the PATH that adds the package's node_modules/.bin). - Each distinct printed line counts once, in first-occurrence order. - Every shell runs with the package's binaries on PATH. Evidence block - Law: a printed command replays in each shell it names (the register's per-shell rule); each failing unit prints one line (witness rule). - RED: run 43561333340, the witness: "4 Replay lines printed" for 2 random units; "'vitest' is not recognized". - GREEN: pending the next Windows run. - Mutant: not run. - Limits: as in the previous commit (Rerun lines are not exact). Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): the replay witness pairs each printed line with its cmd line and checks coverage Run 43563021693 (257a5b0): "2 random units failed, but 4 Replay lines printed" and "Replay 4 has no cmd line": a failing fixed unit prints its replay under the random unit's name, so one failing unit can have more than one replay line, and index pairing breaks. A random unit's violation also prints its replay under the Rerun label, so a Rerun line can carry ORACLE_ variables, and running it with `vitest run` in front broke it. - Each distinct PowerShell line pairs with the cmd line printed after it. - A line that carries ORACLE_ variables is a replay and runs as printed; a bare -t line is a rerun and runs as `vitest run` plus its arguments. - Coverage: every failing unit is matched by a replay whose ORACLE_PROPERTY and ORACLE_UNIT decode to its names (a fixed unit by the random unit it replays). Evidence block - Law: every failing unit prints a replay that names it exactly, and each printed command replays in each shell it names (register: deterministic replay; the witness rule). - RED: run 43563021693: "2 random units failed, but 4 Replay lines printed"; "Replay 4 has no cmd line"; "Rerun 2 did not reproduce in cmd". - GREEN: pending the next Windows run. - Mutant: not run. - Limits: a bare Rerun line is not exact (see F3). Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): restore the replay witness's helpers that the pairing rewrite removed Run 0c42c33 (the Windows CLI job): "ReferenceError: decodePs is not defined". The pairing rewrite replaced the block that held the FAIL map, the PowerShell and cmd decoders, and the no-form constant. They are restored, and a local smoke run of the replay branch on a fabricated output reaches the report (pwsh is absent on this Mac, so its runs fail as expected; no reference error). Evidence block - Law: the replay witness reports a failing unit's printed commands (witness rule). - RED: run 0c42c33: ReferenceError in the replay step. - GREEN: pending the next Windows run. - Mutant: not run. - Limits: as before. Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): a Rerun line counts only for its own failing fixed unit (F3 ruling b) The coordinator's ruling: Rerun lines stay coarse -t filters (a sibling whose name the anchored pattern matches also runs). The witness now counts a Rerun line only when the failing fixed unit whose exact name it selects shows its own FAIL line in its output, so a sibling's failure cannot satisfy it. An exact selector is tracked in #78; Replay lines select exactly, through ORACLE_PROPERTY and ORACLE_UNIT. Evidence block - Law: a Rerun line runs the failing unit it names, and only it counts (register amendment: Replay lines select exactly; Rerun lines are anchored, coarse filters). - Reach: the Windows fixtures (the `Q"1` unit has no Rerun line in CI; the sibling case is the Limit's example). - RED: none in CI yet; the sibling case is not exercised by the fixtures. - GREEN: pending the next Windows run. - Mutant: not run. - Limits: a sibling case is not in the CI fixtures (recorded in the PR body). Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): the witness reads a fixed unit's FAIL line (`fixed seed 1: <name>`) Run 43569602268 (bd208ac): "Rerun 1 selects no failing fixed unit" for both fixtures. The FAIL regex expected `fixed seed: ` with no number, but vitest prints `fixed seed 1: <name>`, so no fixed unit was recorded. (The earlier fix attempt did not apply; this commit applies it and checks the match.) Evidence block - Law: a Rerun line counts only for the failing fixed unit whose exact name it selects (witness rule; register: Rerun lines are anchored coarse filters). - RED: run 43569602268: "Rerun 1 selects no failing fixed unit". - GREEN: pending the next Windows run. - Mutant: not run. - Limits: as recorded in the PR body (sibling case, #78). Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): the Rerun name check ignores vitest's colors Run 43571581118 (3b97795): each Rerun line reproduced (exit 1, "Failed Tests 1"), but the check that the failing unit's exact name appears in its output failed: vitest colors the output, so the name is split by color codes. The witness now strips the color codes before it matches a unit's name. Evidence block - Law: a Rerun line counts for the failing fixed unit whose exact name it selects and whose FAIL line its output shows (witness rule). - RED: run 43571581118: "Rerun 1 did not reproduce in pwsh (exit 1 ... Failed Tests 1)" with the name check failing. - GREEN: pending the next Windows run. - Mutant: not run. - Limits: as recorded in the PR body (sibling case, #78). Co-authored-by: Isaac <no-reply@databricks.com> * fix(windows): exact FAIL-line matching, a percent-and-bang witness, a control-name oracle case (F3, F9, L2, L3) - F3: a Rerun line counts only when its target's whole FAIL line appears, anchored to the end of the line, after the color codes are removed. `generated2` does not satisfy `generated`. The comment now says so. - F9: the classify oracle's hostile names include a control character (U+0001). The printed `-t` pattern escapes it as `\u0001` (stream.mjs escapeControls). The register says controls become `.`; the code escapes them, and the code is right (the coordinator's correction). - L2: the CI step prints replay-out.txt before the witness reads it. - L3: a third fixture, `fixture 100% done!`, witnesses the cmd env no-form branch. Evidence block - Law: a printed pattern carries no raw control character (the printer's escape rule); a Rerun line counts only for its exact target (witness rule). - RED (F9): dropping escapeControls from the CLI printer fails 4 classify tests ("the stdout has a line that is not a line of the stream"), exit 1, locally. - GREEN (F9): classify 276/276 with the U+0001 name, locally (POSIX). - GREEN (F3): the exact-match regex accepts `generated` and rejects `generated2` (checked locally); Windows: the next run. - Mutant: dropping escapeControls (above). - Limits: the framework's own Rerun escaping has no oracle; the Windows fixtures are the only witness for it (L6 and L1 are filed). Co-authored-by: Isaac <no-reply@databricks.com> --------- Co-authored-by: Isaac <no-reply@databricks.com>
# Conflicts: # packages/oracles/oracle-gaps/index.mjs
The fixed-seed units added with the spawn stop, the stream log, and the overlap (five units) were not in any Windows fixed-seed shard, so the pr-shards partition check failed in the Test job. Placed in shards 2 and 3. Co-authored-by: Isaac <no-reply@databricks.com>
The unsupervised (win32) path is being replaced by a win32 supervisor (#74), so the seam that forced it on POSIX is removed; its stop witness was not kept. The unsupervised path's stop law (no done line on a stop) is a Limit of this PR. Co-authored-by: Isaac <no-reply@databricks.com>
…ake over an unreadable claim The takeover mutex was made as a directory and its pid written after, so a racer could read it empty, take it for dead, and remove a live mutex. The pid is now written to a temp file and linked into place, so no reader sees an empty mutex. An unreadable or empty mutex or claim counts as live and is never taken over. Witness (two concurrent starts against a stale claim, a test pause between the create and the pid write): the current code gives one claimed and one crashing run in every trial; the fix gives one claimed and one refused in every trial. Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
…l-clock hold The overlap and the spawn stop 'after' case kept the first run alive with a wall-clock hold (HOLD_EXIT_MS): under load the first run can end before the second starts, so the overlap outcome depended on timing. The hold is now a named point: after the done line the process keeps its exit (and its output claim) until ORACLE_GAPS_TEST_HOLD_UNTIL names an existing file. The driver releases it once the second run has been refused, or once the 'after' stop has been sent. HOLD_EXIT_MS is deleted. The README documents the new hook. Co-authored-by: Isaac <no-reply@databricks.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The
oracle-gapsrun owns its stream log. The supervisor claims the output directory, writes the note line, and only then starts the child, so a run that is stopped after its note still leaves a log and one done line.--outis resolved once and passed to the child and to the daemon request. A second run on a live output directory is refused without writing into it. The CLI installs its stop handlers before its project modules load, and a test-only marker shows which side of that point a stop landed on.Review items: F1 is refuted (the e2e
missingSourceis an owns-entry fault refused after the check starts, so its[note, done]expectation is correct; the argument-stage case is the static oracle'sabsentSource). F2, F3 and F4 have RED results on the parent commit. The spawn-stop window (review P1) is now judged by an observation, not a timing threshold.Decisions
Entries from
~/.cache/oracle-grammar/decisions-register.mdthat this change touches or relies on:ORACLE_GAPS_TEST_STARTED).logBlockedoroverlapdimensions; the end-to-end histories own them. Scoped in one named function,staticResolve.<out>/stream.log, and its first line isoracle-gaps: note log <path>.--out(2026-11-13): the second run refuses, reportless, and names the pid that holds the directory.--out, a live first run, and a fault-free history. Default output directories are unique per run, so they cannot overlap, and a blocked log or a refusing fault ends the first run before it is live.Decisions (register entries cited)
Evidence
stream.logequal to stderr. A partial result fails, including started-but-no-output.requiredand reached by constructed histories: a stop with the default output directory, a daemon check with the default output directory, a stream log that cannot be written, two runs on one output directory, and a stop as the CLI starts (which waits for the started marker). Each is also run as fixed-seed, random-seed and determinism units. Generated-campaign reach was not measured./tmp/gapwork/RED-batch.log): the default-out stop fails "stream.log is not its stderr, line for line"; the default-out daemon fails "results.json is not beside its stream log"; the blocked log writes an EISDIR line to stderr; the second run on a live--outexits 0./tmp/gapwork/green4-r2.log, count-checked): stop default-out, daemon default-out, stop as the CLI starts, blocked log, overlap, apiLess, and both calibrations (bound to a completing history).await import('./check.mjs')before the handlers) is rejected with started-but-no-output (/tmp/gapwork/law-real.log,/tmp/gapwork/law-mutant.log).--outto the child) fails the stop and daemon default-out units; F3 (no log open check) fails the blocked-log unit; F4 (no live-run refusal) fails the overlap unit.cli.mjs, 97,386 and 36,060. (a) is smaller and installs its handlers before its heavy loads, so it was kept.e2e-shards check("5 shards partition the e2e tests") andpr-shards check("3 partitions split their tests exactly") both pass on the merged tree.Post-merge state
Main (#58, 35422e3) is merged in. The index.mjs conflict kept this PR's handlers-first ordering, started marker, pause hooks, and claim mutex, and ported #58's file-based stop hooks and its unsupervised stop law. The pr-shards partition places the new Windows fixed-seed units. Weight after the seam removal: 100,214 bytes minified and 36,969 gzip -9, against main's 97,161 and 35,910 (the fold of the stop installers is not done; the win32-supervisor PR is the planned removal of the unsupervised path).
Limits
Windows Ctrl+C delivery: Windows itself delivers Ctrl+C to the CLI; this PR's tests don't exercise that delivery path.
Stops of refusing runs: not generated. A stop sent to a run that refuses (an argument or declaration refusal) is not in any history, so the stop law does not judge that case.
CI runs fixed-seed units only: random-seed units are not run on pull requests. That is CI-1 (maintainer decision of 2026-11-12), a known gap.
No Windows CI job yet: fix(windows): Windows CI for the oracle framework and gap CLI, and the path rule #58 adds it. The unsupervised Windows path is not exercised here.
Calibrations: four stop and stream calibrations are bound to completing histories in this PR. The other 20 are unbound and tracked in oracle calibrations: 20 of 24 have no history binding (predates #57) #77.
Stale claim takeover: a crashed racer's takeover mutex with a dead pid is removed and retried. That is rare, and documented here rather than tested.
Windows static and end-to-end shards: red on main as well, and non-blocking under Windows static and e2e gap oracles: remaining failures by class (non-blocking on #58) #72. The blocking Windows Test job passes after 6222e25 (the new fixed-seed units are placed in Windows shards).
Batch 3, open (issue oracle-gaps batch 3: default-out stop and daemon results missing beside the stream log (intermittent) #76): in
/tmp/gapwork/batch3-r1.log(exact messages), the default-out stop and daemon units failed "the run completed, but its results.json is not beside its stream log", and the overlap unit failed "the second run on a live output directory exited 0, not refusing it". The batch did not overlap a bisect file swap (it finished at 10:50; the swaps started about 10:53). Not reproduced in four later runs of the same code (two sequential, two variants) or in two concurrent overlap copies under load. Open until a reproduction exists.Pre-Node window: a signal delivered before Node has started and before the CLI installs its handlers produces no output and exits by signal. That is outcome (a), allowed only because the started marker is absent. The marker is written as the CLI's first project statement.
Random delays: the generated histories draw a 0–150 ms delay, but no run shows that a drawn delay lands in the load window. The constructed history waits for the marker instead, which is deterministic.
Stop-only witness: the
stopmode counts only where steps are null (stopsOnly). A history with steps is a legal history without it.Fault-history reset: constructed fault histories reset
logBlocked,overlap,spawnStopandstopWitnessto their inert values, whatever the generated base drew. A constructed history declares its own dimensions.Overlap constraint reasons: explicit
--out, live first run, fault-free history (see Decisions).Batch-size numbers: the gzip figures compare wrapper overhead only; both bundles include every module.
Full fixed-seed campaign: not run locally. CI runs the fixed, random and determinism campaigns; this PR was verified with the targeted units and the mutants above.
Windows: the unsupervised in-process path has the same stop law and early handlers, but no Windows run has been done here.
Not judged: a mid-run failure of
stream.log(removed, replaced, or disk full), and V8 out-of-memory output (teed by inspection only). A daemon run's lines reach the file at the end of its check.Stale claim: a
run.pidleft by a SIGKILLed run can name a pid that a different process has reused. Then the next run refuses, and the message names the pid and the directory and says to deleterun.pidif no run uses it. Start-time checks were judged not worth the bytes.Commit history: the local checkpoint was first made with hooks bypassed; it was replaced (soft reset) by a hooks-on commit before anything was pushed.
Test hooks:
ORACLE_GAPS_TEST_STARTEDandORACLE_GAPS_TEST_HOLD_EXIT_MSare test-only and documented in the README.This pull request and its description were written by Isaac.