Thanks to visit codestin.com
Credit goes to github.com

Skip to content

installer-setup WS-J: extract one slot-render reconcile seam shared by install + update#1138

Merged
thinmintdev merged 1 commit into
mainfrom
feat/1103-reconcile-seam
Jul 6, 2026
Merged

installer-setup WS-J: extract one slot-render reconcile seam shared by install + update#1138
thinmintdev merged 1 commit into
mainfrom
feat/1103-reconcile-seam

Conversation

@thinmintdev

Copy link
Copy Markdown
Contributor

Seam shape

The routine: ContainerProvider._render_unit_text(self, slot_cfg, model_info) -> str in src/hal0/providers/container.py.

It is the ONE renderer and sole producer of slot-unit text:

  • resolves the slot's provider (_spec_provider_for(slot_cfg) or self),
  • builds its RuntimeLaunchPlan via container_spec,
  • renders through the single adapter _render_unit_from_plan(...) with the live [slots].publish_host (publish_host=_slot_publish_host()).

Both call sites now route through it:

  • Installload_sync() calls self._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).
  • Updatererender_unit_sync() calls self._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_units in src/hal0/updater/updater.py still calls rerender_unit_sync + batches one daemon_reload).

What had to be unified: the divergence was a single dropped argument. load_sync already passed publish_host=_slot_publish_host(); rerender_unit_sync called _render_unit_from_plan(slot_name, plan, runtime_bin=_container_runtime()) and inherited the loopback default 127.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:

  1. monkeypatches _slot_publish_host -> 0.0.0.0 (the LAN-exposed box the pre-fix update path regressed),
  2. runs load_sync (systemctl mocked) -> captures the fresh-install unit text; asserts --publish=0.0.0.0:8095:8095 rendered,
  3. seeds a stale unit file and runs rerender_unit_sync for the same slot config,
  4. asserts changed is True and 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 formatted
  • uv run ruff check src tests -> All checks passed!
  • uv run --extra dev pytest tests/providers/test_container.py -> 60 passed
  • Broader tests/providers tests/slots tests/updater -> only test_container_spec_dispatch.py::test_tts_kokoro_slot_renders_spec_unit fails, confirmed pre-existing (fails on clean tree via git stash -u; matches the known "container spec dispatch" box-ordering failure).

Files changed

  • src/hal0/providers/container.py — new _render_unit_text seam; load_sync + rerender_unit_sync route through it.
  • tests/providers/test_container.py — byte-identical regression test.

Closes #1103

🤖 Generated with Claude Code

…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]>
@thinmintdev thinmintdev merged commit f9e6e24 into main Jul 6, 2026
3 checks passed
@thinmintdev thinmintdev deleted the feat/1103-reconcile-seam branch July 6, 2026 06:14
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.

installer-setup WS-J: extract one slot-render reconcile seam shared by install + update

1 participant