Skip to content

refactor(kernel): track held execution locks in keyed-lock - #3879

Merged
thymikee merged 1 commit into
mainfrom
refactor/keyed-lock-held-keys
Oct 22, 2026
Merged

thymikee merged 1 commit into
mainfrom
refactor/keyed-lock-held-keys

Conversation

@thymikee

@thymikee thymikee commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Summary

Follow-up to #3323 (merged as c8b944c). Replayed from its stack onto main with an identical patch (same git patch-id).

The kernel keyed lock now answers which execution locks a context holds, including locks taken partway through a request. Request locks keep no registry of their own.

  • keyed-lock.ts:
    • Scopes link to live parents only.
    • withKeyedLockHolder can hold locks until its task ends. heldKeyedLockKeys lists held keys, including keys still being taken.
    • A scope that wants a key its holder is still taking waits for the hold, then re-enters it. If the hold is cancelled, the scope fails with it.
  • request-execution-locks.ts applies the same-Mac rule (ADR 0035) as one check; its registry and re-entry special cases are gone.
  • A nested request re-enters a lock its parent took partway through instead of waiting on its parent.
  • The close-refusal test now uses the real platform refusal.

5 files. Closes #3876.

Validation

Head e5813a1d02bf8c9066381f576c1aacdf9251661d, on main c8b944c.

  • check:affected --run --head <head>: passed, run-jL09Mn, exactCommit: true, 4,523 related tests.
  • Before the replay, at 9e2ad9b on 7519086: run-KLsDWf passed (12,421 related tests); three independent review rounds found nothing blocking; and a native live run passed, with two apps in parallel in one daemon, conflicts and close scope held, and no claims left. These are attributed to 9e2ad9b; the patch is unchanged.
  • New kernel and daemon tests time out on the old code.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Size Report

Metric Base Current Diff
Installed (including dependencies) 5.52 MB 5.52 MB +1.2 kB
Package (unpacked) 5.52 MB 5.52 MB +1.2 kB
Package (download) 1.67 MB 1.68 MB +386 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 34.2 ms 34.2 ms +0.1 ms
CLI --help 69.7 ms 68.7 ms -1.0 ms

The kernel keyed lock now answers which locks an async context holds,
including locks a request retains partway through, instead of a second
registry in request-execution-locks.

- Lock scopes form a chain with live parents, so a lock a holder scope
  takes later is visible to every scope nested in it.
- `withKeyedLockHolder` runs a task that can `hold` locks until it ends;
  `heldKeyedLockKeys` lists the keys the current context holds.
- Request execution locks use them: a held key re-enters, and the
  same-Mac rule (ADR 0035) is one check. The enclosing-request store, the
  held set, and the two re-entry special cases are gone.
- A nested request whose initial key its parent retained now re-enters
  it; before, it waited on its own parent.
- The close-refusal test builds its error from the production platform
  refusal over a stubbed app list.

Closes #3876.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@thymikee
thymikee force-pushed the refactor/keyed-lock-held-keys branch from 9e2ad9b to e5813a1 Compare October 21, 2026 19:09
@thymikee
thymikee changed the base branch from stack/pr-3323-app-devices to main October 21, 2026 19:09
@thymikee

Copy link
Copy Markdown
Member Author

Closing and reopening to re-run CI against the new base: the Size job of the retarget push measured the deleted stack base 7519086 (unable to read tree).

@thymikee thymikee closed this Oct 21, 2026
@thymikee thymikee reopened this Oct 21, 2026
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-22 03:09 UTC

@thymikee

Copy link
Copy Markdown
Member Author

This PR is ready at e5813a1. Not blocking, and you can take or leave these: the pending-hold tracking in packages/kernel/src/keyed-lock.ts only matters if work runs concurrently inside one request, and on the routes I traced the device is retained before the next step starts, so drop it or name a router-level caller in a test. The re-entry fix is covered at the createRequestExecutionLocks seam in request-execution-locks.test.ts but not through the replay router, so a later same-device step in the dynamic-selection replay test would close that gap. heldKeyedLockKeys could be generic over the key type to avoid the string[] cast in request-execution-locks.ts. The ended-holder test matches on error message text.

Bundle Size failed only because it could not read the deleted base tree 7519086, and the Smoke Tests, Repo Guards and Coverage runs were cancelled, not failed. The diff touches no bundling or packaging inputs, so the failures look unrelated. There are no conflicts. This was a read-only review, so I ran no tests. I also could not check the patch-id match with 9e2ad9b or the live two-app run at that SHA, because that object is not in my clone. Before merge, CI needs to go green on e5813a1 after the reopen.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Oct 21, 2026
@thymikee
thymikee merged commit d70665f into main Oct 22, 2026
18 of 24 checks passed
@thymikee
thymikee deleted the refactor/keyed-lock-held-keys branch October 22, 2026 03:09
thymikee added a commit that referenced this pull request Oct 22, 2026
* origin/main:
  feat(test-app): add a Bluesky-depth heavy feed screen (#3884)
  fix(android): read a child that vanished mid-read as gone (#3901)
  feat(ios): route iPad Simulator snapshots through the host AX bridge (#3895)
  Prepare shared resource ownership and selection for #3325 (#3887)
  refactor(kernel): track held execution locks in keyed-lock (#3879)
  perf(ios): ask a ready runner about surface hosts before spawning probes (#3877)
  fix(ios): keep the bridge while a surface host only lingers (#3873)
  perf(ios): synthesize taps on resolved in-app back controls (#3880)
  fix(macos): open a running app by its own path instead of its bundle id (#3889)
  fix(macos): accept mixed-case bundle ids in open (#3867)
  fix(macos-helper): scroll SwiftUI forms whose rows are scroll-area children (#3888)
thymikee added a commit that referenced this pull request Oct 22, 2026
* origin/main:
  fix(android): read a child that vanished mid-read as gone (#3901)
  feat(ios): route iPad Simulator snapshots through the host AX bridge (#3895)
  Prepare shared resource ownership and selection for #3325 (#3887)
  refactor(kernel): track held execution locks in keyed-lock (#3879)
  perf(ios): ask a ready runner about surface hosts before spawning probes (#3877)
  fix(ios): keep the bridge while a surface host only lingers (#3873)
  perf(ios): synthesize taps on resolved in-app back controls (#3880)
  fix(macos): open a running app by its own path instead of its bundle id (#3889)
  fix(macos): accept mixed-case bundle ids in open (#3867)
  fix(macos-helper): scroll SwiftUI forms whose rows are scroll-area children (#3888)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Track held execution locks in keyed-lock instead of a request-level registry

1 participant