Skip to content

🤖 tests: add the memory and foreign-holder SessionLocks layers to the contract - #7367

Merged
ThomasK33 merged 6 commits into
mainfrom
phase4/fakes
Oct 23, 2026
Merged

ThomasK33 merged 6 commits into
mainfrom
phase4/fakes

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds two test layers for SessionLocks and runs the lock contract on four layers: node, memory, node + foreign and memory + foreign. It is PR 6 of phase 4. It changes only test harnesses and one test file.

Order

Background

Phase 4 moves the loop's lock calls behind SessionLocks. Later PRs (9 to 16) test the moved code with locks that need no real files and no real waits, and that play other backends. One contract runs on every layer, so the fakes cannot drift from the Node locks.

Implementation

  • memorySessionLocks.testHarness.ts: SessionLocksMemory builds a fresh MemoryLockTable at each build of the layer. An acquire takes a free or dead lock at once. Otherwise it waits in FIFO order until a release hands the lock over, or until the HostClock passes the timeout. Under a TestClock the test moves time with adjust. Refusals use today's text (fileLockTimeoutMessage, crossProcessLockTimeoutMessage) and today's argument asserts. An aborted signal throws today's abort error. A record lock creates its missing parent, as Node does. Three parts stay on the Node locks:
    • Init-record locks (foundByReaddir: the path has the segment /locks/init-record/). InitStateManager lists their folder, so a holder in memory would leave no file and a live init would look abandoned.
    • Record locks with createParentDirectory: false. WorkflowRunStore needs their acquire to fail with ENOENT once the run directory is gone, with no window between a check and the take. Only the Node lock's own write gives that.
    • The use leases. The mutation gate, isHeld and taskService read other backends' lease files. Phase 5 moves them.
  • foreignHolders.testHarness.ts: makeForeignHolders() gives the test a handle (hold, release, reclaimed). withForeignHolders(inner, holders) wraps a layer. A live foreign holder refuses at once with today's text, and an aborted signal wins over it. A dead one is reclaimed by the next acquire, and its path goes to reclaimed. A probe reclaims nothing. hold() publishes the lease first and probes the gate second, as WorkspaceUseLeases.hold does. A live holder on workspaceMutationLockPath makes it release the lease and throw WorkspaceMutationInProgressError with today's text. isHeld counts a live fake lease in the workspace's lease folder. Every fake holder records an identity (foreignIdentity()), so its text equals the Node text for a current record. liveBlocker(pid) gives that blocker. Fake pids are foreignPid(n) = process.pid + n, so a fake holder is never this process.
  • sessionLocks.contract.test.ts: the contract runs on the three new layers. The Node text test now compares against liveBlocker, so the fake text equals the Node text for the child's pid. Four new contract cases run on all 4 layers: an aborted signal wins over a live holder, createParentDirectory: false on a missing parent rejects with ENOENT, an aborted signal wins over a missing parent, and a record lock creates its missing parent by default. Eight more cases:
    • memory: a 60 s timeout passes on TestClock.adjust, and it has not settled 1 ms before the timeout.
    • memory: a release hands the file lock to the waiters in FIFO order, and the old handle's assertStillOwned then throws.
    • memory: an init-record lock makes a real file, and inspect sees it.
    • memory: each build of SessionLocksMemory has its own table.
    • foreign: dead holders are reclaimed in order, and a probe reclaims none.
    • foreign: a live foreign mutator makes hold() refuse with today's text.
    • foreign: hold() publishes its lease before it probes the gate.
    • foreign: a live fake lease of another backend makes isHeld true.

