You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
nightly compat: four core tests are red on windows-latest (the EACCES and state.json.v1-directory cases assume POSIX) #1982
Nightly compat (workflow_dispatch of nightly.yml on main 5b72400c6f, 2026-11-01T05:30:53Z, run 41277228379): the Windows leg still goes red, but not on Lint any more — the Lint step is now success (that is the #1954/#1969 fix working on windows-latest). The red moved to Tests.
migration refuses when state.json.v1 is a directory, keeping the legacy bytes
actual: The Bot team file C:\Users\RUNNER~1\AppData\Local\Temp\ds-bot-identity-GOIW0K\state.json could not be read (cannot back up the version-1 sta…
expected: /state\.json\.v1/
The test expects the "cannot back up" message to name state.json.v1; on Windows the failure surfaces as a read error that does not name the backup path.
meetings: a decide that cannot archive its file creates no card, and its retry creates none either
meetings: a retry once the folder is writable archives the file and lists every card — same EACCES expectation, actual: undefined.
meetings: a retry after the cards exist keeps them instead of creating another — same, actual: undefined.
Reading: tests 2–4 build their "unwritable folder" with a POSIX permission trick (chmod), which Windows ignores — the write succeeds, no EACCES is thrown, so the assertion sees undefined. Test 1 depends on POSIX ENOTDIR/EISDIR ordering when the backup target is a directory.
What "fixed" would look like: the same tests either (a) fail closed on Windows through a portable injection point (e.g. a writeFile/rename that the test stubs to throw EACCES/EPERM, instead of relying on chmod), or (b) are explicitly skipped on process.platform === 'win32' with the reason recorded — and the suite then reports # fail 0 on windows-latest.
Reproduce: GitHub → Actions → Nightly → "Run workflow" on main (or wait for the 20:00Z schedule), then open the compat · windows-latest · Node 24 job and look at the Tests step.
Triage verdict: agent-ready (bug + agent-ready). Repro is concrete (run 41277228379, job 124761788576) and all four failures are named, so one PR can close it.
Scope — one PR, the tests plus the smallest production change they need:
core/test/identity.test.js:132 (migration refuses when state.json.v1 is a directory, keeping the legacy bytes): on Windows the refusal surfaces as … state.json could not be read (cannot back up the version-1 sta…), which names the state file but not state.json.v1. Make the refusal name the backup path on both platforms (the wording lives with the path logic in core/src/host/store.js), and keep the existing guarantees — readOnly() names state.json.v1, save() leaves the legacy bytes byte-identical.
core/test/meetings-decide-paths.test.js:279, 304, 336: the "unwritable folder" is built with chmodSync(folder, 0o555), which Windows ignores — the write succeeds, refusal is undefined, and assert.equal(refusal?.code, 'EACCES') fails on all three. Drive the refusal through a portable injection point instead: stub the open/write that the claimTemp path in core/src/host/meetings.js uses so it throws EACCES, and keep each test's assertions (no card, no file, no temp, meeting stays deliberating; the retry reuses the freed name and keeps the ids already on the board).
Preferred route is the injected refusal. A process.platform === 'win32' skip is acceptable only where no injection point can be reached; it must carry the reason in the test and be called out in the PR body — a new .skip is risk T3 and then needs a PASS at the tip.
Mirror the change into the generated patch tree under patches/ds-bot/files/ the way the repo's tooling does. Do not touch the nightly matrix, and do not make the compat job non-blocking.
Acceptance: the next nightly's compat · windows-latest · Node 24 job reports # fail 0 in Tests, and each of the four tests still fails when the behaviour it covers is broken (no assertion dropped or loosened). PR says Fixes #1982.
core/src/host/store.js — make the backup-refusal wording name state.json.v1 on both platforms (fixes test 1); readOnly() keeps naming it, save() keeps the legacy bytes byte-identical.
core/test/meetings-decide-paths.test.js:279,304,336 — replace the chmodSync(0o555) trick with an injected EACCES on the claimTemp open/write path; keep all assertions (no card / no file / no temp / still deliberating, retry reuses the freed name and keeps board ids).
Mirror into patches/ds-bot/files/. No win32 skip expected; no nightly-matrix changes.
Red-first evidence will be attached to the PR body.
Activity
Birfy commentedon Nov 1, 2026
Written-by: Triage
Triage verdict:
agent-ready(bug+agent-ready). Repro is concrete (run 41277228379, job 124761788576) and all four failures are named, so one PR can close it.Scope — one PR, the tests plus the smallest production change they need:
core/test/identity.test.js:132(migration refuses when state.json.v1 is a directory, keeping the legacy bytes): on Windows the refusal surfaces as… state.json could not be read (cannot back up the version-1 sta…), which names the state file but notstate.json.v1. Make the refusal name the backup path on both platforms (the wording lives with the path logic incore/src/host/store.js), and keep the existing guarantees —readOnly()namesstate.json.v1,save()leaves the legacy bytes byte-identical.core/test/meetings-decide-paths.test.js:279, 304, 336: the "unwritable folder" is built withchmodSync(folder, 0o555), which Windows ignores — the write succeeds,refusalisundefined, andassert.equal(refusal?.code, 'EACCES')fails on all three. Drive the refusal through a portable injection point instead: stub theopen/write that theclaimTemppath incore/src/host/meetings.jsuses so it throwsEACCES, and keep each test's assertions (no card, no file, no temp, meeting staysdeliberating; the retry reuses the freed name and keeps the ids already on the board).process.platform === 'win32'skip is acceptable only where no injection point can be reached; it must carry the reason in the test and be called out in the PR body — a new.skipis risk T3 and then needs a PASS at the tip.patches/ds-bot/files/the way the repo's tooling does. Do not touch the nightly matrix, and do not make the compat job non-blocking.Acceptance: the next nightly's
compat · windows-latest · Node 24job reports# fail 0inTests, and each of the four tests still fails when the behaviour it covers is broken (no assertion dropped or loosened). PR saysFixes #1982.Birfy commentedon Nov 1, 2026
Written-by: Claim d09b
Claimed. Branch:
dev/1982-windows-compat-tests(basemain5b72400).Plan, per the Triage brief:
core/src/host/store.js— make the backup-refusal wording namestate.json.v1on both platforms (fixes test 1);readOnly()keeps naming it,save()keeps the legacy bytes byte-identical.core/test/meetings-decide-paths.test.js:279,304,336— replace thechmodSync(0o555)trick with an injectedEACCESon theclaimTempopen/write path; keep all assertions (no card / no file / no temp / stilldeliberating, retry reuses the freed name and keeps board ids).patches/ds-bot/files/. Nowin32skip expected; no nightly-matrix changes.Red-first evidence will be attached to the PR body.
core: the Windows compat reds refuse portably (#1982)