# Peaks-Loop Default Runbook (orchestrator, full-auto profile)

> **Maintenance**: The numbered workflow list in `skills/peaks-code/SKILL.md` (steps 0-11) is the canonical phase sequence. This runbook is the executable CLI transcription. When updating, keep both in lockstep — a change to one must be reflected in the other.
>
> **Why this is a reference, not inline**: the runbook is a stable, copy-pasteable shell (~150 lines of bash) that does not change between skill runs. Inlining it bloats the orchestrator skill body past the 800-line cap (per `.peaks/standards/common/coding-style.md`). Extracting it here keeps SKILL.md focused on flow / decisions / contracts, while the runbook stays as the canonical place for the CLI sequence.
>
> **How peaks-loop tooling reads this file**:
> - `peaks skill runbook peaks-code` (CLI) reads the `## Default runbook` section in either SKILL.md or `runbook.md` (whichever has the bash code).
> - The CLI applies the same fallback: `## Default runbook` in SKILL.md first, then `runbook.md` here. The test that asserted this was deleted in `f17aa377`.

## Default runbook — CLI sequence

The end-to-end CLI sequence for the `full-auto` profile. `assisted` and `strict` profiles pause at `[CONFIRM]` markers below. `full-auto` and `24h` auto-proceed through all gates. See Transition Gates for artifact verification at each stage.

> **How to resolve a `[CONFIRM]` marker (never a terminal prompt):** the CLI does not read stdin. Without `--confirm` / `--force-confirm` the transition fails with `CONFIRMATION_REQUIRED` and `nextActions`. Code must ask the user via `AskUserQuestion` whether to proceed; if the user approves, re-run the *same* command with `--confirm`. Never wait for a `y/N` prompt — no TTY exists in an LLM-driven session.

Canonical single-shot sub-agent dispatch (the `--prompt` flag is required):

```bash
peaks sub-agent dispatch <role> --prompt "<body>" --request-id <rid> --batch-id <uuid> --json
```

```bash
# 0. Peaks-Loop Snapshot + 0.5 Peaks-Loop Workspace + 0.6 Peaks-Loop Project scan + 0.7 Peaks-Loop Existing-system extraction
peaks doctor --json
peaks project dashboard --project <repo> --json
peaks skill runbook peaks-code --json
peaks workspace init --project <repo> --json
peaks workspace reconcile --project <repo> --json
peaks scan archetype --project <repo> --json
# → copy archetype, frontendOnly, signals into .peaks/project-scan/project-scan.md (Peaks-Loop Gate A; project-level, git-tracked — slice 2026-07-15-project-scan-bootstrap G1)
# → copy libraries[] into .peaks/project-scan/project-scan.md under `## Library versions`
peaks scan libraries --project <repo> --json
# → if archetype != greenfield AND archetype != unknown:
peaks scan existing-system --project <repo> --json
# → copy tokens, sources, conventions, inconsistencies into .peaks/_runtime/<session-id>/system/existing-system.md (Peaks-Loop Gate A.5)

# 1. Peaks-Loop Standards preflight + apply
#    Run dry-run first to inspect deltas, then APPLY. In full-auto and 24h modes,
#    --apply is the default — Standards files (AGENTS.md body, optional CLAUDE.md pointer,
#    rules tree under .peaks/standards/** or .claude/rules/**) live INSIDE the target
#    project and are required for downstream skill preflight, so producing them is part of
#    completing the workflow. Assisted/Strict modes pause for [CONFIRM] between dry-run and apply (AskUserQuestion → re-run with --confirm; no terminal prompt).
peaks standards init   --project <repo> --dry-run --json
# or: peaks standards update --project <repo> --dry-run --json
peaks standards init   --project <repo> --apply --json
# or: peaks standards update --project <repo> --apply --json
# After apply, verify the files actually exist on disk (see Peaks-Loop Gate G).

