iter-142: session hygiene — daemon stop pid honesty, disk GC, eval ASI fix - #181
Merged
Conversation
…val ASI fix, wait sleep Root-causes the daemon-stop false-negative (dogfooding session 63, 3/3 reproducible) to launch-record.json being a single global file clobbered by concurrent launches on different ports; scopes it per port and makes the proxy-registry fallback path kill the real Firefox pid instead of the daemon's own. Adds immediate (age-independent) reclamation of dead-owner temp profiles, GC for stale throttle-state files, and GC for the legacy port-less spawn lock. Fixes eval's async-IIFE wrapper to detect ASI-separated statement boundaries (not just `;`) and to auto-return a trailing bare expression instead of silently dropping it as undefined. Adds `wait --sleep-ms` (with a `--time` legacy alias) as a plain-delay form that skips the Firefox connection entirely. Defers Theme C (auto-consent honesty + BBC CMP coverage), Theme D (full-page screenshot header dedup), and the console-locale item to iteration-144 — see that plan's "why these were deferred" section. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Move backtick-quoted test-function references onto each checkbox's first line so the ac-fidelity gate's diff-evidence heuristic can find them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
README and --help text had fallen behind the iter-142 code: the new `wait --sleep-ms` form, the launch-time GC sweep for stale spawn locks/throttle-state/legacy locks, the dead-owner-pid immediate-reclaim policy, and eval's new "auto-return the trailing bare expression" await semantics were all undocumented.
…C test unit_gc_stale_throttle_states_removes_dead_keeps_live failed on Windows CI: the test's own std::process::Child stayed in scope through the is_process_alive check. On Windows, OpenProcess succeeds for an already-exited process as long as any handle to it (including our own Child) is still open, so the test's dead-pid check spuriously reported "alive" and the GC never removed the entry. Scope the spawn+wait into a helper that drops Child before returning the pid, matching the working pattern already used in util/profile_dir.rs's spawn_and_reap_child_pid. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
daemon stopwas reporting the proxy daemon's PID as if it were Firefox's, and escalating the port-free wait against that same wrong PID — so a stop that actually left Firefox running could still report success, and a stop that genuinely needed more time to free the port never escalated against the right process. Root cause:launch-record.jsonwas a single global file clobbered by concurrent ports. Fixed by scoping it per port (launch-record.<port>.json) and independently resolving/stopping the real Firefox PID via port-owner lookup.launch, not gated behind the 7-day age threshold (this is exactly what let 62 profiles / 2.7 GB accumulate in a day per dogfooding session 63). Added GC for staledaemon.<port>.throttle.jsonstate files and the legacy port-lessdaemon.spawn.lockname, and moved the sweep to run on everylaunch(not just the rare daemon-autostart path) so a session that reuses an already-running daemon still gets swept.;-only, so ASI-separated (newline-only) multi-statement scripts leaked the wrapper into a confusing syntax error. Now tracks newline-based ASI boundaries too (with string/template-literal and bracket-depth awareness). Also fixed the await path silently discarding a trailing bare expression asundefined— it now auto-returns the last top-level expression, matching non-await completion-value semantics, while leaving earlier statements (and any explicitreturn) untouched.wait --sleep-msform (with a--timelegacy alias) so dogfooders no longer have to shell out tosleep.kb/iterations/iteration-144-session-hygiene-followup.md— each needs either a JSON-contract design decision (Theme C) or dedicated pixel-level before/after verification against iteration-135's stitching fixtures (Theme D), or a non-English-locale Firefox to reproduce against (Theme F), none of which were safe to rush into this iteration. See that plan's "Why these three were deferred" section.Test plan
cargo fmt --check,cargo clippy --workspace --all-targets -- -D warnings,cargo test --workspace -q— all cleanFF_RDP_LIVE_TESTS=1 cargo test-livefiltered tolive_142_*— all 4 live tests pass against real headless Firefox on the default daemon path:live_142_daemon_stop_pid_honesty::live_142_daemon_stop_no_false_errorlive_142_disk_growth::live_142_profile_growth_boundedlive_142_disk_growth::live_142_throttle_json_gclive_142_eval_asi_await::live_142_eval_asi_await_scriptunit_legacy_spawn_lock_collected(unit) ande2e_wait_sleep_form(e2e) passcargo run -p xtask -- check-iteration-ready --plan kb/iterations/iteration-142-session-hygiene.md --base origin/main— 10/10 PASS (withFF_RDP_LIVE_TESTS=1for the dogfood gate)## Claims vs code<generated 2026-08-11T13:22:33Z by ralph-loop>
immediate→ ✅ matched in diffeval→ ✅ matched in diff## Claims vs code<generated 2026-08-11T13:35:46Z by ralph-loop>
immediate→ ✅ matched in diffeval→ ✅ matched in diff