Fix main's red app-host shards and intermittent CI failures

Merged
AU
23d ago
+158-34

Summary

Main's app-host shards 2, 3 and 5 have been red on every run since #20248 merged. This fixes the causes and four intermittent failures seen in the same runs.

Real regression from #20246: a stale Codex record could resume a dead session on restore. #20246 treats an agent as running when the session index isn't authoritative, so a cached quit index can't mark a live session stopped. It read that authority from isComplete(). For Codex, that is also false whenever the panel's recorded checkpoint fails verification. So a fresh index holding only a rejected stale record left wasAgentRunning nil, and restore queued the dead current binding's resume command (SurfaceResumeAgentBindingGenerationTests: hasInitialInput: true). Authority now comes from whether the kind's hook store was observed (observesEveryLiveSession(forKind:)) in both the workspace and Dock snapshot paths, which is what #20246 meant. A cached markingIncomplete() index and an unreadable store still count as not authoritative, so #20246's Claude liveness case is unchanged.

Stale tests:

  • MuseVaultRegistrationTests expected an unquoted muse resume …. Registered agents have quoted each argument and added a cd -- prefix since August. It now asserts the exact command, like the Pi, RovoDev and Hermes vault tests.
  • GhosttyMinimumContrastLayerBackgroundTests.darkTextOnLightThemeStaysDark never renders on Blacksmith (draws=0 visible=false): the app-host process isn't the active app there, so the window is never key or reported visible. It passes on owned minis. ScrollbackTestTerminal can now opt into a window that reports .visible occlusion, as SimulatorPanelThemeTests already does.

Intermittent failures:

  • cmuxd-remote dispatch could return context.Canceled instead of the queued attach write error, because the select could see the cancellation first (TestStdioRPCAsyncAttachWriteFailureInterruptsReadLoop).
  • TestWebSocketPTYReplacedAttachmentCannotWriteInput: macOS sh can print a job-control warning between SIZE: and stty's output. One printf now writes both.
  • repeatedWorkerPastesPreservePayload: four jobs share one FIFO whose 5s deadline starts at admission, so a slow runner expired the fourth. This test checks payload fidelity, so its deadline now ends only on cancellation.
  • testUnreadChangeUpdatesOnlyAffectedSidebarRow: an unrelated Workspace update inside the measured window re-evaluated WorkspaceContentView. The test now counts those updates and allows exactly that many. The ContentView and sidebar checks stay strict.

Cloud window test: CloudWorkspaceCreationRevealTests "Closing the window during ⌘N releases its manager…" failed because of when the test checked, not because of a leak. The Cloud create path holds the manager only weakly. The test checked it in the same main-actor job as commitMainWindowClose, while the close's own notification (whose object is the manager) and the cleanup it queued on the main queue still held it. It now runs the close in an autorelease pool and waits one main-queue turn, with the create still blocked, before checking.

Claude project-directory fixtures: claudeRestorableIndexMapsNestedTranscriptPathToProjectCwd failed on runners whose temp path contains _. The fixture built the Claude project directory name by replacing only / and ., but Claude replaces every character that isn't a letter or digit. Four test files now share one slug helper that matches Claude's rule.

Testing

  • python3 scripts/verify-local.py: 17/17 checks passed. App-host tests and Go tests run in this PR's CI; local test runs aren't allowed here.
  • The red results on main are in run 38511822800.
  • This PR at c217589161: all 64 checks pass. The changed-suites job ran 832 tests in 48 suites, all passing, including the Cloud window test (both cases), the Muse vault test, darkTextOnLightThemeStaysDark on Blacksmith, the sidebar unread test, and the Claude project-directory test. remote-daemon-macos-tests passed with the dispatch fix. SurfaceResumeAgentBindingGenerationTests is in a full app-host shard, not the changed-suites job, so its first run will be on main after merge.

Changelog

Fixed: A restored Codex terminal no longer re-runs an ended session's resume command when its saved checkpoint couldn't be verified

🤖 Generated with Claude Code