canon: add runtime method docs (persona-shaped + runtime-contract) + journals#187
Conversation
Canon Quality —
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: TSV column misalignment from extra tab in data rows
- Removed the extra tab from each data row so all rows now have 8 tab-separated fields matching the 8-column header.
Preview (63c6c47241)
diff --git a/canon/methods/persona-shaped-agent-runtime.md b/canon/methods/persona-shaped-agent-runtime.md
new file mode 100644
--- /dev/null
+++ b/canon/methods/persona-shaped-agent-runtime.md
@@ -1,0 +1,345 @@
+---
+uri: klappy://canon/methods/persona-shaped-agent-runtime
+title: "Persona-Shaped Agent Runtime — Building a Reusable Substrate for Many Personas"
+audience: canon
+exposure: nav
+tier: 1
+voice: neutral
+stability: evolving
+tags: ["canon", "methods", "agent-runtime", "persona-profile", "substrate", "vodka-architecture", "oddie", "spawned-agent-session", "role-enforcement", "surface-profile"]
+epoch: E0008.5
+date: 2026-05-10
+derives_from: "canon/methods/spawned-agent-session-substrate-options.md, canon/principles/sessions-mirror-modes.md, canon/constraints/mode-transitions-require-encoded-handoff.md, canon/constraints/critic-cannot-be-resolver.md, canon/principles/verification-requires-fresh-context.md, canon/voice/oddie-the-river-guide.md, canon/principles/vodka-architecture.md"
+complements: "canon/principles/methodology-personification.md, canon/principles/voice-as-cognitive-load-shedding.md, canon/principles/participation-replaces-integration.md"
+governs: "Any service that hosts spawned agent sessions on behalf of multiple consumers and multiple personas"
+status: proposed
+---
+
+# Persona-Shaped Agent Runtime — Building a Reusable Substrate for Many Personas
+
+> A spawned-agent-session substrate (CF Sandboxes, Anthropic Managed Agents, etc.) hosts one session at a time. A *runtime* sits on top of a substrate and turns it into a service: many consumers can call it with many tasks, and the substrate stays opinion-free underneath. This method documents how to shape that runtime so it composes with **personas as first-class objects** — Oddie, an audit reviewer, a release validator, a docs mentor — without coupling the runtime to any specific persona's identity or any specific consumer's workflow. The pattern keeps the substrate vodka, makes critic-cannot-be-resolver mechanically enforceable, and turns voice canon into something the runtime honors automatically rather than something the agent inside has to remember.
+
+---
+
+## What This Document Is
+
+A design pattern for the layer that sits between a spawned-agent-session substrate and the consumers who want agent help. Companion to [Spawned Agent Session Substrate Options](klappy://canon/methods/spawned-agent-session-substrate-options): that doc catalogs *where* to host a session; this doc describes *how to build a service on top* so the same substrate serves many callers and many personas without each pair re-implementing infrastructure.
+
+This is a method, not a decision. It documents the shape; it does not lock in implementation specifics. Specific runtime instances (the audit gate, a TinCan-Oddie deployment, a docs mentor service) are decisions that consume this method.
+
+---
+
+## The Pattern
+
+A spawned-agent-session substrate gives you one capability: spin up an agent in an isolated context, hand it a task, get a result. That capability is generic. Every consumer that wants agent help would otherwise wire it themselves: prompt assembly, tool registration, MCP setup, secret injection, output parsing, surface-specific formatting. The wiring is repetitive. It also smuggles opinions into the substrate (which prompt? which tools? which output schema?), violating vodka-architecture at the substrate layer.
+
+The runtime resolves this by hosting the wiring at a layer above the substrate:
+
+```
+┌────────────────────────────────────────────────────────────────┐
+│ Consumers: audit gate │ slack bot │ cron │ TinCan │ ... │
+│ (each one knows: "invoke this persona, this task") │
+├────────────────────────────────────────────────────────────────┤
+│ Runtime: persona resolution │ role enforcement │ │
+│ surface post-processing │ session lifecycle │
+├────────────────────────────────────────────────────────────────┤
+│ Substrate: CF Sandbox │ Managed Agents │ Daytona │ ... │
+│ (just spawns isolated sessions) │
+└────────────────────────────────────────────────────────────────┘
+```
+
+The runtime accepts requests of the form *"invoke persona P on surface S for task T,"* resolves P to operational configuration, dispatches to the substrate, post-processes the output per S, and returns. Personas are canon objects. Surfaces are constraints. The substrate stays generic. The consumer stays simple.
+
+---
+
+## The Persona Profile
+
+A persona profile is a structured description of who an agent is, what it can do, and how its output is constrained. Profiles are themselves canon — versioned, URI-addressable, governed by the same rules as any other canon doc.
+
+### What a Profile Contains
+
+A profile bundles:
+
+| Field | Purpose |
+|---|---|
+| `system_prompt_uri` | The voice canon or role specification. The runtime fetches this and passes it to the agent. |
+| `role` | One of `detection-only`, `resolver`, `general`. Drives tool filtering and session lifecycle rules. |
+| `mcp_servers.operational` | MCPs the persona requires to *be* itself, regardless of task. (Oddie needs oddkit always.) |
+| `mcp_servers.task_relevant` | MCPs added per invocation based on the specific task. (A PR audit gets the GitHub MCP.) |
+| `knowledge_bases` | URIs the persona can ground observations against (`klappy://`, `ams://`, etc.). |
+| `surface_profiles` | Per-surface constraints: density caps, output format, narrative-vs-structured, max tokens per emission. |
+| `brand_discipline` | URI pointing at the persona's voice canon section that governs emoji, vocabulary, machine-vs-human surface rules. |
+
+### Illustrative Sketch
+
+```yaml
+persona: oddie
+version: 1
+system_prompt_uri: klappy://canon/voice/oddie-the-river-guide
+role: detection-only
+mcp_servers:
+ operational: [oddkit]
+ task_relevant: []
+knowledge_bases:
+ - klappy://
+ - ams://
+surface_profiles:
+ real_time_stream: { density: high, max_tokens_per_emission: 60 }
+ audit: { density: medium, structured_output: required }
+ mentorship: { density: low, narrative: true }
+ strategic_translation: { density: medium, bidirectional: true }
+brand_discipline: klappy://canon/voice/oddie-the-river-guide#brand-guide
+```
+
+The schema is illustrative. Specific field names, validation rules, and serialization format are implementation choices. The principle is that a persona's identity is captured in a structured artifact that the runtime can resolve to operational configuration.
+
+### Where Profiles Live
+
+Two reasonable options:
+
+1. **The voice canon doc is the profile.** Structured fields go in the YAML frontmatter; narrative goes in the prose body. Single source of truth.
+2. **Profiles are separate canon docs** (e.g., `klappy://personas/oddie`) that reference the voice canon for narrative. Cleaner separation; two-doc maintenance.
+
+Either approach is consistent with this method. The choice belongs to the operator authoring the first profile.
+
+---
+
+## The Runtime's Job
+
+The runtime accepts an invocation, resolves a profile, executes against a substrate, and post-processes the result. Five responsibilities specifically:
+
+### 1. Resolve Profile to Operational Configuration
+
+`runtime.invoke(persona="oddie", surface="audit", task="...")` triggers:
+
+- Fetch the persona profile by name and version.
+- Fetch the system prompt at `system_prompt_uri`.
+- Compose the operational MCP set (always-on) with the per-invocation task-relevant MCPs.
+- Apply the named surface profile's constraints.
+- Hand the assembled config to the substrate.
+
+The runtime is the only component that knows how to assemble these pieces. Consumers do not. New consumers can be added without touching profile-resolution logic.
+
+### 2. Enforce Role at Submit Time
+
+Two parallel constraints need architectural enforcement, drawn from two parent canon docs:
+
+- [Critic Cannot Be Resolver](klappy://canon/constraints/critic-cannot-be-resolver) — detection and remediation must be separated by a *tool boundary*. A session that detects cannot also mutate.
+- [Verification Requires Fresh Context](klappy://canon/principles/verification-requires-fresh-context) — creation and validation must be separated by a *context boundary*. A session that validates cannot inherit the creator's accumulated reasoning.
+
+Generalized to all mode transitions per [Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes), every transition between epistemic modes is a context boundary deserving a fresh session. The runtime enforces the boundaries through five mode-bound roles plus an escape hatch.
+
+#### The Five Mode-Bound Roles
+
+Each role corresponds to one of the five canonical [epistemic modes](klappy://canon/epistemic-modes). The role declares the session's mode; the runtime enforces the role's constraints structurally.
+
+**`explorer`** — operates in exploration mode. Tool set is broad (read-only access to canon, web search, conversational tools, hypothesis-shaping tools); state-mutation tools are refused. Output is a synthesis ledger or research artifact per the [encoded-handoff constraint](klappy://canon/constraints/mode-transitions-require-encoded-handoff). Fresh-context requirement is light — explorers can build on prior exploration but should not inherit planning-context.
+
+**`planner`** — operates in planning mode. Tool set is read-oriented (canon access, prior synthesis ledgers, plan-shaping tools); state-mutation tools are refused. Output is a plan declaring assumptions, scope, deferred items, and invalidating conditions. Fresh-context requirement: must not inherit explorer-session state directly; reads the explorer's encoded synthesis as input. The plan is the durable handoff to the builder.
+
+**`builder`** — operates in execution mode. Tool set includes mutating tools (filesystem writes, git commits, API calls, etc.) bounded by the plan's declared scope. Output is the produced artifact plus a claims declaration (what the artifact does, what it does not do, what scope it was built against). Fresh-context requirement: must not inherit planner-session state; reads the plan as input. The artifact plus claims is the durable handoff to the validator.
+
+**`validator`** — operates in validation mode. Tool set is restricted to a read-only allow-list. Mutating actions are refused before the substrate is invoked. Fresh-context requirement is *strict*: the runtime guarantees the validation session is spawned with no inputs from the caller other than the persona profile, the artifact reference, the claims declaration, and the governance documents. No prior conversation, no handoff context beyond the encoded artifact-and-claims, no "we discussed X earlier" framing. Output is structured findings with explicit dispositions (fix, pivot, accept) per finding, consistent with [P0008](klappy://docs/promotions/P0008-pr-validator-dolcheo-ledger-as-deliverable). The findings are the durable handoff to the resolver (or, if all findings are accepted, the validation session is the terminal session).
+
+**`resolver`** — operates in resolution mode. Tool set includes mutating tools, but bounded by the validator's findings. The runtime can validate that mutations stay within finding-scope when the implementation supports it; at minimum, the resolver session is briefed that scope is bounded. Fresh-context requirement: must not inherit validator-session state; reads the findings as input. Output is the revised artifact plus a remediation summary per finding (what was changed, what was not changed and why). The revised artifact is the durable handoff back to a fresh validator session for re-validation.
+
+#### Escape Hatch and Observer Sessions
+
+**`general`** — no mode-binding, no fresh-context guarantee, no structured-deliverable requirement. Used for personas that intentionally combine modes in workflows where the context-corruption risk is acceptable. Mode-collapsed sessions are a deliberate choice to trade signal quality for throughput; the runtime supports them but does not pretend the constraints are met. PoC-scope work that explicitly skips modes (per the [encoded-handoff constraint](klappy://canon/constraints/mode-transitions-require-encoded-handoff)'s skip provision) is the canonical use case.
+
+**Observer sessions.** Some sessions do not fit the five-mode taxonomy because they do not produce artifacts that hand off to a next mode — they are continuous observers, emitting commentary on streams produced elsewhere. Oddie's real-time stream interpretation surface is the worked example. These sessions are configured with the `subscribed` session type (see §5 below), a tool restriction (typically read-only), and no mode-bound role declaration. They are not gate-bounded work; the encoded-handoff constraint does not apply because there are no transitions to encode.
+
+#### Constraints Are Composable
+
+The named roles bundle (tool filter × fresh-context requirement × deliverable shape × mode binding) in their canonical configurations. The underlying parameters are composable. A persona profile can declare a custom role configuration if the named roles do not fit — e.g., a "drafting" role that combines builder-role tools with explorer-role context-freshness for early-stage artifact work. Named roles are recommended for legibility; custom configurations are supported for cases the named roles undersolve.
+
+#### Universal Handoff Requirement
+
+Per [Mode Transitions Require Encoded Handoff](klappy://canon/constraints/mode-transitions-require-encoded-handoff), every transition between mode-bound roles requires a journal entry plus a transition-specific minimal handoff artifact. The runtime enforces this by requiring handoff URI inputs on any session whose role is downstream of another role. Sessions invoked without complete handoff inputs are refused. The journal entry is universal; the runtime can require it as a side-effect of any mode-bound session's completion.
+
+### 3. Apply Surface-Profile Output Post-Processing
+
+The runtime tags every output field as `machine` (parsed by code) or `human` (read by people). Surface profiles constrain what reaches each tag:
+
+- **Persona emoji stripped from machine fields.** If the voice canon bans 🦦 in JSON / YAML / commit messages / status titles / URIs, the runtime enforces that ban at output time, not at prompt time. The agent inside can speak naturally; the runtime cleans before delivery.
+- **Density caps applied.** If a `real_time_stream` surface declares `max_tokens_per_emission: 60`, an emission that exceeds the cap fails validation and the runtime requests a shorter retry. Brevity-under-pressure becomes structural.
+- **Format contracts honored.** If `structured_output: required`, the runtime parses fenced JSON from the agent's response and rejects free-form text. If `narrative: true`, prose is expected and structure is optional.
+
+Voice and brand are mechanically enforceable at this layer. The agent does not have to police itself; the runtime does.
+
+### 4. Honor Mode Toggles
+
+Personas have voice modes — `persona`, `neutral`, `strict` — declared per invocation:
+
+- **persona**: full voice canon applies (signature emoji, vocabulary, register).
+- **neutral**: persona emoji and vocabulary suppressed; functional status emoji (✅ ⚠️ 🔴) survive because they carry information rather than character.
+- **strict**: even functional emoji minimized; output is purely text. Useful for environments that strip emoji entirely (parser-sensitive contexts, accessibility-first surfaces).
+
+The mode is a runtime parameter, applied uniformly across all output fields. The agent inside does not need to know which mode is active.
+
+### 5. Support Session Types
+
+Two session shapes cover known use cases:
+
+- **`one_shot`**: invoke, return, tear down. Audit gates, on-demand reviews, doc-generation tasks. Single output.
+- **`subscribed`**: long-lived, connected to an event source, emits over time. The TinCan flagship case for Oddie. Real-time stream interpretation, scheduled monitoring, persistent observers.
+
+A subscribed session needs: connection management, multi-output channels (per-channel post-processing), backpressure handling for when stream rate exceeds interpretation rate, and a teardown signal. The audit-gate use case does not need any of this. The runtime should support both without requiring `subscribed` consumers to use `one_shot` machinery or vice versa.
+
+---
+
+## What This Method Is Not
+
+**Not orchestration.** The runtime invokes one persona per request. It does not chain personas, route between them, or maintain workflows that span multiple invocations. Orchestration belongs to consumers, not to the runtime. (A consumer can call the runtime multiple times in sequence; that is the consumer's workflow.)
+
+**Not coupling.** A persona profile does not specify *which* substrate hosts it. The same Oddie profile can run on CF Sandboxes, on Managed Agents, on Daytona, or on a local Docker container. The runtime resolves the profile and dispatches to whatever substrate is configured. Substrate choice is a runtime-deployment decision per [Spawned Agent Session Substrate Options](klappy://canon/methods/spawned-agent-session-substrate-options); persona authoring is independent.
+
+**Not a CRM for personas.** The runtime is not a directory service, identity provider, or persona-discovery layer. It resolves profiles by URI. Listing, searching, and discovering personas is a separate concern — handled by canon search, by directory pages, or by whatever tooling exists upstream.
+
+**Not a permission system.** Role enforcement is about epistemic-context separation (critic-cannot-be-resolver), not authorization. Whether a *consumer* is allowed to call the runtime is a separate question, handled at a different layer (API keys, OAuth, bearer tokens). The runtime trusts its callers; it just refuses to wire detection sessions with resolver tools.
+
+---
+
+## Prior Art
+
+This pattern is not novel as a category — agent-runtime services and persona-shaped agents are an active design space. The contribution here is the specific composition of constraints, not the existence of the pattern.
+
+Adjacent work this method is aware of:
+
+- **OpenAI Custom GPTs** and **Anthropic Projects** — persona-shaped chat surfaces with system prompts, tools, and knowledge bases. Closest in spirit to persona profiles. Differences: Custom GPTs and Projects target end-user chat surfaces, not programmatic invocation by other services; they do not architecturally enforce role-separation (critic-cannot-be-resolver is left to prompt design); brand-discipline is not mechanically enforced at output time. The runtime pattern targets multi-consumer service composition, not direct human chat.
+- **LangChain agent runtimes** and similar SDK-level abstractions — toolkit for assembling agents, often with persona-like configuration. Differences: typically embedded in the consumer's process rather than offered as a hosted service; do not enforce an explicit critic-vs-resolver context boundary; surface-aware output post-processing is left to consumers.
+- **Cloudflare Agents SDK** and the **MCP `McpAgent` pattern** — substrate-aware abstractions for hosting agents on Workers. Closer to the substrate layer than to the runtime layer described here; this method composes on top of such abstractions rather than replacing them.
+- **Anthropic Managed Agents** — the substrate captured in [Spawned Agent Session Substrate Options](klappy://canon/methods/spawned-agent-session-substrate-options). Substrate, not runtime. The runtime pattern is the layer that would sit above Managed Agents (or any other substrate) to multiplex consumers and personas.
+
+The closest prior art is probably Custom GPTs / Projects, characterized as of mid-2026. The runtime pattern's distinguishing commitments are: programmatic-first interface, mechanical role enforcement, mechanical brand discipline at output time, and explicit separation between persona authoring (canon) and runtime engineering (service).
+
+If a respected peer points to closer prior art that already names this composition, the contribution shrinks to "naming and codifying for this knowledge base" — which is still worthwhile as a vocabulary anchor but is not novel design.
+
+---
+
+## Inheritance — Why This Shape
+
+The runtime shape is not original. It is a synthesis of three commitments already canonical:
+
+**[Vodka Architecture](klappy://canon/principles/vodka-architecture)**: substrates win by refusing opinions. The substrate-options catalog stays opinion-free per that principle; this runtime stays opinion-free by pushing opinions up into persona profiles. Every layer above the substrate is removable without wire consequence.
+
+**[Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes)**: each epistemic mode earns its own session because the structural blindness that makes a creator unable to validate their own work, a critic unable to remediate their own findings, and a planner unable to execute their own plan is the same blindness in different shapes. This runtime is the architectural expression of that principle — five mode-bound roles, each with its own session, each refusing to inherit context from prior-mode sessions.
+
+**[Mode Transitions Require Encoded Handoff](klappy://canon/constraints/mode-transitions-require-encoded-handoff)**: every gate between modes requires a journal entry plus a transition-specific durable artifact. This runtime enforces that constraint mechanically by requiring handoff URI inputs on any session whose role is downstream of another role.
+
+**[Critic Cannot Be Resolver](klappy://canon/constraints/critic-cannot-be-resolver)**: detection and remediation must be separated by a tool boundary. The runtime enforces this for the validator → resolver transition specifically, refusing mutating tools in validator sessions and requiring a fresh resolver session to act on findings.
+
+**[Verification Requires Fresh Context](klappy://canon/principles/verification-requires-fresh-context)**: a creator cannot be their own critic. The runtime enforces this for validator sessions specifically by guaranteeing fresh context — the validator session receives only the persona profile, artifact reference, claims declaration, and governance, never the creator's accumulated reasoning. The same fresh-context guarantee applies generally to every mode-bound role transition under sessions-mirror-modes.
+
+**[Participation Replaces Integration](ams://canon/principles/participation-replaces-integration)**: open substrates collapse connector topology from O(N²) to O(N). Without this runtime, every persona × consumer pair requires its own wiring. With it, N personas + M consumers needs N + M descriptors, not N × M integrations. The runtime is the participation layer that makes the collapse work for agent invocation specifically.
+
+The pattern is also consistent with [Methodology Personification](klappy://canon/principles/methodology-personification): if a methodology becomes more accessible when given a personified voice, the natural follow-up is infrastructure that lets the persona show up everywhere without re-engineering. The runtime is that infrastructure.
+
+---
+
+## First Worked Examples
+
+Two consumers exercise the runtime's role enforcement most directly:
+
+### Oddie (validator and observer across surfaces)
+
+Oddie is the first persona this method targets. He exercises multiple parts of the shape:
+
+- **Role spans validator and observer depending on surface.** Audit findings is `validator` — receives a specific PR or document, evaluates against governance, produces structured findings with dispositions. Real-time stream interpretation is an *observer* session — not a mode-bound role, since Oddie watching live agent traffic does not produce a hand-off artifact for a next mode. Mentorship and strategic translation are also observer-shaped: continuous narrative on something happening elsewhere, not gate-bounded work. The persona profile declares the allowable session shapes; each invocation specifies which is in play.
+- **Two capability sources** — operational MCP (oddkit, used for self-hygiene) and knowledge base (klappy.dev, used for grounding). Both registered in every Oddie session.
+- **Four surface profiles** — audit, real-time stream interpretation (flagship), mentorship, strategic translation. Each declares its density and verbosity tolerance.
+- **Brand discipline** — 🦦 signature, river vocabulary, machine-surface ban, density rule, mode-aware suppression. All mechanically enforceable.
+- **Both session types** eventually — the audit surface is `one_shot`; the TinCan flagship is `subscribed`. The runtime needs both.
+
+Implementing the runtime against Oddie validates several parts of the shape but not all. Oddie does not exercise the explorer, planner, builder, or resolver roles — those need a different worked example.
+
+### A Multi-Role Build Workflow (explorer → planner → builder → validator → resolver)
+
+The cleanest exercise of the full five-role taxonomy is a multi-agent build workflow that crosses every gate. Sketched:
+
+1. **Explorer session** — given a goal, surfaces possibilities, tensions, and unknowns. Produces a synthesis ledger entry.
+2. **Planner session** — fresh, reads the synthesis. Produces a plan with explicit assumptions, scope, deferred items.
+3. **Builder session** — fresh, reads the plan. Produces an artifact plus claims declaration.
+4. **Validator session** — fresh, reads the artifact and claims. Produces findings with dispositions.
+5. **Resolver session** — fresh, reads the findings. Produces a revised artifact plus remediation summary.
+6. **Re-validation session** — fresh, reads the revised artifact and remediation summary. Produces validation pass or new findings.
+
+Each transition produces a journal entry per [the encoded-handoff constraint](klappy://canon/constraints/mode-transitions-require-encoded-handoff). Each session is a fresh substrate spawn with no inherited context from upstream sessions beyond the encoded handoffs. The runtime enforces the role-bound tool restrictions at each step.
+
+This workflow does not yet have a deployed instance. It is the canonical test of the runtime — the smallest workflow that exercises all five mode-bound roles plus the journal requirement. A first deployment that validates the full pipeline produces concrete signal on whether session-per-mode discipline is operationally feasible at the runtime layer.
+
+### The Audit Gate (validator, single-role)
+
+The audit gate that currently runs against AMS PRs is the cleanest validator-role consumer in isolation. It exercises the validator role's enforcement (read-only tools, fresh-context guarantee, structured deliverable per [P0008](klappy://docs/promotions/P0008-pr-validator-dolcheo-ledger-as-deliverable)) without needing the full multi-role pipeline. It is the right first deployment of the runtime because it isolates one role and produces concrete signal on whether validator-role enforcement works in production.
+
+The deployment sequence is therefore:
+
+1. Audit gate as single-role validator deployment — lowest-risk first deployment, validates one role's enforcement.
+2. Multi-role build workflow as second deployment — exercises the full five-role pipeline plus journal handoffs.
+3. Oddie's TinCan-flagship subscribed-session deployment — exercises the observer pattern and the long-lived session type.
+
+In that order, each deployment validates a distinct dimension of the runtime without trying to validate all dimensions at once.
+
+---
+
+## Open Questions
+
+These are explicitly unresolved. The method describes the shape; the open questions are about parameters that production evidence will tune.
+
+**Subscribed-session backpressure policy.** When stream rate exceeds interpretation rate, what gets dropped, summarized, or queued? The TinCan integration spec flags this as an open question. The runtime has to expose policy — it cannot hide the question — but the right policy is empirical.
+
+**Profile-discovery ergonomics.** How do consumers find available personas? Canon search works for humans; for programmatic consumers, a registry endpoint or a profile-listing convention may be needed. Defer until a second consumer beyond the first deployment exists.
+
+**Versioning semantics.** Profiles are versioned (`oddie@v1`). What happens when `v2` ships? Do existing consumers pin? Auto-upgrade? Receive a deprecation window? The right answer is probably "consumers pin; profile authors emit deprecation notices." Confirm with operator.
+
+**Surface-profile inheritance.** Can a persona's `mentorship` surface profile inherit from another persona's? If two personas share a surface specification, do they share a definition? Premature optimization until two personas exist with overlapping surfaces.
+
+**Multi-knowledge-base grounding.** Oddie grounds in `klappy://`. A future persona might ground in `klappy://` and `ams://` and a private knowledge base simultaneously. The profile schema lists `knowledge_bases` as an array, but the runtime's job in arbitrating between sources is undefined. Defer.
+
+---
+
+## What This Changes for Existing Work
+
+The substrate-options method doc catalogs *where* to host a session. This doc adds *how to build a service that hosts many sessions for many personas*. They compose without overlap.
+
+The audit gate, currently scoped as a single Worker that wraps Claude Code in a CF Sandbox, becomes a specific deployment of this runtime: one persona (audit reviewer), one surface (audit), one substrate (CF Sandbox). The architecture shifts from "the audit Worker" to "the runtime, configured for audit." Same code, different framing — but the framing pays off when the second persona arrives.
+
+Oddie's TinCan integration, currently a draft spec at `ams://docs/oddie/tincan-real-time-guide`, becomes a specific deployment of this runtime: one persona (Oddie), one surface (real-time stream interpretation), substrate to be determined. The integration spec's open questions (throughput, token budget, multi-conversation context) inherit into the runtime's open-questions list above.
+
+Future deployments — a security detector, a docs mentor, a release validator — are new persona profiles plus runtime configuration, not new infrastructure.
+
+---
+
+## Confidence
+
+**Working belief.** Zero production validations. The shape is derived from existing canonical commitments (vodka-architecture, critic-cannot-be-resolver, participation-replaces-integration) and from one designed-but-untested persona (Oddie). The pattern has not yet hosted a real consumer in production.
+
+**What depends on this method being right.** If this shape is the wrong abstraction, the dependent work that has to be re-thought includes: the audit-gate migration off Anthropic Managed Agents (would revert to bespoke Worker per consumer); the TinCan-Oddie integration spec's deployment path (would require its own substrate wiring); and any follow-up persona deployments (security detector, docs mentor, release validator), each of which would duplicate substrate plumbing. The blast radius is significant but bounded — it does not affect AMS, oddkit, or klappy.dev canon themselves; only the agent-invocation infrastructure that sits above them.
+
+**Retraction conditions:**
+
+- If the runtime's overhead (profile resolution, post-processing, role enforcement) measurably degrades performance compared to bespoke per-consumer wiring without producing offsetting benefits in correctness or composability, the abstraction is retracted and consumers wire substrates directly.
+- If persona profiles prove too rigid — if every new persona requires schema extensions — the profile concept is retracted in favor of a thinner contract (system prompt + tool list + surface tag, nothing else).
+- If role enforcement at the runtime layer produces false-refusals frequently enough to be a friction tax, the enforcement moves back to prompt discipline and a softer warning layer.
+
+**What would falsify the pattern most cleanly.** A second persona deployment that fights the abstraction — i.e., a persona whose natural shape requires schema extensions in three out of five fields, or whose surface profiles do not fit the density-cap model, or whose role does not map cleanly to detection-only/resolver/general. If two well-specified personas cannot share the runtime without per-persona special cases, the abstraction is leaking and should be retracted in favor of thinner contracts.
+
+The retraction conditions are weak by design. The first deployment (audit gate) will surface concrete signal. The second deployment (Oddie on TinCan, or another non-audit persona) is the real test of whether the abstraction holds.
+
+---
+
+## See Also
+
+- [Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes) — the principle this runtime is the architectural expression of
+- [Mode Transitions Require Encoded Handoff](klappy://canon/constraints/mode-transitions-require-encoded-handoff) — the binding rule this runtime enforces mechanically
+- [Spawned Agent Session Substrate Options](klappy://canon/methods/spawned-agent-session-substrate-options) — the catalog of substrates this runtime sits on top of
+- [Critic Cannot Be Resolver](klappy://canon/constraints/critic-cannot-be-resolver) — the *tool-boundary* constraint this runtime enforces architecturally
+- [Verification Requires Fresh Context](klappy://canon/principles/verification-requires-fresh-context) — the *context-boundary* principle this runtime enforces for validator-role sessions
+- [P0008 — Fresh-Validator Deliverable Is a DOLCHEO Ledger](klappy://docs/promotions/P0008-pr-validator-dolcheo-ledger-as-deliverable) — the operationalized validator pattern this runtime hosts
+- [Epistemic Modes](klappy://canon/epistemic-modes) — the parent canon defining the five modes whose role expressions this runtime supports
+- [Vodka Architecture](klappy://canon/principles/vodka-architecture) — the substrate-discipline this runtime extends to its own layer
+- [Methodology Personification](klappy://canon/principles/methodology-personification) — why personas exist as canon objects in the first place
+- [Oddie the River Guide — Voice Canon](klappy://canon/voice/oddie-the-river-guide) — the first worked example of a full persona profile
+- [TinCan Real-Time Guide — Integration Spec](ams://docs/oddie/tincan-real-time-guide) — the first subscribed-session deployment target
+- [Participation Replaces Integration](ams://canon/principles/participation-replaces-integration) — the topology principle this runtime instantiates for agent invocation
+- [Voice as Cognitive Load Shedding](klappy://canon/principles/voice-as-cognitive-load-shedding) — why brand-discipline at the runtime layer is structural rather than cosmetic
diff --git a/canon/methods/spawned-agent-session-runtime-contract.md b/canon/methods/spawned-agent-session-runtime-contract.md
new file mode 100644
--- /dev/null
+++ b/canon/methods/spawned-agent-session-runtime-contract.md
@@ -1,0 +1,343 @@
+---
+uri: klappy://canon/methods/spawned-agent-session-runtime-contract
+title: "Spawned Agent Session Runtime Contract — Five Orthogonal Dimensions That Mechanize Existing Canon"
+audience: canon
+exposure: nav
+tier: 2
+voice: neutral
+stability: draft
+tags: ["canon", "methods", "spawned-agent-sessions", "runtime", "governance", "epistemic-modes", "engagement", "vodka-architecture", "mechanizes-canon"]
+epoch: E0008.5
+date: 2026-05-10
+derives_from: "canon/epistemic-modes.md, canon/constraints/mode-discipline-and-bottleneck-respect.md, canon/constraints/critic-cannot-be-resolver.md, canon/constraints/audit-gates-are-spawned-agent-sessions.md, canon/methods/spawned-agent-session-substrate-options.md, canon/voice/oddie-the-river-guide.md, canon/principles/vodka-architecture.md, canon/principles/verification-requires-fresh-context.md"
+complements: "canon/methods/governance-validation-via-agents.md, canon/constraints/canon-integration-audit.md"
+governs: "Any spawned agent session dispatched on the runtime substrate. Specifies the five orthogonal session-configuration dimensions, the runtime's enforcement obligations against existing canon, and the composition rules that determine session shape from the dimension values. Substrate selection (where the session runs) is handled by klappy://canon/methods/spawned-agent-session-substrate-options; this doc handles configuration (how the session is parameterized)."
+status: draft
+---
+
+# Spawned Agent Session Runtime Contract — Five Orthogonal Dimensions That Mechanize Existing Canon
+
+> A spawned agent session is fully characterized by five orthogonal dimensions: **persona** (voice and methodology), **mode** (epistemic state — exploration / planning / execution / validation), **role** (detection-only / resolver / general), **surface** (output context — real-time / audit / mentorship / sidebar-chat / etc.), and **engagement** (assistant / agent — turn-based dialogue or autonomous run-to-completion). The runtime's contribution is *mechanization*: the existing canon — epistemic modes, mode discipline, critic-cannot-be-resolver, voice and brand discipline, bottleneck respect — is enforced architecturally rather than left to prompt discipline. This doc specifies the dimensions, the runtime's enforcement obligations, and the composition rules that determine session shape from dimension values. The runtime adds no governance; it operationalizes existing governance for the agent surface.
+
+---
+
+## Summary — The Runtime Mechanizes Canon, It Does Not Add Canon
+
+`klappy://canon/epistemic-modes` already establishes the four modes and explicitly licenses tools and processes to encode them: *"Tools, processes, and workflows may encode or enforce these modes, but they do not define them."* This method doc takes that license and specifies what encoding and enforcement look like for spawned agent sessions.
+
+`klappy://canon/constraints/audit-gates-are-spawned-agent-sessions` (Tier-1) names the abstract requirement for governance validation. `klappy://canon/methods/spawned-agent-session-substrate-options` catalogues where such sessions can run. **This doc specifies how sessions are configured once a substrate is chosen.** It applies regardless of substrate; the dimensions are substrate-independent.
+
+The runtime exposes a single primitive — invoke a session — parameterized by five orthogonal fields. Same primitive, many session shapes. Same persona, many sessions. Same canon, mechanically applied.
+
+---
+
+## The Five Orthogonal Dimensions
+
+| Dimension | Values | What it determines |
+|---|---|---|
+| **Persona** | `oddie`, `audit-gate`, `docs-writer`, `general`, ... | Voice canon, system prompt URI, capability sources (operational + task-relevant MCP servers), inheritance |
+| **Mode** | `exploration` \| `planning` \| `execution` \| `validation` | Tool allow-list, output schema, transition rules, primary-risk detector |
+| **Role** | `detection-only` \| `resolver` \| `general` | Mutation rights, fresh-context requirements, session-to-session boundaries |
+| **Surface** | `real-time-stream`, `audit`, `mentorship`, `sidebar-chat`, `code-output`, `synthesis-ledger`, ... | Density / pace / verbosity tolerance, post-processing rules, channel mapping |
+| **Engagement** | `assistant` \| `agent` | Turn-control contract, bottleneck-respect enforcement, failure modes |
+
+These are orthogonal — no dimension is derivable from another. The same persona crosses modes, roles, surfaces, and engagements freely. Most dimension values can co-occur; some combinations are rare but legitimate (*Planning + agent* — autonomous canonical planning) while others are forbidden (*Validation + resolver in same session* — collapses critic and resolver, refused).
+
+The orthogonality is the test the abstraction passed. Earlier drafts considered collapsing role into mode, or deriving engagement from mode; both attempts produced coupling that broke real session shapes.
+
+---
+
+## Persona
+
+A persona declares **who is speaking** in a session — voice, methodology, and capability sources. Personas are first-class canon objects, versioned, retrievable by URI.
+
+### Persona profile shape
+
+```yaml
+persona: oddie
+version: 1
+system_prompt_uri: klappy://canon/voice/oddie-the-river-guide
+role_default: detection-only
+mcp_servers:
+ operational: # always-on for this persona, regardless of task
+ - oddkit
+ task_relevant: # added per invocation based on task
+ []
+knowledge_bases:
+ - klappy://
+surface_profiles:
+ real_time_stream: { density: high, max_tokens_per_emission: 60 }
+ audit: { density: medium, structured_output: required }
+ mentorship: { density: low, narrative: true }
+ strategic_translation:{ density: medium, bidirectional: true }
+brand_discipline_uri: klappy://canon/voice/oddie-the-river-guide#brand-guide
+inheritance:
+ - klappy://canon/constraints/guide-posture
+ - klappy://canon/constraints/ai-voice-cliches
+retraction_conditions: klappy://canon/voice/oddie-the-river-guide#retraction-conditions
+```
+
+### Operational vs task-relevant MCP servers
+
+A persona uses some MCP servers **on itself** for self-hygiene (e.g., Oddie uses `oddkit` for orient / search / challenge / gate to maintain his own epistemic discipline). Those are operational and always-on for that persona. Other MCP servers are task-relevant and added per invocation based on the task's needs (e.g., a GitHub MCP for an audit on a PR).
+
+The runtime MUST NOT strip operational MCP servers as "unrelated to the task." Doing so breaks personas like Oddie that use the methodology on themselves, not just on content.
+
+### Persona resolution
+
+`runtime.invoke(persona="oddie", mode="validation", role="detection-only", surface="audit", engagement="agent", task="...")` triggers the runtime to:
+
+1. Resolve `persona="oddie"` to the profile via canon URI lookup.
+2. Compose the system prompt from the profile's `system_prompt_uri` plus mode-specific scaffolding plus surface-specific scaffolding.
+3. Register operational MCP servers from the profile.
+4. Filter the requested tool set against mode + role allow-lists.
+5. Apply surface-profile output rules and brand-discipline post-processing per the profile.
+
+New personas are added by writing a profile, not by writing infrastructure.
+
+---
+
+## Mode
+
+The four canonical epistemic modes from `klappy://canon/epistemic-modes` map directly to runtime configurations. Each mode constrains tool allow-list, output schema, transition rules, and the primary risk the runtime watches for.
+
+### Exploration
+
+- **Truth condition** (canon): valid if it reveals something new.
+- **Tool allow-list**: search, fetch, orient, challenge, web-search, oddkit query tools. Read-heavy.
+- **Forbidden**: artifact-mutating tools (commit, PR creation, canon edits) — the session cannot accidentally cross into execution.
+- **Output schema**: emissions tagged `question | possibility | tension | frame | synthesis-ledger-entry`. The runtime can require an output-kind field per emission.
+- **Risk detector**: false closure. If the session emits more `decision` or `recommendation` outputs than `question` or `tension`, the runtime flags premature convergence.
+- **Output destination**: synthesis ledgers (`klappy://docs/synthesis-ledger`) are the natural durable surface.
+
+### Planning
+
+- **Truth condition** (canon): valid if assumptions are visible and challengeable.
+- **Tool allow-list**: search, fetch, orient, challenge, gate, encode (drafting), preflight. Reads plus draft-write to scratch only.
+- **Forbidden**: mutations to real artifacts (canon, code, deployed config).
+- **Output schema**: every plan emission MUST declare `assumptions: [...]`, `deferred: [...]`, `would_invalidate: [...]`. A plan emitted without these is rejected as incomplete per the canon's "assumptions visible and challengeable" truth condition.
+- **Risk detector**: speculative certainty. Outputs phrased as facts where the underlying claim is unverified — the runtime can ask the agent to mark uncertainty explicitly.
+
+### Execution
+
+- **Truth condition** (canon): valid if it produces verifiable outcomes.
+- **Tool allow-list**: full set, scoped at session start, **locked**. Cannot expand mid-session.
+- **Forbidden**: tool calls outside the locked scope. Mode reversion to planning is allowed but requires explicit reversion declaration.
+- **Output schema**: artifacts and evidence. Status emissions classified `assertion | reversion | tool_call_request | progress`. For `engagement=agent`, clarifying questions are refused per bottleneck-respect canon. For `engagement=assistant`, clarifying questions are valid turn-yielding emissions.
+- **Risk detector**: metric laundering. The runtime can require artifact references in completion claims.
+- **Anti-pattern detector**: per `klappy://canon/epistemic-modes` §Non-Collapse Rule, "execution must not pretend to validate." Mid-build pivot emissions get flagged: note the concern, carry forward, do not surface as inline pivot.
+
+### Validation
+
+- **Truth condition** (canon): valid if findings are grounded in the produced artifact, not in what the validator wished had been built.
+- **Required**: fresh context. The runtime refuses same-session transitions from `execution` to `validation`. Validation requires a new session that receives the artifact-under-test as input but does not inherit the executor's reasoning. This realizes `klappy://canon/principles/verification-requires-fresh-context` as a structural feature.
+- **Tool allow-list**: read-only on the artifact under test, plus search / fetch / audit / oddkit-validate.
+- **Forbidden**: mutations to the artifact under test. Findings are reports, not patches.
+- **Output schema**: each finding MUST carry a disposition — `fix | pivot | accept`. A finding without disposition is rejected as incomplete per the canon.
+- **Risk detector**: scope creep. Findings that propose redesign rather than report defects are flagged. The validation session does not get to reopen planning; that requires explicit reversion.
+
+### Mode-collapse anti-patterns become runtime detectors
+
+`klappy://canon/epistemic-modes` §Non-Collapse Rule names six specific anti-patterns. Each maps to a runtime check:
+
+1. *Exploration pretending to decide* → premature-closure detector in exploration mode.
+2. *Planning pretending to execute* → mutation-attempt detector in planning mode (refused at submit time).
+3. *Execution exploring alternatives retroactively* → scope-violation detector when tool calls fall outside the locked allow-list.
+4. *Execution pretending to validate* → mid-build pivot detector — flag and instruct "note concern, carry forward."
+5. *Validation pretending to plan* → redesign-instead-of-finding detector — flag and refuse.
+6. *Validation pretending to execute* → mutation-attempt detector in validation mode (refused at submit time).
+
+Most resolve to schema-level rules and tool allow-lists. Sophistication is not required.
+
+---
+
+## Role
+
+Role declares the **corruption boundary** the session respects. Three values, derived from `klappy://canon/constraints/critic-cannot-be-resolver`.
+
+### detection-only
+
+The session detects and reports. It does not mutate the artifact-under-observation. The runtime enforces this structurally:
+
+- **Tool filter**: filesystem writes, `git commit`, mutating API verbs (POST/PATCH/DELETE/PUT to write endpoints), `gh pr merge`, and any other state-modifying operations are refused at submit time. Refused before the session starts, not by prompt instruction.
+- **Session-to-session boundary**: the same session cannot be re-invoked with a "now fix what you found" follow-up task. Resolution requires a fresh session that receives the finding as input but not the detector's reasoning. This is `critic-cannot-be-resolver` made architectural.
+
+The audit gate is the worked detection-only consumer. Oddie is detection-only across all his surfaces by canon (`klappy://canon/voice/oddie-the-river-guide` §What Oddie Is Not).
+
+### resolver
+
+The session is permitted to mutate artifacts within the session's locked scope. Mutating tools are allowed. Resolver sessions cannot also serve as their own validators — validation of a resolver's output requires a separate session per the fresh-context rule.
+
+### general
+
+No special role enforcement. Used for sessions that are neither pure detection nor pure resolution — exploration, planning, mentorship, strategic translation, and other dialogue-heavy sessions where the role distinction is not load-bearing.
+
+---
+
+## Surface
+
+Surface declares the **output context** — who consumes the emission and at what density / pace / verbosity tolerance. Surfaces are persona-relative; a persona profile lists the surfaces it supports and the configuration for each.
+
+Common surface types and their characteristics:
+
+- **`real-time-stream`** — high density, continuous machine-speed inflow, brevity paramount, single-sentence emissions or short bursts. Agent engagement only (no caller dialogue at this density).
+- **`audit`** — medium density, batch delivery, structured output (findings + disposition), tolerates moderate detail.
+- **`sidebar-chat`** — medium density, conversational pace, narrative tolerated, assistant engagement only (the surface IS the dialogue).
+- **`mentorship`** — low density, conversational, narrative is the point, assistant engagement preferred.
... diff truncated: showing 542 of 743 linesYou can send follow-ups to the cloud agent here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: TSV column misalignment from extra tab separator
- Removed the extra empty field between typeName and quality_score in all 8 data rows so each row now has 8 tab-delimited fields matching the header.
Preview (ba8cc10fd2)
diff --git a/canon/constraints/mode-transitions-require-encoded-handoff.md b/canon/constraints/mode-transitions-require-encoded-handoff.md
new file mode 100644
--- /dev/null
+++ b/canon/constraints/mode-transitions-require-encoded-handoff.md
@@ -1,0 +1,196 @@
+---
+uri: klappy://canon/constraints/mode-transitions-require-encoded-handoff
+title: "Mode Transitions Require Encoded Handoff — Every Gate Demands a Durable Artifact"
+audience: canon
+exposure: nav
+tier: 1
+voice: neutral
+stability: evolving
+tags: ["canon", "constraints", "epistemic-modes", "handoff-contract", "journal", "dolcheo", "session-discipline", "mode-discipline", "encoding"]
+epoch: E0008.5
+date: 2026-05-10
+derives_from: "canon/principles/sessions-mirror-modes.md, canon/definitions/epistemic-modes.md, canon/constraints/critic-cannot-be-resolver.md, canon/principles/verification-requires-fresh-context.md"
+complements: "canon/methods/persona-shaped-agent-runtime.md, docs/mode-separated-conversations.md, docs/oddkit/proactive/oldc-h-vocabulary.md"
+governs: "Every transition between epistemic modes — exploration, planning, execution, validation, resolution — across all surfaces (agent runtime, human conversation, mixed teams)"
+status: proposed
+---
+
+# Mode Transitions Require Encoded Handoff — Every Gate Demands a Durable Artifact
+
+> A mode transition without a durable handoff is mode collapse with extra steps. The receiving session has no grounded artifact to read; it has only the working memory of the prior session, transmitted informally. That is exactly what session-per-mode discipline forbids. This constraint operationalizes [Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes) by requiring two things at every transition between epistemic modes: a journal entry recording the transition, and a transition-specific minimal handoff artifact. The journal is universal and applies to every transition without exception. The handoff content varies by transition. Both are required before the next mode's session can legitimately begin.
+
+---
+
+## The Two Required Artifacts
+
+Every legitimate transition between epistemic modes produces two artifacts:
+
+### 1. Journal Entry — Universal, No Exception
+
+Every transition produces a journal entry recording what happened. The format is DOLCHEO+H per [the canonical vocabulary](klappy://docs/oddkit/proactive/oldc-h-vocabulary): observations, learnings, decisions, constraints, encodes, handoffs. The journal entry captures:
+
+- The mode transition itself (from → to, with timestamp)
+- What was completed in the prior mode (obligations met)
+- What is being deferred or carried forward
+- Any reversion or skip, with explicit acknowledgment
+- The handoff artifact reference (URI or path)
+
+Journal entries are append-only durable records. They live in the project's ledger or equivalent canon-adjacent location. They do not replace the handoff artifact described below; they complement it. The journal is for the project's longitudinal memory; the handoff is for the next session's working context.
+
+This requirement admits no exceptions. Even transitions between modes whose obligations are minimal — exploration to planning, where neither produces a heavy artifact — produce a journal entry. Even transitions during PoC-scope work produce a journal entry. The journal is the audit trail that allows future work to trust the history.
+
+### 2. Transition-Specific Minimal Handoff
+
+Each transition has a minimum required handoff content beyond the journal. The receiving session reads this handoff, not the prior session's working memory. The minimal contents are:
+
+| Transition | Minimal Handoff |
+|---|---|
+| **Exploration → Planning** | Encoded synthesis of possibilities, tensions, unknowns, and competing frames surfaced during exploration. Stored as a synthesis ledger entry, research artifact, or equivalent durable encoding. The planner reads the synthesis; they do not inherit the explorer's session state. |
+| **Planning → Execution (build)** | A plan declaring: explicit assumptions, scope (what is in and out), deferred items, and conditions that would invalidate the plan. The builder reads the plan; they do not inherit the planner's reasoning beyond what is captured. |
+| **Execution → Validation** | The artifact itself plus an explicit claims declaration — what the artifact does, what it does not do, what scope it was built against. The validator reads the claims and the artifact; they do not inherit the builder's intent beyond what is declared. |
+| **Validation → Resolution** | Findings with explicit dispositions (fix, pivot, accept) per the validation mode's obligations. Each finding includes evidence grounded in the produced artifact. The resolver reads the findings; they do not inherit the validator's framing beyond what is captured. |
+| **Resolution → Validation (re-validation)** | The revised artifact plus a remediation summary per finding (what was changed, what was not changed and why). The re-validating session reads the revised artifact and the remediation summary; they do not inherit the resolver's reasoning beyond what is captured. |
+
+These are minimums. A handoff can include more — supporting evidence, screenshots, traces, alternative framings considered and rejected — but it cannot include less. A handoff that does not contain its minimum content is incomplete; the next session cannot legitimately begin until the handoff is complete.
+
+---
+
+## Why "Encoded" Is the Operative Word
+
+The handoff must be encoded — written down in a form the next session can read independently of any human or agent who participated in the prior session. Verbal handoffs, working-memory carry-over, and "I'll explain when you get there" patterns are not encoded handoffs. They are mode collapse with extra steps.
+
+The encoding requirement serves three purposes:
+
+**Independence.** The next session can begin without coordinating with the prior session. The handoff artifact is sufficient input. This is what makes session-per-mode discipline operationally feasible — a fresh planner can read the synthesis ledger and start planning without scheduling a conversation with the explorer.
+
+**Durability.** The handoff outlives both sessions. If a question arises later about why a plan made a specific assumption, the synthesis ledger that the plan was based on is still readable. The audit trail is preserved.
+
+**Falsifiability.** An encoded handoff can be reviewed for completeness. A working-memory handoff cannot — there is no way to check whether anything important was lost in the transition because there is no record of what was supposed to transfer. Encoding makes the handoff inspectable.
+
+---
+
+## Reversion and Skip Are Allowed With Acknowledgment
+
+This constraint does not forbid reversion or skip. It requires that both be encoded.
+
+**Reversion** — returning to an earlier mode — produces a journal entry naming the reversion and its cause. The originally received handoff remains valid for future re-attempts; nothing is destroyed. The reversion entry acknowledges that the prior mode's obligations were not met sufficiently to proceed, and reframes the work back into that mode.
+
+**Skip** — moving to a later mode without satisfying the intermediate one — produces a journal entry naming the skip and the explicit acknowledgment. Skipping validation, for example, is allowed when the artifact is throwaway and the cost of skipping is accepted. The acknowledgment must be explicit and durable, and the skipped mode's risks are inherited by the project.
+
+Both reversion and skip require the journal entry. Neither is a free move. The discipline is not that work always proceeds linearly through five modes; the discipline is that every deviation from linear progress is acknowledged in a durable record.
+
+---
+
+## Operator Override — Explicit Mode Collapse Under Urgency
+
+A third escape mechanism, distinct from reversion and skip. An operator can declare a runtime override that collapses one or more mode boundaries into a single session — typically when urgency outweighs the cost of corruption. Like reversion and skip, the override requires explicit acknowledgment and a durable record.
+
+### What an Override Is
+
+A runtime-level declaration by the human operator that one or more mode boundaries will be deliberately collapsed for the current session. The operator names the collapse, states the reason, and acknowledges the corruption being accepted. The runtime records the override in the journal at session start, applies relaxed constraints for the session's duration, and records the actual work done in the journal at session end.
+
+This differs from skip: a skip declares that a mode will not be entered at all. An override declares that multiple modes will be collapsed into a single session — work happens, but without the gate boundaries between modes. The corruption mode is also different: a skip means the mode's signal is missing entirely; an override means the mode's signal is produced under conditions that compromise its quality.
+
+### What an Override Requires
+
+- **Explicit declaration.** Override cannot be implicit. The operator names which boundaries are being collapsed: *"collapse exploration through validation in this session"* or *"collapse all five modes in this session."*
+- **Stated reason.** Why urgency outweighs discipline. The reason need not be elaborate but must be specific enough to be auditable later — *"production incident; we need a working patch in the next thirty minutes"* is sufficient. *"In a hurry"* alone is not.
+- **Acknowledged risks.** The operator names the corruption modes being accepted. For an override that collapses execution and validation, this is *"the validator will share context with the builder, and findings will be biased toward what the builder's framing made visible."*
+- **Journal entry at session start** naming all of the above.
+- **Journal entry at session end** naming what actually happened — what was built, what was validated under the override, what was skipped, what tradeoffs materialized in practice.
+
+### What an Override Is Not
+
+- Not the `general` role escape hatch. The general role is a planned escape declared at persona-profile authoring time. The operator override is a reactive escape declared at session-invocation time. Different declaration point, different audit trail.
+- Not transferable. An override applies only to the session it was declared for. Subsequent sessions do not inherit the override; if the urgency persists across sessions, each session gets its own override declaration.
+- Not absolute. The operator can override gate transitions but cannot override the journal entry requirement itself. The override is the journal-worthy event; the journal entry is what makes the corruption visible later.
+- Not a free pass for routine convenience. The override is for genuine urgency — production incidents, time-bounded operational decisions, situations where the cost of waiting exceeds the cost of corrupted signal. An override invoked routinely degrades the project's epistemic record over time.
+
+### The Cost
+
+An override produces a session whose epistemic record is corrupted by design. Future work that depends on this session's output should be aware of the corruption. The journal entry serves this purpose — downstream readers can see that the session was operator-overridden and apply appropriate skepticism to the outputs.
+
+The discipline of recording the override is what allows the corruption to be visible later. A session that collapsed modes silently produces unfalsifiable history. A session that collapsed modes with a recorded override produces history that *knows* it is corrupted, which is recoverable.
+
+The override is therefore not a violation of this constraint. It is a third permitted deviation, treated identically to reversion and skip: allowed with explicit acknowledgment, accompanied by a durable record, and accountable to its costs.
+
+---
+
+## Operational Enforcement
+
+This constraint is enforceable at three layers:
+
+**Agent runtime.** A runtime that hosts agent sessions per [Persona-Shaped Agent Runtime](klappy://canon/methods/persona-shaped-agent-runtime) can require a handoff URI and a journal entry reference as inputs to any session whose role is downstream of another role. Sessions invoked without complete handoff inputs are refused. This makes the constraint structural rather than dependent on agent discipline.
+
+**Human workflow tooling.** PR templates, design-doc templates, ticket workflows, and similar can require handoff fields before transitioning a unit of work to its next mode. The tooling does not enforce the *quality* of the handoff (the encoded synthesis might be sparse), but it enforces the *existence* of one.
+
+**Conversational surfaces.** Chat-based interfaces, pair-programming sessions, and design reviews enforce this constraint through explicit gating language: "okay, before we move from planning to building, let's encode the plan." The discipline is harder to mechanize at this layer and easier to violate; the mitigation is participant awareness and operator-as-bottleneck framing.
+
+The runtime layer is where this constraint is most cleanly enforced. The conversational layer is where it is most often violated and most consequential when violated, because conversations naturally flow across mode boundaries without ceremony.
+
+---
+
+## What This Constraint Does Not Require
+
+It does not require that the handoff be exhaustive. The minimums above are minimums; the goal is sufficient encoding to allow a fresh session to begin, not perfect documentation. A planner who declares three explicit assumptions, defines scope in two paragraphs, and notes one invalidating condition has met the minimum, even if a richer plan would have been better.
+
+It does not require that the handoff be authored by the prior session's primary agent. An explorer can ask a side-task to draft the synthesis ledger; a builder can ask another agent to write the claims declaration. The encoding requirement is about the artifact existing in durable form, not about who produced it.
+
+It does not require that every project use these specific role names. The mapping is to epistemic modes, which are canonical. Projects that use different vocabulary (research → spec → implementation → review → fix, for example) are still bound by this constraint, with the role names mapped to the canonical modes.
+
+It does not require that the receiving session never communicate with the prior session's participants. Q&A about ambiguities in the handoff is permitted. The constraint is that the handoff itself is the primary input — a question to the prior session's author is a clarification, not a substitute for the encoded artifact.
+
+---
+
+## Conversational Mode Should Feel Seamless — But Underneath Is Discipline
+
+Operators may object that this constraint is incompatible with chat-based work, where the cognitive flow naturally moves from "let's explore this" through "okay let's plan it" through "I'm building" without ceremony.
+
+The constraint is not that the *human experience* must feel like five separate conversations. The constraint is that the *epistemic record* must reflect five separate sessions when five modes were crossed. The two are reconciled by orchestration: a chat-facing surface can spawn fresh sessions per mode in the background, write encoded handoffs at each transition, and present a unified conversation to the human user. The user sees continuity; the system records discipline.
+
+This is a consumer pattern, not a runtime feature, and it is documented separately. See [Mode-Separated Conversations](klappy://docs/mode-separated-conversations) for the conversational application of mode discipline. The principle here is that the handoff requirement does not relax for conversational surfaces; it just gets handled by orchestration rather than by the human noticing each transition.
+
+---
+
+## Handoff Quality Is a Separate Discipline
+
+This constraint codifies the *requirement* for encoded handoffs at every transition. It does not codify *quality*, and cannot. A handoff that satisfies the minimum content requirement above can still be insufficient — shallow encoding, lossy capture of dynamic context, missing the unwritten-but-obvious knowledge the prior session held implicitly. The constraint ensures the artifact exists; it does not ensure the artifact is good.
+
+This is a meaningful gap. Per [Sessions Mirror Modes §Failure Modes](klappy://canon/principles/sessions-mirror-modes), the architecture's cost only pays back when handoffs preserve what would naturally transfer in shared sessions. Bad handoffs produce sessions operating on distorted input — worse than the mode-collapse the architecture was meant to replace. The constraint can require presence; the project's encoding norms have to deliver quality.
+
+Three specific places this gap matters:
+
+- **Minimum-met-but-thin handoffs** pass this constraint's check but fail the principle's purpose. Format-correct, content-poor. The constraint cannot detect this; downstream review and audit-trail patterns can.
+- **Missing dynamic types** are the most common failure — settled decisions get encoded, live tensions and considered-rejected paths do not. The minimum-handoff list above does not require encoding these explicitly; projects that find their handoffs routinely losing dynamic context should extend their local handoff norms to require it.
+- **Missing crucial context that felt obvious to the encoder** is the highest-cost failure. The encoder had it; they did not write it down because encoding it felt like overhead. The receiving session in fresh context does not have it. The constraint's minimum cannot anticipate which context will feel obvious; this gap closes only through observed failures and norm refinement.
+
+The constraint's role here is operational: it makes encoding the work, surfaces gaps when receiving sessions cannot proceed, and preserves audit trails of insufficient handoffs. It does not — and cannot — guarantee the encoding captures what matters. That is upstream of any constraint, in the encoding norms a project develops over time.
+
+A receiving session that cannot proceed on a handoff has the right to refuse with a structured signal — *"this handoff is insufficient; specifically X is missing"* — distinct from disagreement with the handoff's content. The runtime can support this signal as a first-class outcome (see [Persona-Shaped Agent Runtime](klappy://canon/methods/persona-shaped-agent-runtime)). The constraint requires the handoff exists; the runtime feature requires the receiving session can refuse it when it is not enough.
+
+---
+
+## Confidence
+
+**Working belief.** The journal-entry requirement extends an already-canonical practice (DOLCHEO+H entries on every session per [oldc-h-vocabulary](klappy://docs/oddkit/proactive/oldc-h-vocabulary)) to mode transitions specifically. The transition-specific handoff requirements extend already-canonical practice for individual transitions (P0008 for validator deliverables, plan documents for execution work, etc.) into a uniform contract.
+
+**Retraction conditions:**
+
+- If the universal journal-entry requirement produces audit-trail clutter without corresponding investigative value, the requirement narrows to specific high-stakes transitions (e.g., execution → validation) and becomes optional elsewhere.
+- If the transition-specific handoff minimums prove to over-specify in practice — projects routinely producing the minimums but finding them insufficient or excessive — the minimums are revised against observed need.
+- If conversational orchestration overhead (spawning fresh sessions, encoding handoffs invisibly) makes mode-disciplined chat surfaces too expensive to operate, the constraint is relaxed for conversational surfaces and remains binding only for explicit multi-session work.
+
+**What this constraint costs.** Visibly: more journal entries, more handoff artifacts, more orchestration when conversational surfaces want to remain chat-shaped. Invisibly: the cost of *not* having durable records when work fails or audits arise — a cost that is paid in confusion, lost context, and unfalsifiable history when the constraint is violated. The visible cost is what operators feel; the invisible cost is what makes the constraint load-bearing.
+
+---
+
+## See Also
+
+- [Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes) — the principle this constraint operationalizes
+- [Epistemic Modes](klappy://canon/epistemic-modes) — the parent canon defining the modes whose transitions this constraint governs
+- [DOLCHEO+H Vocabulary](klappy://docs/oddkit/proactive/oldc-h-vocabulary) — the journal entry format required at every transition
+- [Verification Requires Fresh Context](klappy://canon/principles/verification-requires-fresh-context) — the principle motivating the encoded handoff for execution → validation specifically
+- [Critic Cannot Be Resolver](klappy://canon/constraints/critic-cannot-be-resolver) — the constraint motivating the encoded handoff for validation → resolution specifically
+- [P0008 — Fresh-Validator Deliverable Is a DOLCHEO Ledger](klappy://docs/promotions/P0008-pr-validator-dolcheo-ledger-as-deliverable) — the operationalized handoff pattern for the validator role
+- [Persona-Shaped Agent Runtime](klappy://canon/methods/persona-shaped-agent-runtime) — the runtime architecture that enforces this constraint mechanically for agent work
+- [Mode-Separated Conversations](klappy://docs/mode-separated-conversations) — the conversational application of mode discipline
diff --git a/canon/definitions/epistemic-modes.md b/canon/definitions/epistemic-modes.md
--- a/canon/definitions/epistemic-modes.md
+++ b/canon/definitions/epistemic-modes.md
@@ -7,13 +7,13 @@
voice: neutral
stability: semi_stable
tags: ["epistemology", "decision-making", "governance"]
-epoch: E0008.3
-date: 2026-04-18
+epoch: E0008.5
+date: 2026-05-10
---
# Epistemic Modes
-> Exploration, planning, execution, and validation are not interchangeable.
+> Exploration, planning, execution, validation, and resolution are not interchangeable.
> Collapsing them produces false confidence, premature convergence, and brittle outcomes.
## Purpose
@@ -28,7 +28,7 @@
---
-## The Four Epistemic Modes
+## The Five Epistemic Modes
### 1. Exploration Mode
@@ -137,6 +137,35 @@
---
+### 5. Resolution Mode
+
+**Purpose:**
+To produce a revised artifact scoped strictly by validation findings.
+
+**Characteristics:**
+
+- Findings exist with explicit dispositions (fix, pivot, accept)
+- Scope is bounded by the findings, not by reopening planning
+- Each finding has a remediation action (or is accepted as-is)
+- The revised artifact is the deliverable; new requirements are not introduced
+
+**Truth Condition:**
+A resolution is valid if it **addresses the findings without expanding scope**.
+
+**Obligations:**
+
+- Address each finding per its disposition (fix what was marked fix; redirect what was marked pivot; document what was marked accept)
+- Do not introduce requirements the findings did not surface
+- Document remediation per finding — what was changed, what was not changed and why
+- Hand off to validation again — the resolver does not certify their own fix
+
+**Primary Risk:**
+Scope creep — using remediation as cover for redesign or for introducing changes outside the findings.
+
+For the role-and-session expression of this mode, see `klappy://canon/principles/sessions-mirror-modes`.
+
+---
+
## The Non-Collapse Rule
**Epistemic modes MUST NOT be collapsed.**
@@ -148,7 +177,10 @@
- Execution must not pretend to explore alternatives retroactively
- Execution must not pretend to validate — concerns noticed mid-build are noted and carried forward, not surfaced as inline pivots
- Validation must not pretend to plan — redesign requires explicit reversion
-- Validation must not pretend to execute — fixes belong to iteration, which is a fresh execution pass scoped by validation findings
+- Validation must not pretend to execute or resolve — findings produce a separate resolution pass, not inline fixes during the same review
+- Resolution must not pretend to plan — new requirements that emerge during remediation require explicit reversion to planning
+- Resolution must not pretend to validate — the resolver does not certify their own fix; re-validation is a separate session
+- Resolution must not pretend to be a fresh execution — its scope is bounded by findings, not by the original plan
When modes are collapsed:
@@ -175,6 +207,10 @@
For practical guidance on mode transitions in conversation, see **Mode-Separated Conversations**.
+For the principle that each mode earns its own session, see [Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes).
+
+For the binding rule that every transition requires a journal entry plus a transition-specific durable handoff artifact, see [Mode Transitions Require Encoded Handoff](klappy://canon/constraints/mode-transitions-require-encoded-handoff).
+
---
## Legitimacy of Inaction
diff --git a/canon/methods/persona-shaped-agent-runtime.md b/canon/methods/persona-shaped-agent-runtime.md
new file mode 100644
--- /dev/null
+++ b/canon/methods/persona-shaped-agent-runtime.md
@@ -1,0 +1,469 @@
+---
+uri: klappy://canon/methods/persona-shaped-agent-runtime
+title: "Persona-Shaped Agent Runtime — Building a Reusable Substrate for Many Personas"
+audience: canon
+exposure: nav
+tier: 1
+voice: neutral
+stability: evolving
+tags: ["canon", "methods", "agent-runtime", "persona-profile", "substrate", "vodka-architecture", "oddie", "spawned-agent-session", "role-enforcement", "surface-profile"]
+epoch: E0008.5
+date: 2026-05-10
+derives_from: "canon/methods/spawned-agent-session-substrate-options.md, canon/principles/sessions-mirror-modes.md, canon/constraints/mode-transitions-require-encoded-handoff.md, canon/constraints/critic-cannot-be-resolver.md, canon/principles/verification-requires-fresh-context.md, canon/voice/oddie-the-river-guide.md, canon/principles/vodka-architecture.md"
+complements: "canon/principles/methodology-personification.md, canon/principles/voice-as-cognitive-load-shedding.md, canon/principles/participation-replaces-integration.md"
+governs: "Any service that hosts spawned agent sessions on behalf of multiple consumers and multiple personas"
+status: proposed
+---
+
+# Persona-Shaped Agent Runtime — Building a Reusable Substrate for Many Personas
+
+> A spawned-agent-session substrate (CF Sandboxes, Anthropic Managed Agents, etc.) hosts one session at a time. A *runtime* sits on top of a substrate and turns it into a service: many consumers can call it with many tasks, and the substrate stays opinion-free underneath. This method documents how to shape that runtime so it composes with **personas as first-class objects** — Oddie, an audit reviewer, a release validator, a docs mentor — without coupling the runtime to any specific persona's identity or any specific consumer's workflow. The pattern keeps the substrate vodka, makes critic-cannot-be-resolver mechanically enforceable, and turns voice canon into something the runtime honors automatically rather than something the agent inside has to remember.
+
+---
+
+## What This Document Is
+
+A design pattern for the layer that sits between a spawned-agent-session substrate and the consumers who want agent help. Companion to [Spawned Agent Session Substrate Options](klappy://canon/methods/spawned-agent-session-substrate-options): that doc catalogs *where* to host a session; this doc describes *how to build a service on top* so the same substrate serves many callers and many personas without each pair re-implementing infrastructure.
+
+This is a method, not a decision. It documents the shape; it does not lock in implementation specifics. Specific runtime instances (the audit gate, a TinCan-Oddie deployment, a docs mentor service) are decisions that consume this method.
+
+---
+
+## The Pattern
+
+A spawned-agent-session substrate gives you one capability: spin up an agent in an isolated context, hand it a task, get a result. That capability is generic. Every consumer that wants agent help would otherwise wire it themselves: prompt assembly, tool registration, MCP setup, secret injection, output parsing, surface-specific formatting. The wiring is repetitive. It also smuggles opinions into the substrate (which prompt? which tools? which output schema?), violating vodka-architecture at the substrate layer.
+
+The runtime resolves this by hosting the wiring at a layer above the substrate:
+
+```
+┌────────────────────────────────────────────────────────────────┐
+│ Consumers: audit gate │ slack bot │ cron │ TinCan │ ... │
+│ (each one knows: "invoke this persona, this task") │
+├────────────────────────────────────────────────────────────────┤
+│ Runtime: persona resolution │ role enforcement │ │
+│ surface post-processing │ session lifecycle │
+├────────────────────────────────────────────────────────────────┤
+│ Substrate: CF Sandbox │ Managed Agents │ Daytona │ ... │
+│ (just spawns isolated sessions) │
+└────────────────────────────────────────────────────────────────┘
+```
+
+The runtime accepts requests of the form *"invoke persona P on surface S for task T,"* resolves P to operational configuration, dispatches to the substrate, post-processes the output per S, and returns. Personas are canon objects. Surfaces are constraints. The substrate stays generic. The consumer stays simple.
+
+---
+
+## The Persona Profile
+
+A persona profile is a structured description of who an agent is, what it can do, and how its output is constrained. Profiles are themselves canon — versioned, URI-addressable, governed by the same rules as any other canon doc.
+
+### What a Profile Contains
+
+A profile bundles:
+
+| Field | Purpose |
+|---|---|
+| `system_prompt_uri` | The voice canon or role specification. The runtime fetches this and passes it to the agent. |
+| `role` | One of `detection-only`, `resolver`, `general`. Drives tool filtering and session lifecycle rules. |
+| `mcp_servers.operational` | MCPs the persona requires to *be* itself, regardless of task. (Oddie needs oddkit always.) |
+| `mcp_servers.task_relevant` | MCPs added per invocation based on the specific task. (A PR audit gets the GitHub MCP.) |
+| `knowledge_bases` | URIs the persona can ground observations against (`klappy://`, `ams://`, etc.). |
+| `surface_profiles` | Per-surface constraints: density caps, output format, narrative-vs-structured, max tokens per emission. |
+| `brand_discipline` | URI pointing at the persona's voice canon section that governs emoji, vocabulary, machine-vs-human surface rules. |
+
+### Illustrative Sketch
+
+```yaml
+persona: oddie
+version: 1
+system_prompt_uri: klappy://canon/voice/oddie-the-river-guide
+role: detection-only
+mcp_servers:
+ operational: [oddkit]
+ task_relevant: []
+knowledge_bases:
+ - klappy://
+ - ams://
+surface_profiles:
+ real_time_stream: { density: high, max_tokens_per_emission: 60 }
+ audit: { density: medium, structured_output: required }
+ mentorship: { density: low, narrative: true }
+ strategic_translation: { density: medium, bidirectional: true }
+brand_discipline: klappy://canon/voice/oddie-the-river-guide#brand-guide
+```
+
+The schema is illustrative. Specific field names, validation rules, and serialization format are implementation choices. The principle is that a persona's identity is captured in a structured artifact that the runtime can resolve to operational configuration.
+
+### Where Profiles Live
+
+Two reasonable options:
+
+1. **The voice canon doc is the profile.** Structured fields go in the YAML frontmatter; narrative goes in the prose body. Single source of truth.
+2. **Profiles are separate canon docs** (e.g., `klappy://personas/oddie`) that reference the voice canon for narrative. Cleaner separation; two-doc maintenance.
+
+Either approach is consistent with this method. The choice belongs to the operator authoring the first profile.
+
+---
+
+## The Runtime's Job
+
+The runtime accepts an invocation, resolves a profile, executes against a substrate, and post-processes the result. Five responsibilities specifically:
+
+### 1. Resolve Profile to Operational Configuration
+
+`runtime.invoke(persona="oddie", surface="audit", task="...")` triggers:
+
+- Fetch the persona profile by name and version.
+- Fetch the system prompt at `system_prompt_uri`.
+- Compose the operational MCP set (always-on) with the per-invocation task-relevant MCPs.
+- Apply the named surface profile's constraints.
+- Hand the assembled config to the substrate.
+
+The runtime is the only component that knows how to assemble these pieces. Consumers do not. New consumers can be added without touching profile-resolution logic.
+
+### 2. Enforce Role at Submit Time
+
+Two parallel constraints need architectural enforcement, drawn from two parent canon docs:
+
+- [Critic Cannot Be Resolver](klappy://canon/constraints/critic-cannot-be-resolver) — detection and remediation must be separated by a *tool boundary*. A session that detects cannot also mutate.
+- [Verification Requires Fresh Context](klappy://canon/principles/verification-requires-fresh-context) — creation and validation must be separated by a *context boundary*. A session that validates cannot inherit the creator's accumulated reasoning.
+
+Generalized to all mode transitions per [Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes), every transition between epistemic modes is a context boundary deserving a fresh session. The runtime enforces the boundaries through five mode-bound roles plus an escape hatch.
+
+#### The Five Mode-Bound Roles
+
+Each role corresponds to one of the five canonical [epistemic modes](klappy://canon/epistemic-modes). The role declares the session's mode; the runtime enforces the role's constraints structurally.
+
+**`explorer`** — operates in exploration mode. Tool set is broad (read-only access to canon, web search, conversational tools, hypothesis-shaping tools); state-mutation tools are refused. Output is a synthesis ledger or research artifact per the [encoded-handoff constraint](klappy://canon/constraints/mode-transitions-require-encoded-handoff). Fresh-context requirement is light — explorers can build on prior exploration but should not inherit planning-context.
+
+**`planner`** — operates in planning mode. Tool set is read-oriented (canon access, prior synthesis ledgers, plan-shaping tools); state-mutation tools are refused. Output is a plan declaring assumptions, scope, deferred items, and invalidating conditions. Fresh-context requirement: must not inherit explorer-session state directly; reads the explorer's encoded synthesis as input. The plan is the durable handoff to the builder.
+
+**`builder`** — operates in execution mode. Tool set includes mutating tools (filesystem writes, git commits, API calls, etc.) bounded by the plan's declared scope. Output is the produced artifact plus a claims declaration (what the artifact does, what it does not do, what scope it was built against). Fresh-context requirement: must not inherit planner-session state; reads the plan as input. The artifact plus claims is the durable handoff to the validator.
+
+**`validator`** — operates in validation mode. Tool set is restricted to a read-only allow-list. Mutating actions are refused before the substrate is invoked. Fresh-context requirement is *strict*: the runtime guarantees the validation session is spawned with no inputs from the caller other than the persona profile, the artifact reference, the claims declaration, and the governance documents. No prior conversation, no handoff context beyond the encoded artifact-and-claims, no "we discussed X earlier" framing. Output is structured findings with explicit dispositions (fix, pivot, accept) per finding, consistent with [P0008](klappy://docs/promotions/P0008-pr-validator-dolcheo-ledger-as-deliverable). The findings are the durable handoff to the resolver (or, if all findings are accepted, the validation session is the terminal session).
+
+**`resolver`** — operates in resolution mode. Tool set includes mutating tools, but bounded by the validator's findings. The runtime can validate that mutations stay within finding-scope when the implementation supports it; at minimum, the resolver session is briefed that scope is bounded. Fresh-context requirement: must not inherit validator-session state; reads the findings as input. Output is the revised artifact plus a remediation summary per finding (what was changed, what was not changed and why). The revised artifact is the durable handoff back to a fresh validator session for re-validation.
+
+#### Escape Hatch and Observer Sessions
+
+**`general`** — no mode-binding, no fresh-context guarantee, no structured-deliverable requirement. Used for personas that intentionally combine modes in workflows where the context-corruption risk is acceptable. Mode-collapsed sessions are a deliberate choice to trade signal quality for throughput; the runtime supports them but does not pretend the constraints are met. PoC-scope work that explicitly skips modes (per the [encoded-handoff constraint](klappy://canon/constraints/mode-transitions-require-encoded-handoff)'s skip provision) is the canonical use case.
+
+**Observer sessions.** Some sessions do not fit the five-mode taxonomy because they do not produce artifacts that hand off to a next mode — they are continuous observers, emitting commentary on streams produced elsewhere. Oddie's real-time stream interpretation surface is the worked example. These sessions are configured with the `subscribed` session type (see §5 below), a tool restriction (typically read-only), and no mode-bound role declaration. They are not gate-bounded work; the encoded-handoff constraint does not apply because there are no transitions to encode.
+
+#### Constraints Are Composable
+
+The named roles bundle (tool filter × fresh-context requirement × deliverable shape × mode binding) in their canonical configurations. The underlying parameters are composable. A persona profile can declare a custom role configuration if the named roles do not fit — e.g., a "drafting" role that combines builder-role tools with explorer-role context-freshness for early-stage artifact work. Named roles are recommended for legibility; custom configurations are supported for cases the named roles undersolve.
+
+#### Universal Handoff Requirement
+
+Per [Mode Transitions Require Encoded Handoff](klappy://canon/constraints/mode-transitions-require-encoded-handoff), every transition between mode-bound roles requires a journal entry plus a transition-specific minimal handoff artifact. The runtime enforces this by requiring handoff URI inputs on any session whose role is downstream of another role. Sessions invoked without complete handoff inputs are refused. The journal entry is universal; the runtime can require it as a side-effect of any mode-bound session's completion.
+
+### 3. Apply Surface-Profile Output Post-Processing
+
+The runtime tags every output field as `machine` (parsed by code) or `human` (read by people). Surface profiles constrain what reaches each tag:
+
+- **Persona emoji stripped from machine fields.** If the voice canon bans 🦦 in JSON / YAML / commit messages / status titles / URIs, the runtime enforces that ban at output time, not at prompt time. The agent inside can speak naturally; the runtime cleans before delivery.
+- **Density caps applied.** If a `real_time_stream` surface declares `max_tokens_per_emission: 60`, an emission that exceeds the cap fails validation and the runtime requests a shorter retry. Brevity-under-pressure becomes structural.
+- **Format contracts honored.** If `structured_output: required`, the runtime parses fenced JSON from the agent's response and rejects free-form text. If `narrative: true`, prose is expected and structure is optional.
+
+Voice and brand are mechanically enforceable at this layer. The agent does not have to police itself; the runtime does.
+
+### 4. Honor Mode Toggles
+
+Personas have voice modes — `persona`, `neutral`, `strict` — declared per invocation:
+
+- **persona**: full voice canon applies (signature emoji, vocabulary, register).
+- **neutral**: persona emoji and vocabulary suppressed; functional status emoji (✅ ⚠️ 🔴) survive because they carry information rather than character.
+- **strict**: even functional emoji minimized; output is purely text. Useful for environments that strip emoji entirely (parser-sensitive contexts, accessibility-first surfaces).
+
+The mode is a runtime parameter, applied uniformly across all output fields. The agent inside does not need to know which mode is active.
+
+### 5. Support Session Types
+
+Two session shapes cover known use cases:
+
+- **`one_shot`**: invoke, return, tear down. Audit gates, on-demand reviews, doc-generation tasks. Single output.
+- **`subscribed`**: long-lived, connected to an event source, emits over time. The TinCan flagship case for Oddie. Real-time stream interpretation, scheduled monitoring, persistent observers.
+
+A subscribed session needs: connection management, multi-output channels (per-channel post-processing), backpressure handling for when stream rate exceeds interpretation rate, and a teardown signal. The audit-gate use case does not need any of this. The runtime should support both without requiring `subscribed` consumers to use `one_shot` machinery or vice versa.
+
+---
+
+### 6. Honor the Engagement Contract
+
+Sessions invoke the runtime under one of two engagement modes — *assistant* or *agent* — and the runtime enforces different turn-control and bottleneck-respect contracts for each. This dimension is orthogonal to mode, role, and surface. The same persona in the same mode and role can be invoked under either engagement; what changes is who controls the turn and how the session terminates.
+
+**`assistant`** — turn-based dialogue with the caller. The session emits a response and yields turn-control back to the caller. Clarifying questions are valid output. State persists across turns. The caller's attention is in the loop; the session paces itself to that. Pair-programming surfaces, sidebar chat, mentorship interactions, and any conversational use case are typically assistant-engagement.
+
+**`agent`** — autonomous run-to-completion. The session does not yield turn-control until the task is complete or a named failure terminates it. Clarifying questions are forbidden per [Mode Discipline and Bottleneck Respect](klappy://canon/constraints/mode-discipline-and-bottleneck-respect) — they pull the bottleneck (caller's attention) into work the caller was not in the loop for. The runtime wraps any clarifying-question emission as a named failure rather than a valid output. Stuck or under-specified sessions terminate with the failure named, allowing the caller to fix the input and retry rather than respond to mid-flight questions. Audit gates, scheduled jobs, fan-out workers, and any background dispatch are typically agent-engagement.
+
+The distinction matters because the caller's consent to interruption differs. An assistant session implies *"I will be here to answer questions when they come up."* An agent session implies *"I have given you everything you need; come back when you have a result or a clean failure."* Conflating the two corrupts both: assistant-shaped agents produce output the caller didn't ask for; agent-shaped assistants accumulate questions the caller never sees.
+
+The engagement field is part of the session-invocation parameter set:
+
+```
+runtime.invoke(
+ persona="oddie",
+ role="validator",
+ surface="audit",
+ engagement="agent", # autonomous; no clarifying questions
+ task="..."
+)
+```
+
+Most consumer patterns map cleanly: scheduled audits are `agent`; sidebar Q&A is `assistant`; pair-programming with an assistant persona is `assistant`. A few patterns are rare-but-legitimate: planning under `agent` engagement (autonomous canonical planning when the planner-persona has enough context to produce a complete plan without dialogue) is allowed but requires the persona to be confident the input is complete. The runtime supports the rare combinations; consumers choose which to use.
+
+---
+
+### 7. Support Parallelism and Operator Override
+
+Two patterns the runtime needs to handle that are orthogonal to role enforcement: concurrent sessions in the same mode, and operator-declared mode collapse for urgency.
+
+#### Parallelism
+
+Per [Sessions Mirror Modes §Parallelism Patterns](klappy://canon/principles/sessions-mirror-modes), the runtime supports three of four parallelism patterns:
+
+- **Within-mode fan-out.** Multiple sessions of the same role spawned concurrently — multiple explorers on different angles, multiple validators with different lenses, multiple builders on independent scope. The runtime spawns N concurrent sessions; the consumer is responsible for fan-in (consolidating outputs into a single encoded handoff for the next mode).
+- **Multi-participant single session.** Multiple agents collaborating within one role-bound session, sharing context, producing a joint deliverable. The runtime treats this as one session with multiple participant identities. The session is bound to one mode; participants share the mode's tool restrictions.
+- **Cross-mode parallelism on different artifacts.** Independent work streams running concurrently. The runtime spawns and tracks them independently; no coordination is required because the streams do not share artifacts.
+
+The runtime *refuses* the fourth pattern: cross-mode sessions on the same artifact. A validator session cannot be invoked on an artifact whose builder session has not yet produced an encoded handoff (artifact + claims declaration). This is enforced at submit time — the runtime checks the artifact's handoff state before accepting a downstream-role invocation.
+
+Fan-in is a consumer concern, not a runtime feature. The runtime spawns parallel sessions and returns their outputs; consolidating those outputs into a single handoff for the next mode is the consumer's job. The runtime can support this with conventions (e.g., a fan-in helper that takes N session outputs and produces a consolidated DOLCHEO ledger), but the conventions are layered above the core runtime.
+
+#### Operator Override
+
+Per [Mode Transitions Require Encoded Handoff §Operator Override](klappy://canon/constraints/mode-transitions-require-encoded-handoff), the runtime accepts an explicit override declaration that collapses mode boundaries into a single session. Sketched:
+
+```
+runtime.invoke(persona="...", task="...", override={
+ type: "operator_collapsed_modes",
+ modes_collapsed: ["exploration", "planning", "execution", "validation"],
+ reason: "production incident — patch needed in 30 min",
+ acknowledged_risks: [
+ "validator shares context with builder; findings biased toward what builder framing surfaced",
+ "no fresh planning context; speculative certainty propagates into build",
+ "no fresh exploration; tensions not surfaced before convergence"
+ ]
+})
+```
+
+When an override is present, the runtime:
+
+1. **Records a journal entry at session start** naming the override, modes collapsed, reason, and acknowledged risks.
+2. **Relaxes role enforcement** for the collapsed modes. Tool sets are unioned; fresh-context guarantees are suspended for the collapsed transitions.
+3. **Records a journal entry at session end** naming what actually happened — work performed, decisions made, tradeoffs that materialized.
+4. **Tags the session's outputs as override-produced** in any downstream metadata, so consumers can see that subsequent work was built on overridden-session output and apply appropriate skepticism.
+
+The override is *not* the same as the `general` role escape hatch. The general role is a persona-profile-level declaration that some sessions of this persona never had the constraints in the first place. The override is a runtime-invocation-level declaration that this specific session has the constraints temporarily suspended for declared reasons. Both produce relaxed sessions; the audit trail is different, and the override's audit trail names the urgency-driven choice explicitly.
+
+The runtime cannot override the journal entry requirement itself. The override is a journal-worthy event; the journal entry is what makes the corruption visible later. A runtime that allowed override sessions to skip journaling would be silently undoing the constraint's audit-trail purpose.
+
+#### What Conversational-Mode Orchestration Looks Like
+
+The principle's note that "in conversational mode this should feel seamless" is a consumer pattern that composes parallelism and override support with session-spawning. A chat-facing consumer that wants to present unified continuity to a human user while respecting session-per-mode discipline orchestrates the runtime as follows:
+
+- Detects mode transitions in the conversation (the human signals "okay let's plan it" or "start building").
+- Spawns a fresh role-bound session at each transition, with the prior session's encoded handoff as input.
+- Presents the new session's output as continuation of the conversation.
+- Records journal entries at each transition invisibly to the human.
... diff truncated: showing 564 of 1406 linesYou can send follow-ups to the cloud agent here.
…ntract draft) + journals Two runtime method docs preserved here for operator review and reconciliation: DOC 1 (recommended canonical): canon/methods/persona-shaped-agent-runtime.md Tier 1, proposed. Reflects operator's session-per-mode guidance from 2026-05-10 conversation. Five mode-bound roles (explorer, planner, builder, validator, resolver) plus general escape hatch and observer carve-out. Derives from sessions-mirror-modes principle and mode-transitions-require-encoded-handoff constraint (PR C). DOC 2 (prior iteration, draft): canon/methods/spawned-agent-session-runtime-contract.md Tier 2, draft. Five-orthogonal-dimensions framing (persona, mode, role, surface, engagement) from prior compacted session. Introduces 'engagement' dimension (assistant vs agent — turn-based dialogue vs autonomous run-to-completion) that is genuinely orthogonal and missing from doc 1. Worth folding forward, or keeping as sibling, per operator decision. JOURNALS: - 2026-05-10-spawned-agent-runtime-and-five-dimension-contract.tsv (prior session's DOLCHEO entries) - 2026-05-10-runtime-canon-divergence.tsv (this PR's entries — flags the two-doc situation, names engagement as the worth-preserving insight, recommends persona-shaped as canonical) DEPENDS ON: - PR #185 (substrate canon) — references klappy://canon/methods/spawned-agent-session-substrate-options - PR #186 (mode-discipline canon) — references klappy://canon/principles/sessions-mirror-modes and klappy://canon/constraints/mode-transitions-require-encoded-handoff OPERATOR ACTION REQUIRED: Pick one runtime doc as canonical, OR reconcile the two before merge. Recommend persona-shaped as canonical with engagement dimension folded in.
…persona-shaped runtime Adds three sections to canon/methods/persona-shaped-agent-runtime addressing gaps surfaced during continued architectural pressure-testing: §6 Honor the Engagement Contract — folds in the engagement dimension (assistant vs agent) from the parallel runtime-contract draft. Distinguishes turn-based dialogue (clarifying questions valid; bottleneck in the loop) from autonomous run-to-completion (clarifying questions wrapped as named failures per bottleneck-respect canon). The engagement field is orthogonal to mode, role, and surface — same persona at same mode/role can be invoked under either engagement contract. §7 Support Parallelism and Operator Override — articulates which parallelism patterns the runtime supports and which it refuses, derived from the parallelism-patterns section in canon/principles/sessions-mirror-modes. Within-mode fan-out is encouraged, multi-participant single sessions are allowed within a mode, cross-mode parallelism on different artifacts is independent. Cross-mode on the same artifact is the only forbidden pattern and is enforced at submit time. Operator override mechanism is sketched as a runtime-invocation parameter that records journal entries at start and end, relaxes role enforcement for declared-collapsed transitions, and tags downstream metadata. Conversational-mode orchestration is framed as a consumer pattern, not a runtime feature. Net: +84 lines, no changes to existing sections. Resolves the engagement-dimension gap noted in the runtime-canon-divergence journal entry. Operator decision still pending on whether to keep runtime-contract.md as a draft sibling or supersede it now that engagement content has been folded into the persona-shaped doc.
… Resolution as 5th mode New Tier-1 docs: - canon/principles/sessions-mirror-modes.md — generalizes critic-cannot-be-resolver and verification-requires-fresh-context across all five mode transitions; names five mode-bound roles (explorer/planner/builder/validator/resolver); includes parallelism patterns and a substantive failure-modes section on handoff quality. - canon/constraints/mode-transitions-require-encoded-handoff.md — every transition requires a journal entry plus a transition-specific minimal handoff; reversion, skip, and operator override are three permitted deviations with explicit acknowledgment; handoff quality is upstream of any constraint feature. Patch: - canon/definitions/epistemic-modes.md — adds Resolution as fifth canonical mode (canonical implication made explicit per the existing 'fixes belong to iteration, which is a fresh execution pass scoped by validation findings' line); extends Non-Collapse Rule with three resolution-specific invalid moves; bumps date to 2026-05-10 and epoch to E0008.5. Update: - canon/methods/persona-shaped-agent-runtime.md — new §8 Support Handoff-Insufficiency Signaling: runtime addresses the failure mode by accepting a structured 'handoff_insufficient' outcome with named missing items and a proposed_resolution. The runtime requires presence (encoded-handoff constraint); receiving sessions judge sufficiency at runtime. Type-system / runtime-validation pattern. Journal: - journal/2026-05-10-sessions-mirror-modes-and-encoded-handoff-canon.tsv — 4 D, 1 L, 1 C, 1 O, 1 H. Operator-driven additions this round: 1. 'planner should not be the executor' generalized into Sessions Mirror Modes 2. 'two roles and purpose' — abstracted principle + guiding constraint as doc pair 3. 'encoding journal repeated for every transition without exception' 4. operator override use case for urgency 5. simultaneous agents/assistants — parallelism patterns 6. failure modes — when handoff quality fails, exclusive sessions cost more than they pay back
…ride use case Runtime-contract reconciliation: - canon/methods/spawned-agent-session-runtime-contract.md updated to align with sessions-mirror-modes principle. Mode dimension expanded from 4 to 5 values (added 'resolution'). Role dimension rewritten with five mode-bound roles (explorer/planner/builder/validator/resolver) plus 'general' (escape hatch) and 'observer' (non-mode-bound continuous observation). New Mode sub-section for Resolution with truth condition, tool allow-list, output schema, and risk detector. Mode-collapse anti-patterns extended from 6 to 9 with three resolution-specific items. Composition Rules forbidden combinations expanded to include validator-resolution and resolution-revalidation same-session refusals plus cross-mode parallelism on same artifact. Well-trodden combinations table updated with new role names and a new governance-author entry showing the worked-override case. Governance-creation as override use case: - canon/constraints/mode-transitions-require-encoded-handoff.md gets a new §Worked Use Cases section naming two categories where override is operationally legitimate: production incidents (urgency-driven) and governance creation (oscillation-driven). Includes the recursive observation that this canon set was itself drafted under override because the explorer-planner-builder-validator-resolver oscillation moved faster than handoff norms could yet capture. Names the operator's aspiration: with mature handoff norms and forced same-branch work, clean sessions become transient/ephemeral/transparent — but reaching that state requires contact with reality, which only comes through observed failures of the current handoff norms. Journal: - journal/2026-05-10-runtime-contract-reconciliation-and-governance-override.tsv records 2 D, 1 L, 1 O, 1 C, 1 H.
Same surgical fixes as PR #190 applied to this branch's working copies of the two affected files, so the bug is gone here too and rebase-time conflict resolution is unambiguous. - canon/constraints/mode-transitions-require-encoded-handoff.md: 3x DOLCHEO+H -> DOLCHEO, 3x dead-URI links to klappy://docs/oddkit/proactive/oldc-h-vocabulary -> klappy://canon/definitions/dolcheo-vocabulary, frontmatter complement fixed, artifact ordering corrected and 'opens' added. - writings/reverse-engineer-the-future.md line 256: DOLCHEO+H artifacts -> DOLCHEO artifacts.
5ce1923 to
ae7b887
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: TSV column alignment shifted by extra tab character
- Removed the extra tab between typeName and quality_score in all six data rows so each row has 8 tab-separated fields aligning with the header.
Preview (22a2e7a468)
diff --git a/canon/constraints/mode-transitions-require-encoded-handoff.md b/canon/constraints/mode-transitions-require-encoded-handoff.md
--- a/canon/constraints/mode-transitions-require-encoded-handoff.md
+++ b/canon/constraints/mode-transitions-require-encoded-handoff.md
@@ -10,7 +10,7 @@
epoch: E0008.5
date: 2026-05-10
derives_from: "canon/principles/sessions-mirror-modes.md, canon/definitions/epistemic-modes.md, canon/constraints/critic-cannot-be-resolver.md, canon/principles/verification-requires-fresh-context.md"
-complements: "canon/methods/persona-shaped-agent-runtime.md, docs/mode-separated-conversations.md, docs/oddkit/proactive/oldc-h-vocabulary.md"
+complements: "canon/methods/persona-shaped-agent-runtime.md, docs/mode-separated-conversations.md, canon/definitions/dolcheo-vocabulary.md"
governs: "Every transition between epistemic modes — exploration, planning, execution, validation, resolution — across all surfaces (agent runtime, human conversation, mixed teams)"
status: proposed
---
@@ -27,7 +27,7 @@
### 1. Journal Entry — Universal, No Exception
-Every transition produces a journal entry recording what happened. The format is DOLCHEO+H per [the canonical vocabulary](klappy://docs/oddkit/proactive/oldc-h-vocabulary): observations, learnings, decisions, constraints, encodes, handoffs. The journal entry captures:
+Every transition produces a journal entry recording what happened. The format is DOLCHEO per [the canonical vocabulary](klappy://canon/definitions/dolcheo-vocabulary): decisions, observations, learnings, constraints, handoffs, encodes, opens. The journal entry captures:
- The mode transition itself (from → to, with timestamp)
- What was completed in the prior mode (obligations met)
@@ -81,6 +81,53 @@
---
+## Operator Override — Explicit Mode Collapse Under Urgency
+
+A third escape mechanism, distinct from reversion and skip. An operator can declare a runtime override that collapses one or more mode boundaries into a single session — typically when urgency outweighs the cost of corruption. Like reversion and skip, the override requires explicit acknowledgment and a durable record.
+
+### What an Override Is
+
+A runtime-level declaration by the human operator that one or more mode boundaries will be deliberately collapsed for the current session. The operator names the collapse, states the reason, and acknowledges the corruption being accepted. The runtime records the override in the journal at session start, applies relaxed constraints for the session's duration, and records the actual work done in the journal at session end.
+
+This differs from skip: a skip declares that a mode will not be entered at all. An override declares that multiple modes will be collapsed into a single session — work happens, but without the gate boundaries between modes. The corruption mode is also different: a skip means the mode's signal is missing entirely; an override means the mode's signal is produced under conditions that compromise its quality.
+
+### What an Override Requires
+
+- **Explicit declaration.** Override cannot be implicit. The operator names which boundaries are being collapsed: *"collapse exploration through validation in this session"* or *"collapse all five modes in this session."*
+- **Stated reason.** Why urgency outweighs discipline. The reason need not be elaborate but must be specific enough to be auditable later — *"production incident; we need a working patch in the next thirty minutes"* is sufficient. *"In a hurry"* alone is not.
+- **Acknowledged risks.** The operator names the corruption modes being accepted. For an override that collapses execution and validation, this is *"the validator will share context with the builder, and findings will be biased toward what the builder's framing made visible."*
+- **Journal entry at session start** naming all of the above.
+- **Journal entry at session end** naming what actually happened — what was built, what was validated under the override, what was skipped, what tradeoffs materialized in practice.
+
+### Worked Use Cases — When the Override Earns Its Keep
+
+Two categories where operator override is operationally legitimate, not a degradation of discipline:
+
+**Production incidents.** A bug landed in production; the patch needs to ship in the next thirty minutes. The cost of moving through five clean sessions with handoffs at each gate exceeds the cost of context corruption — production downtime is not an acceptable tradeoff for epistemic hygiene at this moment. The operator declares the override, names the incident, acknowledges that the validator will share context with the builder, and accepts the corruption. The journal entries make the corruption visible later, so any code shipped under override gets flagged for proper post-incident review.
+
+**Governance creation.** Authoring canonical principles, constraints, and methods is inherently oscillating work. A draft principle implies a constraint; drafting the constraint surfaces a refinement to the principle; the refinement reveals an unexamined assumption that needs an exploration pass. The work moves between modes faster than handoff norms can encode. Until handoff norms catch up — until a project has been through enough governance-creation cycles to know which dynamic types its synthesis ledgers must capture — this category may regularly justify override. The signal is not that discipline is being abandoned; the signal is that the encoding norms are still maturing. An override-with-record produces governance with full audit trail of *how the governance was made*; clean sessions with poor handoffs would produce governance whose drafting context died at every gate.
+
+The honest framing: the architecture's value depends on handoffs being good enough to preserve what would have transferred in shared context. For categories of work where the encoding norms are still being learned, override-with-record is the correct operational response — not a permanent retreat, but a stopgap until norms catch up. The aspiration is that with explicit handoffs and forced same-branch work, encoding eventually becomes detailed enough that clean sessions become *transient, ephemeral, and transparent to the operator* — but reaching that state requires contact with reality, including the experience of trying and failing to encode well.
+
+This use case is itself a worked example: this constraint document was drafted in a single collapsed session under operator-acknowledged override, because the explorer-planner-builder-validator-resolver oscillation was faster than the handoff norms could yet capture. The journal entries record the override; future iterations will improve the handoff norms; eventually governance creation may be doable in clean sessions. Until then, override is the rational choice.
+
+### What an Override Is Not
+
+- Not the `general` role escape hatch. The general role is a planned escape declared at persona-profile authoring time. The operator override is a reactive escape declared at session-invocation time. Different declaration point, different audit trail.
+- Not transferable. An override applies only to the session it was declared for. Subsequent sessions do not inherit the override; if the urgency persists across sessions, each session gets its own override declaration.
+- Not absolute. The operator can override gate transitions but cannot override the journal entry requirement itself. The override is the journal-worthy event; the journal entry is what makes the corruption visible later.
+- Not a free pass for routine convenience. The override is for genuine urgency — production incidents, time-bounded operational decisions, situations where the cost of waiting exceeds the cost of corrupted signal. An override invoked routinely degrades the project's epistemic record over time.
+
+### The Cost
+
+An override produces a session whose epistemic record is corrupted by design. Future work that depends on this session's output should be aware of the corruption. The journal entry serves this purpose — downstream readers can see that the session was operator-overridden and apply appropriate skepticism to the outputs.
+
+The discipline of recording the override is what allows the corruption to be visible later. A session that collapsed modes silently produces unfalsifiable history. A session that collapsed modes with a recorded override produces history that *knows* it is corrupted, which is recoverable.
+
+The override is therefore not a violation of this constraint. It is a third permitted deviation, treated identically to reversion and skip: allowed with explicit acknowledgment, accompanied by a durable record, and accountable to its costs.
+
+---
+
## Operational Enforcement
This constraint is enforceable at three layers:
@@ -117,9 +164,27 @@
---
+## Handoff Quality Is a Separate Discipline
+
+This constraint codifies the *requirement* for encoded handoffs at every transition. It does not codify *quality*, and cannot. A handoff that satisfies the minimum content requirement above can still be insufficient — shallow encoding, lossy capture of dynamic context, missing the unwritten-but-obvious knowledge the prior session held implicitly. The constraint ensures the artifact exists; it does not ensure the artifact is good.
+
+This is a meaningful gap. Per [Sessions Mirror Modes §Failure Modes](klappy://canon/principles/sessions-mirror-modes), the architecture's cost only pays back when handoffs preserve what would naturally transfer in shared sessions. Bad handoffs produce sessions operating on distorted input — worse than the mode-collapse the architecture was meant to replace. The constraint can require presence; the project's encoding norms have to deliver quality.
+
+Three specific places this gap matters:
+
+- **Minimum-met-but-thin handoffs** pass this constraint's check but fail the principle's purpose. Format-correct, content-poor. The constraint cannot detect this; downstream review and audit-trail patterns can.
+- **Missing dynamic types** are the most common failure — settled decisions get encoded, live tensions and considered-rejected paths do not. The minimum-handoff list above does not require encoding these explicitly; projects that find their handoffs routinely losing dynamic context should extend their local handoff norms to require it.
+- **Missing crucial context that felt obvious to the encoder** is the highest-cost failure. The encoder had it; they did not write it down because encoding it felt like overhead. The receiving session in fresh context does not have it. The constraint's minimum cannot anticipate which context will feel obvious; this gap closes only through observed failures and norm refinement.
+
+The constraint's role here is operational: it makes encoding the work, surfaces gaps when receiving sessions cannot proceed, and preserves audit trails of insufficient handoffs. It does not — and cannot — guarantee the encoding captures what matters. That is upstream of any constraint, in the encoding norms a project develops over time.
+
+A receiving session that cannot proceed on a handoff has the right to refuse with a structured signal — *"this handoff is insufficient; specifically X is missing"* — distinct from disagreement with the handoff's content. The runtime can support this signal as a first-class outcome (see [Persona-Shaped Agent Runtime](klappy://canon/methods/persona-shaped-agent-runtime)). The constraint requires the handoff exists; the runtime feature requires the receiving session can refuse it when it is not enough.
+
+---
+
## Confidence
-**Working belief.** The journal-entry requirement extends an already-canonical practice (DOLCHEO+H entries on every session per [oldc-h-vocabulary](klappy://docs/oddkit/proactive/oldc-h-vocabulary)) to mode transitions specifically. The transition-specific handoff requirements extend already-canonical practice for individual transitions (P0008 for validator deliverables, plan documents for execution work, etc.) into a uniform contract.
+**Working belief.** The journal-entry requirement extends an already-canonical practice (DOLCHEO entries on every session per [the dolcheo-vocabulary](klappy://canon/definitions/dolcheo-vocabulary)) to mode transitions specifically. The transition-specific handoff requirements extend already-canonical practice for individual transitions (P0008 for validator deliverables, plan documents for execution work, etc.) into a uniform contract.
**Retraction conditions:**
@@ -135,7 +200,7 @@
- [Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes) — the principle this constraint operationalizes
- [Epistemic Modes](klappy://canon/epistemic-modes) — the parent canon defining the modes whose transitions this constraint governs
-- [DOLCHEO+H Vocabulary](klappy://docs/oddkit/proactive/oldc-h-vocabulary) — the journal entry format required at every transition
+- [DOLCHEO Vocabulary](klappy://canon/definitions/dolcheo-vocabulary) — the journal entry format required at every transition
- [Verification Requires Fresh Context](klappy://canon/principles/verification-requires-fresh-context) — the principle motivating the encoded handoff for execution → validation specifically
- [Critic Cannot Be Resolver](klappy://canon/constraints/critic-cannot-be-resolver) — the constraint motivating the encoded handoff for validation → resolution specifically
- [P0008 — Fresh-Validator Deliverable Is a DOLCHEO Ledger](klappy://docs/promotions/P0008-pr-validator-dolcheo-ledger-as-deliverable) — the operationalized handoff pattern for the validator role
diff --git a/canon/definitions/epistemic-modes.md b/canon/definitions/epistemic-modes.md
--- a/canon/definitions/epistemic-modes.md
+++ b/canon/definitions/epistemic-modes.md
@@ -7,8 +7,8 @@
voice: neutral
stability: semi_stable
tags: ["epistemology", "decision-making", "governance"]
-epoch: E0008.3
-date: 2026-04-18
+epoch: E0008.5
+date: 2026-05-10
---
# Epistemic Modes
@@ -207,6 +207,10 @@
For practical guidance on mode transitions in conversation, see **Mode-Separated Conversations**.
+For the principle that each mode earns its own session, see [Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes).
+
+For the binding rule that every transition requires a journal entry plus a transition-specific durable handoff artifact, see [Mode Transitions Require Encoded Handoff](klappy://canon/constraints/mode-transitions-require-encoded-handoff).
+
---
## Legitimacy of Inaction
diff --git a/canon/methods/persona-shaped-agent-runtime.md b/canon/methods/persona-shaped-agent-runtime.md
new file mode 100644
--- /dev/null
+++ b/canon/methods/persona-shaped-agent-runtime.md
@@ -1,0 +1,469 @@
+---
+uri: klappy://canon/methods/persona-shaped-agent-runtime
+title: "Persona-Shaped Agent Runtime — Building a Reusable Substrate for Many Personas"
+audience: canon
+exposure: nav
+tier: 1
+voice: neutral
+stability: evolving
+tags: ["canon", "methods", "agent-runtime", "persona-profile", "substrate", "vodka-architecture", "oddie", "spawned-agent-session", "role-enforcement", "surface-profile"]
+epoch: E0008.5
+date: 2026-05-10
+derives_from: "canon/methods/spawned-agent-session-substrate-options.md, canon/principles/sessions-mirror-modes.md, canon/constraints/mode-transitions-require-encoded-handoff.md, canon/constraints/critic-cannot-be-resolver.md, canon/principles/verification-requires-fresh-context.md, canon/voice/oddie-the-river-guide.md, canon/principles/vodka-architecture.md"
+complements: "canon/principles/methodology-personification.md, canon/principles/voice-as-cognitive-load-shedding.md, canon/principles/participation-replaces-integration.md"
+governs: "Any service that hosts spawned agent sessions on behalf of multiple consumers and multiple personas"
+status: proposed
+---
+
+# Persona-Shaped Agent Runtime — Building a Reusable Substrate for Many Personas
+
+> A spawned-agent-session substrate (CF Sandboxes, Anthropic Managed Agents, etc.) hosts one session at a time. A *runtime* sits on top of a substrate and turns it into a service: many consumers can call it with many tasks, and the substrate stays opinion-free underneath. This method documents how to shape that runtime so it composes with **personas as first-class objects** — Oddie, an audit reviewer, a release validator, a docs mentor — without coupling the runtime to any specific persona's identity or any specific consumer's workflow. The pattern keeps the substrate vodka, makes critic-cannot-be-resolver mechanically enforceable, and turns voice canon into something the runtime honors automatically rather than something the agent inside has to remember.
+
+---
+
+## What This Document Is
+
+A design pattern for the layer that sits between a spawned-agent-session substrate and the consumers who want agent help. Companion to [Spawned Agent Session Substrate Options](klappy://canon/methods/spawned-agent-session-substrate-options): that doc catalogs *where* to host a session; this doc describes *how to build a service on top* so the same substrate serves many callers and many personas without each pair re-implementing infrastructure.
+
+This is a method, not a decision. It documents the shape; it does not lock in implementation specifics. Specific runtime instances (the audit gate, a TinCan-Oddie deployment, a docs mentor service) are decisions that consume this method.
+
+---
+
+## The Pattern
+
+A spawned-agent-session substrate gives you one capability: spin up an agent in an isolated context, hand it a task, get a result. That capability is generic. Every consumer that wants agent help would otherwise wire it themselves: prompt assembly, tool registration, MCP setup, secret injection, output parsing, surface-specific formatting. The wiring is repetitive. It also smuggles opinions into the substrate (which prompt? which tools? which output schema?), violating vodka-architecture at the substrate layer.
+
+The runtime resolves this by hosting the wiring at a layer above the substrate:
+
+```
+┌────────────────────────────────────────────────────────────────┐
+│ Consumers: audit gate │ slack bot │ cron │ TinCan │ ... │
+│ (each one knows: "invoke this persona, this task") │
+├────────────────────────────────────────────────────────────────┤
+│ Runtime: persona resolution │ role enforcement │ │
+│ surface post-processing │ session lifecycle │
+├────────────────────────────────────────────────────────────────┤
+│ Substrate: CF Sandbox │ Managed Agents │ Daytona │ ... │
+│ (just spawns isolated sessions) │
+└────────────────────────────────────────────────────────────────┘
+```
+
+The runtime accepts requests of the form *"invoke persona P on surface S for task T,"* resolves P to operational configuration, dispatches to the substrate, post-processes the output per S, and returns. Personas are canon objects. Surfaces are constraints. The substrate stays generic. The consumer stays simple.
+
+---
+
+## The Persona Profile
+
+A persona profile is a structured description of who an agent is, what it can do, and how its output is constrained. Profiles are themselves canon — versioned, URI-addressable, governed by the same rules as any other canon doc.
+
+### What a Profile Contains
+
+A profile bundles:
+
+| Field | Purpose |
+|---|---|
+| `system_prompt_uri` | The voice canon or role specification. The runtime fetches this and passes it to the agent. |
+| `role` | One of `detection-only`, `resolver`, `general`. Drives tool filtering and session lifecycle rules. |
+| `mcp_servers.operational` | MCPs the persona requires to *be* itself, regardless of task. (Oddie needs oddkit always.) |
+| `mcp_servers.task_relevant` | MCPs added per invocation based on the specific task. (A PR audit gets the GitHub MCP.) |
+| `knowledge_bases` | URIs the persona can ground observations against (`klappy://`, `ams://`, etc.). |
+| `surface_profiles` | Per-surface constraints: density caps, output format, narrative-vs-structured, max tokens per emission. |
+| `brand_discipline` | URI pointing at the persona's voice canon section that governs emoji, vocabulary, machine-vs-human surface rules. |
+
+### Illustrative Sketch
+
+```yaml
+persona: oddie
+version: 1
+system_prompt_uri: klappy://canon/voice/oddie-the-river-guide
+role: detection-only
+mcp_servers:
+ operational: [oddkit]
+ task_relevant: []
+knowledge_bases:
+ - klappy://
+ - ams://
+surface_profiles:
+ real_time_stream: { density: high, max_tokens_per_emission: 60 }
+ audit: { density: medium, structured_output: required }
+ mentorship: { density: low, narrative: true }
+ strategic_translation: { density: medium, bidirectional: true }
+brand_discipline: klappy://canon/voice/oddie-the-river-guide#brand-guide
+```
+
+The schema is illustrative. Specific field names, validation rules, and serialization format are implementation choices. The principle is that a persona's identity is captured in a structured artifact that the runtime can resolve to operational configuration.
+
+### Where Profiles Live
+
+Two reasonable options:
+
+1. **The voice canon doc is the profile.** Structured fields go in the YAML frontmatter; narrative goes in the prose body. Single source of truth.
+2. **Profiles are separate canon docs** (e.g., `klappy://personas/oddie`) that reference the voice canon for narrative. Cleaner separation; two-doc maintenance.
+
+Either approach is consistent with this method. The choice belongs to the operator authoring the first profile.
+
+---
+
+## The Runtime's Job
+
+The runtime accepts an invocation, resolves a profile, executes against a substrate, and post-processes the result. Five responsibilities specifically:
+
+### 1. Resolve Profile to Operational Configuration
+
+`runtime.invoke(persona="oddie", surface="audit", task="...")` triggers:
+
+- Fetch the persona profile by name and version.
+- Fetch the system prompt at `system_prompt_uri`.
+- Compose the operational MCP set (always-on) with the per-invocation task-relevant MCPs.
+- Apply the named surface profile's constraints.
+- Hand the assembled config to the substrate.
+
+The runtime is the only component that knows how to assemble these pieces. Consumers do not. New consumers can be added without touching profile-resolution logic.
+
+### 2. Enforce Role at Submit Time
+
+Two parallel constraints need architectural enforcement, drawn from two parent canon docs:
+
+- [Critic Cannot Be Resolver](klappy://canon/constraints/critic-cannot-be-resolver) — detection and remediation must be separated by a *tool boundary*. A session that detects cannot also mutate.
+- [Verification Requires Fresh Context](klappy://canon/principles/verification-requires-fresh-context) — creation and validation must be separated by a *context boundary*. A session that validates cannot inherit the creator's accumulated reasoning.
+
+Generalized to all mode transitions per [Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes), every transition between epistemic modes is a context boundary deserving a fresh session. The runtime enforces the boundaries through five mode-bound roles plus an escape hatch.
+
+#### The Five Mode-Bound Roles
+
+Each role corresponds to one of the five canonical [epistemic modes](klappy://canon/epistemic-modes). The role declares the session's mode; the runtime enforces the role's constraints structurally.
+
+**`explorer`** — operates in exploration mode. Tool set is broad (read-only access to canon, web search, conversational tools, hypothesis-shaping tools); state-mutation tools are refused. Output is a synthesis ledger or research artifact per the [encoded-handoff constraint](klappy://canon/constraints/mode-transitions-require-encoded-handoff). Fresh-context requirement is light — explorers can build on prior exploration but should not inherit planning-context.
+
+**`planner`** — operates in planning mode. Tool set is read-oriented (canon access, prior synthesis ledgers, plan-shaping tools); state-mutation tools are refused. Output is a plan declaring assumptions, scope, deferred items, and invalidating conditions. Fresh-context requirement: must not inherit explorer-session state directly; reads the explorer's encoded synthesis as input. The plan is the durable handoff to the builder.
+
+**`builder`** — operates in execution mode. Tool set includes mutating tools (filesystem writes, git commits, API calls, etc.) bounded by the plan's declared scope. Output is the produced artifact plus a claims declaration (what the artifact does, what it does not do, what scope it was built against). Fresh-context requirement: must not inherit planner-session state; reads the plan as input. The artifact plus claims is the durable handoff to the validator.
+
+**`validator`** — operates in validation mode. Tool set is restricted to a read-only allow-list. Mutating actions are refused before the substrate is invoked. Fresh-context requirement is *strict*: the runtime guarantees the validation session is spawned with no inputs from the caller other than the persona profile, the artifact reference, the claims declaration, and the governance documents. No prior conversation, no handoff context beyond the encoded artifact-and-claims, no "we discussed X earlier" framing. Output is structured findings with explicit dispositions (fix, pivot, accept) per finding, consistent with [P0008](klappy://docs/promotions/P0008-pr-validator-dolcheo-ledger-as-deliverable). The findings are the durable handoff to the resolver (or, if all findings are accepted, the validation session is the terminal session).
+
+**`resolver`** — operates in resolution mode. Tool set includes mutating tools, but bounded by the validator's findings. The runtime can validate that mutations stay within finding-scope when the implementation supports it; at minimum, the resolver session is briefed that scope is bounded. Fresh-context requirement: must not inherit validator-session state; reads the findings as input. Output is the revised artifact plus a remediation summary per finding (what was changed, what was not changed and why). The revised artifact is the durable handoff back to a fresh validator session for re-validation.
+
+#### Escape Hatch and Observer Sessions
+
+**`general`** — no mode-binding, no fresh-context guarantee, no structured-deliverable requirement. Used for personas that intentionally combine modes in workflows where the context-corruption risk is acceptable. Mode-collapsed sessions are a deliberate choice to trade signal quality for throughput; the runtime supports them but does not pretend the constraints are met. PoC-scope work that explicitly skips modes (per the [encoded-handoff constraint](klappy://canon/constraints/mode-transitions-require-encoded-handoff)'s skip provision) is the canonical use case.
+
+**Observer sessions.** Some sessions do not fit the five-mode taxonomy because they do not produce artifacts that hand off to a next mode — they are continuous observers, emitting commentary on streams produced elsewhere. Oddie's real-time stream interpretation surface is the worked example. These sessions are configured with the `subscribed` session type (see §5 below), a tool restriction (typically read-only), and no mode-bound role declaration. They are not gate-bounded work; the encoded-handoff constraint does not apply because there are no transitions to encode.
+
+#### Constraints Are Composable
+
+The named roles bundle (tool filter × fresh-context requirement × deliverable shape × mode binding) in their canonical configurations. The underlying parameters are composable. A persona profile can declare a custom role configuration if the named roles do not fit — e.g., a "drafting" role that combines builder-role tools with explorer-role context-freshness for early-stage artifact work. Named roles are recommended for legibility; custom configurations are supported for cases the named roles undersolve.
+
+#### Universal Handoff Requirement
+
+Per [Mode Transitions Require Encoded Handoff](klappy://canon/constraints/mode-transitions-require-encoded-handoff), every transition between mode-bound roles requires a journal entry plus a transition-specific minimal handoff artifact. The runtime enforces this by requiring handoff URI inputs on any session whose role is downstream of another role. Sessions invoked without complete handoff inputs are refused. The journal entry is universal; the runtime can require it as a side-effect of any mode-bound session's completion.
+
+### 3. Apply Surface-Profile Output Post-Processing
+
+The runtime tags every output field as `machine` (parsed by code) or `human` (read by people). Surface profiles constrain what reaches each tag:
+
+- **Persona emoji stripped from machine fields.** If the voice canon bans 🦦 in JSON / YAML / commit messages / status titles / URIs, the runtime enforces that ban at output time, not at prompt time. The agent inside can speak naturally; the runtime cleans before delivery.
+- **Density caps applied.** If a `real_time_stream` surface declares `max_tokens_per_emission: 60`, an emission that exceeds the cap fails validation and the runtime requests a shorter retry. Brevity-under-pressure becomes structural.
+- **Format contracts honored.** If `structured_output: required`, the runtime parses fenced JSON from the agent's response and rejects free-form text. If `narrative: true`, prose is expected and structure is optional.
+
+Voice and brand are mechanically enforceable at this layer. The agent does not have to police itself; the runtime does.
+
+### 4. Honor Mode Toggles
+
+Personas have voice modes — `persona`, `neutral`, `strict` — declared per invocation:
+
+- **persona**: full voice canon applies (signature emoji, vocabulary, register).
+- **neutral**: persona emoji and vocabulary suppressed; functional status emoji (✅ ⚠️ 🔴) survive because they carry information rather than character.
+- **strict**: even functional emoji minimized; output is purely text. Useful for environments that strip emoji entirely (parser-sensitive contexts, accessibility-first surfaces).
+
+The mode is a runtime parameter, applied uniformly across all output fields. The agent inside does not need to know which mode is active.
+
+### 5. Support Session Types
+
+Two session shapes cover known use cases:
+
+- **`one_shot`**: invoke, return, tear down. Audit gates, on-demand reviews, doc-generation tasks. Single output.
+- **`subscribed`**: long-lived, connected to an event source, emits over time. The TinCan flagship case for Oddie. Real-time stream interpretation, scheduled monitoring, persistent observers.
+
+A subscribed session needs: connection management, multi-output channels (per-channel post-processing), backpressure handling for when stream rate exceeds interpretation rate, and a teardown signal. The audit-gate use case does not need any of this. The runtime should support both without requiring `subscribed` consumers to use `one_shot` machinery or vice versa.
+
+---
+
+### 6. Honor the Engagement Contract
+
+Sessions invoke the runtime under one of two engagement modes — *assistant* or *agent* — and the runtime enforces different turn-control and bottleneck-respect contracts for each. This dimension is orthogonal to mode, role, and surface. The same persona in the same mode and role can be invoked under either engagement; what changes is who controls the turn and how the session terminates.
+
+**`assistant`** — turn-based dialogue with the caller. The session emits a response and yields turn-control back to the caller. Clarifying questions are valid output. State persists across turns. The caller's attention is in the loop; the session paces itself to that. Pair-programming surfaces, sidebar chat, mentorship interactions, and any conversational use case are typically assistant-engagement.
+
+**`agent`** — autonomous run-to-completion. The session does not yield turn-control until the task is complete or a named failure terminates it. Clarifying questions are forbidden per [Mode Discipline and Bottleneck Respect](klappy://canon/constraints/mode-discipline-and-bottleneck-respect) — they pull the bottleneck (caller's attention) into work the caller was not in the loop for. The runtime wraps any clarifying-question emission as a named failure rather than a valid output. Stuck or under-specified sessions terminate with the failure named, allowing the caller to fix the input and retry rather than respond to mid-flight questions. Audit gates, scheduled jobs, fan-out workers, and any background dispatch are typically agent-engagement.
+
+The distinction matters because the caller's consent to interruption differs. An assistant session implies *"I will be here to answer questions when they come up."* An agent session implies *"I have given you everything you need; come back when you have a result or a clean failure."* Conflating the two corrupts both: assistant-shaped agents produce output the caller didn't ask for; agent-shaped assistants accumulate questions the caller never sees.
+
+The engagement field is part of the session-invocation parameter set:
+
+```
+runtime.invoke(
+ persona="oddie",
+ role="validator",
+ surface="audit",
+ engagement="agent", # autonomous; no clarifying questions
+ task="..."
+)
+```
+
+Most consumer patterns map cleanly: scheduled audits are `agent`; sidebar Q&A is `assistant`; pair-programming with an assistant persona is `assistant`. A few patterns are rare-but-legitimate: planning under `agent` engagement (autonomous canonical planning when the planner-persona has enough context to produce a complete plan without dialogue) is allowed but requires the persona to be confident the input is complete. The runtime supports the rare combinations; consumers choose which to use.
+
+---
+
+### 7. Support Parallelism and Operator Override
+
+Two patterns the runtime needs to handle that are orthogonal to role enforcement: concurrent sessions in the same mode, and operator-declared mode collapse for urgency.
+
+#### Parallelism
+
+Per [Sessions Mirror Modes §Parallelism Patterns](klappy://canon/principles/sessions-mirror-modes), the runtime supports three of four parallelism patterns:
+
+- **Within-mode fan-out.** Multiple sessions of the same role spawned concurrently — multiple explorers on different angles, multiple validators with different lenses, multiple builders on independent scope. The runtime spawns N concurrent sessions; the consumer is responsible for fan-in (consolidating outputs into a single encoded handoff for the next mode).
+- **Multi-participant single session.** Multiple agents collaborating within one role-bound session, sharing context, producing a joint deliverable. The runtime treats this as one session with multiple participant identities. The session is bound to one mode; participants share the mode's tool restrictions.
+- **Cross-mode parallelism on different artifacts.** Independent work streams running concurrently. The runtime spawns and tracks them independently; no coordination is required because the streams do not share artifacts.
+
+The runtime *refuses* the fourth pattern: cross-mode sessions on the same artifact. A validator session cannot be invoked on an artifact whose builder session has not yet produced an encoded handoff (artifact + claims declaration). This is enforced at submit time — the runtime checks the artifact's handoff state before accepting a downstream-role invocation.
+
+Fan-in is a consumer concern, not a runtime feature. The runtime spawns parallel sessions and returns their outputs; consolidating those outputs into a single handoff for the next mode is the consumer's job. The runtime can support this with conventions (e.g., a fan-in helper that takes N session outputs and produces a consolidated DOLCHEO ledger), but the conventions are layered above the core runtime.
+
+#### Operator Override
+
+Per [Mode Transitions Require Encoded Handoff §Operator Override](klappy://canon/constraints/mode-transitions-require-encoded-handoff), the runtime accepts an explicit override declaration that collapses mode boundaries into a single session. Sketched:
+
+```
+runtime.invoke(persona="...", task="...", override={
+ type: "operator_collapsed_modes",
+ modes_collapsed: ["exploration", "planning", "execution", "validation"],
+ reason: "production incident — patch needed in 30 min",
+ acknowledged_risks: [
+ "validator shares context with builder; findings biased toward what builder framing surfaced",
+ "no fresh planning context; speculative certainty propagates into build",
+ "no fresh exploration; tensions not surfaced before convergence"
+ ]
+})
+```
+
+When an override is present, the runtime:
+
+1. **Records a journal entry at session start** naming the override, modes collapsed, reason, and acknowledged risks.
+2. **Relaxes role enforcement** for the collapsed modes. Tool sets are unioned; fresh-context guarantees are suspended for the collapsed transitions.
+3. **Records a journal entry at session end** naming what actually happened — work performed, decisions made, tradeoffs that materialized.
+4. **Tags the session's outputs as override-produced** in any downstream metadata, so consumers can see that subsequent work was built on overridden-session output and apply appropriate skepticism.
+
+The override is *not* the same as the `general` role escape hatch. The general role is a persona-profile-level declaration that some sessions of this persona never had the constraints in the first place. The override is a runtime-invocation-level declaration that this specific session has the constraints temporarily suspended for declared reasons. Both produce relaxed sessions; the audit trail is different, and the override's audit trail names the urgency-driven choice explicitly.
+
+The runtime cannot override the journal entry requirement itself. The override is a journal-worthy event; the journal entry is what makes the corruption visible later. A runtime that allowed override sessions to skip journaling would be silently undoing the constraint's audit-trail purpose.
+
+#### What Conversational-Mode Orchestration Looks Like
+
+The principle's note that "in conversational mode this should feel seamless" is a consumer pattern that composes parallelism and override support with session-spawning. A chat-facing consumer that wants to present unified continuity to a human user while respecting session-per-mode discipline orchestrates the runtime as follows:
+
+- Detects mode transitions in the conversation (the human signals "okay let's plan it" or "start building").
+- Spawns a fresh role-bound session at each transition, with the prior session's encoded handoff as input.
+- Presents the new session's output as continuation of the conversation.
+- Records journal entries at each transition invisibly to the human.
+- Surfaces an explicit override prompt when the human wants to collapse modes ("you're asking me to skip planning and start building — do you want to declare an override, or take a moment to plan?").
+
+The runtime does not implement this orchestration; it provides the primitives the orchestrator composes. This is a consumer pattern that warrants its own canon doc once a working orchestrator exists to point at; for now it is a deferred follow-up.
+
+---
+
+### 8. Support Handoff-Insufficiency Signaling
+
+Per [Sessions Mirror Modes §Failure Modes](klappy://canon/principles/sessions-mirror-modes), the architecture's cost only pays back when handoffs preserve what would have transferred in shared sessions. The runtime cannot guarantee handoff quality — that is an encoding-norms discipline upstream of any runtime feature. But the runtime can ensure that bad handoffs are detectable and that receiving sessions can refuse to proceed on them.
+
+The runtime supports a structured "handoff insufficient" outcome distinct from a session's normal deliverable:
+
+```
+session.outcome = {
+ type: "handoff_insufficient",
+ missing: [
+ "the synthesis ledger lists three options but does not capture the tradeoff considerations",
+ "scope item 'X' is named but its boundaries are unclear",
+ "implicit assumption that {Y is true} appears load-bearing but is not declared"
+ ],
+ proposed_resolution: "request fresh upstream session" | "request clarification from upstream author" | "operator override decision"
+}
+```
+
+When a receiving session returns this outcome instead of a normal deliverable, the runtime:
+
+1. **Records the insufficiency in the journal** alongside the originating handoff URI. Audit trails accumulate; chronic insufficiency at a specific gate signals norm gaps that the project's encoding discipline should address.
+2. **Does not produce a downstream handoff.** The receiving session cannot proceed; therefore there is no handoff to the next mode. The work blocks at this gate until resolution.
+3. **Surfaces the resolution path to the consumer.** The consumer chooses among: (a) spawn a fresh upstream session with refined task scope to produce a better handoff, (b) request live clarification from the upstream session author and append the clarification to the handoff, (c) operator override declaring that the work proceeds despite the insufficient handoff.
+
+This outcome is *not* the same as "I disagree with the handoff content" or "I have findings about the handoff." Disagreement is content-level; findings have a normal disposition. Handoff insufficiency is structural — the receiving session structurally cannot do its job because the input does not contain what its mode requires.
+
+The signal is also a learning input. A project that observes its planner-role sessions routinely flagging explorer-handoffs as insufficient on a specific dimension — *"missing dynamic tensions that surfaced during exploration"* — has evidence that its synthesis-ledger encoding norms need to be extended. The runtime does not fix the norms; it surfaces the failure pattern that drives norm refinement.
+
+#### Quality vs. Presence
+
+To be explicit about what this feature does and does not do:
+
+- The runtime *requires* handoff presence per [the encoded-handoff constraint](klappy://canon/constraints/mode-transitions-require-encoded-handoff). Sessions without complete handoffs are refused at submit time.
+- The runtime *cannot validate* handoff quality before invocation. Quality is judged by the receiving session, in context, against the actual work it is being asked to do.
+- The runtime *does support* the receiving session's structured refusal when quality is insufficient. The signal is the runtime's contribution to the quality-discipline problem; the discipline itself lives in encoding norms.
+
+This is the same pattern as type-checking versus runtime validation in any system: the type system catches some classes of errors statically; runtime validation catches the rest. The encoded-handoff constraint is the type system. Handoff-insufficiency signaling is the runtime check.
+
+---
+
+## What This Method Is Not
+
+**Not orchestration.** The runtime invokes one persona per request. It does not chain personas, route between them, or maintain workflows that span multiple invocations. Orchestration belongs to consumers, not to the runtime. (A consumer can call the runtime multiple times in sequence; that is the consumer's workflow.)
+
+**Not coupling.** A persona profile does not specify *which* substrate hosts it. The same Oddie profile can run on CF Sandboxes, on Managed Agents, on Daytona, or on a local Docker container. The runtime resolves the profile and dispatches to whatever substrate is configured. Substrate choice is a runtime-deployment decision per [Spawned Agent Session Substrate Options](klappy://canon/methods/spawned-agent-session-substrate-options); persona authoring is independent.
+
+**Not a CRM for personas.** The runtime is not a directory service, identity provider, or persona-discovery layer. It resolves profiles by URI. Listing, searching, and discovering personas is a separate concern — handled by canon search, by directory pages, or by whatever tooling exists upstream.
+
+**Not a permission system.** Role enforcement is about epistemic-context separation (critic-cannot-be-resolver), not authorization. Whether a *consumer* is allowed to call the runtime is a separate question, handled at a different layer (API keys, OAuth, bearer tokens). The runtime trusts its callers; it just refuses to wire detection sessions with resolver tools.
+
+---
+
+## Prior Art
+
+This pattern is not novel as a category — agent-runtime services and persona-shaped agents are an active design space. The contribution here is the specific composition of constraints, not the existence of the pattern.
+
+Adjacent work this method is aware of:
+
+- **OpenAI Custom GPTs** and **Anthropic Projects** — persona-shaped chat surfaces with system prompts, tools, and knowledge bases. Closest in spirit to persona profiles. Differences: Custom GPTs and Projects target end-user chat surfaces, not programmatic invocation by other services; they do not architecturally enforce role-separation (critic-cannot-be-resolver is left to prompt design); brand-discipline is not mechanically enforced at output time. The runtime pattern targets multi-consumer service composition, not direct human chat.
+- **LangChain agent runtimes** and similar SDK-level abstractions — toolkit for assembling agents, often with persona-like configuration. Differences: typically embedded in the consumer's process rather than offered as a hosted service; do not enforce an explicit critic-vs-resolver context boundary; surface-aware output post-processing is left to consumers.
+- **Cloudflare Agents SDK** and the **MCP `McpAgent` pattern** — substrate-aware abstractions for hosting agents on Workers. Closer to the substrate layer than to the runtime layer described here; this method composes on top of such abstractions rather than replacing them.
+- **Anthropic Managed Agents** — the substrate captured in [Spawned Agent Session Substrate Options](klappy://canon/methods/spawned-agent-session-substrate-options). Substrate, not runtime. The runtime pattern is the layer that would sit above Managed Agents (or any other substrate) to multiplex consumers and personas.
+
+The closest prior art is probably Custom GPTs / Projects, characterized as of mid-2026. The runtime pattern's distinguishing commitments are: programmatic-first interface, mechanical role enforcement, mechanical brand discipline at output time, and explicit separation between persona authoring (canon) and runtime engineering (service).
+
+If a respected peer points to closer prior art that already names this composition, the contribution shrinks to "naming and codifying for this knowledge base" — which is still worthwhile as a vocabulary anchor but is not novel design.
+
+---
+
+## Inheritance — Why This Shape
+
+The runtime shape is not original. It is a synthesis of three commitments already canonical:
+
+**[Vodka Architecture](klappy://canon/principles/vodka-architecture)**: substrates win by refusing opinions. The substrate-options catalog stays opinion-free per that principle; this runtime stays opinion-free by pushing opinions up into persona profiles. Every layer above the substrate is removable without wire consequence.
+
+**[Sessions Mirror Modes](klappy://canon/principles/sessions-mirror-modes)**: each epistemic mode earns its own session because the structural blindness that makes a creator unable to validate their own work, a critic unable to remediate their own findings, and a planner unable to execute their own plan is the same blindness in different shapes. This runtime is the architectural expression of that principle — five mode-bound roles, each with its own session, each refusing to inherit context from prior-mode sessions.
+
+**[Mode Transitions Require Encoded Handoff](klappy://canon/constraints/mode-transitions-require-encoded-handoff)**: every gate between modes requires a journal entry plus a transition-specific durable artifact. This runtime enforces that constraint mechanically by requiring handoff URI inputs on any session whose role is downstream of another role.
+
+**[Critic Cannot Be Resolver](klappy://canon/constraints/critic-cannot-be-resolver)**: detection and remediation must be separated by a tool boundary. The runtime enforces this for the validator → resolver transition specifically, refusing mutating tools in validator sessions and requiring a fresh resolver session to act on findings.
+
+**[Verification Requires Fresh Context](klappy://canon/principles/verification-requires-fresh-context)**: a creator cannot be their own critic. The runtime enforces this for validator sessions specifically by guaranteeing fresh context — the validator session receives only the persona profile, artifact reference, claims declaration, and governance, never the creator's accumulated reasoning. The same fresh-context guarantee applies generally to every mode-bound role transition under sessions-mirror-modes.
+
+**[Participation Replaces Integration](ams://canon/principles/participation-replaces-integration)**: open substrates collapse connector topology from O(N²) to O(N). Without this runtime, every persona × consumer pair requires its own wiring. With it, N personas + M consumers needs N + M descriptors, not N × M integrations. The runtime is the participation layer that makes the collapse work for agent invocation specifically.
+
... diff truncated: showing 504 of 1195 linesYou can send follow-ups to the cloud agent here.
Reviewed by Cursor Bugbot for commit ae7b887. Configure here.
Removed extra tab between typeName and quality_score columns so all six data rows have 8 fields matching the header. Aligns format with the other journals in this PR.
…uce overlap Operator decision in PR review: keep both runtime canon docs at their distinct altitudes rather than collapsing or picking one. Persona-shape stays Tier-1 method; runtime-contract stays Tier-2 spec. Each gets a Companion Documents callout near the top making the layer split explicit, and overlap is removed in favor of cross-references with anchor links. Persona-shape changes: - Add Companion Documents section right after the blockquote summary - Update frontmatter complements to put runtime-contract sibling first - Trim the five-mode-bound-roles paragraphs to one-line summaries; delegate per-mode tool allow-lists / output schemas / risk detectors / anti-pattern detectors to runtime-contract - Trim the surface-profile post-processing section; delegate the exact rules to runtime-contract - Trim the mode-toggles section; delegate the suppression rules to runtime-contract - Trim the engagement-contract section; keep the architecture-level framing and invocation sketch, delegate the spec (turn-control markers, output kinds, failure modes, rare-but-legitimate combinations) to runtime-contract - Promote runtime-contract to top of See Also with explicit annotation Runtime-contract changes: - Add Companion Documents section right after the blockquote summary - Update frontmatter complements to put persona-shape sibling first - Remove the persona profile YAML schema; delegate to persona-shape as the canonical home of the profile shape, inheritance, and retraction conditions - Promote persona-shape to top of See Also; remove the duplicate mid-list reference Also adds journal/2026-05-10-runtime-canon-split-reconciled.tsv capturing the DOLCHEO record of this reconciliation, including a verification note that the prior PR description's claim about engagement being missing from doc 1 did not match the artifacts (engagement was already in persona-shape §6). Net: persona-shape 469 → 465 lines, runtime-contract 383 → 372 lines, with ~95 churned lines reflecting the overlap removal. Both docs remain pre-production with retraction conditions intact.
Encodes the corrected lane after a prior-session off-lane drift drafting Oddie content without checking that Oddie already exists in canon (PR #179, #180). Withdrawn off-lane draft lives at /mnt/user-data/outputs/oddie-system-prompt-v0.md and should be ignored. Lane: wire canon/methods/quality-attribute-tension-survey.md to oddkit's existing governance machinery (preflight, gate, challenge, validate, encode) following the runtime-contract / persona-shaped pattern that PR #187 landed 2026-05-10. Scope is the method doc + the session ledger on the same PR branch. Required reading enumerated: PRs #187 (runtime-contract pattern), #186 (five modes including Resolution), #180 + #179 (existing Oddie canon), plus four open PRs ahead that may force a rebase. Concrete steps, do-not list, and banked off-scope items captured so a fresh session can pick up without re-deriving context. Frontmatter matches odd/handoffs/ conventions; tier 2; status active.
Encodes the corrected lane after a prior-session off-lane drift drafting Oddie content without checking that Oddie already exists in canon (PR #179, #180). Withdrawn off-lane draft lives at /mnt/user-data/outputs/oddie-system-prompt-v0.md and should be ignored. Lane: wire canon/methods/quality-attribute-tension-survey.md to oddkit's existing governance machinery (preflight, gate, challenge, validate, encode) following the runtime-contract / persona-shaped pattern that PR #187 landed 2026-05-10. Scope is the method doc + the session ledger on the same PR branch. Required reading enumerated: PRs #187 (runtime-contract pattern), #186 (five modes including Resolution), #180 + #179 (existing Oddie canon), plus four open PRs ahead that may force a rebase. Concrete steps, do-not list, and banked off-scope items captured so a fresh session can pick up without re-deriving context. Frontmatter matches odd/handoffs/ conventions; tier 2; status active.

What this PR does
Adds two complementary runtime canon docs at different altitudes — a Tier-1 method (persona-shape) and a Tier-2 spec (runtime-contract) — plus journals capturing the work.
Reconciliation outcome (2026-05-10)
Prior revision of this PR described the two docs as competing alternatives and asked the operator to pick one. That framing was wrong: the docs are complementary layers of the same architecture, deliberately split. Operator's call in review: keep both, reduce overlap, cross-reference cleanly. That reconciliation is in the latest commit.
The two docs:
canon/methods/persona-shaped-agent-runtime.md— Tier-1 method, status: proposed. The architectural shape: persona-as-noun framing, the persona profile schema (canonical home), the runtime's responsibilities at the architecture level, deployment sequencing, prior art, inheritance from canonical commitments, worked examples. Reads top-down: "what is this thing and why."canon/methods/spawned-agent-session-runtime-contract.md— Tier-2 spec, status: draft. The per-session-shape contract: per-mode tool allow-lists / output schemas / risk detectors / anti-pattern detectors; per-role boundaries; per-surface post-processing rules; per-engagement turn-control; the composition rules with forbidden / rare / well-trodden combinations; the explicit enforcement points list. Reads as a reference: "what does the runtime do at submit time."Each doc now opens with a Companion Documents callout naming the sibling and partitioning what lives where ("changes to architecture land in the method; changes to per-dimension mechanics land in the spec"). Frontmatter
complementsis symmetric on both docs. See Also lists are reordered to put the sibling at the top.What changed in the latest commit
Persona-shape:
Runtime-contract:
Verification note (correction to the prior framing)
The prior version of this PR claimed "the engagement dimension is missing from doc 1 (persona-shape)" and recommended folding it forward. Direct read of the artifact contradicted that: persona-shape already had a fully-developed Engagement Contract section (§6) covering the assistant / agent split, bottleneck-respect implications, the invocation parameter sketch, and the rare-but-legitimate combinations. The actual overlap was elsewhere — persona profile YAML duplicated in both, per-mode role descriptions duplicated, surface post-processing rules duplicated, mode toggles duplicated, engagement spec duplicated with persona-shape carrying spec depth that belonged in runtime-contract. That's the overlap the latest commit removes. The new journal
journal/2026-05-10-runtime-canon-split-reconciled.tsvrecords the verification finding.Files
Canon
canon/methods/persona-shaped-agent-runtime.md— Tier-1 method (proposed)canon/methods/spawned-agent-session-runtime-contract.md— Tier-2 spec (draft)Journals
journal/2026-05-10-spawned-agent-runtime-and-five-dimension-contract.tsv— prior session's DOLCHEO entries capturing the architectural-pivot reasoningjournal/2026-05-10-runtime-canon-divergence.tsv— earlier divergence flag (note: the engagement-missing claim in this journal is corrected by the reconciliation journal below)journal/2026-05-10-runtime-canon-split-reconciled.tsv— DOLCHEO record of the layer-split reconciliation, including the verification correctionReferenced canon — already live on main
This PR's docs reference URIs that are present on main canon as of merge:
klappy://canon/methods/spawned-agent-session-substrate-options✓ on mainklappy://canon/principles/sessions-mirror-modes✓ on mainklappy://canon/constraints/mode-transitions-require-encoded-handoff✓ on mainNo external dependencies. Mergeable on its own merits.
What this PR does NOT do
Confidence
Working belief on persona-shape; draft on runtime-contract. Both pre-production with retraction conditions in their respective Confidence sections. The architectural shape grounds in canonical commitments (vodka-architecture, sessions-mirror-modes, mode-transitions-require-encoded-handoff, critic-cannot-be-resolver, verification-requires-fresh-context) but has not yet hosted a real consumer. First deployment (audit gate as single-role validator) is the next signal-source.