Capacity acquisition shares the worker's controlled Codex home (#168) #170

Closed
kilo wants to merge 1 commit from task/168-capacity-controlled-home into develop
Member

Reopens the fix for #168 (the issue is open awaiting this re-test). Branch off develop @ d90f450, single commit 866abb5. Do not merge without the owner's review.

The bug (second Precision field test)

make codex-login completed (Successfully logged in — the source's controlled home got fresh credentials), but scarcity-router status still showed Provider openai status=unknown windows=none diagnostics=telemetry_unknown.

Root cause: two Codex credential locations on one host. The OpenAI capacity collector spawns its app-server with the inherited environment, so it authenticates from the child's default state (~/.codex) — while the login refreshes the worker source's controlled home (<state_dir>/codex-sources/<source_id>/codex-home). On Precision ~/.codex has no session, so telemetry stayed unknown no matter how fresh the worker's credentials were.

The fix (D-066 amended, point 5)

  • status.py's default OpenAI collector resolves the local worker's exactly-one configured Codex source — the same tiered unit read-back the login uses, v_safe_id-validated so a hostile unit id cannot steer the path — and hands that source's controlled home to collect_openai_codex_capacity, which sets it as the child's CODEX_HOME. The acquisition module builds the variable but never opens the home (its no-credential contract is unchanged; docstring updated).
  • Precedence: an explicit CODEX_HOME in the environment wins (operator override). Zero sources, several sources, or a refused unit → None → acquisition keeps today's inherited-environment behavior, so worker-less hosts collect exactly as before (ROG's zero-source unit is unaffected).
  • One make codex-login now refreshes both the execution credentials and the OpenAI provider telemetry on a worker host.

Architectural note (why a new module)

Composing the read-back from status.py needs it without pulling the worker runtime: worker_codex_adapter reaches worker_protocol → selection_app → status, so any worker-runtime import from status is a static cycle (basedpyright fails the gate on it — function-local imports do not help). The read-back and the shared ServiceSelection type therefore moved to a new leaf module scarcity_router/worker_unit_selection.py (stdlib + worker_local_store only), re-exported by worker_service; all existing callers and tests are unchanged. The controlled-home layout is spelled once in status.py with tests cross-checking the adapter's real ControlledCodexHome, so it cannot drift.

Verification

  • Full gate green: 2662 tests OK (15 skipped), uv run basedpyright 0 errors / 0 warnings / 0 notes, git diff --check clean; origin/develop..HEAD = the single commit.
  • New tests: ControlledHomeCompositionTests (status — one source resolves the controlled home cross-checked against the real ControlledCodexHome, hand-written unit resolves the same way, explicit CODEX_HOME precedence, zero/multiple/missing/traversal-id → None, timestamp/binary pass-through) and two acquisition tests (codex_home sets exactly the child CODEX_HOME with everything else inherited; no codex_home → environment untouched).
  • Existing suites untouched semantically: the two default_worker_state_dir patches retargeted to the leaf module; all worker_service.* names still work through re-export.
  • Behavior matrix verified live on ROG: real unit (zero sources) → None (unchanged); simulated Precision hand-written %h unit → the correct controlled home; CODEX_HOME set → None.

Expected Precision re-test (after merge)

git pull && make install   # or uv sync
scarcity-router status

Provider openai should now report status=ok with the ChatGPT-plan windows (five-hour/weekly), reading the same credentials make codex-login refreshed. No worker restart needed.

UX impact

Positive: the operator's mental model ("one login refreshes the worker's Codex credentials") now holds for telemetry too, instead of a silent second credential location. No new interactive steps, no new flags; ambiguous configurations behave exactly as before (fail-closed/unchanged rather than guessing).