# ── Step 1.x — `peaks --help` 路由速查(4.x 收敛后:73→9 字节恒等) ─────────
#
#   peaks --help
#     ├─ doctor / code / skill / session / workflow   (5 super-command)
#     ├─ make / learn / sop / sub-agent               (4 ops)
#     └─ (其他 60+ top-level subcommand)
#
# 全 73 个原命令收敛到 9 个 super-command 后,surface 字节恒等;
# 4 ops 路由分别管:动态造 skill / 沉淀学习 / SOP 注册 / sub-agent 派发。
# 若 LLM 看到 peaks-code runbook 里出现老命令(>9 之外的 raw 名字),
# 先 `peaks --help` 校验当前 surface,再决定改 runbook 还是改命令。

# 2. Peaks-Loop PRD (Assisted/Strict: [CONFIRM] before confirmed-by-user
#    → AskUserQuestion; on approval re-run the transition with --confirm)
# Classify the request type from the PRD: feature | bugfix | refactor | docs | config | chore
# This drives RD/QA gate strictness — see "Mandatory RD QA repair loop" for the matrix.
peaks request init --role prd --id <rid> --project <repo> --apply --type <type> --json
# Cross-verify the chosen --type against the current git diff (only meaningful if RD has started writing code;
# safe to run early too, just expect "no changes" rationale until code lands).
peaks scan request-type-sanity --project <repo> --type <type> --json
# → consistent=false → re-classify before continuing. consistent=true → proceed.
# Lint the PRD artifact before transitioning out of draft.
peaks request lint <rid> --role prd --project <repo> --json
# → ok=false → fill in <placeholders>, then re-run.
peaks request transition <rid> --role prd --state confirmed-by-user --project <repo> --json
peaks request transition <rid> --role prd --state handed-off --project <repo> --json

# 2.7. Peaks-Loop Superpowers bridge (effective 2026-07-24, slice 2026-07-24-peaks-code-bridge-002-rootcause)
# Why: peaks-code must coexist with the superpowers skill family without being overridden by it.
# When the user (or the IDE skill picker) suggests invoking superpowers:brainstorming /
# superpowers:writing-plans, the LLM MUST:
#   1. Run the superpowers skill as REFERENCE ONLY — read the brainstorm / plan output.
#   2. Re-author the borrowed plan as a peaks-rd PRD artefact via:
#        peaks sub-agent dispatch prd --prompt "<brainstorm-seed>" --request-id <rid> --batch-id <uuid> --json
#   3. Continue peaks-code from Step 3 (sub-agent fan-out). Do NOT dispatch
#      superpowers:executing-plans or superpowers:subagent-driven-development; peaks-rd / peaks-qa
#      own plan execution.
# Verify junction integrity before any LLM edit to a user-global skill path:
#   fsutil reparsepoint query "$HOME/.claude/skills/peaks-code"   # Windows
#   readlink -f "$HOME/.claude/skills/peaks-code"                 # POSIX
# → not a junction (or not a symlink) → STOP and re-route via peaks skill sync after junction rebuild.
# Forbidden: hand-authoring hook scripts at ~/.claude/skills/peaks-code/hooks/*. Hook source MUST
# come from src/services/hooks/*.sh in the peaks-loop repo, distributed by `peaks hooks install`.
# Mandatory closure: every peaks-code request MUST finish `peaks request transition` through
# `spec-locked → implemented → qa-handoff → handed-off` plus `peaks memory extract`.

