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
Adds atomic daemon/session-owned process records with {pid,startTime,command,purpose}, exact-identity startup reaping, and spawn/reap wiring for simulator recording and managed agent-browser processes.
Reuses the existing typed Apple recording descriptor and live appleSimulatorRecordingCommandMatches seam. The simulator host refreshes the root identity after output readiness, when xcrun has exec'd CoreSimulator's simctl, so the generic exact-identity reaper receives the stable post-exec identity.
Makes managed-web record clearing contingent on semantic JSON success, so an exit-0 {success:false} close cannot erase the sole durable record.
Replaces ps reconstruction in the daemon leak oracle with record-reading, exact identity checks, and fail-closed ownership-loss reporting.
Rebased onto current main (including fix(daemon): close web sessions on daemon shutdown instead of leaking the browser fleet #2012's web-shutdown teardown and shared timeout constant). Scope is 30 touched files, limited to the owned-process contract/recording owners, managed web lifecycle, and leak-model/oracle coverage. The existing Apple runner xcodebuild lease remains its separate durable owner seam; this change does not duplicate it.
No docs or skills changed: behavior is owned by the runtime contracts and existing test procedures.
Validation
pnpm check:affected --run — all runnable checks passed: format, lint, typecheck, layering (including durable-owner rules), fallow, build, Node integration (92 passed / 9 expected skips), and related Vitest (310 files, 2,090 tests). The first sandboxed attempt stopped only because its leak-model preflight could not invoke /bin/ps (spawnSync ps EPERM); the identical gate passed with host process visibility.
Focused follow-up: 3 files, 32 tests passed for Apple simulator recording, managed web provider, and the durable record store.
macOS-host native evidence is now available. On a booted iPhone 17 Pro simulator, the built CLI record start --scope device persisted the live CoreSimulator simctl io ... recordVideo identity (the exact ps command matched it); record stop exited successfully, produced the MP4 and gesture telemetry, cleared owned-processes.json, and left the recorder PID dead.
Native crash/startup-reap evidence: after a real recording, killing the daemon left the recorded CoreSimulator PID and durable record in place; the next daemon startup through devices read the record, reaped the recorder, and cleared the record. The crashed session was then cleaned up.
pnpm vitest run test/integration/provider-scenarios/ios-record-trace.test.ts — 2 passed; the fixture starts a real child through the injected simulator transport and verifies record write/clear.
node --experimental-strip-types --test test/integration/daemon-leak-oracle-cli.test.ts — passed, including the exact daemon-owned process record case.
Adversarial review attempt: the approved claude -p invocation was made; the sandbox reported not logged in, and bounded Keychain-backed retries produced no output and were stopped. No Claude findings were available; local diff audit, maintainer findings, and planted-red checks were completed.
Design and size accounting
Against origin/main at 07217c53f, the diff is 30 files, +1,733/-226. The regenerated size report is +7.5 kB JS/unpacked, +2.3 kB gzip, and +2.2 kB tarball.
Runtime/package paths: +906/-165 across 16 files (net +741). The durable record store is 228 lines and the generic reaper is 217 lines (+445 total) for atomic versioned daemon/session state, path-safe validation, PID/start-time/command fencing, purpose filtering, escalation, and startup cleanup. The managed-web owner adds 185 lines for process-table observation at the provider lifecycle seam; provider wiring is +93/-12 and lifecycle extraction is +43/-136. The remaining +140/-17 is typed contract, daemon wiring, and Apple host/descriptor integration.
Test/fixture/oracle support: +827/-61 across 14 files, including the device-free model/oracle rules, CLI exact-record coverage, provider scenarios, fixture wrapper-to-exec proof, and semantic-close regression.
A smaller owner-specific implementation was rejected because it would duplicate atomic file format, validation, startup reaping, escalation, and daemon/session scope semantics between Apple and web. The shared record/reaper owns only durable identity mechanics; Apple retains the typed AppleRecordingDescriptor and purpose-owned live matcher, while web retains the narrow process-observation owner. A generic purpose/command matcher would type-erase semantic identity and caused the original simulator P0.
No physical iOS device, Android/Harmony/Vega target, or managed Chrome web E2E was available locally for this change. The repository's GitHub native/device and AGENT_DEVICE_WEB_E2E=1 lanes remain authoritative for those live OS/provider gaps.
Touched-file count: 30. Ready for review; do not merge.
P0 — normal iOS simulator record stop is broken. Exact-head source evidence on iPhone 17 Pro: record start succeeded and persisted /bin/bash …/usr/bin/simctl io …, but the live PID exec'd to CoreSimulator's /Library/Developer/…/bin/simctl io …; record stop then failed with simctl recordVideo process ownership changed before cleanup (mt7peeyz-e24f3d72). Identity is captured pre-exec in packages/platform-apple/src/recording/runtime.ts:92-102, while src/platform-runtime-screen-recording-apple-simulator-host.ts:22-34 and the generic reaper reject the post-exec identity. Use a typed/purpose-owned matcher shared by live cleanup and startup recovery, or capture stable post-exec identity. Add a planted wrapper→exec regression plus real CLI start/stop and crash/startup-reap evidence.
P1 — web close can erase the sole durable record on semantic failure.agent-browser-provider.ts:273-280 finalizes before unwrapAgentBrowserJson; canClear... treats exit 0 as success, so an exit-0 {success:false} close clears the record while the browser may remain. Clear only after semantic JSON success (or re-record identities), with a regression for that case.
Required size/design accounting. This is +1,648/-214 total; production net is roughly 900–1,000 lines and Size CI reports npm unpacked +7.1 kB. Please itemize justified retained growth and explain why the smaller owner-specific design was rejected: reuse the existing typed simctl capture descriptor/matcher for simulator recording and keep a narrow web-owned durable record. The current generic {purpose:string, command} layer type-erases semantic identity and already caused finding 1.
Focused exact-head build and 67 tests passed; they do not cover the two failure modes above. CI is still pending, so no readiness label.
Web semantic failure: record clearing now requires semantic JSON success in addition to exit 0 and command completion. The planted exit-0 {success:false} close regression goes red without the guard and passes with it.
Design/size accounting: the PR body now itemizes the current rebased diff (+1,733/-226 across 30 files), runtime versus test support, the +7.3 kB unpacked/+2.2 kB gzip size report, and why shared durable mechanics plus owner-specific Apple/web identity seams are safer than a type-erased generic matcher.
The branch is rebased onto current main; local pnpm check:affected --run is fully green (including 310 related Vitest files / 2,090 tests). GitHub checks for the new head are running now.
CI follow-up: the first iOS smoke attempt hit an unrelated live-runner TEXT_INPUT_COMMIT_NOT_OBSERVED failure in the existing smoke:form-input scenario (empty xcodebuild output); no text-input/XCTest code changed here. Rerunning the failed job passed end to end in 13m47s. All PR checks are now green, including Android, iOS, macOS, Linux, coverage, CodeQL, size, package, and repo guards. The regenerated size report is +7.5 kB JS/unpacked, +2.3 kB gzip, and +2.2 kB tarball; the PR body has the corrected figures.
Re-reviewed 2fc31c22: clean and ready for human review.
The two prior correctness blockers are resolved at their owning seams: Apple re-reads the recorder root identity after xcrun execs into simctl, so explicit stop and startup reaping use the stable post-exec identity; web durable ownership is cleared only after semantic close success, so exit-0 { success: false } retains the record. PID/start-time/command fencing remains fail-closed, and purpose-specific identity stays in the platform owners rather than leaking into the shared record layer.
The large-change threshold is triggered (+7.5 kB unpacked; roughly 741 net runtime lines), but the growth is itemized and the shared durable-record/reaper construction path is materially smaller and safer than duplicating lifecycle logic. Current checks are all green, planted-red regression evidence is recorded, and the PR includes exact-head macOS Simulator start/stop plus daemon-restart reaping evidence.
No actionable code findings. Residual coverage is limited to managed-web/provider and physical-device paths not independently reproduced here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ready-for-humanValid work that needs human implementation, judgment, or maintainer merge
1 participant
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #1882.
{pid,startTime,command,purpose}, exact-identity startup reaping, and spawn/reap wiring for simulator recording and managed agent-browser processes.appleSimulatorRecordingCommandMatchesseam. The simulator host refreshes the root identity after output readiness, whenxcrunhas exec'd CoreSimulator'ssimctl, so the generic exact-identity reaper receives the stable post-exec identity.{success:false}close cannot erase the sole durable record.psreconstruction in the daemon leak oracle with record-reading, exact identity checks, and fail-closed ownership-loss reporting.daemon-owned-process-probe.tsis already absent on currentmain(removed by test: catch daemon lifecycle and durable-state leaks (#1781 B1) #1859), so this diff does not recreate or delete it; the replacement is the record-reading rule indaemon-leak-model.ts.main(including fix(daemon): close web sessions on daemon shutdown instead of leaking the browser fleet #2012's web-shutdown teardown and shared timeout constant). Scope is 30 touched files, limited to the owned-process contract/recording owners, managed web lifecycle, and leak-model/oracle coverage. The existing Apple runner xcodebuild lease remains its separate durable owner seam; this change does not duplicate it.Validation
pnpm check:affected --run— all runnable checks passed: format, lint, typecheck, layering (including durable-owner rules), fallow, build, Node integration (92 passed / 9 expected skips), and related Vitest (310 files, 2,090 tests). The first sandboxed attempt stopped only because its leak-model preflight could not invoke/bin/ps(spawnSync ps EPERM); the identical gate passed with host process visibility.publishes the post-exec simulator identity after readinessfail; temporarily removing semantic-success fencing made the exit-0{success:false}close regression observeclearbeing called. Existing web: agent-browser Chrome fleets leak and can spin at 100% CPU for days — add idle lifecycle/reaper #1109/iOS simulator recorder leaks on session/daemon teardown while recording is active (0-byte recording.mp4, "Host recording is already in progress") #1324 record-reading and publication tests also have planted violations and fail closed.record start --scope devicepersisted the live CoreSimulatorsimctl io ... recordVideoidentity (the exactpscommand matched it);record stopexited successfully, produced the MP4 and gesture telemetry, clearedowned-processes.json, and left the recorder PID dead.devicesread the record, reaped the recorder, and cleared the record. The crashed session was then cleaned up.pnpm vitest run test/integration/provider-scenarios/ios-record-trace.test.ts— 2 passed; the fixture starts a real child through the injected simulator transport and verifies record write/clear.node --experimental-strip-types --test test/integration/daemon-leak-oracle-cli.test.ts— passed, including the exact daemon-owned process record case.claude -pinvocation was made; the sandbox reported not logged in, and bounded Keychain-backed retries produced no output and were stopped. No Claude findings were available; local diff audit, maintainer findings, and planted-red checks were completed.Design and size accounting
Against
origin/mainat07217c53f, the diff is 30 files, +1,733/-226. The regenerated size report is +7.5 kB JS/unpacked, +2.3 kB gzip, and +2.2 kB tarball.AppleRecordingDescriptorand purpose-owned live matcher, while web retains the narrow process-observation owner. A generic purpose/command matcher would type-erase semantic identity and caused the original simulator P0.Evidence gaps
xcrun simctlstart/stop and crash/startup-reap evidence. The fixture-level wrapper-to-exec stand-in remains explicit and is the planted-red proof for the pre-exec identity race.AGENT_DEVICE_WEB_E2E=1lanes remain authoritative for those live OS/provider gaps.Touched-file count: 30. Ready for review; do not merge.