ADR-0222shipped
Prompt-Layer Role Matrix and Session Handles
Context
The prompt stack had the right pieces but the hierarchy was still too fuzzy in practice.
Problems observed:
SYSTEM.mdsaid identity came from layered files, but it did not explain the hierarchy clearly enough for agents to reason about who they are in a session.roles/system.mdexisted and~/.joelclaw/ROLE.mdalready pointed at it, but the mental model aroundsystemvsinteractivewas drifting.- Agent-to-agent coordination (
joelclaw mail) and operator relay (joelclaw notify→ gateway → Joel) were not stated sharply enough, so the transport split was muddy. - System sessions lacked a session-local identifier. Reusing the same stable agent name makes mail, logs, and operator summaries harder to attribute to a specific session.
Decision
1. Make the prompt-layer hierarchy explicit in SYSTEM.md
SYSTEM.md now states the layer order and purpose of each layer:
SYSTEM.md
→ IDENTITY.md
→ SOUL.md
→ ROLE.md
→ USER.md
→ TOOLS.md
→ AGENTS.md
→ skillsThe key rule is:
- identity is stable
- role is contextual
- session handles are local identifiers only
2. Canonical role matrix
The system recognizes these role contracts:
system— default interactive pi role on Pandagateway— operator-facing orchestration/triagecodex-worker— bounded implementation workerloop-worker— pipeline implementation workervoice— conversational capture/synthesisinteractive— legacy alias; prefersystem
Role selection remains resolved by identity-inject via:
JOELCLAW_ROLE_FILEJOELCLAW_ROLEGATEWAY_ROLE=central- fallback
~/.joelclaw/ROLE.md
3. Split coordination transport from operator relay
This distinction is now explicit:
joelclaw mail= agent coordination, reservations, handoffsjoelclaw notify= gateway/operator relay
The system role sends operator-facing progress/status packets through the gateway, not through ad hoc direct channel assumptions.
4. System-session relay policy
For non-trivial work, system sessions should send concise relay packets:
- at start
- on major state changes (
delegated,blocked,recovered,done) - periodically during long active work
Relay packets should include, when relevant:
- session handle
- current objective
- touched surfaces
- notable memory or slog references
- desired system improvements
- blockers / risks
- next move
Gateway remains the final router and applies ADR-0189 before anything reaches Joel.
5. Session-local handles for system sessions
pi/extensions/session-lifecycle/index.ts generates a session-local handle for system sessions.
Properties:
- compact
AdjectiveNounidentifier - derived from session context, with a slightly funny/system-flavoured tone
- shown in the session identity block
- intended for
joelclaw mail --agent <handle>/mail_*agentparameters, logs, handoffs, and relay packets - does not replace the stable identity or role
Implementation Plan
Required skills before implementation
system-prompt— prompt-layer design and anti-pattern avoidanceclawmail— coordination vs relay transport splitadr-skill— ADR shape and consequences
Affected paths
SYSTEM.mdroles/system.mddocs/gateway.mddocs/prompt-architecture.mdpi/extensions/session-lifecycle/index.ts
Pattern
- keep universal prompt law in
SYSTEM.md - keep role-specific behaviour in
roles/system.md - use docs to explain the matrix explicitly
- use session-lifecycle to inject per-session identity metadata without mutating stable identity
Verification
-
SYSTEM.mdexplains prompt-layer hierarchy and role matrix explicitly -
systemrole documents gateway relay policy - docs distinguish
mailfromnotify - prompt architecture doc exists and matches reality
- session-lifecycle generates and surfaces session-local handles for system sessions
- session handoff includes the generated handle when present
Consequences
- Agents have a clearer answer to “who am I right now?”
systembecomes the explicit default interactive role instead of an implied alias- Gateway becomes the clean operator relay path for system-session progress
- Mail traffic and logs gain better per-session attribution
- Stable identity stays stable; session handles add precision without creating role drift