Validation

  • bun test ./src/node/services/sessionLocks/: pass. The contract file has 53 pass, 0 fail.
  • Scratch checks, each reverted:
    • Drop the live check in wrapWithForeignHolders: the 4 live cases of node + foreign and memory + foreign fail.
    • Drop foundByReaddir: the init-record case fails.
    • Share one table across builds of SessionLocksMemory: the fresh-table case fails.
    • Drop the abort check in the foreign layer: the abort case of both foreign layers fails.
    • Send createParentDirectory: false to the memory table instead of the Node locks: the ENOENT case of both memory layers fails.
    • Drop the memory layer's mkdir: the create-parent case of both memory layers fails.
    • Drop the fake-lease check in the foreign isHeld: the isHeld case fails.
    • Probe the fake gate before the lease: the gate-order case fails.
  • make static-check: pass.
  • make crap-check, make dry-check, make mutate-check (base = the parent commit): PASS with 0 functions in scope. The PR changes only test harnesses and a test file.
  • make test on 3e31a0aa6a, which is this diff on 🤖 tests: put the session lock modules under local/no-host-imports with their 1 pair #7355's head 2f34c99: 27689 pass, 0 fail in the main run, and every other run passes. The second half (tests/ui/storybook/, tests/ui/domIsolation.test.ts, vscode/src/, scripts/): 732 pass, 0 fail.
  • Tripwire (scripts/perf/loopTestBaseline.ts --runs 3, base = 🤖 tests: put the session lock modules under local/no-host-imports with their 1 pair #7355's head 2f34c99, on 3e31a0aa6a): 0 trips.
  • On the head 423f813: bun test ./src/node/services/sessionLocks/, make static-check and make lint-eslint pass. The tripwire and make test were not rerun after the move to main and the Codex fixes, because the PR changes only test files under sessionLocks/.

Follow-ups

  • Codex round 4 (deferred, not a blocker): the memory layer's acquireProcessFileLock does not create the missing parent of lockPath, while fileLock.ts does. No test uses the memory layer yet. PR 9 adds the mkdir and a contract case before it moves any caller. Tracked in 🤖 tests: declined review findings of the phase 4 call-record PRs #7326. (PR 9 fixes this one.)
  • Codex round 5 (deferred, not a blocker): in the foreign-holder layer, a fake live holder on a record lock with createParentDirectory: false refuses with a timeout even when the parent is gone, where Node gives ENOENT. No test combines the two yet. The first PR that runs such a caller on withForeignHolders fixes it. Tracked in 🤖 tests: declined review findings of the phase 4 call-record PRs #7326.

Risks

Test-only. No production file imports the new harnesses.


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high • Cost: $103.72

…ontract

SessionLocksMemory keeps lock state in a table per build and waits on the HostClock, so a TestClock test moves time instead of waiting. withForeignHolders plays other backends: a live holder refuses at once with today's text, and a dead one is reclaimed. The contract now runs on node, memory, node + foreign and memory + foreign.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T23:04:49.640610Z 991b02f Manual request
🔒 Security Review ✅ Completed 2026-10-23T23:03:14.699396Z 991b02f Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e3cfd1ca5f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/sessionLocks/memorySessionLocks.testHarness.ts
Comment thread src/node/services/sessionLocks/foreignHolders.testHarness.ts
Comment thread src/node/services/sessionLocks/foreignHolders.testHarness.ts Outdated
Comment thread src/node/services/sessionLocks/foreignHolders.testHarness.ts
Comment thread src/node/services/sessionLocks/foreignHolders.testHarness.ts Outdated
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

🟢 e2e stories (Haiku): 14 passed

27 agent steps · 7 replayed from cache · 32 model calls · 230.0k tokens (71% cached)
Spend: $0.10 of the $1.00 cap (proxy ledger)

All 14 tests in 9 files
Test Agent Time
🟢 chatRestart.e2e.ts · 1 passed 2 steps · 4 calls 25.4s
🟢 a chat survives a restart of the server 2 steps · 4 calls 25.4s
🟢 compaction.e2e.ts · 1 passed 3 steps · 8 calls 44.4s
🟢 /compact replaces the old chat with a summary 3 steps · 8 calls 44.4s
🟢 pluginTrustRestart.e2e.ts · 1 passed 4 steps · 2 calls 11.5s
🟢 a trusted plugin hook stays trusted after the server restarts 4 steps · 2 calls 11.5s
🟢 settingsRoundTrip.e2e.ts · 1 passed 3 steps · 5 calls 29.5s
🟢 a chat survives trips through Settings 3 steps · 5 calls 29.5s
🟢 sidebarPerWorkspace.e2e.ts · 1 passed 4 steps · 1 call 4.9s
🟢 a new workspace starts with its right sidebar collapsed while another keeps it open 4 steps · 1 call 4.9s
🟢 smoke.e2e.ts · 1 passed 2 steps · 1 call 2.8s
🟢 the agent opens the playground workspace 2 steps · 1 call 2.8s
🟢 streamErrors.e2e.ts · 1 passed 1 step · 1 call 6.6s
🟢 stream errors show in the chat, and the chat recovers 1 step · 1 call 6.6s
🟢 todoNudge.e2e.ts · 1 passed 2 steps · 4 calls 25.6s
🟢 the agent finishes open TODO items after the turn-end nudge 2 steps · 4 calls 25.6s
🟢 touchAlignment.e2e.ts · 6 passed 6 steps · 6 calls 25.1s
🟢 the Settings close button is level with the title on a touch screen 390px wide 1 step · 1 call 3.7s
🟢 the Settings close button is level with the title on a touch screen 768px wide 1 step · 1 call 5.5s
🟢 Backup settings checkboxes are small and level with their labels on a touch phone 1 step · 1 call 5.9s
🟢 the heartbeat checkbox is small and level with its label on a touch phone 1 step · 1 call 3.3s
🟢 a reply's model and time stay on one line on a touch phone 1 step · 1 call 3.7s
🟢 the workspace actions menu stays on the title row on a touch phone 1 step · 1 call 3.1s

e2e 0.20.0 · 3m 0s · web · run artifacts

🟢 e2e Electron stories (Haiku): 3 passed

3 agent steps · 3 model calls · 8.1k tokens (21% cached)
Spend: $0.02 of the $1.00 cap (proxy ledger)

All 3 tests in 3 files
Test Agent Time
🟢 electron/deepLink.e2e.ts · 1 passed 1 step · 1 call 6.2s
🟢 a deep link of a second launch starts a chat in the running app 1 step · 1 call 6.2s
🟢 electron/menuBar.e2e.ts · 1 passed 1 step · 1 call 8.9s
🟢 the workspace menu bar is the desktop title bar 1 step · 1 call 8.9s
🟢 electron/smoke.e2e.ts · 1 passed 1 step · 1 call 5.0s
🟢 Xum Electron opens the playground workspace 1 step · 1 call 5.0s

e2e 0.20.0 · 22.2s · electron · run artifacts

🟢 e2e agent repros (Haiku): no tests selected

Spend: $0.00 of the $1.00 cap (proxy ledger)

e2e 0.20.0 · 5.3s · 2 targets (web, phone) · run artifacts

…nts, gate order and holder text

Codex round 1 on #7367: an aborted signal wins over a fake live holder, the memory layer rejects with ENOENT when createParentDirectory is false and the parent is gone, the fake gate is probed after the lease is published, fake holders record an identity so the text equals the Node text for a current record, and fake pids are offsets from process.pid.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 30fe6b1db7

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 30fe6b1db7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/sessionLocks/memorySessionLocks.testHarness.ts Outdated
Comment thread src/node/services/sessionLocks/memorySessionLocks.testHarness.ts Outdated
…the memory record lock

Codex round 2 on #7367: an aborted signal wins over a missing parent, and a parent removed after the first check (or during the wait) refuses with ENOENT and frees the lock, as Node's write would.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9675e47d03

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/sessionLocks/memorySessionLocks.testHarness.ts Outdated
Comment thread src/node/services/sessionLocks/foreignHolders.testHarness.ts Outdated
Comment thread src/node/services/sessionLocks/memorySessionLocks.testHarness.ts
…ake leases in isHeld

Codex round 3 on #7367. The memory layer's parent checks did not converge, so a record lock with createParentDirectory false now goes to the Node locks, whose own write gives WorkflowRunStore the ENOENT it needs. Other record locks create their parent as Node does. The foreign layer's isHeld counts a live fake lease in the workspace's lease folder.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: f7525029ff

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f7525029ff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/sessionLocks/memorySessionLocks.testHarness.ts
@typescript-eslint/await-thenable (CI lint-full): bun types rejects.toThrow and rejects.toBeInstanceOf as void.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 423f813f42

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 423f813f42

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 423f813f42

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/sessionLocks/foreignHolders.testHarness.ts
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 991b02fc1d

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 991b02fc1d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 23, 2026
Merged via the queue into main with commit 7aaca3f Oct 23, 2026
33 of 34 checks passed
@ThomasK33
ThomasK33 deleted the phase4/fakes branch October 23, 2026 23:29
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