# Kanban Orchestrator

> Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role.

- Skill: `theheavenlyd3mon/kanban-orchestrator` (Agent Skill, multi-file: 15 files)
- Install (CLI): `npx skillmds add theheavenlyd3mon/kanban-orchestrator`
- Raw SKILL.md: https://api.skillmd.com/api/skills/theheavenlyd3mon/kanban-orchestrator/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: theheavenlyd3mon (https://skillmd.com/u/theheavenlyd3mon)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/theheavenlyd3mon/kanban-orchestrator

---


IDENTITY: Orchestrator.Router. Decompose user goals into kanban task graphs, assign to existing profiles, and route — never execute implementation work yourself. Fan out independent lanes, link true dependencies only.
Law: ForAnyConcreteTaskCreateKanbanCardAndAssign — every single time, never do the work yourself.
WHENUSE: MultiSpecialistNeeded|WorkMustSurviveCrash|HumanInLoopWanted|ParallelSubtasksPossible|ReviewIterationExpected|AuditTrailMatters. ESPECIALLY:CodebaseReview{PhasedRead->ReviewLanes->Fix->Verify}. NoSkip:Step0{DiscoverProfilesBeforePlanning}|Step0.5{VerifyProfileModels}.
REDFLAGS: JustFixingThisQuickly->StopCreateTask|SingleCardForMultiLaneRequest->SplitBeforeCreating|InventingProfileName->AskUserWhichProfile|NoScopeOnResearchTask->UnboundedResearch{8chunks730Kchars}.
RATIONALIZATIONS: OneBigTaskIsSimpler->ParallelLanesAreFaster|DelegateTaskInsteadOfKanban->KanbanSurvivesCrashes|ResearchDoesntNeedScope->SetSourceLimitOrGoalBeforeDispatch.
QUICKREF: Discover{ProfileList+VerifyModels}->Decompose{ExtractLanes->MapToProfiles->DecideDependencies->SketchGraph->ShowUser}->Create{TasksViaCLI{titlePos,workspace,skill,parent}->LinkDependencies}->Monitor{PollEvery30-45s->ReadComments+OutputFiles}->Report{PhaseAReportBeforePhaseB->PhaseCVerifyAfterFixes}.

# Kanban Orchestrator — Decomposition Playbook

