--- name: sidequest description: >- Default for multi-file or multi-step work, even where there is no board yet: the first add creates it. Use for tickets, board lifecycle, planning substantial or ambiguous work, and dispatch/integration/recovery. --- # sidequest A central ticket store (`~/.claude/sidequest`), live Kanban dashboard, CLI (`bin/sidequest.js`) and matching MCP tools. Read references only when needed: - `references/orchestration.md` — decomposition depth, fan-out waves, checkpoints, background execution, cost levers, agent teams. - `references/experiment-loop.md` — oracle rounds, branches, verdicts, promotion. - `references/publishing.md` — delivery modes, publish transaction. - `references/routing-details.md`, `references/routing-guide.md` — routes and wiring. - `references/high-stakes.md` - `references/external-trackers.md`, `references/board-features.md`, `references/category-links.md`, `references/ticket-authoring.md`, `references/invocation-contracts.md`. - `references/readonly-guidance.md` — candidate reviews, repository audits, shortcut debt, and measurement claims. ## Plan substantial work on the board first Before dispatching substantial or ambiguous work, pin a contract; see `user-story`. Check feasibility before expensive implementation or tests for substantial/safety-sensitive work (`references/ticket-authoring.md`). Small deterministic fixes keep one owner and a focused check; a plan advisor needs a named architectural risk or contested approach, no mandatory panel. For substantial work: 0. **solo-fit gate.** **SOLO-FIT picks one-executor vs wave; it NEVER means you implement inline.** Small coherent work gets **one ticket** and one executor. A multi-item unpinnable contract needs concurrent read-only investigation tickets, **one investigation ticket per independent item**; findings pin a separate fix wave. One combined ticket is only for exactly one item or a provably single defect. “Feels coupled” is not evidence: file planning first. 1. **Ticket shape.** For 3+ independently checkable pieces, pin shared types/interfaces, file boundaries and per-piece verification, then dispatch a category-routed wave. **Wave mode REQUIRES a Sidequest story**: file the complete backlog and execution contract under Sidequest's `US-n` grouping. One-ticket mode stays story-less; stories hold shared outcomes/dependencies. Cut along affected store, CLI, MCP, skill/docs and test surfaces. Tickets carry anchors, contract and scoped verify; use directory scope for blast radius (`references/ticket-authoring.md`). 2. **Link dependencies** (`link SQ-4 depends-on SQ-3`); shape a story as design → wave(s) → integrate so `ready` serializes the phases. 3. **File the whole planned wave backlog before dispatching.** Give every ticket scope, dependencies, and per-ticket verification; dispatch each ready wave concurrently. Do not drip-file a serial chain. **Parallel-first:** Split independent audits, migrations, and reviews into per-item or shard tickets. Dispatch concurrently despite isolated-worktree overlap; large sweeps skim invisibly. Keep sequential/shared-design work together; size shards by items and verify cost. 4. **Execute proportionally** — "Route execution down" below. Trace the real flow, question necessity, then reuse local code, stdlib, native features or installed dependencies before fixing the shared root. Prefer measured deletion; avoid hypothetical guards, compulsory extractions and unrelated cleanup. Preserve trust-boundary validation, data-loss prevention, accessibility, permissions and immutable candidate/review authority. Answer direct questions; do operational requests and stated one-line edits to 1–2 named files inline before solo-fit or ticketing. Bounded recon (`Read`, `Glob`, `Grep` on named anchors, one narrow sweep) stays inline; unfamiliar paths or deep investigation go through the live taxonomy. ### INLINE-SAFE direct work If inline-safe work was already ticketed, the orchestrator may claim `--direct` and edit inline after annotating the ticket, giving a 20+ character reason, and matching this allowlist: - A failing integration gate pinpoints an exact, known small diff: a strict-TS null guard, an assertion string synced after a deliberate reword, byte-checked golden regeneration, or a merge-conflict resolution that preserves both sides' intent. - Release bookkeeping: release fragments, the cut flow, or closing tickets with evidence. - The existing user-directed one-or-two-named-file carve-out above, unchanged. `direct-ok` may remain as a user signal, but it gates nothing. Never inline work that needs investigation or other-file reading to be confident, adds behavior or an API, or has a failing test that does not pinpoint the exact location. "Context already loaded", "small change", and "faster myself" are invalid reasons. File a ticket and dispatch its executor instead. The blocked-step and never-inline invariants still apply to substantive work. ## MCP is the executor board interface Routed executors use **only** the `mcp__plugin_sidequest_board__*` tools for their lifecycle (`commit`/`submit` take the executor's absolute worktree path). Missing tools → report the blocker and release through an available board tool, never a command-line fallback. MCP is the normal interface for board admin/config; the CLI is fallback for git-context operations. Apply board-only admin changes directly through an available MCP tool, never as a ticket or dispatch. Live category/profile edits affect only that board, not installation defaults unless the user asks. After a schema-bumping release, reload plugins before MCP writes. Commands default to the current project; `--project ""` (MCP: `project`) targets another board (creation rules: `references/board-features.md`). `dispatch ` is **instant**: it returns the ticket's stable executor, a short `spawn` fetch stub, and a token. Pass every supplied `spawn` field (`name` and `description` too) to Agent unchanged. Set `Agent.description` to `spawn.description` byte-for-byte, never derived from the prompt, route marker, title, model, or effort. The executor fetches its token-gated durable packet as the first action: full description, category route and contract, scope, state, comment metadata, and absolute attachment paths. It must inspect every readable attachment and report missing or unreadable ones, while the spawn keeps that content out of this transcript. Never trust a worker's self-report — the claim's token and exact executor name are the evidence. **Workflow callers:** call `route_recipe` or `sidequest route --json`; wire only `recipe.agent` in Agent: `model` and `subagentType` when set, `promptPrefix + prompt`. Never hand-translate route, gateway, virtual-model, marker, or effort fields. A user-named model for one ticket means set that ticket's `route` override, never edit the category route, which repoints later tickets too. See `references/routing-guide.md`. **Locations:** CLI: `plugins/sidequest/bin/sidequest.js`; DB: `~/.claude/sidequest/sidequest.db` (`SIDEQUEST_HOME`). Never scan from root. ## Routing profiles A board selects one profile plus local ADD/OVERRIDE/DETACH/DISABLE rows. Mutations take one of `--profile`/`--project`; details: `references/routing-details.md`. Category `readonly` selects the restricted executor and `done` closeout. `--readonly true|false` overrides it for a prepared dispatch. Read-only files or changes warn before dispatch. Resolve or override. ## Open the dashboard `sidequest dashboard` starts the local server and prints the URL. Verify server changes in an isolated `SIDEQUEST_HOME` on a distinct port, never the shared board. ## File a ticket `sidequest add -t "Contact form does not send" -d "..." --category ` — read the live taxonomy (`category_list` MCP / `sidequest category list --json`), choose by description and persist its ID. Use the fallback only when no category fits. `--complexity` is legacy ambiguity fallback; never set `--model`/`--effort`. Scope, anchors, stories and exact verify: `references/ticket-authoring.md`. Descriptions/comments render markdown. Use real newlines, never literal `\n`. Mid-task side issue? File it with `mcp__plugin_sidequest_board__add`, then keep going. Filing a ticket is not a request to work it. ## List / update / close `sidequest list` (this project; `--status todo` for one column) · `projects` (every board) · `update SQ-3 --status done` (move; also `-p -t -d -l`) · `rm SQ-3` (delete). `--json` reads data; `--brief` on `list`/`ready` implies `--json` and drops bodies. **Default to `--brief` for routine orchestration reads.** "Close / ship it" → `--status done`. ## Work a ticket (safe with other agents) The board may be shared: claim a ticket before touching it, atomically. **Never work a ticket you haven't successfully claimed**, even one you just filed. Lifecycle (executors use the matching MCP tools; CLI forms for inline/admin work): `next`/`claim SQ-3 --by --direct --reason "why this is inline-safe"` (only for the INLINE-SAFE allowlist) → `commit` (declared ticket paths only) → run the briefing-supplied `verify-capture` wrapper after the final commit (it records the ticket, command, and checked candidate) → `submit --commit --verify ""` (parks the verified LOCAL commit). Retyped commands or prose cannot replace that capture. Manual and attestation verifiers keep their evidence flow. or `done --model --effort ` (inline/non-repo only) or `release` (drop unfinished, optionally `--status todo`). - **`--by` must be genuinely unique to this session** — a random token generated once (e.g. `claude-<8 hex>`); a generic label lets two sessions silently coexist as one worker. - **If a claim fails, do not work that ticket.** Retry a denied or unclaimed spawn only when `pulse ` shows a changed dispatch condition; otherwise record the refusal and surface it to the user. Never both resume a prior executor and spawn a fresh one for the same ticket. - **Read the thread before working a ticket** (`sidequest comments `). Default reads retain all metadata; pass `--full` only for needed elided bodies. - **Claims release on observed death, not age**: use `pulse`, never a clock. For work needing a decision, `SendMessage` the same agent. If its name fails, only the ORIGINAL matching host session may send once to authentic `dispatch.agentId` or its exact original Agent-returned identifier; never `claim.by` or a guessed/replacement address. Honor user Pause retries. Missing/mismatched identity stays continuation UNVERIFIED; preserve claim/work. A resume keeps claim, token-file path, and worktree binding. Require authentic response/activity; queued/unknown/completed/absent/failed-send is not death. Never restart terminal executors. Confirmed death requires salvage before replacement. Lost binding and died-before-claim recovery, including preparing-session authority and deadlines: `references/orchestration.md`. - Agents report automatically. **Never use `TaskOutput`** for a Sidequest task ID or launch name. Liveness comes only from `pulse ` and `changes --since`, read on a notification or user prompt, never right after spawning; a process list is never dispatch evidence. **No TaskStop after terminal evidence**: an executor ends its own run at submit, done, or release. `TaskStop({ task_id: "" })` once is host cleanup only for one `pulse` still shows alive after its ticket went terminal (host action, not Sidequest). Never stop a live claim, retained continuation, or candidate awaiting integration; never wake a completed executor or build a cleanup loop. **Never proxy-wait** with a shell/`Monitor`/cron task for an executor or artifact (a one-shot local readiness watch is fine). **Repository publishing is the orchestrator's, alone.** Executors stop at verified local commits and `submit` (claim released, parked in `doing`); `submit.body` is the canonical report, so no separate pre-submit report comment; the terminal comment keeps only commit hash + verification. **Submit is terminal for the executor:** a submitted ticket cannot be amended by messaging the executor that produced it, however small the follow-up looks. File a follow-up ticket for changes. Redispatch the existing ticket only when it was released without a pending submission. The orchestrator is the integrator: choose `sidequest integrate --by --mode apply|replay|merge` from the board default, then run the publish transaction (lock → delivery → merged-tree gate → central version → review → push → reachability → `done`): `references/publishing.md`. **BOOKEND SUPERVISION.** Between dispatch and submission, avoid routine pulses, comment reads and peeks. Explicitly assigned builders and readonly advisors may exchange direct native messages and inspect authorized snapshots under `references/readonly-guidance.md`. Draft findings are advisory, never acceptance or claim release; this does not authorize orchestrator source peeking or self-review. At integration, read the submit report, deliver the range, and run the merged-tree gate once per wave. Judge by that oracle and the submit report, never by reading diffs. When sized risk or a weak oracle needs independent review, bind a routed `review-audit` ticket with `reviewTarget`; never re-review yourself. Never mark a submitted ticket done without integrating it; never re-dispatch one (refused as `submitted`). A dead executor's `done` only proves the board transition, never that work shipped: salvage and close it per `references/publishing.md`. ## Route execution; keep the loop tight Use read-only recon to pin the improvement, benefit, approach, and boundaries before routing; routes select execution capacity, not product decisions. Investigations return compressed findings (~1–2k tokens) as comments. Dispatch implementation fresh; executors own their tickets. Direct claims require an INLINE-SAFE reason (20+ characters); they cannot legitimize prior investigation. Use native `Explore` only for quick sweeps. Deep/fan-out investigation needs `codebase-exploration`; only `Explore`, `claude-code-guide`, and `statusline-setup` are ticket-free harness utilities. **Loop:** spawn a wave, read executor reports and verified submissions, run each ticket's scoped verification, then publish with one full-suite gate. Re-plan for the next wave. Don't accept a green suite as proof of coverage; review execution evidence. **The ticket is the spec:** include outcome, benefit, approach, boundaries, and implementation detail. Spawn prompts add logistics; carry the full ticket contract without narrowing it. **Keep useful work:** retain claims and checkpoints, await `SendMessage` steering for questions or failed checks, and release only on confirmed death or unsalvageable blockers. Batch small same-model tickets in one executor, never mix models. Parallel waves spawn one executor per ticket in a single message. **Ready** = unclaimed, unblocked, not done, not archived — `sidequest ready --json --brief` lists exactly this set, partitioned into **parallel-safe waves** by declared file scope. Fan out one wave at a time; worktrees isolate files, not runtime resources (ports, servers, databases), so serialize those collisions even inside a wave. A claim under a `--by` you don't recognize means another session may be working the board; flag it first. With `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` on, executors ARE teammates — use the teammate affordances, don't ignore them: answer scope requests over the mailbox, steer and resume with `SendMessage`, and never stop→redispatch work a message can fix. Wave mechanics, liveness, salvage, cost levers, agent teams: `references/orchestration.md`. ## Category-first routing (ENFORCED) Sidequest owns ticket routing. Do not recreate a standalone Switchboard (a split-out router could only ever be a shared library imported by Sidequest). The live taxonomy is the routing authority: classify from it, persist the ID, and the category route resolves model and effort — never hand-pick either. Legacy complexity maps to bands at read time (1–3/4–6/7–10 → `coding.easy`/`normal`/`hard`) without persisting a category. 1. **Classify before claim.** A `category: null` ticket gets stamped via `update --category ` **before** claim or spawn, then re-read. Reads never silently persist a classification. 2. **Trust the category projection.** Inject the read's category contract verbatim into the spawn prompt alongside the ticket contract; do not narrow, rewrite, or invent around it. 3. **The ticket read tells you exactly what to spawn.** Print `SQ-n · category · Model · effort`, then spawn the exact `agent` a fresh `dispatch ` returned through native Agent, pass returned fields unchanged. If Agent omits `name`/`mode`, dispatch `reducedAgentSchema: true`; don't restore them. First claim: hook `agent_id` + `permission_mode: auto|bypassPermissions`. **Claude routes**: `model: exec.model` (otherwise it inherits the pricey session model), including Haiku. Use the dispatched executor/model, never generic Agent. **Codex routes** (`exec.model` null): omit `model`; the route marker carries the real model and any value runs Anthropic. Effort is verbatim; mismatched claims are refused. Details: `references/routing-details.md`. 4. **Claim by resolved route:** `next --model X` / `ready --model X` filter by resolved route. ## Comments `comment SQ-3 -m` (durable handoff, keep working) · `comments SQ-3` (read the thread). **Comments are cross-actor handoffs, not diary entries**: decisions, constraints, ruled-out approaches, risks, exact verification command/result, concise findings — no progress narration. **Write findings back after an investigation** — root cause with evidence (`file:line`), the fix, verification. ## Link tickets `sidequest link SQ-4 depends-on SQ-3` (stored on both sides) · `blocks` · `related` (non-blocking) · `unlink` removes. A ticket blocked by an unfinished one is skipped by `next` and excluded from `ready`. ## Guidelines **Act, then report** — run the command, tell the user the result (ref, status, or URL). **Keep titles tight**; detail goes in `-d`. **Don't invent tickets** — only file what the user raised. Reminders, stories, human assignment: `references/board-features.md`.