/ouroboros:unstuck skill

Break through stagnation with lateral thinking personas — single or multi-persona debate

by Q00·MIT license·★ 6,178 Stars on the repo·GitHub ↗

Use now

Files of /ouroboros:unstuck

Q00/main1 file shown
SKILL.md
Show the full text294 lines

/ouroboros:unstuck

Break through stagnation with lateral thinking personas. Two modes:

  • Solo — one persona reframes the problem (fast, cheap).
  • Debate — multiple personas run in parallel as sub-agents and the user picks the verdict (visual, thorough).

Usage

ooo lateral                       # debate (default) — all 5 lateral personas
ooo lateral <persona>             # solo — single persona
ooo lateral debate <p1> <p2> ...  # debate with explicit members
ooo lateral @<preset>             # debate with preset (Phase 1: only @all = 5 personas)

Trigger keywords: "I'm stuck", "think sideways", "ooo lateral", "/ouroboros:unstuck".

Personas (Lateral Pool)

The lateral pool is stateless mindset personas only — five reframing lenses. Stateful roles (evaluator, qa-judge, ontologist, socratic-interviewer, etc.) are NOT mixed into this pool; they have their own SKILLs.

Persona Style When to Use
hacker "Make it work first, elegance later" When overthinking blocks progress
researcher "What information are we missing?" When the problem is unclear
simplifier "Cut scope, return to MVP" When complexity is overwhelming
architect "Restructure the approach entirely" When the current design is wrong
contrarian "What if we're solving the wrong problem?" When assumptions need challenging

When to Call

Direct user invocation — ooo lateral … from the prompt.

Autonomous chain from another SKILL — when you (the main session) are operating in another SKILL's persona (e.g., socratic-interviewer during ooo interview, or any agent role) and judge that the current question requires multi-perspective deliberation, you MAY invoke this SKILL on your own. No forced trigger; this is your self-assessment. After the debate, summarize the options for the user, return to the original SKILL's flow, and let the user decide. The user will see the sub-agent fan-out as it happens — that visibility is the point.

Instructions

Step 1 — Parse args → mode

Parse the user's argument string (or your autonomous-chain intent) into a mode (solo / debate):

Input Mode Members
no args debate all 5 lateral personas
debate (keyword alone) debate all 5 lateral personas
<persona> (e.g., hacker) solo that one persona
debate <p1> <p2> ... debate the listed personas
@all debate all 5 lateral personas
@<unknown-preset> error reject + list known presets
<unknown-persona> error reject + list the 5 lateral personas
<persona1> <persona2> ... (no debate keyword) error reject + suggest ooo lateral debate <p1> <p2>

Validate every persona name against the lateral pool above. If invalid, emit a brief error message naming the valid personas — do NOT silently coerce. Multiple persona tokens without the explicit debate keyword are rejected to keep the syntax unambiguous.

Step 2 — Gather required context before the MCP call

ouroboros_lateral_think hard-fails if either problem_context or current_approach is empty (LateralThinkHandler.handle in src/ouroboros/mcp/tools/lateral_think_handler.py). A bare ooo lateral from a fresh session has neither — calling MCP directly would crash before any persona work. Resolve both fields before Step 3, in this order:

  1. Reuse session state. If a parent SKILL is invoking this one (autonomous chain) or the current Claude Code / Codex session has clearly recent stuck-point context, extract it. Build:
    • problem_context — what the user is stuck on (1–3 sentences, current state of the world).
    • current_approach — what has been tried so far (1–3 sentences). For a brand-new attempt, this can be "none yet — first attempt".
    • failed_attempts (optional) — short list of prior failures, when the user has volunteered them.
  2. If either field is unrecoverable, ask the user one short combined question before going further (this applies to both solo and debate — the handler requires both fields either way):

    "Two things I need before lateral thinking can run: (1) what are you stuck on right now, (2) what have you already tried? A sentence each is enough." Wait for the answer. Do not invent or paraphrase past turns into these fields if you are not certain — current_approach="not specified" is acceptable, fabricated content is not.

  3. Only when both fields are populated, proceed to Step 3.

This pre-call branch applies to solo and debate. Skipping it makes ooo lateral (no args, fresh session) reliably error.

Step 3 — Always call ouroboros_lateral_think (routing contract)