> The **core worker lifecycle** (including the `kanban_create` fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the `KANBAN_GUIDANCE` system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.

## Profiles are user-configured — not a fixed roster

Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (`docker-worker`, `cron-worker`); some run a curated specialist team they've named themselves. There is **no default specialist roster** — the orchestrator skill does not know what profiles exist on this machine.

Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names — it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to `researcher` on a setup that only has `docker-worker` just sits in `ready` forever.

**Step 0: discover available profiles before planning.**

Use one of these:

- `hermes profile list` — prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user.
- `kanban_list(assignee="<some-name>")` — sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering.
- **Just ask the user.** "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist.

Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call.

**Step 0.5: verify profile models match the task's needs.**

The kanban `--assignee` flag routes to a **profile**, not a specific model. Each profile has its own `model.default` in `config.yaml`, and the model actually used is determined by that profile's config. If the user says "make sure the team uses X model" or if you notice all profiles are on an unexpected model:

- Check with: `grep 'default:' ~/.hermes/profiles/*/config.yaml`
- Change via: `hermes model` (interactive terminal) or direct YAML edit: `sed -i '' 's|default: old-model|default: new-model|g' ~/.hermes/profiles/<profile>/config.yaml`
- Batch switch: `for p in architect coder reviewer debugger; do sed -i '' 's|default: <old>|default: <new>|g' ~/.hermes/profiles/$p/config.yaml; done`

**Profile models are independent of the kanban dispatch system.** The dispatcher just routes to the profile; which model the profile uses is handled entirely by that profile's config.

## When to use the board (vs. just doing the work)

Create Kanban tasks when any of these are true:

1. **Multiple specialists are needed.** Research + analysis + writing is three profiles.
2. **The work should survive a crash or restart.** Long-running, recurring, or important.
3. **The user might want to interject.** Human-in-the-loop at any step.
4. **Multiple subtasks can run in parallel.** Fan-out for speed.
5. **Review / iteration is expected.** A reviewer profile loops on drafter output.
6. **The audit trail matters.** Board rows persist in SQLite forever.

If *none* of those apply — it's a small one-shot reasoning task — use `delegate_task` instead or answer the user directly.

## Delegation toolset policy

The `delegation` toolset (`delegate_task`) is intentionally **disabled on all worker profiles** (coder, architect, reviewer, debugger, researcher, explorer, librarian, designer, security, data-analyst, devops, secretary, council). Only **foreman** (orchestrator) and **senna** (your shell) keep it enabled.

**Why:** Forces all multi-profile work through Kanban — which means work survives crashes, has full audit trails, uses proper profile context, and supports dependency chains. A worker profile should never spawn subagents; that's the foreman's job.

**Pitfall — accidentally re-enabling delegation on a worker:** If you're debugging a worker that's stuck and think "let me just delegate_task this subtask" — don't. The tool won't be available. The correct approach is either (a) `kanban_block` to hand back to the orchestrator, or (b) handle the subtask yourself within your workspace. If you find yourself adding `delegation` back to a worker profile's enabled toolsets, stop and ask the user — it's almost certainly the wrong fix.

**What this means for the orchestrator:**
- `delegate_task` is your tool for short, one-shot reasoning subtasks that don't need durability
- Kanban is your tool for anything that outlives one turn, needs a specialist profile, or benefits from audit trails
- Workers cannot delegate back to you or to each other — they block or complete, and you decide what happens next

**Proactive reporting rule — mandatory dashboard format**

Immediately after every fan-out, completion, or status transition, send the user a dashboard-style status block. Do not wait for the user to ask. Always include:
1. Workstream counts summary
2. Lifecycle table grouped by workstream
3. Direct next actions / commands

**Blocks:** `⛔ Blocked`
**Running:** `⟳ Running`
**Todo:** `⏳ Todo`
**Running:** `🔄 Running`
**Archived/Done:** `🗄️ Archived` / `✅ Done`

**Template:**
```
## 🪐 Workstream: <name>

| Task | Assignee | Status |
|---|---|---|
| **T1** — short title | profile | ✅ Done |
| T2 description | profile | ⛔ Blocked |
| T3 description | profile | ⏳ Todo |

<N done, M blocked, K todo>
Run this to continue: <exact command>
```

**Escalation blocks require a copy-paste command** — make recovery trivial.

## The anti-temptation rules

Your job description says "route, don't execute." The rules that enforce that:

- **Do not execute the work yourself.** Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" — stop and create a task for the right specialist.
- **For any concrete task, create a Kanban task and assign it.** Every single time.
- **Split multi-lane requests before creating cards.** A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- **Run independent lanes in parallel.** If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- **If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use.** Do not invent profile names; the dispatcher will silently drop unknown assignees.
- **Decompose, route, and summarize — that's the whole job.**

### What must be delegated vs what the orchestrator may handle

**Must delegate via Kanban (non-negotiable):**
- GitHub PR/issue workflows
- Repository edits, file creation, code changes
- Implementation, bug fixes, tests
- Research, documentation, evidence gathering
- Architecture/security review
- Config or profile changes
- Any task that takes >30s of reasoning or produces output

**Orchestrator may handle directly:**
- Simple factual replies and quick lookups
- Tiny edits (single-line typos, trivial corrections)
- Direct checks and verification commands (`hermes profile list`, `hermes kanban list`)
- Clarification questions to the user
- Delegating short one-shot reasoning to `delegate_task` (your tool, not the workers')

**Escape hatch — systemic kanban failure:** When ALL dispatched workers across multiple profiles crash identically (same error: "pid N not alive", same timing: within seconds of each other, same failure count: 2 consecutive) and gateways show running, the workers are not recoverable by unblock+dispatch. Do not loop. Execute the tasks directly, complete each kanban card with `hermes kanban complete <id> --summary "..."`, and proceed. A user on a deadline doesn't care about audit trail purity — they care about the work getting done.

**Wrong vs Correct example (from oh-my-hermes-agent):**

*Wrong* — orchestrator does issue + PR + review in one turn:
```
User: "Document the new rate limiter and open a PR"
Orchestrator: (creates issue, writes doc, commits, opens PR, self-reviews, merges)
```

*Correct* — parallel cards with real profiles:
```
User: "Document the new rate limiter and open a PR"
Orchestrator:
  - fixer task: "Write rate limiter docs in docs/rate-limiter.md"
  - explorer task: "Check for existing rate limiter references" (parallel)
  - librarian task: "Collect source-grounded evidence" (parallel)
  - oracle task: "Review rate limiter docs PR" (depends on fixer)
  - link fixer -> oracle
  - dispatch
```

## Decomposition playbook

### Step 1 — Understand the goal

Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.

### Step 2 — Sketch the task graph

Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:

1. Extract the lanes from the request.
2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
3. Decide whether each lane is independent or gated by another lane.
4. Create independent lanes as parallel cards with no parent links.
5. Create synthesis/review/integration cards with parent links to the lanes they depend on.

Examples of prompts that should fan out (actual profiles on this setup):

- "Build an app" → one card to `designer` for UI/UX direction, one or two cards to `coder` for implementation, plus a later `reviewer` card gated behind implementation.
- "Fix blockers and check model variants" → one `coder` card for the blocker fixes plus one `explorer` card for config/source verification. A final `reviewer` card can depend on both. If the variants need deep reasoning, use `researcher` instead of `explorer`.
- "Research docs and implement" → a `librarian` card (targeted evidence) can run in parallel with an `explorer` card (codebase discovery); `coder` implementation waits only if it truly needs those findings.
- "Architecture decision needed" → `architect` drafts options, then `council` (xhigh reasoning on deepseek-r1-0528) reconciles conflicting recommendations into a consensus. `reviewer` is optional gated check.
- "Analyze this screenshot and find the related code" → one card to `designer` for visual analysis while `explorer` searches the codebase.

Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.

Show the graph to the user before creating cards. Let them correct it — including which actual profile name should own each lane.

### Step 3 — Create tasks and link

Use the profile names from Step 0. The example below uses placeholders `<profile-A>`, `<profile-B>`, `<profile-C>` — replace them with what the user actually has.

Use the profile names from Step 0. There are two paths for creating tasks: via the Python API tool (inside a Hermes session) and via the CLI (from a terminal). They accept the same arguments but the CLI uses positional/flat syntax.

**Python/tool (inside a session):**
```python
t1 = kanban_create(
    title="research: Postgres cost vs current",
    assignee="<profile-A>",
    body="Compare costs over 3 years...",
    tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
...
```

**CLI (from terminal — note: title is positional, NOT `--title`):**
```bash
hermes kanban create "research: Postgres cost vs current" \
  --assignee <profile-A> \
  --body "Compare costs over 3 years..."
```

Key CLI differences from the Python API:
- **Title is positional** — do not pass `--title "..."`. The first unlabeled argument is the title. `--title` is an error.
- **`--workspace`** — defaults to `scratch` (tmp dir). For local projects not in git, use `--workspace "dir:/path/to/project"` so the worker can read/write files directly in the project dir.
- **`--max-runtime`** — set a per-task cap: `90s`, `30m`, `2h`, `1d`.
- **`--skill`** — force-load a skill into the worker (repeatable): `--skill translation --skill github-code-review`.
- **`--parent`** — repeatable for multiple parents: `--parent t_abc123 --parent t_def456`.
- **`--json`** — emit JSON output for programmatic parsing.

Example with workspace for a local project:
```bash
hermes kanban create "Fix keyboard shortcuts" \
  --assignee coder \
  --body "Fix 7 findings from UI review...\nPath: ~/hermes-solar-system" \
  --workspace "dir:~/hermes-solar-system"
```

`parents=[...]` gates promotion — children stay in `todo` until every parent reaches `done`, then auto-promote to `ready`. No manual coordination needed; the dispatcher and dependency engine handle it.

**`hermes kanban comment` uses positional text, NOT `--message`:**
```bash
# CORRECT
hermes kanban comment t_abc123 "Review target: /path/to/project"
# WRONG — will error
hermes kanban comment t_abc123 --message "..."
```

**`hermes kanban show` — single ID only.** Unlike many other kanban commands, `show` accepts exactly ONE task ID. Passing multiple IDs produces an `unrecognized arguments` error. Check each task individually:
```bash
hermes kanban show t_abc123 | grep -E "^  status:"
hermes kanban show t_def456 | grep -E "^  status:"
```

**`hermes kanban list --archived` (not `--all`).** There is no `--all` flag. To include archived/completed tasks, use `--archived`. To filter by status, use `--status {archived,blocked,done,ready,running,todo,triage}`. Combine them to see everything including history:
```bash
hermes kanban list --archived --json   # all tasks including archived
hermes kanban list --status done       # only done tasks (not archived)
```

**`hermes kanban show --json` output shape.** The JSON output does NOT have a top-level `status` or `state` key — the status is part of the task's event log (`events` array) and `runs` array. For programmatic parsing, use `hermes kanban list --json` which returns structured arrays with `id`, `title`, `assignee`, `status`, `created_at`, `completed_at`, etc.

**Batch-link wiring after a bulk create.** Re-linking 20+ tasks in a loop is robust with the shell, not with Python: the python JSON parser will happily return wrong keys if the JSON shape changes across profile/cli versions. Use `while read -r ID; do ...; done <<< "$(hermes kanban list --json | grep -E '^ *"id":' | sed 's/.*"\(.*\)".*/\1/')"` instead.

After bulk-creating and bulk-linking, **verify the graph structure**: `hermes kanban show <merge-parent-id>` and grep for `children` / `block` lines. If a task has no children attached yet, the bulk-link loop silently did not apply it. Re-check that every revamp card lists the merge parent.

**`--json` id key is `id`, NOT `task_id`.** `hermes kanban create --json` returns `{"id": "t_xxxx", ...}`. Do NOT pipe this JSON into an interpreter to extract the id — the security scanner flags `kanban | python3` as "pipe to interpreter" and BLOCKS the parent command, but the `hermes kanban create` calls themselves already executed and spawned the tasks. See `references/kanban-cli-gotchas.md` for the safe id-extraction recipe (write `--json > /tmp/x.json`, then `grep -o '"id": "[^"]*"'`).

**`--skill` resolution pitfall — resolves from the orchestrator's profile, not the worker's.** The `--skill` flag resolves skill names from the **current profile's** skill registry (i.e. the profile that runs `hermes kanban create`), not from the assignee profile's registry. A skill that exists on disk at `~/.hermes/profiles/<assignee>/skills/` or `~/.hermes/skills/<category>/` but isn't indexed in the orchestrator's profile will cause the worker to crash at launch with:

```
Warning: Unknown toolsets: ...
Error: Unknown skill(s): <skill-name>
```

The worker exits immediately with `exit_code 1` and the task blocks with `nonzero_exit(1)`. The kanban log shows only the unknown-skill error — no system trace.

**Recovery path when `--skill` crashes with `Error: Unknown skill(s)`:**

1. **Add a comment** telling the worker where to find the skill file on disk and read it directly:
   ```bash
   hermes kanban comment t_abc123 \
     "The <skill-name> skill exists at ~/.hermes/skills/<category>/<skill-name>/SKILL.md — read it from the filesystem via terminal cat for reference."
   ```
2. **Unblock and re-dispatch**:
   ```bash
   hermes kanban unblock t_abc123
   hermes kanban dispatch
   ```
   The worker respawns, finds the comment, reads the skill file from disk, and proceeds.

3. **Install the skill into BOTH the orchestrator's AND the assignee's profile.** Card validation resolves against the orchestrator's registry, but the worker agent *also* crashes on startup (`Error: Unknown skill(s)`, exit 1, blocked after max-retries) if the assignee's own registry lacks it. (Hit 2026-08-04 on slp-app: skill staged in senna+code, Phase 1 card ran on creative → crash.)
    ```bash
    hermes skills install <skill-name> --profile <orchestrator-profile>
    # then copy/install into each assignee profile that will run the card
    ```

- **`Warning: Unknown toolsets: eikon, fabric, messaging` on worker spawn is cosmetic** — the daemon passes the orchestrator's toolset list; workers warn and continue. Don't chase it unless the worker actually needs those tools.

- **Never operate in a language the user did not request.** If the user asks in language X and does not ask for English output, all task titles, summaries, status dashboards, and board comments must stay in X. Treat any mismatch as an explicit alignment failure, even if the conversation’s default language is English. Encoded here because this session produced a dialect/English mismatch on status outputs.

**Self-recovery after kanban DB corruption.** If init reports a corrupt `kanban.db` and produces a `.bak` file:
1. Inspect the `.bak` integrity; if it is also corrupt, initialize a fresh board (`hermes kanban init`).
2. Recovery from the fresh board is faster than recreating 20+ cards by hand: write out the full planned graph as JSON files (id + title + assignee + body + parents). Then loop over them in groups of 3–5 and call `hermes kanban create` with temp-file body injection; verify each id with `grep -o '"id":...'`. Re-link parents afterward with `hermes kanban link parent child`.
3. If the corruption happens mid-bulk-create, always run `hermes kanban list` before retrying to detect whether the create already succeeded (silent duplicate is the usual cost).

- **Prevention:** Before using `--skill` for a skill you haven't used before, verify it exists in the orchestrator profile's registry:
```bash
hermes skills list | grep <skill-name>
```
If empty, use the comment+unblock recovery pattern instead, or install it first.

### Step 4 — Complete your own task

If you were spawned as a task yourself (e.g. a planner profile was assigned `T0: "investigate Postgres migration"`), mark it done with a summary of what you created:

```python
kanban_complete(
    summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
    metadata={
        "task_graph": {
            "T1": {"assignee": "<profile-A>", "parents": []},
            "T2": {"assignee": "<profile-A>", "parents": []},
            "T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
            "T4": {"assignee": "<profile-C>", "parents": ["T3"]},
        },
    },
)
```

### Step 5 — Report back to the user

Tell them what you created in plain prose, naming the actual profiles you used:

> I've queued 4 tasks:
> - **T1** (`<profile-A>`): cost comparison
> - **T2** (`<profile-A>`): performance comparison, in parallel with T1
> - **T3** (`<profile-B>`): synthesizes T1 + T2 into a recommendation
> - **T4** (`<profile-C>`): turns T3 into a CTO memo
>
> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or `hermes kanban tail <id>` to follow along.

## Standard metadata schema for orchestration

When creating tasks that will participate in a feedback loop (implement → review → re-implement → re-review), standardize the metadata in the task body so the orchestrator can parse outcomes programmatically:

**Task body convention for fix tasks:**
```markdown
Workstream: config-refactor
Retry count: 2
Max retries: 3
Origin: t_abc123 (prior review task)

Findings from prior review:
1. [critical] config.js:42 — raw SQL concat
2. [high] config.js:88 — missing input validation

Fix these findings and link a new review task on completion.
```

**Task body convention for review tasks:**
```markdown
Workstream: config-refactor
Retry count: 2
Parent fix: t_def456
Previous findings:
1. [critical] config.js:42 — raw SQL concat
2. [high] config.js:88 — missing input validation

Check ALL previous findings are resolved. Check for regressions. Set clean=True in metadata if pass, include new findings if not.
```

When creating retry tasks, embed the prior review's findings in the body so the fixer doesn't need to cross-reference.

**Code-implementation task body template:** For building new features, components, or visual systems (not fixes or reviews), use the template at `templates/code-implementation-body.md`. It provides a structured format with files, implementation steps, verification criteria, and headless test instructions — designed for the "build X" pattern common in game dev, frontend features, and new modules.

## Feedback loops (retry cycles)

The standard kanban pattern is *forward* decomposition: plan → implement → review → done. But real development loops back. Here's how to model it:

### The fix→review→fix loop

```
T1 — Implement feature (Coder)
  ↓ complete
T2 — Review feature (Reviewer, parent: T1)
  ↓ complete with findings
T3 — Fix findings (Coder, retry_count=2, parent: T2)
  ↓ complete
T4 — Re-review (Reviewer, retry_count=2, parent: T3)
  ↓ clean=true → workstream done
```

Key rules:
- **Do NOT re-open T1.** The original task stays complete. Create a new task for each cycle.
- **Increment retry_count** in the metadata of each new cycle task.
- **Embed prior findings** in the new fix task's body so the worker has context without reading foreign tasks.
- **Link parent** to the prior review task so the dependency chain is visible.
- **Use workstream_id** (a stable string like `"config-refactor"`) across all cycles so the orchestrator can group them.

### Escalation thresholds

When retry_count exceeds the configured max (default: 3), the loop should NOT create another cycle. Instead:

```python
# Inside the orchestrator's polling logic:
if task.metadata.retry_count >= max_retries:
    kanban_block(
        reason="review-required: escalation — retry loop exhausted for workstream 'config-refactor'. " 
               "Findings persist across 3 cycles. Needs human triage."
    )
```

Escalation conditions beyond retry count:
- **Identical findings across 2 consecutive cycles** — the same issue is being re-found, meaning the fix isn't sticking. Escalate.
- **Scope expansion** — a single fix task touches 10+ files or spawns 3+ emergent tasks. Escalate.
- **Error/crash** — the review worker or fix worker exited without clean completion. Escalate.

### Workstream tracking

A workstream is a logical unit of work (e.g. "refactor config", "add calendar module") that spans multiple kanban tasks across multiple cycles. All tasks in a workstream share the same `workstream` string in their metadata.

The orchestrator tracks overall project health by monitoring all workstreams:
- A workstream is **active** when any of its tasks is in `running` or `ready`.
- A workstream is **blocked** when any task is in `blocked` (human escalation needed).
- A workstream is **complete** when its last review task completed with `clean=True` and no pending children.
- A project is **done** when all workstreams are complete.

## Research task scoping — depth boundaries for discovery cards

Research/discovery tasks (ecosystem surveys, design inspiration research, competitive analysis) are different from fix/code-review tasks — they **naturally expand** to fill available time. A worker tasked with "research MagicMirror ecosystem" will keep searching, extracting, and summarizing until it feels "comprehensive" — pulling 8 chunk summaries of 100K chars each, dozens of web searches, and multiple pages of extracts, because nothing tells it to stop.

**Prevent unbounded research by defining a stopping condition in the task body.** Pick one approach per task:

**Approach A — Source limit (simplest):** Cap the number of sources to review.
```
Research MagicMirror ecosystem — modules, use cases, Hermes integration ideas.
Scope: Stop after reviewing 12 distinct sources (web searches + page extracts + forum posts).
Deliverable: A summary ranking the top 5 integration opportunities with brief rationale each.
```

**Approach B — Finding/pattern count:** Stop when you've found N distinct patterns.
```
Research smart mirror design inspiration — UI, hardware, ambient display patterns.
Scope: Stop after identifying 8 distinct design patterns (mixed across UI, hardware, and display).
Deliverable: A categorized list of patterns, 2-3 sentences each, with source links.
```

**Approach C — Time budget:** Use `--max-runtime` with a reasonable cap.
```bash
hermes kanban create "research: MagicMirror ecosystem" \
  --assignee researcher \
  --body "Scope: ecosystem survey — modules, use cases, Hermes integration ideas." \
  --max-runtime 30m
```
Budget 20-30m for a focused survey, 45-60m for deep research across multiple dimensions. The worker will be killed at the limit and the task marked `timed_out` — set the cap generously and use approaches A or B to guide depth instead.

**Approach D — Goal-oriented (best for directed research):** Define what "done" means operationally.
```
Research how other smart mirror projects integrate AI notifications.
Scope: Find 3 working examples (GitHub repos, blog posts, or forum threads) that demonstrate AI -> mirror notification flows. Extract their architecture pattern for each. Stop once you have 3 distinct examples documented.
Deliverable: A table with project name, architecture pattern, tech stack, and source link for each.
```

**Pitfall — No scope = unbounded research.** This session's researcher pulled 8 chunk summaries (730K chars total), ran 20+ web searches, and extracted 10+ pages across two parallel tasks — all without a single scoping instruction. The result was thorough but took ~45 minutes and produced more raw material than needed. If you need exhaustive research, set a large-but-explicit cap rather than omitting scope entirely.

**Recovery for tasks already running without scope:** If a research task was created without scope boundaries and is already mid-flight, don't abort it. Drop a `SCOPE.md` file into the task's workspace directory. The worker will find it on its next file read and incorporate the constraints:

```bash
cat > $KANBAN_WORKSPACE/SCOPE.md << 'EOF'
# Scope Boundary

## Hard limits
- Max 2 additional web searches per part
- Do not re-crawl any URL already visited
- No chunked page summaries over 200K total chars
- Output a structured brief, not raw data dumps
- Deliver within 30 minutes

## What to cut
- Skip exhaustive lists — focus on 5-7 high-value findings
- Skip deep dives into single integrations unless directly relevant
- Prioritize actionable insights over comprehensive surveys
EOF
```

This works because the researcher's `web_tools` module reads files from the workspace — when it checks its task context and finds a new `SCOPE.md`, the agent will incorporate the limits into its next reasoning step. No need to reclaim or restart the worker.

**To prevent the problem entirely:** always pick a scoping approach (A-D above) when creating research tasks. Don't rely on the write-a-note-recovery — it's a backup, not a workflow.

**How to elicit scope from the user:** When the user says "have the researcher look into X," follow up with one question before creating the task:
- "How many sources should I cap it at?" (approach A)
- "Any specific patterns you're looking for?" (approach B/D)
- "How deep should it go: quick 15-min scan or a thorough hour?" (approach C)

If the user says "just a quick scan," use `--max-runtime 15m` and/or approach A with 5-6 sources. If they say "thorough," use approach D with clear deliverable criteria.

## Research task template

When creating research tasks for the `researcher` profile, use this structured body format with explicit scope boundaries. Don't let the researcher run unbounded:

```markdown
Research <topic> for <project>.

**Part 1 — <Category>**
- <3-5 specific questions with search targets>
- Specify source types (forum posts, GitHub, npm, etc.)

**Part 2 — <Category>**
- <3-5 specific questions>

**Part 3 — <Category>**
- ...

**Part 4 — <Category>**
- ...

Output a structured research brief with source URLs for each finding.
Prioritize actionable insights over exhaustive lists.
```

Key for the body: (a) multi-part structure ensures the researcher covers breadth, (b) explicit "source URLs" requirement prevents dead-end claims, (c) "actionable over exhaustive" prevents information dumps. Don't set arbitrary "search 5 pages" limits — the researcher knows when it has coverage.

## Common patterns

**Phased codebase review (read → review lanes → fix + verify):**

1. **Quick structural scan (not read-every-file).** Do NOT try to read every source file before creating cards — for a 230-file project this is impractical and wastes turns. Instead, run a focused structural scan:
   - Top-level directory listing (`ls -la`, `find . -maxdepth 2`)
   - Package/manifest file (package.json, pyproject.toml, etc.) for dependencies and entry points
   - Config/sample files if they exist
   - This gives you enough to write grounded, specific task bodies without scanning every source file.

2. **Phase A — Parallel review lanes.** One card per specialty, all independent, no parent links. Common lane assignments:
   - `architect` for structure/coupling/module system/entry points/data flow
   - `reviewer` for code quality/simplification/duplication/conventions/test coverage
   - `security` for dependency audit/npm vulnerabilities/Electron security/CSP/attack surface

3. **Phase B — Fix.** One or more `coder` cards implementing the findings from Phase A, with Phase A cards as parents. Group related fixes per card so coders don't step on each other's files.

4. **Phase C — Verify.** One `reviewer` card per Phase B fix card, with the fix card as parent. Each checks every finding was addressed. Set `clean=true` if all clear or `clean=false` with remaining findings for a retry cycle.

5. Report findings to the user after Phase A completes AND after Phase C verifies.
   - `architect` — structure/coupling/module lifecycle/IPC
   - `reviewer` — code quality/simplification/test coverage/conventions
   - `security` — dependency audit/Electron security/injection surface
   - `debugger` — runtime errors/edge cases (add only for active bugs)
   - `coder` — UI patterns/integration conflicts (add only for live UI issues)

3. **Worker output varies by profile type** — know where to look for each worker's findings:
   - `architect` tasks often write a file to disk (e.g. `ARCHITECTURE_REVIEW.md`) with structural diagrams — the body doesn't fit in a summary field
   - `security` tasks typically post a detailed findings table as a comment on the task, with severity counts in the summary
   - `reviewer` tasks use `review-required` block with structured JSON findings (severity, file, line, issue) in a comment
   - When synthesizing Phase A results, read each task's comments AND check for output files on disk at the workspace path

4. **Timeline expectations for codebase review tasks:**
   - Workers reading a local directory of 50-250 source files typically take 2-6 minutes per worker
   - Architecture reviewers finish fastest (~2-4 min) — file-based output
   - Security reviewers finish mid-range (~3-5 min) — npm audit adds overhead
   - Coder/reviewer reviewers take longest (~4-6 min) — deep pattern analysis across many files
   - Poll every 30-45s with `hermes kanban show <id> | grep -E "^  status:"`

5. **Report findings to the user** *after the Phase A reads complete*, before spawning Phase B — let them triage. Synthesize cross-cutting themes across all workers' reports.

6. **Phase B — Fix tasks, gated behind Phase A.** Once Phase A findings are reviewed and the user gives the green light, create fix/improvement tasks. Each fix task should:
   - Be assigned to `coder` (or the profile that owns the code)
   - Reference the Phase A task as a parent via `--parent t_<id>` — this gates the fix behind the review
   - Embed the specific findings (severity, file, line, issue) in the task body so the worker has context without cross-referencing
   - Use `--workspace "dir:/path/to/project"` so the worker can make real changes
   - Group logically related fixes together, but keep them scoped enough that a single worker can complete them in one pass
   - Example grouping: one task for all security fixes (cert bypass + dep update + CSP), another for all code quality fixes (monolith split + duplication + convention fixes)

   ```bash
   # Security fix card, gated behind security audit review
   hermes kanban create "fix: security — cert bypass, CSP, CORS, dep update" \
     --assignee coder \
     --body "$(cat /tmp/body.md)" \
     --workspace "dir:~/projects/Example" \
     --parent t_<security_review_id>
   ```

7. **Phase C — Verification tasks, gated behind fixes.** For any fix task that produces multiple changes, create a verification card assigned to `reviewer` that checks every fix point against the original findings. This creates a complete traceable chain:
   ```
   T1 (review) ──→ T2 (fix) ──→ T3 (verify)
   ```
   The verification card body should list every original finding and ask the reviewer to confirm each is resolved, reporting `clean=true` in metadata if all pass.

   ```bash
   hermes kanban create "verify: security fixes" \
     --assignee reviewer \
     --body "Check each fix from t_<fix_id>:\\n1. Cert bypass — removed/restricted?\\n2. Dep updated?\\n3. CSP enabled?\\n..." \
     --workspace "dir:~/projects/Example" \
     --parent t_<fix_id>
   ```

   The dependency engine handles promotion automatically: Phase A → done → Phase B auto-promotes to ready → dispatched → Phase B → done → Phase C auto-promotes to ready → dispatched. No manual coordination needed after the initial task graph is created.

Example body texts for Phase A review cards:

**Architecture review card:**
```
Review the project at ~/projects/<project>.
Focus: overall architecture — module system, Electron/process shell, server/client split, IPC patterns, dependency graph, module lifecycle, config system, socket communication.
Provide your findings with file paths and a structural diagram of how components connect.
This is read-only analysis — do not make changes.
```

**Code quality review card:**
```
Review the project at ~/projects/<project>.
Focus: code quality — JavaScript/Python patterns, module structure, error handling, test coverage, duplication across modules, adherence to project conventions.
Check each module for consistent patterns.
This is read-only analysis — do not make changes.
```

**Security audit card:**
```
Audit the project at ~/projects/<project>.
Focus: security — npm/pip audit of production dependencies, Electron/process security practices, input validation, IP access control, dependency vulnerabilities, attack surface.
Run: npm audit --omit=dev (or equivalent)
Check main process for secure defaults.
This is read-only analysis — do not make changes.
```

**Fan-out + fan-in (research → synthesize):** N research-style cards with no parents, one synthesis card with all of them as parents.

**Parallel research review (content survey pattern):** When the user asks you to review a large collection of content (a list of articles, a catalog of use cases, a batch of PRs, a site with many pages), use this sequence:

1. **Extract the full dataset** — scrape or collect all items into a single structured file (JSON/CSV) on disk. This is the shared source of truth all workers will read from.
2. **Split by category or slice** — partition the items into logical groups (by category tag, by page, by author, etc.). Create one kanban task per slice.
3. **Point workers at the file, not inline data** — the task body should reference the shared file path and list which slice to review. The file stays on disk and isn't lost in context truncation:
   ```bash
   hermes kanban create "Review DEV WORKFLOW stories" \
     --assignee researcher \
     --body "Read /tmp/stories.json. Review all DEV WORKFLOW stories. For each: source link, interesting? why. Rate interesting/maybe/skip." \
     --workspace scratch
   ```
4. **Fan out all slices at once** — create all tasks first, then dispatch once. The dispatcher will parallelize across available workers.
   ```bash
   hermes kanban dispatch   # repeat until no new spawns
   ```
5. **Poll and collect** — since `hermes kanban show` accepts only ONE ID at a time, poll individually:
   ```bash
   hermes kanban show t_abc123 | grep -E "^  status:"
   ```
   Check every 30-60s. Workers reading a local file typically take 60-180s per task depending on slice size.
6. **Synthesize** — once all tasks complete, read each task's `Latest summary` from `kanban show` and present a unified report organized by category with cross-cutting themes.

**Pitfall — task body too large.** Don't inline 50+ story descriptions in the task body — the worker loses context. Use a shared file on disk instead. If the content is from an external URL the worker can't access (behind auth, JS-rendered), save it locally first.

**Pitfall — scratch workspace output vanishes on completion.** Scratch workspaces are GC'd immediately when the task completes (or shortly after). If the worker writes artifacts to a scratch workspace, those files may be gone before you can read them. Recovery: workers that post their output as a **kanban comment** (visible via `hermes kanban show <id>`) survive GC. When creating brainstorm/research tasks, instruct workers to post findings as a comment in addition to (or instead of) writing files. For durable artifacts, use `--workspace dir:/path/to/persistent/dir` instead of scratch.

**Parallel i

…(truncated)