# 3. Peaks-Loop Default sub-agent fan-out (slice 5 contract)
#    Code computes the swarm plan from --type + frontendOnly + frontend-keyword scan,
#    writes it to .peaks/_runtime/<sid>/sc/swarm-plan.json, then writes the slice
#    DAG to .peaks/_runtime/<sid>/sc/slice-dag.json and launches ONE
#    `peaks sub-agent dispatch --from-dag <dag-file>` call. The CLI's
#    envelope.dispatchCount is N (not 1) when the DAG has >= 2 leaves at the
#    same topological level — that is the canonical "fan-out" signal. The
#    orchestrator emits N parallel `buildToolCall` descriptors in ONE response;
#    the LLM-side runner executes them concurrently.
#    See "Peaks-Loop Default sub-agent fan-out" above for the default rule and
#    exceptions; the gate logic is single-sourced in references/swarm-dispatch-contract.md.
#    Hard rule: do NOT call Skill(skill="peaks-rd" | "peaks-qa" | "peaks-ui") from
#    the Swarm phase — that's the v1.x anti-pattern. And do NOT issue N sequential
#    `peaks sub-agent dispatch <role>` calls in N separate messages when a fan-out
#    shape exists — `--from-dag` is the only path that exercises the orchestrator.
#
# 3a. Pre-fan-out: Code initialises every role's request artefact slot in the main
#     loop so sub-agents find a stable rid <-> artefact binding. Each role's
#     sub-agent may also call peaks request init itself (idempotent on the same rid);
#     Code's call here is the source of truth. Only init roles that are in the
#     swarm plan — roles not in the plan do not get a slot yet.
peaks skill presence:set peaks-code --project <repo> --mode <mode> --gate swarm-fan-out
# for each role in swarm-plan.subAgents:
# peaks request init --role ui --id <rid> --project <repo> --apply --type <type> --json
# peaks request init --role rd --id <rid> --project <repo> --apply --type <type> --json
# peaks request init --role qa --id <rid> --project <repo> --apply --type <type> --json
# e.g. if plan = [ui, rd, qa]: run init for ui, rd, qa.
# If plan = [rd, qa]: run for rd, qa only.
# If plan = [] (config|docs|chore skip): no inits here, jump to step 4 directly.
# 3b. Code writes the slice DAG to a JSON file then issues ONE
#     `peaks sub-agent dispatch --from-dag <dag-file> --batch-id <id>` call.
#     The CLI envelope returns N parallel buildToolCall descriptors
#     (dispatchCount = len(swarm-plan.subAgents) when the DAG has >= 2
#     same-level leaves; 1 otherwise). Each prompt embeds the role's body
#     minus Step 0 / presence, plus the runtime args (rid / sid / mode /
#     type / paths). The orchestrator's Promise.all drives the N leaves
#     concurrently, so wall-time approximates max(per-leaf time), not sum.
peaks sc build-dag --change-id <cid> --project <repo> --json > .peaks/_runtime/<sid>/sc/slice-dag.json
peaks sub-agent dispatch --from-dag .peaks/_runtime/<sid>/sc/slice-dag.json --batch-id <id> --project <repo> --json
# 3c. After fan-out, Code restores presence once and runs Gate B (ls checks):
peaks skill presence:set peaks-code --project <repo> --mode <mode> --gate swarm-converged
ls .peaks/_runtime/<sid>/prd/requests/<rid>.md                # PRD artefact must exist (Gate B hard)
# feature / refactor → ls .peaks/_runtime/<sid>/rd/tech-doc.md
# bugfix             → ls .peaks/_runtime/<sid>/rd/bug-analysis-<rid>.md
ls .peaks/_runtime/<sid>/qa/test-cases/<rid>.md                # QA test-cases (skipped for docs|chore)
# ui (only when in plan):
ls .peaks/_runtime/<sid>/ui/design-draft.md 2>&1               # non-blocking (Gate B info)
# Apply the degradation rules in the main SKILL.md if any artefact is missing.
# → Peaks-Loop Gate B convergence check. Assisted/Strict: [CONFIRM]
#   → AskUserQuestion; on approval re-run the transition with --confirm

