installer-setup WS-J: extract one slot-render reconcile seam shared by install + update#1138
Merged
Merged
Conversation
…y install + update Install rendered slot units via `load_sync` (passing the live `[slots].publish_host`); update re-rendered via `rerender_unit_sync`, which dropped that argument and fell back to the loopback default. On a LAN-exposed box (`publish_host = 0.0.0.0`) an update silently narrowed the bind back to 127.0.0.1, so a fresh box and an updated box ended up with different units for the same slot. Extract `ContainerProvider._render_unit_text(slot_cfg, model_info)` — the ONE renderer and sole producer of slot-unit text. It resolves the slot provider, builds the launch plan, and renders through `_render_unit_from_plan` with the live publish_host. Both `load_sync` (first install) and `rerender_unit_sync` (update) now render through it, so the two produce byte-identical units for the same slot config. `load_sync` keeps its install-only steps (NPU loud-fail guard, write + enable/start); `rerender_unit_sync` keeps write-only (no bounce). Add a regression test asserting a fresh install and an update render byte-identical units on a box with publish_host=0.0.0.0. Closes #1103 Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
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.
Seam shape
The routine:
ContainerProvider._render_unit_text(self, slot_cfg, model_info) -> strinsrc/hal0/providers/container.py.It is the ONE renderer and sole producer of slot-unit text:
_spec_provider_for(slot_cfg) or self),RuntimeLaunchPlanviacontainer_spec,_render_unit_from_plan(...)with the live[slots].publish_host(publish_host=_slot_publish_host()).Both call sites now route through it:
load_sync()callsself._render_unit_text(slot_cfg, model_info), then layers on the install-only steps (NPU loud-fail guard +_write_and_start_unit, which writes the file and enables/starts the service).rerender_unit_sync()callsself._render_unit_text(slot_cfg, model_info), then write-only (no enable/restart — serving is never bounced by an update). Updater sweep is unchanged (rerender_slot_unitsinsrc/hal0/updater/updater.pystill callsrerender_unit_sync+ batches onedaemon_reload).What had to be unified: the divergence was a single dropped argument.
load_syncalready passedpublish_host=_slot_publish_host();rerender_unit_synccalled_render_unit_from_plan(slot_name, plan, runtime_bin=_container_runtime())and inherited the loopback default127.0.0.1. On a LAN-exposed box ([slots].publish_host = 0.0.0.0) a fresh install rendered--publish=0.0.0.0:<port>:<port>but an update silently narrowed it back to--publish=127.0.0.1:<port>:<port>— a fresh box and an updated box ending up with different units for the same slot. Pulling both paths through one renderer removes the second, drifting render path.Extract-not-rewrite: the render log (
container.unit_render) moved into the seam so both paths emit it consistently; no launch behavior changed.Proving byte-identical units
New test
tests/providers/test_container.py::TestLoadSync::test_install_and_update_render_byte_identical_units:_slot_publish_host->0.0.0.0(the LAN-exposed box the pre-fix update path regressed),load_sync(systemctl mocked) -> captures the fresh-install unit text; asserts--publish=0.0.0.0:8095:8095rendered,rerender_unit_syncfor the same slot config,changed is Trueand the rewritten unit is byte-for-byte equal to the fresh-install text.This fails on the pre-fix code (update would render loopback) and passes on the seam.
DoD
uv run ruff format --check src tests->644 files already formatteduv run ruff check src tests->All checks passed!uv run --extra dev pytest tests/providers/test_container.py->60 passedtests/providers tests/slots tests/updater-> onlytest_container_spec_dispatch.py::test_tts_kokoro_slot_renders_spec_unitfails, confirmed pre-existing (fails on clean tree viagit stash -u; matches the known "container spec dispatch" box-ordering failure).Files changed
src/hal0/providers/container.py— new_render_unit_textseam;load_sync+rerender_unit_syncroute through it.tests/providers/test_container.py— byte-identical regression test.Closes #1103
🤖 Generated with Claude Code