fix(cli): resolve a launched agent's flight on every orientation - #85
Merged
Conversation
`tap launch --agent NAME` resolved the agent's flight once and exported the result as TAP_FLIGHT. Environment variables outrank project and user config, and a process cannot change its own environment, so the launched session was pinned to whatever the flight was at launch. Editing the agent's flight and calling `orient` again did nothing, and the session reported success while staying on the old flight. Export the reference instead of the value: TAP_AGENT names the agent, and resolution reads agents[TAP_AGENT].flight out of the merged config on every load. The variable is still constant — the agent driving a process genuinely cannot change while it runs — but the mapping it points into is re-read at each reload boundary, so a config edit plus `orient` now moves a running session. Resolution happens once, at the end of ConfigService.load, rather than in ActiveFlightName. load is what Reload re-runs, so late binding falls out for free, and every consumer — CLI, MCP orientation, keg listing, config explain — reads one already-resolved Flight() with no call-site changes. It needs the env layer in isolation to tell a direct TAP_FLIGHT (which still wins) from a flight that came from a file layer (which the agent overrides). Precedence is --flight, TAP_FLIGHT, the agent's flight, project config, then the user baseline: direct beats indirect, and naming an agent at launch beats an ambient project default. A TAP_AGENT naming an agent that is not configured warns and falls through rather than failing, since a session cannot fix its own environment. The orientation payload names the active agent so a reader is told where the flight came from instead of being pointed at a `flight:` key the agent silently outranks.
The reporter injects the active agent alongside the client version, so neither the CLI nor the MCP call site has to remember to set it, and agent-driven usage separates from human usage in aggregate. It is resolved once at construction: the agent driving a process cannot change while it runs. The alias is user-chosen config text, not an identifier, and is omitted when a human is driving. It is covered by the existing disableTelemetry opt-out and validated by the hub like every other text field. Requires a hub that accepts the field; the hub's decoder rejects unknown fields, so an older hub refuses the batch. That degrades to no telemetry rather than failing a command.
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.
Re-opens the work from #84. That PR merged into its base branch
(
feat/mcp-bootstrap-mode) rather thanmain— #83 had been rebase-mergedseconds earlier, which rewrote the SHAs and left the base branch superseded but
undeleted. GitHub marked #84 merged, truthfully, into a branch that no longer
led anywhere. These two commits are rebased onto current
main; nothing elsechanged.
tap launch --agent NAMEresolved the agent's flight once and exported theresult as
TAP_FLIGHT. Environment variables outrank project and user config,and a process cannot change its own environment, so the launched session was
pinned to whatever the flight was at launch. Editing the agent's flight and
calling
orientagain did nothing — and the session reported success whilestaying on the old flight.
Export the reference instead of the value.
TAP_AGENTnames the agent, andresolution reads
agents[TAP_AGENT].flightout of the merged config on everyload. The variable is still constant — the agent driving a process genuinely
cannot change while it runs — but the mapping it points into is re-read at each
reload boundary, so a config edit plus
orientnow moves a running session.Resolution happens once, at the end of
ConfigService.load, rather than inActiveFlightName.loadis whatReloadre-runs, so late binding falls outfor free and every consumer — CLI, MCP orientation, keg listing,
config explain— reads one already-resolvedFlight()with no call-site changes. Itneeds the env layer in isolation to tell a direct
TAP_FLIGHT(which stillwins) from a flight that came from a file layer (which the agent overrides).
Precedence
Direct beats indirect, and naming an agent at launch beats an ambient project
default — which preserves what
tap launchdid before.A
TAP_AGENTnaming an agent that is not configured warns and falls throughrather than failing: a session cannot fix its own environment, so a typo should
not brick a harness. The orientation payload names the active agent, so a reader
is told where the flight came from instead of being pointed at a
flight:keythe agent silently outranks.
Codex's MCP registration gains
TAP_AGENTin its env allowlist;TAP_FLIGHTstays listed for a human overriding directly. Claude Code forwards its whole
environment and needs no change.
Telemetry
The reporter injects the active agent alongside the client version, so neither
call site has to remember to set it. This needs a matching hub-side field, which
is not yet released — until then an older hub rejects the batch, which degrades
to no telemetry rather than a retry loop thanks to the back-off fix in #81
(already on
main).Testing
attribution
edit-config-then-reorient-moves-the-session — the regression this exists for
Both commits build, pass
go test ./..., and are gofmt-clean individually.