Salvage follow-up to #107955 (Alex Tu) and #109494 (EloquentBrush0x):
- _default_profile_secret_scope: drop the import try/except, the
current_secret_scope() short-circuit and the build-failure fallthrough.
The tick always runs in a fresh Context (no scope can be present) and a
failure to build the launch profile scope must surface, not silently
degrade to an unscoped tick.
- Regression test proven red on origin/main: run the real
auto_decompose_tick through _to_thread_process_service under multiplex
and assert the decomposer reads the launch profile .env value; ports the
contract from #57837 (srojk34) to the post-refactor dispatcher.
- Trim the #109494 test docstring to the invariant.
With gateway.multiplex_profiles on, agent.secret_scope.get_secret() fails closed
whenever no profile secret scope is installed. auto_decompose_tick runs through
_to_thread_process_service in a fresh context, so the decomposer's credential
read raised UnscopedSecretError on every tick before the aux LLM was called,
and every triage card stayed in triage forever (logged at INFO only).
Wrap the tick in _default_profile_secret_scope(): when multiplexing is active
and no scope is installed, build the gateway default profile's scope (the same
home load_gateway_config_for_runner uses) for the duration of the tick. No-op
for single-profile gateways and when a scope is already active.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit c47e3ea6f8a5750182b7534160184210b8d5a110)
For each issue anchor present in BASE 63279301bc non-test .py and absent on HEAD, the BASE comment/docstring block was re-attached at the HEAD location of the code it explained (matched by the distinctive code line / enclosing def). Sentences already covered by an existing HEAD comment were deduped; the issue number always survives. Insert-only: no code lines changed.