Skip to content

Fix Launcher fail-stop races and normal completion - #65

Merged
tmori merged 1 commit into
mainfrom
codex/issue64-launcher-fail-stop
Oct 16, 2026
Merged

tmori merged 1 commit into
mainfrom
codex/issue64-launcher-fail-stop

Conversation

@tmori

@tmori tmori commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • make FAILED monotonic across concurrent activate, lifecycle command, watcher, and terminate paths
  • preserve the historical finite-run behavior: an asset exiting with code 0 terminates the session normally, while nonzero/signaled/unknown exits remain fail-stop failures
  • validate hako-cmd check JSON shape, aggregate status, and status/return-code combinations; uncertain responses become diagnostic UNKNOWN
  • increase the configurable health-check subprocess watchdog default to 3 seconds for Windows process-launch latency without changing the native nonblocking try-lock
  • document normal finite-run completion and fail-stop concurrency behavior

Why

After #63 merged, business-pack Clean Onboarding E2E began failing even though its drone show completed successfully. The finite show runner exited with code 0, but Launcher classified every asset exit as unexpected_asset_exit and persisted FAILED. This restores the prior normal-completion contract without weakening fail-stop handling for actual failures.

Verification

  • PYTHONPATH=src pytest -q — 150 passed on macOS
  • deterministic event/barrier tests cover ABORT during activation, during hako-cmd start, and during after-start spawning
  • regression tests cover code-0 normal completion, nonzero failure evidence, cleanup exactly once, malformed/non-object health JSON, inconsistent summaries, and wrong status/return-code pairs

Closes #64

@tmori

tmori commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Review (agreed with @tmori): OK to merge to unblock hakoniwa-business-pack CI, but this addresses #64 only partly

Fixed:

  • An asset that exits 0 now ends TERMINATED, and status/terminate return ok. This should fix business-pack's Clean Onboarding E2E (drone-fleet-single-host), which has been failing since Add Launcher fail-stop runtime supervision #63.
  • FAILED can no longer be overwritten: there is a state lock, no transition out of FAILED, and after_start is suppressed after a fail-stop.
  • A non-object check report is now UNKNOWN.
  • The default check timeout is now 3 s.
  • The runtime field names are unchanged, so hakoniwa-urban-mobility#102's probe keeps working.

Please change Closes #64 to "Part of #64" and keep these open in #64, or move them to a new issue:

  1. Non-UTF-8 hako-cmd check output (cp932 on Windows). text=True (hako_cli.py:118) raises UnicodeDecodeError, which reaches the watch loop and fail-stops with watch_exception. Decode with errors="replace" and treat the result as UNKNOWN.
  2. A slow version probe (1.0 s) is cached as unsupported for the whole session (hako_cli.py:212-236), which silently disables supervision.
  3. Repeated UNKNOWN never escalates. Add a consecutive-UNKNOWN counter to the session payload.
  4. Windows children survive a stop (hako_asset_runner.py:291,330). The runner returns early when the parent has exited, so taskkill /T never runs. Because a clean exit 0 is now reported as TERMINATED with no failure_report, leftover children become invisible.
  5. WSL-launched Windows .exe assets always report exit_code=None (hako_asset_runner.py:394). Under the new rule (hako_launcher.py:352) every normal finish of such an asset is FAILED again.
  6. _fail_stop merges the stale _last_health_report into asset-exit reports (:199).
  7. Stop-time races:
    • a user terminate can still end FAILED: an in-flight check that returns ABORT, or a killed asset reported as unexpected_asset_exit, because _stop_watch and TERMINATING are not checked;
    • live terminate returns ok:true even when the session ends FAILED (hako_launcher_control.py:467).
  8. activate() can be left in ACTIVATING when the startup check or _prepare_runtime raises.

Tests: every new test uses fakes. Please add one real-process test of the business-pack flow: a real child exits 0, then the background session reports TERMINATED and hako_launcher_ctl status returns ok.

🤖 Generated with Claude Code

@tmori

tmori commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Additional compatibility finding from hakoniwa-business-pack Clean Onboarding E2E:

  • The smoke/show asset completes its assigned work with exit code 0.
  • Merged Add Launcher fail-stop runtime supervision #63 classified every observed asset exit as unexpected_asset_exit, so the session became FAILED after the actual smoke test had succeeded.
  • This PR restores the established contract for a clean exit: exit code 0 with no signal calls normal termination and ends in TERMINATED; nonzero, signaled, or unavailable exit status remains fail-stop FAILED.

The regression is covered by test_asset_exit_zero_terminates_session_without_failure; all 150 tests and the Linux/macOS/Windows PR checks pass. This is the PDU-side fix for the current business-pack Clean Onboarding failure and is unrelated to business-pack #237.

@tmori
tmori merged commit 61eb036 into main Oct 16, 2026
8 checks passed
@tmori
tmori deleted the codex/issue64-launcher-fail-stop branch October 16, 2026 10:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow-up #62: preserve FAILED during concurrent launch, and handle uncertain health reliably

1 participant