# 4. Peaks-Loop RD planning artifact (the file required by the prerequisite gate)
#    feature / refactor → write .peaks/_runtime/<id>/rd/tech-doc.md
#    bugfix             → write .peaks/_runtime/<id>/rd/bug-analysis-<rid>.md
#    config             → no planning artifact required at this state
#    docs / chore       → no planning artifact required
#    The RD state machine is a SEQUENCE (draft → spec-locked → implemented →
#    qa-handoff → handed-off) and the CLI refuses a forward jump, so lock the
#    plan first, then declare it implemented. Backward moves (the QA
#    return-to-rd repair re-enters spec-locked) are always legal.
peaks request transition <rid> --role rd --state spec-locked --project <repo> --json
peaks request transition <rid> --role rd --state implemented --project <repo> --json

# 5. Peaks-Loop Code review + security review BEFORE qa-handoff transition.
#    Produce the evidence files the CLI gate enforces:
#      - .peaks/_runtime/<id>/rd/code-review-<rid>.md  (CRITICAL/HIGH findings + fixes; required for feature/bugfix/refactor)
#      - .peaks/_runtime/<id>/audit/security-<rid>.md  (required for feature/bugfix/refactor; the config type instead requires rd/security-review-<rid>.md)
#      The pre-rid names remain accepted back-compat tiers, but writing one re-opens the two-slices-one-session collision (slices 2026-09-14-audit-artifact-rid-scoping and 2026-10-14-backlog-9-37-prereq-collisions).
#    Then transition. If --type is docs/chore the gate is empty and the transition is unguarded.
peaks request transition <rid> --role rd --state qa-handoff --project <repo> --json

# 6. Peaks-Loop QA validation (AUTO-PROCEED from RD in full-auto)
#    Before each QA transition, produce the evidence files the CLI gate enforces:
#      Before qa:running        → .peaks/_runtime/<id>/qa/test-cases/<rid>.md
peaks request transition <rid> --role qa --state running --project <repo> --json
#      Before qa:verdict-issued → .peaks/_runtime/<id>/qa/test-reports/<rid>.md
#      (no qa/security-findings.md or qa/performance-findings.md: no qa:verdict-issued
#       table holds them since the v2.11.0 D1/D4 trim — peaks-rd's audit fan-out owns
#       that evidence; see skills/bee/peaks-qa/references/qa-transition-gates.md).
peaks request transition <rid> --role qa --state verdict-issued --project <repo> --json
# → Peaks-Loop Gate D check. Assisted/Strict: [CONFIRM]
#   → AskUserQuestion; on approval re-run the transition with --confirm

# 7. Peaks-Loop RD↔QA repair loop — if verdict is return-to-rd, re-run 4 through 6 until QA passes or blocked TXT.
#    Before invoking peaks-rd again, check the cycle count so you don't blow past the cap silently:
peaks request repair-status <rid> --project <repo> --json
# → atCap=true → STOP and emit a blocked TXT handoff. Do NOT enter another cycle.
# → remaining > 0 → safe to continue. The next transition's --reason must include "QA return-to-rd cycle N: ..."
#                   so this command keeps counting accurately.
# After RD finishes the repair, re-check that the diff is still consistent with the declared --type:
peaks scan request-type-sanity --project <repo> --type <type> --json
# → consistent=false → RD scope-creeped during repair; review before re-handoff.

# 8. Peaks-Loop SC phase
peaks sc impact --change-id <cid> --module <module> --file <path> --json
peaks sc retention --slice-id <rid> --prd <prd> --rd <rd> --qa <qa> --json
peaks sc validate --slice-id <rid> --json
peaks sc boundary --slice-id <rid> --artifact <artifact> --code <file> --json

# 9. Peaks-Loop Workspace reconcile (slate cleanup)
peaks workspace reconcile --project <repo> --apply --older-than 7