Per the ooo routing contract in src/ouroboros/codex/ouroboros.md, every ooo lateral invocation MUST route through the MCP tool — solo and debate, in every runtime. This SKILL never substitutes a direct sub-agent fan-out for the MCP call.

  1. Use the active runtime's tool-discovery capability with query "+ouroboros lateral" to load ouroboros_lateral_think (often prefixed, e.g., mcp__plugin_ouroboros_ouroboros__ouroboros_lateral_think). Deferred tools won't appear until runtime tool discovery runs.
  2. Invoke the tool with the parsed mode and the context from Step 2:
    • Solo: persona=<one>, problem_context, current_approach, failed_attempts.
    • Debate: personas=[...], problem_context, current_approach, failed_attempts.
  3. If the tool is not callable even after discovery — neither already exposed nor loadable (an empty discovery result for an already-exposed tool is expected, not a failure) — stop and report that the MCP dispatch surface is broken — same rule the contract applies to ooo auto. Do not improvise a sub-agent fan-out as a workaround; that bypasses the contract the bot review explicitly flagged.

The MCP call is cheap. The handler's inline path is a deterministic prompt builder — it constructs per-persona reframing prompts via LateralThinker.generate_alternative (LateralThinkHandler.handle in src/ouroboros/mcp/tools/lateral_think_handler.py); it does not run an LLM rollout.

Step 4 — Branch on the handler's response shape

The handler picks one of two response shapes based on should_dispatch_via_plugin(...) (src/ouroboros/mcp/tools/subagent.py). You do not choose; you observe and act. The envelope key further depends on the mode you called with — solo and debate are not symmetric:

Mode Plugin response Inline response
Solo (persona=...) single _subagent envelope (one object) — build_subagent_result in subagent.py single # Lateral Thinking: <approach> block in content
Debate (personas=[...]) _subagents array (N objects) — build_multi_subagent_result in subagent.py N blocks joined by \n\n---\n\n in content, plus an appended hidden dispatch block carrying the same canonical N payloads (see "Inline dispatch block" below)

Inline dispatch block (debate, inline response only). The handler appends a versioned, sentinel-bracketed dispatch block to the end of content as a compatibility fallback for clients and runtimes that consume only textual content. MCP SDK v2 preserves structured metadata, while the inline block lets text-only consumers recover the same canonical payloads (written by LateralThinkHandler.handle in src/ouroboros/mcp/tools/lateral_think_handler.py, read back by _inline_lateral_dispatch_payload in src/ouroboros/mcp/tools/subagent.py). Format:

<!-- ouroboros-lateral-inline-dispatch-v1 base64
<base64-encoded-JSON>
-->

Two pieces matter:

  • Hidden HTML comment — markdown viewers render nothing for <!-- ... -->, so the block doesn't pollute the human-visible output.
  • Base64 body — base64's alphabet is [A-Za-z0-9+/=], which can never produce the sequence -->. So even if a user-supplied problem_context or current_approach contains --> (HTML/JS debugging is the obvious case), the encoded body cannot prematurely close the wrapper and leak the dispatch into the visible markdown.

Decoded, the body is JSON. An MCP host that did not declare subagent capability receives the neutral shape:

{"dispatch_mode": "host_decides", "host_action": "dispatch_subagents_if_supported", "execution_preference": "parallel", "fallback_strategy": "sequential", "persona_count": N, "payloads": [...]}

An explicitly sequential execution authority receives dispatch_mode="sequential" with legacy_dispatch_mode="inline_fallback" for compatibility. To recover: locate the substring between <!-- ouroboros-lateral-inline-dispatch-v1 base64\n and \n--> at the end of content, base64-decode it, then JSON.parse.

Shape A — dispatch_mode = "plugin" (OpenCode plugin mode only)

The plugin runtime spawns Task panes automatically from whichever envelope the handler emitted. You only need to read the right key and await the result(s):

Solo (plugin)

The response carries a single _subagent object (singular) — {tool_name, title, prompt, agent, model, context} — produced by build_subagent_result (src/ouroboros/mcp/tools/subagent.py). The plugin spawns one Task pane. Await its single result, then present the persona's reframing.

Debate (plugin)

The response carries a _subagents array (plural) — [{tool_name, title, prompt, agent, model, context}, ...] — produced by build_multi_subagent_result (src/ouroboros/mcp/tools/subagent.py). The plugin spawns N Task panes in parallel. Await all N results, then synthesize per the Synthesize block below.

If you expected plugin mode but the response is inline text (neither _subagent nor _subagents), you are not actually in plugin mode — fall through to Shape B; do not wait for an envelope that will not arrive.

Shape B — inline response (Claude Code, Codex CLI, OpenCode subprocess, every other runtime)

The handler ran the prompt builder internally and returned ready-to-use markdown:

  • Solo response: a single # Lateral Thinking: <approach> block followed by the reframing prompt.
  • Debate response: N such blocks concatenated with \n\n---\n\n separators. The dispatch block distinguishes declared host_driven, capability-neutral host_decides, and explicit sequential execution.
