feat(tui): make the spawned binary part of adapter identity - #399
Draft
albi-bon wants to merge 2 commits into
Draft
feat(tui): make the spawned binary part of adapter identity#399albi-bon wants to merge 2 commits into
albi-bon wants to merge 2 commits into
Conversation
…g#395) A profile's binary was fixed, so running the same CLI under a second name — a work account launched as `cc` beside a personal `claude`, or two aliases splitting usage limits — meant copying the whole packaged profile into .bmad-loop/profiles/ to change one field. That copy then freezes bypass_args, [env], seed_files and env_fault_patterns against upstream forever: the cost of one field is permanent drift on eight others. Add `binary` to [adapter] and [adapter.<stage>]. Empty (the default) keeps the profile's own binary, so existing projects are untouched. Both adapter families already accepted a `binary` argument and resolved it as `binary or profile.binary`; policy is what was never plumbed into it, so make_adapters passes the resolved value and the seam does the rest. Inheritance follows the model/extra_args rule: client-specific, inherited from the base only when the stage runs the same client, so a `cc` alias of claude can never become argv[0] for a stage that switched to codex. Two read paths had to follow the effective binary rather than the profile's: validate's PATH probe (it would report "claude found" for a run that spawns a typo'd `cc`) and the --dry-run invocation render. The override is for an alias or wrapper of the same CLI — the profile still supplies the hook dialect, config path and transcript layout.
…e-org#395) A run on an overridden executable was invisible everywhere except the policy file: the TUI header, the tasks table and status --json all reported the profile name, so a session billed to `cc-work` displayed as `claude` — the same blind spot validate had before the override landed. Carry the binary through the identity path already built for name+model in bmad-code-org#153: SessionRecord, the journal's session-start entry, ActiveAgent, and both --json projections (adapters, adapters_used). The TUI renders `profile(binary)·model`. Both facts are load-bearing and neither substitutes for the other — the profile explains the session's behavior (hook dialect, prompt template, bypass flags), the binary explains which install it billed. Backward compatible by construction: "" means the profile's own executable, which is exactly what a record, journal entry or snapshot predating the field reports, so old runs render and serialize as before and a --json consumer ignoring the key sees no change. The settings editor needed no work — it is schema-driven, so core.toml carried the field the moment the policy field existed.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Jul 30, 2026
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.
What
Makes the spawned executable part of a session's adapter identity, so an overridden binary is visible wherever the profile name already is: the TUI run header, the tasks-table agent cell, and
status --json.Why
Fixes #395 (part 3 of 3).
With #397 alone, a run on an overridden binary is invisible everywhere except
policy.toml. The header, the tasks table and--jsonall report the profile, so a session billed tocc-workdisplays asclaude— the same blind spotvalidatehad before #397 fixed it, and the reason to fix it here is the same: the whole point of the feature is running one profile under two accounts, so the profile name alone stops being an identity.How
binarythrough the identity path Active Agent Indicator #153 already built for name+model:SessionRecord, the journal'ssession-startentry,ActiveAgent, and both--jsonprojections (adapters,adapters_used). The engine stamps it from the samecfgit already readsname/modelfrom.profile(binary)·model. Both facts are load-bearing and neither substitutes for the other — the profile explains the session's behavior (hook dialect, prompt template, bypass flags), the binary explains which install it billed. The parens appear only when an override is set.binarystays client-specific, so a stage that switches client shows that profile's own executable — the gemini review stage in the engine test reports"", not the base'scc-work.The settings editor needed no code. That screen is schema-driven from
data/settings/core.toml, which #397 already populated, so[adapter] binaryand all three[adapter.<stage>] binaryfields render today.test_every_policy_field_is_covered_by_exactly_one_specis what makes that automatic rather than lucky.Compatibility
""means "the profile's own executable" — exactly what aSessionRecord, journal entry or policy snapshot predating the field reports. Old runs render and serialize unchanged, and the--jsonaddition is additive: a consumer ignoring the key reads what it read before, soSTATUS_SCHEMA_VERSIONstays at 1 permachine.py's additive-only rule. This is the only place the stack touches a published contract — say the word if you'd rather bump the version anyway.Testing
uv run pytest -q— 3701 passed, with the same two pre-existing macOS-only failures noted in #397, which reproduce on a clean checkout.pyrightunchanged,ruffclean,black/prettierat the versions pinned in.trunk/trunk.yaml.Coverage: label rendering including the un-overridden no-change case;
ActiveAgentfrom a stamped entry, from a pre-#395 stamp (reads"", notNone), and rebuilt from a snapshot;SessionRecordround-trip and legacy-state default; engine stamping of both the journal entry and the record, including the client-switch carve-out;status --jsoncarrying the override on both projections. The existingtest_status_json_exposes_adapter_identitycontract assertions are widened to the new shape. Per the AGENTS.md ablation rule I deleted the engine stamping and confirmed the engine test FAILS first.Rendering also verified by driving the real dashboard headlessly and by hand against a scratch project, not only through assertions.