A compose request cannot name the seat, so a composing agent carries two identities #280

Closed
opened 2026-08-14 03:05:38 +00:00 by coilyco-ops · 0 comments
Member

🤖 Filed by Claude Code on Kai's behalf.

A consumer that composes a role gets that role's seat identity verbatim, with no way to say who the seat is in its context.

coilyco-gaming/sirens-echo is the concrete case. Sirens Echo composes ops for its operator doctrine and keeps its own neutral voice. The bundle's identity card then renders:

**Agent // Olaf (he)**

while the runtime definition says the agent is Sirens Echo. Two identities in one prompt, and the seat name belongs to a different context entirely.

What exists today

ParseRequest in internal/schema/schema.go:200 is a closed switch: personality-library, person-policy, person-source, role, delivery, model-tier, density, source. Anything else is unknown node, tested at internal/schema/schema_test.go:93. Request carries no identity field.

The nearest existing mechanisms do not reach:

  • person-source replaces the whole embedded package rather than adjusting one role, per internal/person/person.go:427 — "An external package replaces the embedded package rather than extending it."
  • The Claude launch --name override at cmd/agent-compose/main.go:868 changes the prompt box and terminal title only. It does not touch the identity card, the manifest, the statusline, or the overlay.

Proposal — name and pronouns only

compose {
    role "ops"
    identity name="Echo" pronouns="it"
    delivery "native-skills"
}

Deliberately not a personality override. role.Personalities also drives the melded favorite color, the nativeui theme tokens, and validateCorePersonalityMelds's exactly-three rule at internal/person/person.go:746, so filtering a meld is several seams. Name and pronouns is one.

The override must rewrite role.Identity and every role.Seats[i].Name/.Pronouns, because the overlay, statusline, nativelaunch.seatName, and the bundle manifest read the seats rather than the role. Rewriting one and not the other yields a bundle whose card and statusline disagree.

The doctrine question this raises

docs/person-contract.md:77 currently says:

A private overlay may add scoped instructions or selection rules. It may not redefine selected roles, personalities, seats, definitions, or role personality sets.

A request-level identity override is a carve-out to that sentence and should be written as one rather than left to contradict it. The narrow reading that keeps the invariant intact: a caller may say who is speaking in its own deployment, and still may not change what the role is — its skills, methods, personalities, or boundaries. Naming the seat is identity, not role content.

Cache invalidation needs nothing: bundle.cacheKey at internal/bundle/bundle.go:292 already hashes the rendered instructions, which contain the card.

🤖 Filed by Claude Code on Kai's behalf.

> 🤖 Filed by Claude Code on Kai's behalf. A consumer that composes a role gets that role's seat identity verbatim, with no way to say who the seat is in its context. `coilyco-gaming/sirens-echo` is the concrete case. Sirens Echo composes `ops` for its operator doctrine and keeps its own neutral voice. The bundle's identity card then renders: ``` **Agent // Olaf (he)** ``` while the runtime definition says the agent is `Sirens Echo`. Two identities in one prompt, and the seat name belongs to a different context entirely. ## What exists today `ParseRequest` in `internal/schema/schema.go:200` is a closed switch: `personality-library`, `person-policy`, `person-source`, `role`, `delivery`, `model-tier`, `density`, `source`. Anything else is `unknown node`, tested at `internal/schema/schema_test.go:93`. `Request` carries no identity field. The nearest existing mechanisms do not reach: - `person-source` replaces the whole embedded package rather than adjusting one role, per `internal/person/person.go:427` — "An external package replaces the embedded package rather than extending it." - The Claude launch `--name` override at `cmd/agent-compose/main.go:868` changes the prompt box and terminal title only. It does not touch the identity card, the manifest, the statusline, or the overlay. ## Proposal — name and pronouns only ```kdl compose { role "ops" identity name="Echo" pronouns="it" delivery "native-skills" } ``` Deliberately **not** a personality override. `role.Personalities` also drives the melded favorite color, the nativeui theme tokens, and `validateCorePersonalityMelds`'s exactly-three rule at `internal/person/person.go:746`, so filtering a meld is several seams. Name and pronouns is one. The override must rewrite `role.Identity` **and** every `role.Seats[i].Name`/`.Pronouns`, because the overlay, statusline, `nativelaunch.seatName`, and the bundle manifest read the seats rather than the role. Rewriting one and not the other yields a bundle whose card and statusline disagree. ## The doctrine question this raises `docs/person-contract.md:77` currently says: > A private overlay may add scoped instructions or selection rules. It may not redefine selected roles, personalities, seats, definitions, or role personality sets. A request-level identity override is a carve-out to that sentence and should be written as one rather than left to contradict it. The narrow reading that keeps the invariant intact: a caller may say **who is speaking** in its own deployment, and still may not change **what the role is** — its skills, methods, personalities, or boundaries. Naming the seat is identity, not role content. Cache invalidation needs nothing: `bundle.cacheKey` at `internal/bundle/bundle.go:292` already hashes the rendered instructions, which contain the card. > 🤖 Filed by Claude Code on Kai's behalf.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agent-compose#280
No description provided.