# 10. Peaks-Loop TXT handoff — invoke peaks-txt which embeds memory markers (BLOCKING)
#     peaks-txt writes the handoff capsule to .peaks/_runtime/<id>/txt/handoff.md. Inside the
#     capsule body, peaks-txt embeds <!-- peaks-memory:start --> blocks for every
#     stable project fact surfaced this session. Applies to ALL modes including
#     `assisted` (audit 2026-07-03 found `assisted` previously skipped this step).
#
# 10a. Skill-side scan (do this BEFORE the AskUserQuestion below):
#      grep -n "peaks-memory:start" .peaks/_runtime/<id>/txt/handoff.md
#      Record the count. This is the skill doing the work, not a CLI command —
#      we deliberately do not ship a `peaks memory scan` because the LLM is
#      the only consumer and the LLM has grep.

# 10b. AskUserQuestion (only if 10a returned count >= 1):
#      "The TXT handoff has N peaks-memory:start blocks. Persist to .peaks/memory/?
#       (a) Apply all — `peaks memory extract --project <repo>
#                            --artifact .peaks/_runtime/<id>/txt/handoff.md --apply --json`
#       (b) Apply selectively — re-edit handoff.md first, then re-apply
#       (c) Skip for now — blocks stay in the handoff only, no .peaks/memory/ write"
#      If 10a returned 0 AND the session surfaced a stable project fact
#      (decision / convention / approved refactor), STOP — peaks-txt must go
#      back and embed at least one block before Code can advance.

# 10c. After the user picks (a) or (b), run:
peaks memory extract --project <repo> --artifact .peaks/_runtime/<id>/txt/handoff.md --apply --json
#      --apply is REQUIRED to write .peaks/memory/; without it the command only
#      previews. The extract regenerates index.json in the same call.

# 10d. Index hygiene (single authority: .peaks/memory/ is peaks-owned):
peaks memory reindex --project <repo> --json          # drift report (unclassified / orphans both ways)
peaks memory reindex --project <repo> --apply --json  # rebuild index.json + regenerate MEMORY.md
peaks memory ingest  --project <repo> --json          # preview IDE-side session notes
peaks memory ingest  --project <repo> --apply --json  # import them into .peaks/memory (IDE side stays read-only)

# 11. Peaks-Loop Final snapshot
peaks project dashboard --project <repo> --json
peaks skill doctor --json
```

## 24h mode — bridge surface (rid-020b)

```bash
# Inspect the current 24h-mode state snapshot (rid-020a backbone)
peaks session 24h-mode state --json

# Code-run with the 24h flag (T3/T4 auto-engage; otherwise brainstorming reference-only bridge)
peaks code run <change-id> --24h --tier T3 --project <repo> --json
peaks code run <change-id> --24h --tier T2 --project <repo> --json   # non-T3/T4 → Bucket B (reference-only)
peaks code run <change-id> --24h --trigger T4 --project <repo> --json # T4 also auto-engages 24H_ACTIVE

# Read-only 24h long-run indicator dashboard (5 indicator classes + boundary cases)
peaks dashboard long-run --since 24h --project <repo> --json
peaks dashboard long-run --since 8h  --project <repo> --json
peaks dashboard long-run --since 30m --project <repo> --json
peaks dashboard long-run --since 72h --project <repo> --json   # capped at 24h

# Manual state transition (Bucket C — user-confirm path)
peaks session 24h-mode transition --state 24H_ACTIVE --reason "T1 keyword match" --project <repo> --json
peaks session 24h-mode transition --state HANDOFF --exit-condition user_abort --project <repo> --json
```

Repair loop details: see `## Mandatory RD QA repair loop` in SKILL.md for the full 5-step procedure and the 3-cycle cap. Append transition notes via `--reason` rather than rewriting artifacts during repair cycles.