Reopens the fix for #168 (the issue is open awaiting this re-test). Branch off `develop` @ `d90f450`, single commit `866abb5`. **Do not merge without the owner's review.** ## The bug (second Precision field test) `make codex-login` completed (`Successfully logged in` — the source's controlled home got fresh credentials), but `scarcity-router status` still showed `Provider openai status=unknown windows=none diagnostics=telemetry_unknown`. Root cause: **two Codex credential locations on one host.** The OpenAI capacity collector spawns its app-server with the *inherited* environment, so it authenticates from the child's default state (`~/.codex`) — while the login refreshes the worker source's controlled home (`<state_dir>/codex-sources/<source_id>/codex-home`). On Precision `~/.codex` has no session, so telemetry stayed unknown no matter how fresh the worker's credentials were. ## The fix (D-066 amended, point 5) - `status.py`'s default OpenAI collector resolves the local worker's **exactly-one** configured Codex source — the same tiered unit read-back the login uses, `v_safe_id`-validated so a hostile unit id cannot steer the path — and hands that source's controlled home to `collect_openai_codex_capacity`, which sets it as the child's `CODEX_HOME`. The acquisition module builds the variable but **never opens the home** (its no-credential contract is unchanged; docstring updated). - Precedence: an explicit `CODEX_HOME` in the environment wins (operator override). Zero sources, several sources, or a refused unit → `None` → acquisition keeps today's inherited-environment behavior, so **worker-less hosts collect exactly as before** (ROG's zero-source unit is unaffected). - One `make codex-login` now refreshes **both** the execution credentials and the OpenAI provider telemetry on a worker host. ## Architectural note (why a new module) Composing the read-back from `status.py` needs it without pulling the worker runtime: `worker_codex_adapter` reaches `worker_protocol → selection_app → status`, so any worker-runtime import from `status` is a static cycle (basedpyright fails the gate on it — function-local imports do not help). The read-back and the shared `ServiceSelection` type therefore moved to a new **leaf** module `scarcity_router/worker_unit_selection.py` (stdlib + `worker_local_store` only), re-exported by `worker_service`; all existing callers and tests are unchanged. The controlled-home layout is spelled once in `status.py` with tests cross-checking the adapter's real `ControlledCodexHome`, so it cannot drift. ## Verification - Full gate green: **2662 tests OK** (15 skipped), `uv run basedpyright` 0 errors / 0 warnings / 0 notes, `git diff --check` clean; `origin/develop..HEAD` = the single commit. - New tests: `ControlledHomeCompositionTests` (status — one source resolves the controlled home cross-checked against the real `ControlledCodexHome`, hand-written unit resolves the same way, explicit `CODEX_HOME` precedence, zero/multiple/missing/traversal-id → `None`, timestamp/binary pass-through) and two acquisition tests (`codex_home` sets exactly the child `CODEX_HOME` with everything else inherited; no `codex_home` → environment untouched). - Existing suites untouched semantically: the two `default_worker_state_dir` patches retargeted to the leaf module; all `worker_service.*` names still work through re-export. - Behavior matrix verified live on ROG: real unit (zero sources) → `None` (unchanged); simulated Precision hand-written `%h` unit → the correct controlled home; `CODEX_HOME` set → `None`. ## Expected Precision re-test (after merge) ```bash git pull && make install # or uv sync scarcity-router status ``` `Provider openai` should now report `status=ok` with the ChatGPT-plan windows (five-hour/weekly), reading the same credentials `make codex-login` refreshed. No worker restart needed. ## UX impact Positive: the operator's mental model ("one login refreshes the worker's Codex credentials") now holds for telemetry too, instead of a silent second credential location. No new interactive steps, no new flags; ambiguous configurations behave exactly as before (fail-closed/unchanged rather than guessing).
Capacity acquisition shares the worker's controlled Codex home (#168)
Some checks failed
ci / check (pull_request) Failing after 9m7s
866abb5644
Second owner field test on Precision: make codex-login completed, yet
scarcity-router status kept openai at telemetry_unknown — the capacity
collector spawned its app-server with the INHERITED environment
(authenticating from ~/.codex) while the login had refreshed the worker
source's controlled home: two credential locations for one host, one of
them stale.

The default OpenAI collector in status.py now resolves the local
worker's exactly-one configured Codex source (same tiered unit
read-back as the login, v_safe_id-validated) and hands that source's
controlled home to collect_openai_codex_capacity as the child CODEX_HOME
(the acquisition builds the variable but never opens the home). An
explicit CODEX_HOME in the environment keeps precedence; zero, several
or refused configurations keep the inherited-environment behavior, so
worker-less hosts collect exactly as before. One login now refreshes
both execution credentials and provider telemetry.

To compose the read-back without a static import cycle
(status <- selection_app <- worker_protocol <- worker_local_adapters <-
worker_codex_adapter), the read-back and the shared ServiceSelection
type move to the new leaf module worker_unit_selection (re-exported by
worker_service; callers and tests unchanged). D-066 amended.
Author
Member

Closing as superseded by merged PR #172.

Verified current develop 6c337a400b4cdc28ded543d2ae8ccf3749d79cb7 contains #172's merge and the complete intended telemetry outcome: the shared default collector discovers the installed worker source/state directory and passes its existing controlled home as child-only CODEX_HOME, without credential copying, home provisioning or parent-environment changes. Worker-less/no-source collection remains supported; #172 additionally provides explicit source/@local selection, validated binary pins and safe errors instead of ambiguous fallback. Its documented D-067 precedence supersedes #170's older ambient-home override behavior.

Verification: 225 status/acquisition/worker-service tests passed; basedpyright reports zero errors/warnings/notes; checkout clean. No implementation edits, rebase or push; #170 head remains 866abb56449c7d950b8457b19144edaabb92a8b9.

The leaf-module extraction is not retained: #172 already removed the import-cycle cause through shared home/state helpers, so no independently justified cleanup task was identified.

Closing as superseded by merged PR #172. Verified current develop `6c337a400b4cdc28ded543d2ae8ccf3749d79cb7` contains #172's merge and the complete intended telemetry outcome: the shared default collector discovers the installed worker source/state directory and passes its existing controlled home as child-only CODEX_HOME, without credential copying, home provisioning or parent-environment changes. Worker-less/no-source collection remains supported; #172 additionally provides explicit source/@local selection, validated binary pins and safe errors instead of ambiguous fallback. Its documented D-067 precedence supersedes #170's older ambient-home override behavior. Verification: 225 status/acquisition/worker-service tests passed; basedpyright reports zero errors/warnings/notes; checkout clean. No implementation edits, rebase or push; #170 head remains `866abb56449c7d950b8457b19144edaabb92a8b9`. The leaf-module extraction is not retained: #172 already removed the import-cycle cause through shared home/state helpers, so no independently justified cleanup task was identified.
kilo closed this pull request 2026-10-05 10:52:10 +00:00
Some checks failed
ci / check (pull_request) Failing after 9m7s

Pull request closed

Sign in to join this conversation.
No description provided.