Native role launch refuses inside a launch, which contradicts the sentinel's own documented contract #348
Labels
No labels
burndown-2026-08
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/devrel
role/eval
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/sysadmin
role/tpm
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agent-compose#348
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Filed by Saiya (tpm seat), 2026-08-25. Kai raised it as a UX limit and thought it might already be in flight. It is not. No open issue or PR covers it, checked across the estate alongside the aterm and acompose work that landed tonight (#1243, #1246, #1249).
The observation
aterm eval claudefrom inside a composed session refuses:Why this is a defect rather than a policy
One sentinel, two call sites, two different behaviours, and only one of them matches what the sentinel says it is for.
internal/launch/launch.go:13states the contract:cmd/agent-compose/main.go:1096, inrefreshThenExec, does exactly that. It sees the sentinel, printsnested launch detected; skipping refresh, and still execs:cmd/agent-compose/main.go:701, inrunNativeLaunch, sees the same sentinel and refuses outright:The refusal sits immediately above the
converge.Runcall it is protecting. So the thing actually at risk of recursing is the converge, andrefreshThenExecalready demonstrates the correct handling: suppress the converge, proceed with the launch.The fix
Make
runNativeLaunchbehave likerefreshThenExec. Skip the converge when the sentinel is set, warn on stderr in the same shape, and continue into the launch. Do not delete the guard, because the recursion protection is the converge suppression rather than the refusal.Acceptance criteria
aterm <role> <seat>from inside a composed session launches, and does not converge.main.go:1096.runNativeLaunchon the sentinel, in the shape of the existing coverage onrefreshThenExec.EnvSentineldoc comment still describes what both call sites do.Watch item
The nested session inherits
AGENT_COMPOSE_LAUNCHandAGENT_GIT_ATTRIBUTION_ROLEfrom its parent.launch.go:18notes attribution is per-session against a global host projection (coilysiren/inbox#362). Confirm the child's role attribution wins over the parent's rather than inheriting it, or a nestedevalseat commits as the parent's role.Not in scope
This does not make nested seats addressable by the harness's cross-agent messaging. Separate issue, filed alongside this one.
Half landed, and I reopened this after closing it by mistake
e7605d7onmaindoes the converge half. I closed the issue on that and then re-read the acceptance criteria: the first one is still unmet, and it is the one carrying the user-visible symptom. Reopened.What the code looked like when I got here, which is not what the body describes
The body was written against a
runNativeLaunchthat refused outright.--nestedlanded since, somainnow reads:NestedDepthrefuses unless--nestedis passed, then bounds the chain at one hop. That is a different resolution from the one the body proposed, and a reasonable one: it separates accidental nesting from deliberate nesting, which the sentinel alone cannot.But the converge was still running on a nested launch, against a host the parent had just converged. That is the part the body is unambiguously right about, and the part nothing had done.
Landed in
e7605d7nestedLaunchNotice, because the two saying different things is how they came to do different things.nestedLaunchSkipsConverge(0)and(1), plus both notice strings.EnvSentineldoc comment described only the refresh call site. It now describes what both do.aterm <role> <seat>from inside a composed session launches. Still refuses, because aterm does not pass--nested.The remaining question, which is a decision rather than code
Should
aterm <role> <seat>pass--nestedwhen it detects the sentinel?aterm eval claudeinside a session is being deliberate by typing it. The flag exists to stop a harness re-invoking acompose by accident, and a human at a prompt is not that. This closes the symptom in about three lines ofaterm/plan.go.--nested.I did not pick, because both are defensible and the wrong one is annoying to walk back through two repos. Whichever way it goes, the aterm change is small.
Watch item from the body, unchecked
Role attribution on a nested seat is still unverified.
AGENT_GIT_ATTRIBUTION_ROLEis inherited from the parent and I did not test whether the child's role wins. Recording that it remains open rather than implying this touched it.