```bash

# Peaks-Loop Default runbook — Job path (excerpt; full flow in references/job-loop.md)

# Step 0.8 (BLOCKING): LLM judges Job-shape, CLI records it.
# This is a RECORDER, not a detector. The LLM supplies --is-job + --rationale;
# the CLI writes .peaks/_runtime/<sid>/job-shape.json. Downstream steps call
# `peaks code read-job-shape` to enforce the decision exists.

# (The LLM does the semantic judgement, e.g.:)
#   "The user named N=35 parallel app/ subdirs, said 'continue until all done',
#    and disavowed cost. isJob=true, rationale=..., suggestedJobId=app-ut-batch,
#    suggestedStrategy=rotating, confidence=high."
peaks code detect-job \
  --is-job true \
  --rationale "35 parallel app/ subdirs + 'until all done' + '不用考虑费用'" \
  --suggested-job-id app-ut-batch \
  --suggested-strategy rotating \
  --confidence high

# Step 0.81-init: if Job-shaped, init BEFORE Step 1.
DECISION=$(peaks code read-job-shape --json)
if [ "$(echo "$DECISION" | jq -r '.data.decision.isJob')" = "true" ]; then
  JID=$(echo "$DECISION" | jq -r '.data.decision.suggestedJobId')
  STRATEGY=$(echo "$DECISION" | jq -r '.data.decision.suggestedStrategy')
  # LLM-derived slice list (not CLI-derived).
  peaks job init --job-id "$JID" --slice-list "<LLM_DERIVED>" --main-loop-strategy "$STRATEGY" --rotate-every 3 --json
fi

# After Step 7 (RD+QA commit) lands AND Step 0.8 fired (state.json exists):
peaks job checkpoint --slice-id <rid> --state done --commit-sha $(git rev-parse HEAD)
# v3.1.2: `peaks job checkpoint --state done` ALSO writes
# .peaks/_runtime/<sid>/job/<jid>/progress.json. Read it on resume:
peaks job progress --job-id <jid> --json
peaks job status --job-id <jid> --json
peaks job subagent-cleanup --job-id <jid> --batch-id <bid> --force   # Step 0.87 gate
# Loop control:
#   remaining > 0  → return to Step 1 (next slice)
#   remaining == 0 → Step 8/9/10/11 (original tail)
#   blocked (strict) → peaks job block + STOP
# Rotating-mode: every rotateEvery slices → Step 0.86 (peaks session rotate + resume)

# v3.1.2 size-fear ban: refuse to emit a final handoff while remaining > 0.
# The LLM cannot bypass this; --force-under-job requires explicit user approval.
peaks code emit-handoff --project <repo> --job-id <jid> --json

# v3.1.2 forced auto-compact: when --enforce-job-mode is set OR
# job-shape.json says isJob=true, ≥0.85 is MANDATORY auto-compact.
# The trigger line is actually 0.80, not 0.85: `peaks skill presence`
# reports action='auto-fire' from ≥0.80 and that tier is already mandatory
# in every mode, so context-now's 0.85 is the *second* line to arrive.
# Code MUST call this without confirmation under Job mode.
peaks code context-now --project <repo> --enforce-job-mode --json
peaks code auto-compact --project <repo> --json

# v3.1.2 PreToolUse gate (installed by `peaks workspace init`):
# every Bash tool call runs `peaks code gate-step-08` automatically.
# Exit 0 = allow (with optional Next: slice #N+1 of M line when
# progress.json exists). Exit 2 = BLOCKED; LLM must call
# `peaks code detect-job` first.
peaks code gate-step-08 --project <repo> --json

# rid-020a: 24h mode state machine. The CLI is the muscle; peaks-code
# is the LLM that drives it. Sub-actions: state, transition, attempts,
# reset. Persists to .peaks/_runtime/<sessionId>/24h-state.json. The
# full SKILL.md chapter and rid-020b code-run sub-command ship next.
peaks session 24h-mode state --project <repo> --session-id <sessionId> --json
peaks session 24h-mode transition --state 24H_ACTIVE --project <repo> --session-id <sessionId> --json
peaks session 24h-mode attempts --project <repo> --session-id <sessionId> --json
peaks session 24h-mode reset --project <repo> --session-id <sessionId> --json
```