Solo (any runtime)

Present the persona's approach summary, reframing prompt, questions to consider, and a ◆ Current state → next: suggestion routing back to the workflow.

Debate, runtime supports sub-agent dispatch (Claude Code Task tool, Codex CLI sub-agent, etc.)

This is the default debate UX for Claude Code and Codex. The MCP call has already happened (Step 3), so the routing contract is satisfied; this step only changes how the already-built canonical prompts are rendered to the user.

Recover the structured dispatch from the inline dispatch block appended to content (see the "Inline dispatch block" note above the table). Each entry under payloads[] is a {tool_name, title, prompt, agent, model, context} dict; prompt is self-contained — it carries the same canonical reframing plus the "Task for you (subagent)" wrapper that plugin mode dispatches via _subagents (asking for a concrete plan, the biggest assumption challenged, and a one-line verdict). Same builder, byte-identical prompts across runtimes.

Driving fan-out from this dispatch block — instead of from the joined human-display text — avoids two pitfalls the bot review surfaced:

  • Separator collision — \n\n---\n\n can legitimately appear inside a user-supplied problem_context or current_approach, so splitting the joined text would over-fragment and corrupt prompts. The dispatch block uses a unique versioned sentinel that user content cannot collide with.
  • Behavioral drift across runtimes — the dispatch block carries the same canonical payloads _subagents carries, so debate results don't diverge by environment.
  1. Locate the dispatch block at the end of the MCP response's content text. Base64-decode the captured body, then JSON.parse to get {dispatch_mode, host_action, persona_count, payloads}. If the block is missing, fall through to the constrained-runtime path below — do not split the joined text.
  2. Surface a short "what the lateral toolkit suggests" header to the user, with the markdown above the dispatch block, so the MCP call is visible as a real product surface, not silent.
  3. If host_action="dispatch_subagents_if_supported", use the host's native parallel mechanism when available and otherwise process the same payloads sequentially. If host_action="spawn_subagents", spawn N persona subagents in parallel. Each child receives the payload's prompt verbatim plus its context, with strict isolation per child.
    • Claude Code → emit N Task calls (general-purpose subagent) in a single message so they run concurrently when the Task surface is available.
    • Codex → explicitly delegate one Codex subagent per payload in one turn; do not call a nonexistent multi_agent_v1.spawn_agent tool.
  4. Wait for all N to return.
  5. (Optional) Round 2 cross-attack — only if Round 1 answers diverge meaningfully. Dispatch a second N-fan-out where each persona receives short summaries of the other answers and is asked: "Identify one weakness in each. ≤200 words." Skip if Round 1 already converges.
  6. Synthesize per the Synthesize block below.
Debate, constrained runtime without sub-agent dispatch

If the response is stamped with dispatch_mode="sequential", or with dispatch_mode="host_decides" and the host has no native parallel primitive, process each payload in order. Correlate every result by result_correlation_key (normally context.persona), then synthesize after the last payload. Treat legacy_dispatch_mode="inline_fallback" as compatibility metadata only.

Debate, runtime cannot dispatch sub-agents (constrained subprocess, no Task surface)

Present the concatenated markdown the handler returned, as-is — no parsing required, the user reads the whole text. There is no per-persona visualization and no Round 2 cross-attack — both require a sub-agent surface. Synthesize directly from the inline text.

Synthesize (debate, all shapes)

Do not auto-emit a verdict. Present:

## Debate result — N personas

### Options
- **Option A** (from <persona>): <one-liner>
- **Option B** (from <persona>): <one-liner>
- …

### Disagreements
- <persona X> vs <persona Y>: <what they disagree about>

### Recommended (with reasoning)
<your single best read of the debate, clearly labeled as your
recommendation, not a verdict>

◆ Current state → next: pick an option, or `ooo lateral debate <subset>` to drill into a disagreement

The verdict is the user's. Never auto-progress to the next workflow step on the user's behalf — wait for their choice.

Persona-selection heuristics (when args are empty and you must pick one for solo)

You only need this if a parent SKILL or the user explicitly requests one persona but doesn't name one. In debate mode, no selection needed (use all 5).

  • Repeated similar failures → contrarian (challenge assumptions)
  • Too many options → simplifier (reduce scope)
  • Missing information → researcher (seek data)
  • Analysis paralysis → hacker (just make it work)
  • Structural issues → architect (redesign)

When MCP is unavailable

