Repository navigation
fix(host-kit): keep Linux process identity stable across clock steps - #4438
Conversation
There was a problem hiding this comment.
All reported issues were addressed across 2 files
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
|
Thanks for the fix. I reviewed 1347a16 and found one problem that must be fixed before merge: on Linux, upgrading from a pre-fix version can orphan the old daemon. CI is green (14 checks, 0 failing on this head) and there are no conflicts. On Linux the start time now comes from a The rule the code must satisfy: a recorded start time proves a different process only when it was read from the same source as the current observation. A source or format mismatch is unknown evidence, never proof. Could host-kit own one comparison, for example Could the Linux identity row come from one source instead? In Not blocking, take or leave: when procfs fails, host-process.ts#L233 falls back to About the open review thread: the one on two sync procfs reads per pid (discussion) does not apply, so you can resolve it. Procfs reads are kernel-generated with no disk I/O, and owner and claim batches are a few pids. The only cheap win is reading I had no Linux or WSL2 host, so I did not see a real clock step or read a real |
1347a16 to
8e977aa
Compare
|
Published The PR is a draft while validation remains incomplete. The exact prior affected run below failed; its cause remains unproven. Selected failing files pass unchanged on both base and head; this is not a reproduction of the full suite. A full-unit base comparison is now running. No timeout was widened. Exact local validation receipt (paths omitted){
"status": "failed",
"exactCommit": true,
"checkoutChanged": false,
"refs": {
"base": "origin/main",
"head": "HEAD",
"resolvedBase": "80075b6412dfa94fd765a36407270e21adce8981",
"resolvedHead": "8e977aa4696a474550b74ea95592d59c3c8b62e3",
"mergeBase": "80075b6412dfa94fd765a36407270e21adce8981"
},
"results": [
{
"id": "format",
"status": "passed",
"command": [
"pnpm",
"run",
"format:check"
],
"exitCode": 0,
"tests": []
},
{
"id": "lint",
"status": "passed",
"command": [
"pnpm",
"run",
"lint"
],
"exitCode": 0,
"tests": []
},
{
"id": "typecheck",
"status": "passed",
"command": [
"pnpm",
"run",
"typecheck"
],
"exitCode": 0,
"tests": []
},
{
"id": "layering",
"status": "passed",
"command": [
"pnpm",
"run",
"check:layering"
],
"exitCode": 0,
"tests": []
},
{
"id": "fallow",
"status": "passed",
"command": [
"pnpm",
"run",
"check:fallow",
"--base",
"80075b6412dfa94fd765a36407270e21adce8981"
],
"exitCode": 0,
"tests": []
},
{
"id": "build",
"status": "passed",
"command": [
"pnpm",
"run",
"build"
],
"exitCode": 0,
"tests": []
},
{
"id": "vitest-related",
"status": "passed",
"command": [
"pnpm",
"exec",
"vitest",
"related",
"--run",
"--passWithNoTests",
"--project=!unit-core",
"--project=!apple-runner",
"--project=!fuzz-worker",
"packages/daemon-contracts/src/daemon-process.ts",
"packages/host-kit/src/internal/host-process-liveness.test.ts",
"packages/host-kit/src/internal/host-process.ts",
"packages/host-kit/src/internal/owner-identity-liveness.test.ts",
"packages/host-kit/src/internal/owner-identity.test.ts",
"packages/host-kit/src/internal/owner-identity.ts",
"packages/host-kit/src/process.ts",
"packages/platform-web/src/__tests__/agent-browser-process-record.test.ts",
"packages/platform-web/src/agent-browser-process-record.ts",
"src/__tests__/daemon-exit-wait.test.ts"
],
"exitCode": 0,
"tests": [
{
"passed": 406,
"failed": 0,
"skipped": 0
}
]
},
{
"id": "unit",
"status": "failed",
"command": [
"pnpm",
"run",
"check:unit"
],
"exitCode": 1,
"tests": [
{
"passed": 19755,
"failed": 2,
"skipped": 8
}
],
"failures": [
{
"file": "scripts/__tests__/eager-closure-budgets.test.ts",
"test": "rename detection survives a git mv with an edit and a hostile renameLimit",
"error": "Test timed out in 5000ms"
},
{
"file": "scripts/__tests__/release-publish.test.ts",
"test": "reports signal-terminated publish as unknown with its signal",
"error": "Test timed out in 5000ms"
}
]
},
{
"id": "coverage",
"status": "skipped",
"reason": "GitHub-authoritative (jobs: Coverage)",
"tests": []
},
{
"id": "provider-integration",
"status": "not-run",
"tests": []
},
{
"id": "web-smoke",
"status": "skipped",
"reason": "GitHub-authoritative (jobs: Apple / Smoke Tests (${{ matrix.platform }}), Integration Tests, Lint, Typecheck & Package, Perf Nightly / Android Command Perf, Perf Nightly / iOS Command Perf)",
"tests": []
},
{
"id": "replay-ios",
"status": "skipped",
"reason": "parked, workflow_dispatch only (Replay Manual / iOS Replay Suite)",
"tests": []
},
{
"id": "replay-ios-device",
"status": "skipped",
"reason": "parked, workflow_dispatch only (Replay Manual / iOS Replay Suite)",
"tests": []
},
{
"id": "replay-macos",
"status": "skipped",
"reason": "GitHub-authoritative (jobs: Apple / Smoke Tests (${{ matrix.platform }}))",
"tests": []
},
{
"id": "replay-linux",
"status": "skipped",
"reason": "GitHub-authoritative (jobs: Linux / Smoke Tests)",
"tests": []
},
{
"id": "linux-command-evidence",
"status": "skipped",
"reason": "GitHub-authoritative (jobs: Linux / Smoke Tests)",
"tests": []
},
{
"id": "replay-android",
"status": "skipped",
"reason": "parked, workflow_dispatch only (Replay Manual / Android Full Emulator Suite)",
"tests": []
}
]
} |
|
Coverage failed at 8e977aa. The job annotations identify four identity-related failures: the process-lock guard reuse fixture, daemon acquisition of a reused owner, replaced-daemon status, and registration-owner replacement. They supply legacy-format stale timestamps while Linux now observes boot/tick identities, so the new comparison conservatively retains them. I am updating the reuse fixtures to express a comparable different lifetime while retaining separate mixed-format safety tests. A fifth failure reports an unexpected second daemon fixture launch during version/signature replacement; its cause is still under investigation. No CI rerun or readiness label is warranted yet. |
|
Pushed 60ecdaa with the four same-format reuse fixtures corrected. Their assertions and timeouts are unchanged, and the existing mixed-format retention tests remain. Focused macOS run: 131 passed, one Linux-only skip. Exact affected validation is running. The failed Ubuntu Coverage job remains a failed result at 8e977aa. The new run must prove that those four failures and the unexpected second launch are gone. The second launch may have followed the timed-out stale-lock request continuing into the next case; that is a hypothesis until Linux validation confirms it. The PR remains a draft. |
|
At 60ecdaa, Ubuntu Coverage passed, including the full unit-ci lane that contains the unmocked Linux process-identity test. All five failures from 8e977aa are gone after correcting the four reuse fixtures. The unexpected second launch did not recur; no production change or retry was used to address it. Six checks succeeded and six draft entries skipped. Marked ready for review so the remaining lanes can run. The exact local affected gate still failed on the iOS recording provider-test timeout; its cause remains unproven. That local failure and the successful Ubuntu run are separate results. The coordinated Linux-upgrade requirement remains in the PR description. |
There was a problem hiding this comment.
All reported issues were addressed across 14 files
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
…c read Co-Authored-By: Claude Opus 5.5 <[email protected]>
Apex Sentinel · ✅ Approve1 finding(s): 1 minor. 🟡 Minor (1)
2 findings below 💬 Talking to SentinelIn a finding's thread, reply with:
On this conversation, comment |
There was a problem hiding this comment.
Apex Sentinel: 1 new finding on 60ecdaa. The verdict and the full list are in the summary comment.
There was a problem hiding this comment.
All reported issues were addressed across 3 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
This PR is ready at 50182d6. The Linux process identity now stays stable across clock steps, and the earlier findings from the 1347a16 review (#4438 (comment)) are fixed. All 14 checks pass at this head, and there are no conflicts. Not blocking: the "reused lifetime" token literal is hand-copied in four test files (daemon-client-lifecycle.test.ts:387, daemon-registration-status.test.ts:121, process-lock-guard.test.ts:80, daemon-registration-owner.test.ts:238), while owner-identity.test.ts:34 derives it from readProcessStartTime, so one shared host-kit test fixture could own it. Take it or leave it. On the other review threads: the state-and-start-token thread (#4438 (comment)) is fixed at this head. Zero lower-priority threads still apply. These can be resolved: the async snapshot thread, because a /proc stat read is a bounded in-memory kernel read and replaces a per-pid ps spawn (#4438 (comment)); the two test.each title threads, now fixed (#4438 (comment), #4438 (comment)); the Rollout paragraph thread, now fixed (#4438 (comment)); and the host-process.ts:368 comment thread, now fixed (#4438 (comment)). I read the code and relied on the green CI. The Linux-only tests (real /proc, clock-step probes) were skipped on my macOS host. I did not run a mutation to prove the new tests fail on the old code, and I did not run a live old-format daemon against a new CLI. I traced the quiesce, drain, stop and retire routes by reading them. No merge step remains once you are happy with the optional fixture note. |
… token Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
Re-checked b85f3ea. The only change since the clean review at 50182d6 (#4438 (comment)) is a regression test in host-process-liveness.test.ts: it feeds contradictory ps and /proc states in both directions and asserts that state, start token and the zombie fact all come from the one /proc read. Reverting the parser to take state from the ps row fails both cases. An independent review of this head found nothing blocking. No code changed, and there are no conflicts. |
* origin/main: fix(android): carry an empty text on a node labelled by its content description (#4531) fix(ios): restore the back swipe's pre-swipe still span (#4515) fix(daemon-client): type the remote daemon refusal with its dispatch fact (#4532) fix: prepare reinstall artifacts before removing apps (#4533) fix(ios): classify the keyboard dismiss refusal by what it dispatched (#4536) fix(ios): press the navigation bar back button and speed up the back swipe (#4508) refactor(gestures): one owner for the densified gesture path; drop the unproven sendevent transport (#4239) fix(host-kit): keep Linux process identity stable across clock steps (#4438) fix(ios): bound the idle wait of keyboard dismiss and keyboard enter (#4454) fix(device-selection): fail an ambiguous device request with only the tied devices (#4506)
Summary
Fixes #4437. Keep Linux process identity stable across wall-clock steps using boot ID and kernel start ticks. One shared comparison treats legacy timestamps and Linux tokens as incomparable, preserving daemon drain waits, owner locks and browser records. Fourteen files: identity consumers and reuse fixtures.
Validation
Head
60ecdaa0250e18f793956d1926844df1dcca6e3d, based on80075b6. Focused tests: 131 passed, one real-/proctest skipped on macOS. Four isolated regressions fail before the comparison fix and pass after it. Independent review found no remaining production-code blocker; documentation requests are addressed.Coverage failed at
8e977aaon four stale-format reuse fixtures and an unexpected daemon launch. This commit corrects the four fixtures without changing assertions or timeouts. Ubuntu Coverage passed at this head: all five failures are gone. The full unit-ci lane includes the unmocked/proctest, enabled on Linux.Exact affected validation at this head passed format, lint, types, layering, Fallow and build, then failed an iOS recording provider-test timeout (405 related tests passed). The earlier receipt passed all 406 related tests, then failed two unit timeouts. Full-unit base failed at four different tests; timeout attribution remains unproven. Six current-head checks succeeded; six draft entries skipped. Marked ready for review to run the remaining lanes.
Rollout
Upgrade all installations sharing a Linux host together, including global and project-local installs. Older binaries can misclassify new-format owners and reclaim locks. New binaries retain incomparable owners. On Linux, the new CLI refuses to signal a daemon recorded in the old start-time format, so
agent-device daemon stopdoes nothing for it: stop each running daemon with the old binary (or end its process) before upgrading. This cannot repair old binaries.