Repository navigation
🤖 tests: record the session lock calls of 18 more files - #7291
Conversation
Signed-off-by: Thomas Kosiewski <tk@coder.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
🟢 e2e stories (Haiku): 14 passed27 agent steps · 7 replayed from cache · 32 model calls · 233.2k tokens (75% cached) All 14 tests in 9 files
e2e 0.20.0 · 3m 5s · web · run artifacts 🟢 e2e Electron stories (Haiku): 3 passed3 agent steps · 3 model calls · 8.0k tokens (32% cached) All 3 tests in 3 files
e2e 0.20.0 · 17.7s · electron · run artifacts 🟢 e2e agent repros (Haiku): no tests selectedSpend: $0.00 of the $1.00 cap (proxy ledger) e2e 0.20.0 · 5.3s · 2 targets (web, phone) · run artifacts |
Signed-off-by: Thomas Kosiewski <tk@coder.com>
f4e279b to
20f014a
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20f014a217
ℹ️ 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".
|
@codex review |
…e4/call-record-18 # Conflicts: # src/node/services/sessionLocks/__fixtures__/callOptions.json # src/node/services/sessionLocks/sessionLocks.callOptions.test.ts
# Conflicts: # src/node/services/sessionLocks/__fixtures__/callOptions.json
|
@codex review |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c95e6e619a
ℹ️ 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".
# Conflicts: # src/node/services/sessionLocks/__fixtures__/callOptions.json
|
@codex review |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
# Conflicts: # src/node/services/sessionLocks/__fixtures__/callOptions.json
|
@codex review |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
Codex Review: Didn't find any major issues. Can't wait for the next one! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
# Conflicts: # src/node/services/sessionLocks/__fixtures__/callOptions.json # src/node/services/sessionLocks/sessionLocks.callOptions.test.ts
|
@codex review |
|
Codex Review: Didn't find any major issues. Chef's kiss. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
## Summary
Adds a test that records each session lock call that a few real
scenarios make: the source file of the call, the lock function and all
its arguments (every option). A fixture pins today's calls. It is PR 2
of phase 4 (session locks behind one `SessionLocks` service). Each later
move PR must keep this fixture byte for byte, so a move that changes a
lock path, a timeout, a label or any other option fails.
## Background
Phase 4 moves the lock calls of 27 files behind `SessionLocks`, with no
change of behavior. The moved calls keep their options by hand. A
changed timeout or path changes behavior only under contention, which
normal tests do not reach. This record makes such a change visible in
review. This PR covers the 9 files of the first group (history, agent
session, turn manager, removal, branch summary, refine, durable journal,
todo and review pane tools). PR 3 adds the other 18 files.
## Implementation
- `sessionLocks.callOptions.test.ts` spies on the lock modules: the
`fileLock` and `crossProcessLock` namespaces,
`WorkspaceUseLeases.prototype.hold` and the shared
`workspaceFileLocks.withLock`. In Bun, a spy on a module namespace also
reaches the named imports of the callers, so the record sees each call
before and after a move. `callSite()` takes the first source file on the
stack and skips the `SessionLocks` layers, which only forward a call.
Calls from test files are left out.
- `sessionLocks.callOptions.scenarios.testHarness.ts` runs the scenarios
through public entry points: one turn, one refusal of a mutation in a
turn, one removal, one refine apply and one fork.
- Each row records every argument of the call, serialized by kind:
strings are masked, functions and `AbortSignal`s become fixed tokens,
and any other kind fails the test with an assertion. So no option can
drop out of the record (`createParentDirectory`, for example). This
replaced a chosen list of keys in review round 4, because rounds 1, 2
and 4 each found one more key that the list left out.
- The `workspaceFiles.withLock` key and the `WorkspaceUseLeases.hold`
workspace id are arguments, so the record has them too. A move that
passes the wrong id fails.
- `callSite()` reads the stack-frame path up to `.ts:line:col`, so a
checkout path with spaces (or a drive letter) still parses.
- Paths are masked by name, not by order of use. Each scenario names the
temp roots and workspace ids it creates (`<root:turn>`,
`ws-record-turn`), and the removal names its memory target keys. The
test turns each name into digests with the code's own path functions
(`historyWriteLockPath`, `refineApplyLockPath`,
`workspaceMutationLockPath`, `workspaceUseLockDir`,
`targetMutationLockFilePath`), so a digest shows as
`<hash:history:ws-record-turn>`. Each digest scheme has its own name:
`history` (SHA-256 of UTF-8, cut to 32 characters: the history and
refine-apply locks), `workspace-use` (SHA-256 of UTF-16LE: the mutation
gate and the use leases) and `target` (memory target keys). The test
checks that the paths of one scheme share one digest, and that a digest
keeps one name. So a lock built with the other scheme's digest shows the
other name (review round 5). A digest or temp path with no name fails
the test with a clear message (`lock calls with no name: ...`). So a
lock built from the wrong id or root fails even when it occurs once.
This replaced first-use numbering in review round 4, because rounds 2, 3
and 4 each found one more case that the numbering hid. Uuids (lease
tokens) are masked. Rows are sorted and deduplicated, so the fixture is
stable.
- The scenarios build their `HistoryService` with
`createTestHistoryService()`.
- The rows are sorted, so they cannot show lock order. One explicit
check keeps the order of removal: refine, then target, then history.
Another order can deadlock against an apply that holds refine and waits
for history.
- Record again after an intended change: `UPDATE_FIXTURE=1 bun test
./src/node/services/sessionLocks/sessionLocks.callOptions.test.ts`, then
`make fmt`.
## Validation
- Tripwire (`loopTestBaseline.ts --runs 3 --base origin/main`) on the
round-5 head: 0 trips. The round-5 fix changes only names in the test
file and the fixture, and the phase lead counts this tripwire for the
final head.
- `bun test
./src/node/services/sessionLocks/sessionLocks.callOptions.test.ts`:
passes, about 1 s, and 10 more runs passed, also 3 repeats in one
process.
- Scratch edit: the `withLock` key in `tools/todo.ts` changed -> the
test fails with a diff on that row's key. Reverted.
- Scratch edit: `AgentSession` holds the turn lease for a wrong
workspace id -> the test fails on the `hold` row and on the history lock
token. Reverted.
- Scratch edit: `historyService.ts` builds the history write lock from
`${workspaceId}-other` -> the test fails with `lock calls with no name:
<the three new digests>`. Reverted.
- Scratch edit: `historyService.ts` builds the history write lock path
from the `workspaceUseLockDir` digest (the UTF-16LE scheme) -> the test
fails with a diff from `history-<hash:history:...>` to
`history-<hash:workspace-use:...>` on each history row. Reverted.
- Scratch edit: `workspaceUseLeases.ts` passes `createParentDirectory:
false` to the turn lease's `acquireCrossProcessLock` -> the test fails
with a diff that adds `"createParentDirectory": false` to both lease
rows. Reverted. (No call in the scenarios passes `false` today, only
`WorkflowRunStore`, so the scratch edit adds the option where the review
finding said a move could add it. At the turn owner lock in
`workspaceTurnManager.ts` the same edit makes the scenario itself fail
before the record compare, because that lock directory does not exist
yet.)
- Scratch edit: the 10 000 ms timeout of the removal lock in
`workspaceRemoval.ts` changed -> the test fails with a diff on that row.
Reverted.
- `make test` and its second half (`tests/ui/storybook/`,
`tests/ui/domIsolation.test.ts`, `vscode/src/`, `scripts/`) on the coder#7291
head 069b820 (which contains this PR) pass except
`WorkspaceMenuBar.test.tsx` and `scripts/perf/pageTimingCore.test.ts`,
known failures on this older base (fixed on main by coder#7305), and the
known load flake `backgroundProcessManager.test.ts`, which passed alone
(163 of 163).
- Mutation run (`scripts/mutate/check.ts`, base = this PR's base): PASS
with 0 mutants. The PR changes only test files, so no survivor needs a
disposition.
## Known limits of the record
1. The rows are sorted, so they show no lock order except the removal
order that the test checks. The record cannot see if
`WorkspaceUseLeases.hold()` inspects the mutation gate before it
acquires the use-lease file. Phase 4 PR 4 adds an explicit order check
for that (review round 6).
2. The digest names come from the production hash builders. A move that
changes a hash scheme changes the path and its name together, so the
fixture still matches. Phase 4 PR 4 pins fixed digests for the fixed
test IDs and keys, before PRs 9, 12 and 13 touch the files of those
builders (review round 6).
## Deferred review findings
coder#7326 tracks the findings that this PR declined, each with the PR that
must close it: the two limits above, seeding HistoryService in
`beforeEach` (round 4) and Windows path separators (round 2).
## Risks
Test-only. The record depends on stack traces: if a refactor changes
which source file makes a call, the site of a row changes although the
options do not. The PR that does so records the fixture again and
explains the row change.
---
_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking:
`high` • Cost: `$70.87`_
<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high
costs=70.87 -->
…as its Node layer (coder#7345) ## Summary Adds the `SessionLocks` service: one interface over today's session lock functions, with a Node layer that calls those functions. No caller moves in this PR. It is PR 4 of phase 4. ## Background Phase 4 moves the session-dir lock calls of 27 files behind one Effect service, so tests and the in-memory turn can swap the lock medium with a layer. PRs 2 and 3 (coder#7290, coder#7291) record the options of every lock call. This PR adds the service and its contract. Later PRs move the callers. ## Implementation The first commit adds two checks to `sessionLocks.callOptions.test.ts`, on the code before the move. They close the two round-6 findings of coder#7290 that coder#7326 tracks: 1. `hold()` takes the use lease before the mutation lease: `["workspace-use", "workspace-mutation"]`. 2. The lock digests of the record are pinned: `PINNED_DIGESTS` for 11 workspace ids and `PINNED_TARGET` for `/record/target`. A changed hash scheme now fails the record, even when the digest names follow it. The second commit adds the service: - `sessionLocks.ts`: the `SessionLocks` interface. Each member has the signature of today's function: `workspaceFiles.withLock`, `acquireProcessFileLock`, `acquireCrossProcessLock`, `inspectCrossProcessLock` and `useLeasesFor(config)`. - `nodeSessionLocks.ts`: the Node layer. Its members call today's functions at call time, so spies on the lock modules still reach the call. `workspaceFiles` is the shared `workspaceFileLocks` map: a second map would let two writers of one workspace run at once. - `di/tags.ts`, `di/layers/stores.ts`: `SessionLocksTag`, and `StoresLive` provides `SessionLocksNode`, so the app always gets the Node layer. - `utils/concurrency/lockErrors.ts`: `CrossProcessLockTimeoutError` and `WorkspaceMutationInProgressError` move to a pure module. `crossProcessLock.ts` and `workspaceUseLeases.ts` re-export them, so each stays one class for `instanceof`. - The message functions `fileLockTimeoutMessage` and `workspaceMutationInProgressMessage` are extracted with the same text, and `crossProcessLock.ts` exports its holder and blocker types and `describeHolder`. The test layers of PR 6 refuse with today's text through them. - `sessionLocks.contract.testHarness.ts`, `sessionLocks.contract.test.ts`, `sessionLocks.testChild.ts`: the contract, run on the Node layer. A child process is a real foreign holder, live or killed with SIGKILL. ## Validation Checks before and after the move (`bun test src/node/services/sessionLocks/`, bun 1.4.3): - First commit e217b89 (before the move): `moved lock calls keep their options` passes, with both new checks. 2 pass, 0 fail across 2 files. - Service commit 2715877 (after the move): `moved lock calls keep their options` passes. 10 pass, 0 fail across 3 files. Gates on the PR head: - `bun test ./src/node/services/sessionLocks/ ./src/node/utils/concurrency/fileLock.test.ts ./src/node/utils/main/crossProcessLock.test.ts ./src/node/services/workspaceUseLeases.test.ts`: 79 pass, 0 fail on 907f6b0. The three lock test files pass with no edit (`fileLock.test.ts` asserts the timeout text). - `git diff --name-only` shows no lock caller: the changed non-test files are the three lock modules, `lockErrors.ts`, the new service files, `tags.ts` and `stores.ts`. - `make typecheck` and `make static-check` on 907f6b0: pass. - `make test` on 907f6b0: pass, 0 failures. Its second half (`tests/ui/storybook/`, `tests/ui/domIsolation.test.ts`, `vscode/src/`, `scripts/`): pass, 0 failures. An earlier `make test` on 722dc08 (before the last main merge) failed only on the known load flake `backgroundProcessManager.test.ts`, which passed alone (163 of 163). - Tripwire (`loopTestBaseline.ts --runs 3 --base origin/main`): 0 trips on 907f6b0, and 0 trips on 722dc08. - 91dc55d (review round 1, the fresh advisor's nit): it moves the `WorkspaceUseLeases` doc comment back onto its class. `git diff 907f6b0 91dc55d` changes one comment line and no code, so the gates above count for it. `make static-check` passes on it. ## Mutation check Survivors get one of three dispositions: "killed by <test>" (a test in this PR), "equivalent: <reason>" (no input can tell the mutant from the original), or "pre-existing gap: PR 17" (a survivor on a line that this PR does not change). Each gap is listed in coder#7326. A later PR that changes or moves one of those lines must first kill its survivor, in a test commit at its start that passes on the code before the change. - The default `make mutate-check` caps each source file at its 10 nearest test files. That cap leaves out `sessionLocks.callOptions.test.ts` and `sessionLocks.contract.test.ts`. The default run on 722dc08 had 94 mutants, 56 killed and 38 survived. - The table below comes from one scratch run of `scripts/mutate/mutate_report.py` on the PR head 907f6b0, with no cap. Its lane is the nearest tests of the default runs plus the two sessionLocks tests: 94 mutants, 55 killed, 39 survived, 0 uncovered. The call-record test is in the lane of `workspaceUseLeases.ts`, `fileLock.ts` and `crossProcessLock.ts`, and kills `acquireTimeoutMs: 0` -> 1 in `hold`. - Some kills are timing-dependent: the default run killed `parseHolder` :144 `||` and :145 `||`, and this run did not. The table lists them as gaps. - Every mutant in the new code (the message functions, `lockErrors.ts`, the service files) is killed. All 39 survivors are on lines that this PR does not change. The check scores whole functions, and the PR edits one line in each of `hold`, `acquireProcessFileLock`, `parseHolder`, `describeHolder` and `acquireCrossProcessLock` (an extracted message function or a renamed type). - Line numbers are on the PR head. | # | Site | Mutant | Disposition | |---|------|--------|-------------| | 1 | workspaceUseLeases.ts:331 `hold` | `existing.count > 0` -> `>=` | equivalent: release deletes an entry at 0, so no call sequence stores a count of 0 | | 2 | workspaceUseLeases.ts:362 `hold` | `?? new Map` -> `\|\|` | equivalent: a Map is always truthy | | 3 | workspaceUseLeases.ts:373 `release` | `files?.get` -> `files.get` | equivalent: `files` is missing only on an over-release, and no call sequence makes one (each lease releases once, `releasing ??=`, and each hold that returns a lease counts it) | | 4-5 | workspaceUseLeases.ts:375 `release` | `&&` -> `\|\|` (2 sites) | equivalent: the assert fails only on an over-release, which no call sequence makes | | 6 | workspaceUseLeases.ts:375 `release` | `file.count > 0` -> `>=` | equivalent: the same invariant as coder#1 | | 7 | crossProcessLock.ts:515 | `interval.unref?.()` -> `interval.unref()` | equivalent: Bun and Node timers always have `unref` | | 8-10 | fileLock.ts:260, :261 | `lockPath.length > 0` -> `> 1` / `>=`, `timeoutMs > 0` -> `>=` | pre-existing gap: PR 17 (no test passes `""`, a 1-character path or a timeout of 0) | | 11-13 | fileLock.ts:278, :279 | `?? FILE_LOCK_RENEW_INTERVAL_MS` -> `\|\|`, `renewIntervalMs > 0` -> `> 1` / `>=` | pre-existing gap: PR 17 (no test passes an interval of 0 or 1) | | 14 | fileLock.ts:265 | `acquired = false` -> `true` | pre-existing gap: PR 17 (a failed acquire keeps its token live; a lock file with that token then reads as live) | | 15 | fileLock.ts:296 | dispose `renewInFlight !== null` -> `===` | pre-existing gap: PR 17 (release does not join a renewal in flight) | | 16 | fileLock.ts:306 | `reclaimStaleFileLock(..., 0)` -> 1 | pre-existing gap: PR 17 (no test reaches the reclaim depth limit) | | 17 | fileLock.ts:307 | `>= deadline` -> `>` | pre-existing gap: PR 17 (one more retry at the deadline's millisecond) | | 18-19 | fileLock.ts:311 | retry sleep `*` -> `/`, `+` -> `-` | pre-existing gap: PR 17 (no test checks the retry interval) | | 20-30 | crossProcessLock.ts:130, :140-145 `parseHolder` | 11 mutants of the record shape check | pre-existing gap: PR 17 (no test reads a record that is null, an array, or has a bad pid, token or acquiredAt; a backend can be pid 1 in a container) | | 31 | crossProcessLock.ts:226 `describeHolder` | `birth ?? ...` -> `\|\|` | pre-existing gap: PR 17 (no test reads a record with an empty birth) | | 32 | crossProcessLock.ts:499 | renewal guard `\|\|` -> `&&` | pre-existing gap: PR 17 (overlapping renewal ticks) | | 33 | crossProcessLock.ts:504 | renew only our own record `&&` -> `\|\|` | pre-existing gap: PR 17 (a tick that finds another holder's record) | | 34 | crossProcessLock.ts:517 | `stopped = true` -> `false` | pre-existing gap: PR 17 (a tick past its check after release) | | 35-36 | crossProcessLock.ts:528 | release attempts `attempt = 0` -> 1, `< 40` -> `<=` | pre-existing gap: PR 17 (no test makes `rm` fail on every attempt) | | 37 | crossProcessLock.ts:543 | `rm({ force: true })` -> `false` | pre-existing gap: PR 17 (a record that vanishes between observe and `rm`) | | 38 | crossProcessLock.ts:569 | `owned = false` -> `true` | pre-existing gap: PR 17 (`tryTake` throws and the token stays live) | | 39 | crossProcessLock.ts:585 | `>= deadline` -> `>` | pre-existing gap: PR 17 (a zero-timeout try-lock that fails within the deadline's millisecond sleeps once) | ## Deferred review findings coder#7326 tracks the findings that coder#7290 declined. This PR closes items 1 and 2 (the first commit). coder#7326 also lists the 32 pre-existing mutation gaps above, with the rule for later PRs. ## Risks No lock caller changes, and the Node layer calls the same functions. The error classes move module, so a second copy of a class would break `instanceof`. Both lock modules re-export the one class from `lockErrors.ts`. The contract checks `CrossProcessLockTimeoutError` with `toBeInstanceOf` on the Node layer. --- _Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `high` • Cost: `$81.85`_ <!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high costs=81.85 --> --------- Signed-off-by: Thomas Kosiewski <tk@coder.com>
Summary
Extends the session lock call record of PR 2 to the 18 other files that phase 4 moves behind
SessionLocks. The fixture grows to 56 rows. It is PR 3 of phase 4.Background
Phase 4 moves the session-dir lock calls of 27 files. PR 2 records the calls of the first 9 files. This PR adds scenarios that reach the other 18: usage, goal and timing services, the subagent artifact stores, the task handle store, init state, session files, plan migration, workspace refine (full clear), pinned artifacts, the artifact index, workflow runs, refinement rollback and journal appends.
Implementation
sessionLocks.callOptions.scenarios.testHarness.ts:oneUsageAndGoal: one headless usage record, then the timing file clear and a goal read.oneChildReport: the 5 subagent artifact functions, then the task handle publication lock.oneInitAndPlan: backend A starts an init, backend B replays it while A holds the record lock, then A ends it. Then a remote plan migration mark runs.oneWorkspaceRefine: one full clear of the history through the workspace service.oneArtifactAndRun: pinned paths, an artifact version, a workflow run and its lease, the rollback lock and one journal append.WorkspaceUseLeases.prototype.isHeld(the init record check), with its workspace id.lockCallStep()), and the record adds it to each row. The child report scenario names the two calls ofsubagentReportArtifacts.ts, so they stay two rows. Function names from the stack were not usable: another test file in the samebun test srcprocess changes the frame format.createParentDirectory(workflow locks pass false, so a late operation cannot recreate a removed run dir) and thesignalas<AbortSignal>(a canceled artifact publish wakes its wait through it). The artifact scenario passes a live signal. Each new scenario names its temp root and workspace id for the name masks of 🤖 tests: record the options of each session lock call #7290 (<root:artifact>,<hash:history:ws-record-init>), and the usage scenario names its session dir as a memory target. The fixture is recorded again in this format: the same 61 rows.createRunIfAbsentandreleaseLease, which pass the time left of a deadline as the timeout.Date.nowstands still during them, so the record holds the whole budget (120000) in every run.XUM_ROOTto its temp root. A full clear deletes plan files under the local Xum home, and without it the test deleted a real~/.xumplan of the same name (a probe confirmed it).withLockturn behind the init write.unknown: awithLockcall of the full clear. JSC makes proper tail calls, so a non-async caller that returns the lock call leaves no stack frame. A comment incallSite()explains it. The row was the same in 26 runs.Validation
loopTestBaseline.ts --runs 3 --base origin/phase4/call-record) on the round-5 head: 0 trips. The round-5 fix changes only names in the test file and the fixture, and the phase lead counts this tripwire for the final head.bun test ./src/node/services/sessionLocks/sessionLocks.callOptions.test.ts: 10 more runs passed, about 1 s each.createParentDirectory: trueinWorkflowRunStore.ts, and nosignalinartifactVersionStore.ts-> each fails the test. Reverted.~/.xum/plans/ws-record-clear.mdwas deleted by the old scenario and survives the new one.acquireTimeoutMs: 0of the init record lock ininitStateManager.tschanged to 1 -> the test fails with a diff on exactly that row. Reverted.make testand its second half (tests/ui/storybook/,tests/ui/domIsolation.test.ts,vscode/src/,scripts/) on the 🤖 tests: record the session lock calls of 18 more files #7291 head 069b820 (which contains this PR) pass exceptWorkspaceMenuBar.test.tsxandscripts/perf/pageTimingCore.test.ts, known failures on this older base (fixed on main by 🤖 tests: make test-unit runs CI's isolated files alone and ends a leaked metadata loop #7305), and the known load flakebackgroundProcessManager.test.ts, which passed alone (163 of 163).scripts/mutate/check.ts, base = this PR's base): PASS with 0 mutants. The PR changes only test files, so no survivor needs a disposition.Deferred review findings
#7326 tracks the findings that #7290 and this PR declined. This PR declined none of its own.
Risks
Test-only. The
unknownrow changes if a refactor changes how that call returns, although the options stay the same. The PR that does so records the fixture again.Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high• Cost:$70.87