The contract is "fail loud, don't substitute": if ouroboros_lateral_think is not callable at all — neither already exposed nor loadable via discovery — stop and report that the MCP dispatch surface is broken. Do not improvise either solo or debate by reading persona files directly when MCP-driven invocation was requested — that re-introduces the contract bypass the bot review flagged.

The one exception, retained for documented offline use: a parent SKILL operating in degraded-offline mode that has already announced it cannot reach MCP MAY read src/ouroboros/agents/<persona>.md and adopt that persona inline for solo reframing. This is not a fallback for ooo lateral; it's a degraded helper for a parent SKILL that has already given up on MCP. Debate has no offline equivalent — report the broken surface and stop.

Examples

Solo
User: I'm stuck on the database schema design.
> ooo lateral simplifier

# Lateral Thinking: Reduce to Minimum Viable Schema
Start with exactly 2 tables. If you can't build the core feature
with 2 tables, you haven't found the core feature yet.

◆ Current state → next: try this, then `ooo run` — or `ooo interview` to re-examine.
Debate (default — Claude Code / Codex CLI)
> ooo lateral

[Step 2: Confirm problem_context + current_approach are present;
 ask the user one short combined question if not]
[runtime tool discovery loads ouroboros_lateral_think]
[Call ouroboros_lateral_think(personas=[hacker,researcher,simplifier,architect,contrarian], ...)]
[Handler returns: content = N persona blocks joined by ---,
                  followed by hidden <!-- ouroboros-lateral-inline-dispatch-v1 base64
                  <base64 body> --> sentinel block]
[Extract via the sentinel; base64-decode then JSON.parse → payloads[]]
[Spawn 5 parallel persona subagents — one per payloads[] entry — via the
 host's native mechanism (Claude: Task calls; Codex: explicit NL delegation);
 each child receives payload.prompt + payload.context verbatim;
 the visible markdown is shown to the user as the lateral scaffold]
[User sees "Running 5 agents…"]
[Round 1 returns]

## Debate result — 5 personas
### Options
- A (hacker): ship the 50-line version, defer correctness
- B (architect): the data model is wrong, redesign before coding
- C (simplifier): cut feature X, the rest fits in one file
- D (researcher): we don't have user data; instrument first
- E (contrarian): are users actually asking for this?

### Disagreements
- hacker vs architect: ship-first vs redesign-first
- contrarian vs all: whether the problem is real

### Recommended
Lean toward C+E: validate the need (E) before scoping (C); A and B
both assume the feature is wanted.

◆ Current state → next: pick an option, or `ooo lateral debate hacker contrarian` to drill in.
Autonomous chain from interview
[ooo interview mid-flow; main session is wearing the socratic-interviewer persona]
[Main session judges that the next question is too tangled — multiple
 reframings could be valid and asking the user to disambiguate would itself
 be confusing. It chains to this SKILL on its own.]

(autonomous) ooo lateral
[5-agent debate runs in parallel sub-agents; the user sees "Running 5 agents…"]
[Main session presents options + disagreements + a recommendation]
[User picks an option — or asks for a follow-up debate]
[Main session resumes the interview with the chosen framing]

Your final response MUST end with exactly one breadcrumb footer line:

◆ <current state> → next: <recommended action>

Derive <current state> from live session state via ouroboros_session_status when that MCP projection is available; otherwise derive it from this skill's actual outcome. Never use a linear Step N of M footer because Ouroboros is an evolutionary loop. When the next action is genuinely a choice, list 2-3 honest options in the next: clause. The breadcrumb line must be the last line of the response.

1---
2name: unstuck
3description: "Break through stagnation with lateral thinking personas — single or multi-persona debate"
4aliases: [stuck, lateral]
5---
6 
7# /ouroboros:unstuck
8 
9Break through stagnation with lateral thinking personas. Two modes:
10- **Solo** — one persona reframes the problem (fast, cheap).
11- **Debate** — multiple personas run in parallel as sub-agents and the user picks the verdict (visual, thorough).
12 
13## Usage
14 
15```
16ooo lateral # debate (default) — all 5 lateral personas
17ooo lateral <persona> # solo — single persona
18ooo lateral debate <p1> <p2> ... # debate with explicit members
19ooo lateral @<preset> # debate with preset (Phase 1: only @all = 5 personas)
20```
21 
22Trigger keywords: "I'm stuck", "think sideways", "ooo lateral", "/ouroboros:unstuck".
23 
24## Personas (Lateral Pool)
25 
26The lateral pool is **stateless mindset personas only** — five reframing lenses. Stateful roles (evaluator, qa-judge, ontologist, socratic-interviewer, etc.) are NOT mixed into this pool; they have their own SKILLs.
27 
28| Persona | Style | When to Use |
29|---------|-------|-------------|
30| **hacker** | "Make it work first, elegance later" | When overthinking blocks progress |
31| **researcher** | "What information are we missing?" | When the problem is unclear |
32| **simplifier** | "Cut scope, return to MVP" | When complexity is overwhelming |
33| **architect** | "Restructure the approach entirely" | When the current design is wrong |
34| **contrarian** | "What if we're solving the wrong problem?" | When assumptions need challenging |
35 
36## When to Call
37 
38**Direct user invocation** — `ooo lateral …` from the prompt.
39 
40**Autonomous chain from another SKILL** — when you (the main session) are operating in another SKILL's persona (e.g., `socratic-interviewer` during `ooo interview`, or any agent role) and judge that the current question requires multi-perspective deliberation, you MAY invoke this SKILL on your own. No forced trigger; this is your self-assessment. After the debate, summarize the options for the user, return to the original SKILL's flow, and let the user decide. The user will see the sub-agent fan-out as it happens — that visibility is the point.
41 
42## Instructions
43 
44### Step 1 — Parse args → mode
45 
46Parse the user's argument string (or your autonomous-chain intent) into a mode (solo / debate):
47 
48| Input | Mode | Members |
49|---|---|---|
50| no args | `debate` | all 5 lateral personas |
51| `debate` (keyword alone) | `debate` | all 5 lateral personas |
52| `<persona>` (e.g., `hacker`) | `solo` | that one persona |
53| `debate <p1> <p2> ...` | `debate` | the listed personas |
54| `@all` | `debate` | all 5 lateral personas |
55| `@<unknown-preset>` | error | reject + list known presets |
56| `<unknown-persona>` | error | reject + list the 5 lateral personas |
57| `<persona1> <persona2> ...` (no `debate` keyword) | error | reject + suggest `ooo lateral debate <p1> <p2>` |
58 
59Validate every persona name against the lateral pool above. If invalid, emit a brief error message naming the valid personas — do NOT silently coerce. Multiple persona tokens without the explicit `debate` keyword are rejected to keep the syntax unambiguous.
60 
61### Step 2 — Gather required context **before** the MCP call
62 
63`ouroboros_lateral_think` hard-fails if either `problem_context` or `current_approach` is empty (`LateralThinkHandler.handle` in `src/ouroboros/mcp/tools/lateral_think_handler.py`). A bare `ooo lateral` from a fresh session has neither — calling MCP directly would crash before any persona work. Resolve both fields *before* Step 3, in this order:
64 
651. **Reuse session state.** If a parent SKILL is invoking this one (autonomous chain) or the current Claude Code / Codex session has clearly recent stuck-point context, extract it. Build:
66 - `problem_context` — what the user is stuck on (1–3 sentences, current state of the world).
67 - `current_approach` — what has been tried so far (1–3 sentences). For a brand-new attempt, this can be `"none yet — first attempt"`.
68 - `failed_attempts` (optional) — short list of prior failures, when the user has volunteered them.
692. **If either field is unrecoverable**, ask the user *one* short combined question before going further (this applies to both solo and debate — the handler requires both fields either way):
70 > "Two things I need before lateral thinking can run: (1) what are you stuck on right now, (2) what have you already tried? A sentence each is enough."
71 Wait for the answer. Do **not** invent or paraphrase past turns into these fields if you are not certain — `current_approach="not specified"` is acceptable, fabricated content is not.
723. Only when both fields are populated, proceed to Step 3.
73 
74This pre-call branch applies to solo *and* debate. Skipping it makes `ooo lateral` (no args, fresh session) reliably error.
75 
76### Step 3 — Always call `ouroboros_lateral_think` (routing contract)
77 
78Per the `ooo` routing contract in `src/ouroboros/codex/ouroboros.md`, every `ooo lateral` invocation MUST route through the MCP tool — solo *and* debate, in every runtime. This SKILL never substitutes a direct sub-agent fan-out for the MCP call.
79 
801. Use the active runtime's tool-discovery capability with query `"+ouroboros lateral"` to load `ouroboros_lateral_think` (often prefixed, e.g., `mcp__plugin_ouroboros_ouroboros__ouroboros_lateral_think`). Deferred tools won't appear until runtime tool discovery runs.
812. Invoke the tool with the parsed mode and the context from Step 2:
82 - **Solo**: `persona=<one>`, `problem_context`, `current_approach`, `failed_attempts`.
83 - **Debate**: `personas=[...]`, `problem_context`, `current_approach`, `failed_attempts`.
843. If the tool is not callable even after discovery — neither already exposed nor loadable (an empty discovery result for an already-exposed tool is expected, not a failure) — **stop and report that the MCP dispatch surface is broken** — same rule the contract applies to `ooo auto`. Do not improvise a sub-agent fan-out as a workaround; that bypasses the contract the bot review explicitly flagged.
85 
86The MCP call is cheap. The handler's inline path is a *deterministic prompt builder* — it constructs per-persona reframing prompts via `LateralThinker.generate_alternative` (`LateralThinkHandler.handle` in `src/ouroboros/mcp/tools/lateral_think_handler.py`); it does not run an LLM rollout.
87 
88### Step 4 — Branch on the handler's response shape
89 
90The handler picks one of two response shapes based on `should_dispatch_via_plugin(...)` (`src/ouroboros/mcp/tools/subagent.py`). You do not choose; you observe and act. The envelope key further depends on the mode you called with — solo and debate are not symmetric:
91 
92| Mode | Plugin response | Inline response |
93|---|---|---|
94| Solo (`persona=...`) | single `_subagent` envelope (one object) — `build_subagent_result` in `subagent.py` | single `# Lateral Thinking: <approach>` block in `content` |
95| Debate (`personas=[...]`) | `_subagents` array (N objects) — `build_multi_subagent_result` in `subagent.py` | N blocks joined by `\n\n---\n\n` in `content`, **plus** an appended hidden dispatch block carrying the same canonical N payloads (see "Inline dispatch block" below) |
96 
97**Inline dispatch block (debate, inline response only).** The handler appends a versioned, sentinel-bracketed dispatch block to the end of `content` as a compatibility fallback for clients and runtimes that consume only textual content. MCP SDK v2 preserves structured metadata, while the inline block lets text-only consumers recover the same canonical payloads (written by `LateralThinkHandler.handle` in `src/ouroboros/mcp/tools/lateral_think_handler.py`, read back by `_inline_lateral_dispatch_payload` in `src/ouroboros/mcp/tools/subagent.py`). Format:
98 
99```
100<!-- ouroboros-lateral-inline-dispatch-v1 base64
101<base64-encoded-JSON>
102-->
103```
104 
105Two pieces matter:
106 
107- **Hidden HTML comment** — markdown viewers render nothing for `<!-- ... -->`, so the block doesn't pollute the human-visible output.
108- **Base64 body** — base64's alphabet is `[A-Za-z0-9+/=]`, which can never produce the sequence `-->`. So even if a user-supplied `problem_context` or `current_approach` contains `-->` (HTML/JS debugging is the obvious case), the encoded body cannot prematurely close the wrapper and leak the dispatch into the visible markdown.
109 
110Decoded, the body is JSON. An MCP host that did not declare subagent capability
111receives the neutral shape:
112 
113```json
114{"dispatch_mode": "host_decides", "host_action": "dispatch_subagents_if_supported", "execution_preference": "parallel", "fallback_strategy": "sequential", "persona_count": N, "payloads": [...]}
115```
116 
117An explicitly sequential execution authority receives `dispatch_mode="sequential"`
118with `legacy_dispatch_mode="inline_fallback"` for compatibility. To recover:
119locate the substring between `<!-- ouroboros-lateral-inline-dispatch-v1 base64\n`
120and `\n-->` at the end of `content`, base64-decode it, then `JSON.parse`.
121 
122#### Shape A — `dispatch_mode = "plugin"` (OpenCode plugin mode only)
123 
124The plugin runtime spawns Task panes automatically from whichever envelope the handler emitted. You only need to read the right key and await the result(s):
125 
126##### Solo (plugin)
127 
128The response carries a single `_subagent` object (singular) — `{tool_name, title, prompt, agent, model, context}` — produced by `build_subagent_result` (`src/ouroboros/mcp/tools/subagent.py`). The plugin spawns one Task pane. Await its single result, then present the persona's reframing.
129 
130##### Debate (plugin)
131 
132The response carries a `_subagents` array (plural) — `[{tool_name, title, prompt, agent, model, context}, ...]` — produced by `build_multi_subagent_result` (`src/ouroboros/mcp/tools/subagent.py`). The plugin spawns N Task panes in parallel. Await all N results, then synthesize per the **Synthesize** block below.
133 
134If you expected plugin mode but the response is inline text (neither `_subagent` nor `_subagents`), you are not actually in plugin mode — fall through to Shape B; do not wait for an envelope that will not arrive.
135 
136#### Shape B — inline response (Claude Code, Codex CLI, OpenCode subprocess, every other runtime)
137 
138The handler ran the prompt builder internally and returned ready-to-use markdown:
139 
140- Solo response: a single `# Lateral Thinking: <approach>` block followed by the reframing prompt.
141- Debate response: N such blocks concatenated with `\n\n---\n\n` separators. The dispatch block distinguishes declared `host_driven`, capability-neutral `host_decides`, and explicit `sequential` execution.
142 
143##### Solo (any runtime)
144 
145Present the persona's approach summary, reframing prompt, questions to consider, and a `◆ Current state → next:` suggestion routing back to the workflow.
146 
147##### Debate, runtime supports sub-agent dispatch (Claude Code Task tool, Codex CLI sub-agent, etc.)
148 
149This is the **default debate UX for Claude Code and Codex**. The MCP call has already happened (Step 3), so the routing contract is satisfied; this step only changes how the *already-built* canonical prompts are rendered to the user.
150 
151Recover the structured dispatch from the inline dispatch block appended to `content` (see the "Inline dispatch block" note above the table). Each entry under `payloads[]` is a `{tool_name, title, prompt, agent, model, context}` dict; `prompt` is self-contained — it carries the **same canonical reframing plus the "Task for you (subagent)" wrapper** that plugin mode dispatches via `_subagents` (asking for a concrete plan, the biggest assumption challenged, and a one-line verdict). Same builder, byte-identical prompts across runtimes.
152 
153Driving fan-out from this dispatch block — instead of from the joined human-display text — avoids two pitfalls the bot review surfaced:
154- **Separator collision** — `\n\n---\n\n` can legitimately appear inside a user-supplied `problem_context` or `current_approach`, so splitting the joined text would over-fragment and corrupt prompts. The dispatch block uses a unique versioned sentinel that user content cannot collide with.
155- **Behavioral drift across runtimes** — the dispatch block carries the same canonical payloads `_subagents` carries, so debate results don't diverge by environment.
156 
1571. Locate the dispatch block at the end of the MCP response's `content` text. Base64-decode the captured body, then `JSON.parse` to get `{dispatch_mode, host_action, persona_count, payloads}`. If the block is missing, fall through to the constrained-runtime path below — *do not* split the joined text.
1582. Surface a short "what the lateral toolkit suggests" header to the user, with the markdown above the dispatch block, so the MCP call is visible as a real product surface, not silent.
1593. If `host_action="dispatch_subagents_if_supported"`, use the host's native parallel mechanism when available and otherwise process the same payloads sequentially. If `host_action="spawn_subagents"`, spawn N persona subagents in parallel. Each child receives the payload's `prompt` verbatim plus its `context`, with strict isolation per child.
160 - **Claude Code** → emit N `Task` calls (`general-purpose` subagent) in a **single message** so they run concurrently when the Task surface is available.
161 - **Codex** → explicitly delegate one Codex subagent per payload in one turn; do not call a nonexistent `multi_agent_v1.spawn_agent` tool.
1624. Wait for all N to return.
1635. (Optional) **Round 2 cross-attack** — only if Round 1 answers diverge meaningfully. Dispatch a second N-fan-out where each persona receives short summaries of the other answers and is asked: "Identify one weakness in each. ≤200 words." Skip if Round 1 already converges.
1646. Synthesize per the **Synthesize** block below.
165 
166##### Debate, constrained runtime without sub-agent dispatch
167 
168If the response is stamped with `dispatch_mode="sequential"`, or with
169`dispatch_mode="host_decides"` and the host has no native parallel primitive,
170process each payload in order. Correlate every result by
171`result_correlation_key` (normally `context.persona`), then synthesize after the
172last payload. Treat `legacy_dispatch_mode="inline_fallback"` as compatibility
173metadata only.
174 
175##### Debate, runtime cannot dispatch sub-agents (constrained subprocess, no Task surface)
176 
177Present the concatenated markdown the handler returned, as-is — no parsing required, the user reads the whole text. There is no per-persona visualization and no Round 2 cross-attack — both require a sub-agent surface. Synthesize directly from the inline text.
178 
179##### Synthesize (debate, all shapes)
180 
181Do **not** auto-emit a verdict. Present:
182 
183```
184## Debate result — N personas
185 
186### Options
187- **Option A** (from <persona>): <one-liner>
188- **Option B** (from <persona>): <one-liner>
189- …
190 
191### Disagreements
192- <persona X> vs <persona Y>: <what they disagree about>
193 
194### Recommended (with reasoning)
195<your single best read of the debate, clearly labeled as your
196recommendation, not a verdict>
197 
198◆ Current state → next: pick an option, or `ooo lateral debate <subset>` to drill into a disagreement
199```
200 
201The verdict is the user's. Never auto-progress to the next workflow step on the user's behalf — wait for their choice.
202 
203## Persona-selection heuristics (when args are empty and you must pick one for solo)
204 
205You only need this if a parent SKILL or the user explicitly requests *one* persona but doesn't name one. In debate mode, no selection needed (use all 5).
206 
207- Repeated similar failures → **contrarian** (challenge assumptions)
208- Too many options → **simplifier** (reduce scope)
209- Missing information → **researcher** (seek data)
210- Analysis paralysis → **hacker** (just make it work)
211- Structural issues → **architect** (redesign)
212 
213## When MCP is unavailable
214 
215The contract is "fail loud, don't substitute": if `ouroboros_lateral_think` is not callable at all — neither already exposed nor loadable via discovery — stop and report that the MCP dispatch surface is broken. Do not improvise either solo or debate by reading persona files directly when MCP-driven invocation was requested — that re-introduces the contract bypass the bot review flagged.
216 
217The one exception, retained for documented offline use: a parent SKILL operating in degraded-offline mode that has *already* announced it cannot reach MCP MAY read `src/ouroboros/agents/<persona>.md` and adopt that persona inline for solo reframing. This is not a fallback for `ooo lateral`; it's a degraded helper for a parent SKILL that has already given up on MCP. Debate has no offline equivalent — report the broken surface and stop.
218 
219## Examples
220 
221### Solo
222```
223User: I'm stuck on the database schema design.
224> ooo lateral simplifier
225 
226# Lateral Thinking: Reduce to Minimum Viable Schema
227Start with exactly 2 tables. If you can't build the core feature
228with 2 tables, you haven't found the core feature yet.
229 
230◆ Current state → next: try this, then `ooo run` — or `ooo interview` to re-examine.
231```
232 
233### Debate (default — Claude Code / Codex CLI)
234```
235> ooo lateral
236 
237[Step 2: Confirm problem_context + current_approach are present;
238 ask the user one short combined question if not]
239[runtime tool discovery loads ouroboros_lateral_think]
240[Call ouroboros_lateral_think(personas=[hacker,researcher,simplifier,architect,contrarian], ...)]
241[Handler returns: content = N persona blocks joined by ---,
242 followed by hidden <!-- ouroboros-lateral-inline-dispatch-v1 base64
243 <base64 body> --> sentinel block]
244[Extract via the sentinel; base64-decode then JSON.parse → payloads[]]
245[Spawn 5 parallel persona subagents — one per payloads[] entry — via the
246 host's native mechanism (Claude: Task calls; Codex: explicit NL delegation);
247 each child receives payload.prompt + payload.context verbatim;
248 the visible markdown is shown to the user as the lateral scaffold]
249[User sees "Running 5 agents…"]
250[Round 1 returns]
251 
252## Debate result — 5 personas
253### Options
254- A (hacker): ship the 50-line version, defer correctness
255- B (architect): the data model is wrong, redesign before coding
256- C (simplifier): cut feature X, the rest fits in one file
257- D (researcher): we don't have user data; instrument first
258- E (contrarian): are users actually asking for this?
259 
260### Disagreements
261- hacker vs architect: ship-first vs redesign-first
262- contrarian vs all: whether the problem is real
263 
264### Recommended
265Lean toward C+E: validate the need (E) before scoping (C); A and B
266both assume the feature is wanted.
267 
268◆ Current state → next: pick an option, or `ooo lateral debate hacker contrarian` to drill in.
269```
270 
271### Autonomous chain from interview
272```
273[ooo interview mid-flow; main session is wearing the socratic-interviewer persona]
274[Main session judges that the next question is too tangled — multiple
275 reframings could be valid and asking the user to disambiguate would itself
276 be confusing. It chains to this SKILL on its own.]
277 
278(autonomous) ooo lateral
279[5-agent debate runs in parallel sub-agents; the user sees "Running 5 agents…"]
280[Main session presents options + disagreements + a recommendation]
281[User picks an option — or asks for a follow-up debate]
282[Main session resumes the interview with the chosen framing]
283```
284 
285## RFC #1392 State Breadcrumb Footer
286 
287Your final response MUST end with exactly one breadcrumb footer line:
288 
289```
290◆ <current state> → next: <recommended action>
291```
292 
293Derive `<current state>` from live session state via `ouroboros_session_status` when that MCP projection is available; otherwise derive it from this skill's actual outcome. Never use a linear `Step N of M` footer because Ouroboros is an evolutionary loop. When the next action is genuinely a choice, list 2-3 honest options in the `next:` clause. The breadcrumb line must be the last line of the response.
294 

Discussion