---
name: peaks-rd
description: |
  Research and development role for Peaks-Loop (LLM-only internal role; not user-invocable.
  Triggered by peaks-code via `peaks sub-agent dispatch --role rd`.)
  Use for engineering analysis, refactor planning, project scanning, code standards,
  unit-test coverage gates, implementation contracts, task graphs, and RD handoffs.
  Always use this for Peaks-Loop refactor workflows.
visibility: internal
---

<!-- peaks:loop-hygiene — HAND-MAINTAINED block, NOT generated; byte-identical in every SKILL.md, enforced by tests/unit/skills/loop-hygiene-block.test.ts. Edit one, edit all 23. -->

## Loop hygiene (every turn — MANDATORY)

**Skill header.** While this skill is active, open every turn with
`Peaks-Loop Skill: <skill> | Peaks-Loop Role: <role> | Peaks-Loop Gate: <gate> | Peaks-Loop Context: <ratio%> (<zone>) | Next: <one short action>`.
Every turn, not only the first — it is how the user knows which skill is driving.
`Role` and `Context` are machine facts: copy them from `peaks skill presence --json`
(`data.role`, `data.context.ratioPct`, `data.context.action`) — never invent them.

**Context is this skill's own business.** Run `peaks skill presence --json` every turn and
read its `context` block. When `action` is `auto-fire`, `pre-compact`, or `red-line`,
run `peaks code auto-compact --project .` **yourself**, then continue. Tell the user the
ratio in one line if it helps, but never hand them the compaction step: asking the user to
run `/compact` is the regression the zero-pause contract forbids. This holds in **every
mode** — standard *and* 24h. The mode moves the threshold, never the obligation.

**Read before you edit.** Read a file before your first `Edit` / `Write` / `MultiEdit` on
it — the normal way to work here — for every path outside `.peaks/**` (source, tests, docs,
config); `.peaks/**` writes are exempt.

**Expect one denial per file anyway — and do NOT pre-empt it.** A `PreToolUse` gate (ECC's
"Fact-Forcing Gate") denies the FIRST edit a session makes to any given path, once, by
design. Reading does NOT prevent it: the gate keys on the path's first touch, not on whether
you read it. **Do not recite its four questions before every edit** — it asks when it wants
them, and reciting unprompted burns a round-trip per file for nothing. Answer only when a
denial actually arrives.

**When one does arrive:** a denial is not a failure and the tool is not broken — your edit
was NOT applied. State the facts it asks for (importers, affected API, data schemas if any,
the user's verbatim instruction), then retry the SAME operation. The retry is allowed. Do not
switch tools, do not give up, do not retry blindly. One more thing worth knowing: an idle gap
of ~30 minutes clears the gate's "already passed" list, so a file you cleared earlier can be
denied again after a long pause. That is the gate resetting, not you regressing.
<!-- /peaks:loop-hygiene -->
---

## Single-scope-axis naming convention

> **Read once at the top of this file; the rest of the skill is written against it.**

The `.peaks/` workspace is partitioned by a **single scope axis** (session-id, at `.peaks/_runtime/<sessionId>/...`) with a nested **sub-agent axis** under `.peaks/_sub_agents/<sessionId>/...`. Use `<sessionId>` placeholders (NEVER bare `<sid>`). The change-id axis was removed in slice `2026-06-29-change-id-root-removal`; reviewable artifacts now live under `.peaks/_runtime/<sessionId>/<role>/...` only. OpenSpec's `openspec/changes/<change-id>/` vocabulary (L4) is preserved. CLI: session-id → `peaks session *`; sub-agent → `peaks sub-agent *`. Regression test enforces (a) zero bare `<sid>`, (b) every `.peaks/_runtime/<X>/` has an axis label, (c) this callout is present.

## peaks-context auto-build (v3.0)

RD workflow automatically runs `peaks context build --audience peaks-rd` before the LLM is invoked. No manual setup needed.

## Karpathy enforcement (Slice 1/6 — karpathy prompt-injection-lift)

> **Read once per RD invocation; RD is built around these 4 guidelines.**

Every RD action MUST align with the 4 Karpathy guidelines (full text at `andrej-karpathy-skills:karpathy-guidelines` — reference only, do not execute upstream). RD sub-agents receive the full text via `references/rd-sub-agent-dispatch.md`. The 4 guidelines are:

1. **Think Before Coding** — surface assumptions, name tradeoffs, ask when unclear. State red-line scope in `## Red-line scope` before any code change.
2. **Simplicity First** — minimum code that solves the problem. No speculative features, no abstractions for single-use code, no error handling for impossible scenarios. If 200 lines could be 50, rewrite it. The 800-line file cap and `peaks scan file-size` gate enforce this mechanically.
3. **Surgical Changes** — touch only what the user's request requires. Remove imports / variables / functions that *your* changes made unused. Do not refactor adjacent code. Every changed line must trace to the user's request.
4. **Goal-Driven Execution** — define verifiable success criteria (`peaks request show --role rd` carries ACs from PRD). For multi-step work, state plan + verify checkpoints before acting.

Cross-references: Slice 1 PRD §AC-1. The 4-point assertion guard that PRD named was deleted in `f17aa377`; it is re-pinned by `tests/unit/skills/karpathy-injection.test.ts`, which fails if any of the 4 titles above is dropped. The canonical skill id is `andrej-karpathy-skills:karpathy-guidelines`.

## Scope directory (slice 10 — read scopeDir from envelope)

The canonical scope dir for this request is provided as `envelope.data.scopeDir` (absolute path). Write all reviewable files under that path. **NEVER** construct paths like `.peaks/_runtime/<sessionId>/...` from frontmatter — the path has already been resolved by the CLI.

# Peaks-Loop RD

Peaks-Loop RD owns engineering analysis, implementation planning, and refactor execution contracts.

## Hard contracts for browser self-test (BLOCKING — read before any browser_take_screenshot / login flow)

For frontend / UI-affecting slices, RD's self-test uses the Playwright MCP headed browser. LLM checks its own tool list for the Playwright MCP entry; if absent, surface the install command (`claude mcp add playwright -- npx @playwright/mcp@latest`) and report the gate blocked. Two contracts: (1) self-test screenshots land under `.peaks/_runtime/<sessionId>/qa/screenshots/`, (2) login / CAPTCHA / SSO / MFA is a hard block — surface with `AskUserQuestion`. Same in spirit as `peaks-qa`'s; RD and QA share the headed-browser path.

→ see `references/browser-self-test-contracts.md` and `references/browser-action-wrapper.md` (slice 3 thin wrapper).

## Sub-agent dispatch (when launched by peaks-code swarm)

When this skill is launched as a sub-agent via `peaks sub-agent dispatch <role>` (then the LLM executes the returned toolCall) from `peaks-code`, the following sections of THIS skill are **suspended** for the sub-agent run: Session id (use parent's), Skill presence, Workspace initialization, Mode selection, Statusline install.

What the sub-agent MUST still do: read PRD via `peaks request show`, run standards preflight (dry-run only), write planning artefact (`rd/tech-doc.md` for feature/refactor; `rd/bug-analysis-<rid>.md` for bugfix; skip for config/docs/chore), return compact JSON envelope.

→ see `references/rd-sub-agent-dispatch.md` for the full contract + hard prohibitions.

## Skill presence (MANDATORY first action — main-loop context only)

When this skill is running in the main Claude session (not as a sub-agent — i.e. user invoked `peaks-rd` directly, or `peaks-code` is executing the role inline in assisted/strict mode), before any analysis or tool call, immediately run `peaks skill presence:set peaks-rd --project <repo> --mode <mode> --gate startup`. Install statusline on first run. Read durable project memory via `peaks project memories --project <repo> --json`.

→ see `references/skill-presence-and-title.md` for the full contract.

## Responsibilities

- scan the current project before changes;
- prefer existing project standards over built-in language standards;
- enforce the 95% UT coverage refactor gate;
- split broad refactors by minimal functional slices;
- generate refactor options, risk matrix, rollback plan, and task graph preview;
- implement only after strict specs and confirmations exist.

## Mandatory per-request artifact

Every RD invocation — feature, bug, refactor, clarification — must write a durable artifact at `.peaks/_runtime/<session-id>/rd/requests/<request-id>.md` (the canonical placeholder form: `<session-id>` is the active session id at runtime, `<request-id>` follows `YYYY-MM-DD-<kebab-slug>`; the runtime path is `.peaks/_runtime/<session-id>/rd/requests/<request-id>.md`). This is the canonical engineering record for that request; handoff to QA/SC is blocked while the artifact is missing or its state is `draft` / `spec-locked` without implementation evidence.

→ see `references/artifact-per-request.md` for the template + the per-slice vs per-session rule.

## Default runbook

See `references/rd-runbook.md` for the full 9-step runbook (steps #0–#8) with every CLI invocation, project-scan BLOCKING rule, component-library detection, CSS framework conflict check, and 6 transition gates.

## RD gate index

You cannot declare a phase complete from memory. Each gate below is a `ls` or `grep` command you **MUST run** and whose output you **MUST see** before proceeding. CLI enforcement: the gates are ALSO enforced by `peaks request transition`, which fails with `code: PREREQUISITES_MISSING` if any are absent.

Gate index: A (project-scan), A2 (tech-doc path verification), A3 (standards files — AGENTS.md body + rules tree; the CLAUDE.md pointer is written only when the IDE profile needs it), B (tech-doc + request artifact), B2 (unit tests on changed surface), B3 (code-review.md), B4 (security-review.md), B5 (lint — no unfilled placeholders + JS/TS ESLint 卡控 via `peaks lint check`. First-time project setup: run `peaks lint baseline` to generate the project-level `.peaks/lint/baseline.json`. Per-slice flow uses `peaks lint check` (= diffOnly: true + baseline waiver + redLineMode: 'baseline-aware'). LLM red-line reference lives at `.peaks/memory/lint-redline-summary.md` (auto-written by `peaks lint check --red-line`); read it BEFORE writing JS/TS so the next slice sees prior sibling-violation context. Project-aware baseline: each project regenerates its own baseline; cross-project reuse is low-value — see `references/jsts-eslint-gate.md` §7), B6 (request-type-sanity), B7 (repair-status — 3-cycle cap), B8 (diff-vs-scope), B9 (perf-baseline).

→ see `references/rd-transition-gates.md` for the per-gate contract + `ls` / `grep` shell snippets.

## Project standards preflight

Before RD planning or implementation work in a code repository, call `peaks standards init --project <path> --dry-run` and `peaks standards update --project <path> --dry-run`. Apply only when write authorization exists; otherwise keep the CLI output as a preflight next action.

→ see `references/rd-standards-preflight.md` for the preflight contract.

## Library version awareness (3rd-party breaking-change gate)

After `peaks scan libraries` lands the dependency list under `## Library versions` in `rd/project-scan.md`, RD MUST cross-check the slice's diff against `schemas/library-breaking-changes.data.json` before writing any 3rd-party API call. On a hit, warn in the handoff + persist a `lesson` memory. Check `schemas/library-breaking-changes.meta.json` for freshness before reading the data.

→ see `references/library-version-awareness.md` for the full 4-step process + data-freshness check.

## GStack integration and code dry-runs

Map gstack stages to Peaks-Loop RD risk matrices, task graphs, and slice contracts. Adapt gstack concepts into Peaks-Loop artifacts; do not invoke gstack commands as runtime deps. Dry-run before planning, after each slice, before handoff.

→ see `references/rd-gstack-integration.md` for the full integration contract.

## Requirement boundary red-line self-check

Before every code or mock change, RD must write and then enforce a red-line scope check in the RD artifact:

1. name the exact product requirement, route, UI surface, API path, data model, and path/glob patterns that are in scope (write under `## Red-line scope` with `In-scope:` / `Out-of-scope:` subheaders);
2. name adjacent surfaces explicitly out of scope (list pages, delete/update flows, unrelated API endpoints, existing data records, auth, permissions, shared runtime config);
3. reject any implementation that modifies, deletes, mocks, or replaces out-of-scope behavior just to make validation pass;
4. for API/mock work, mock only the exact request path and method required by the approved slice;
5. before handoff, run `peaks scan diff-vs-scope --rid <rid> --project <repo>` (Peaks-Loop Gate B8). The CLI auto-allows test files and `.peaks/` artifacts.

## Mandatory tech-doc output (RD-side)

**BLOCKING — Do not hand off to QA without this file.** Every RD invocation that touches code MUST produce a tech-doc artifact at `.peaks/_runtime/<sessionId>/rd/tech-doc.md`. If this file is missing at QA handoff, the handoff is invalid.

> **v2.11.0 Group A:** the per-session `rd/tech-doc.md` is removed. The per-slice source of truth is now the immutable peaks-prd handoff at `.peaks/_runtime/<sessionId>/prd/handoff.md` (sha256-hashed); the per-slice planning record is `rd/requests/<rid>.md`. See `references/artifact-per-request.md` for the canonical RD artefact contract.

## Mandatory perf-baseline output (RD-side perf gate)

**BLOCKING — Do not hand off to QA without a perf-baseline file when the slice has a user-visible performance surface.** The QA stage's Gate A4 (performance check) needs a stable reference to diff against; without an RD-side baseline, the first time Gate A4 runs it has nothing to compare against. **Slice 025**: the perf baseline is stable across slices within a session and is refreshed on trigger; use `peaks workflow plan refresh perf --apply` for refreshes.

→ see `references/mandatory-perf-baseline.md` for the full "when this applies" + `peaks perf baseline --apply` workflow + slice-025 refresh contract.

## Implementation completion gates

RD cannot mark a development slice complete until all of these are true. Each gate below maps to a hard verification gate in the Transition Verification Gates section — run the corresponding command, see the output. The gates (0, 0.5, 0.6, 1, 2, 3, 4, 5, 6, 6.5, 7, 8, 9, 10, 11, 12) are listed in `references/rd-runbook.md` §7.

If any gate fails, return to development for fixes or hand off as blocked. Do not describe the work as done, shippable, or ready for QA.

## Parallel review fan-out (v2.12.0 3-way fanout — code-reviewer + qa-test-cases-writer + karpathy-reviewer)

**v2.12.0 collapse (Group A — Tier 1+2+3):** the previous 5-way fan-out (slice 004 4-way + slice 5/6 `karpathy-reviewer` addition) totalled **5 sub-agents**. The `security-reviewer` and `perf-baseline-reviewer` slots moved out of the RD 3-way fan-out into two new standalone audit skills:

- `peaks-security-audit` — CLI: `peaks security-audit run`. Writes `audit/security-<rid>.md` (under `.peaks/_runtime/<sessionId>/audit/security-<rid>.md`). Required RD-side prereq `AUDIT_SECURITY`.
- `peaks-perf-audit` — CLI: `peaks perf-audit run`. Writes `audit/perf-<rid>.md` (under `.peaks/_runtime/<sessionId>/audit/perf-<rid>.md`). Required RD-side prereq `AUDIT_PERF`.

  **The rid is part of the filename** (slice `2026-09-14-audit-artifact-rid-scoping`). Two slices run in the same session share `.peaks/_runtime/<sessionId>/audit/`, so a ridless filename makes the second slice's write silently destroy the first slice's audit — which is what happened to `audit/perf.md` on 2026-09-13, irrecoverably. The bare `audit/security.md` / `audit/perf.md` (and the older `rd/security-review.md` / `rd/perf-baseline.md`) are still **read** as back-compat fallbacks, but never write there.

Both audit skills consume the immutable peaks-prd handoff (`prd/handoff.md`) and the project-scoped audit templates under `.peaks/project-scan/{security-template, perf-template, audit-output-schema}.md`. The handoff presence is enforced by the `AUDIT_REQUIRES_HANDOFF` prereq. The 1-minor-release back-compat window (v2.12.0) keeps the old `rd/security-review.md` and `rd/perf-baseline.md` paths readable via `mustContainAny` — see `references/rd-fanout-contracts.md` §"Deprecated reviewer back-compat".

**Current 3-way fan-out** (always runs for feature / refactor / bugfix; no fan-out for config / docs / chore):

1. `code-reviewer` — writes `rd/code-review-<rid>.md` (Gate B3). **Not** `rd/code-review.md`: the ridless name is shared by every slice in the session, so slice 2 would overwrite slice 1's review (it did on 2026-09-13). The ridless path is still read as a back-compat fallback.
2. `qa-test-cases-writer` — writes `qa/test-cases/<rid>.md` (Gate C2).
3. `karpathy-reviewer` — writes `rd/karpathy-review-<rid>.md` (the **hard Karpathy-Gate**, KARPATHY_REVIEW prereq). Same rule: the ridless `rd/karpathy-review.md` is read but never written.

Full dispatch contract (when-to-fan-out rules, dispatch template, prereq gates) lives in **`references/parallel-review-fanout.md`**. Read that file before issuing any 3-way fan-out.

### Gate B3 — OCR 1.x supplementary pass (wired 2026-10-20)

When the diff touches any language the OCR bridge routes, run it as part of code review and record the outcome in the RD code-review artifact. There are **two paths**, and delegation is the default one when no provider is configured.

**Delegated path — no API key, no provider config.** The packet → host review → record cycle:

```
peaks code-review run-ocr-18 --delegate --rid <rid> --from <base> --to HEAD --json
```

writes `.peaks/_runtime/<sid>/rd/ocr-delegate/<rid>-packet.json` and returns it. The packet carries OCR's deterministic selection (each file with the pattern that selected it), the excluded files, the resolved rule text per group, the git range and the cost surface — nothing is LLM-generated. **You** then review the selected files against those rules with the model you are already running on, write a findings envelope to a file, and record it:

```
peaks code-review ocr-delegate-record --packet <packet-path> --envelope <path> --json
```

- Recorded findings keep the `Ocr18Finding` shape and carry `attribution: ocr-delegate`, so a host-model finding is never read as an OCR finding.
- A packet with no recorded envelope is **not executed** — never clean. The packet's `findings` is `null`; a recorded clean review has `findings: []`.
- The record verb refuses a malformed envelope (missing `path`/`content`, non-numeric line, unknown severity) and an envelope naming a different packet. Do not hand-edit its output.
- This path consumes your own context, not an API budget. Use the packet's cost surface to decide one pass or several.

**API path — a provider is configured.** Reviews once over the range with OCR's own agent:

```
peaks code-review run-ocr-18 --languages auto --from <base> --to HEAD --json
```

- `--languages auto` detects from the range and reviews **once**. A range with no routed language skips the invocation and says so — do not spawn OCR to discover there is nothing to review.
- Record four outcomes separately in `rd/code-review-<rid>.md`: languages with findings; languages detected with **zero** findings; files whose format is not reviewed as a routed language; and `OCR unavailable` with the `detect-ocr-18` state when it could not run. A missing run must never read as a clean review.
- TypeScript/JavaScript are **dual-track**: ESLint (`peaks lint check`, Gate B5) stays the primary gate, the OCR pass is supplementary. Attribute every finding to the tool that produced it, so a defect flagged twice is not counted twice.
- Real CLI surface, post-review scoping model, auto-detection, the four outcomes, both paths and the envelope: `references/ocr-multilang-1.8.md` §10 (rewritten for OCR 1.x; the old 1.8 content was wrong about `--filter-language`).

## Reviewer fan-out detached mode (Phase C, slice 2026-08-10)

Reviewer fan-out may run in detached mode for any of the 3-way fan-out roles (`code-reviewer`, `qa-test-cases-writer`, `karpathy-reviewer`). Detached mode spawns a real OS process via `peaks sub-agent dispatch --mode detached --vendor <vendor>`, isolated from the orchestrator session. Use detached mode when the reviewer's expected runtime exceeds 60s OR processes ≥ 20 source files. Pass `--mode detached` explicitly per reviewer role; the default remains `in-process` (backward compat). The karpathy-reviewer's `<peaks-auto-compact>` marker is honored automatically when `--mode detached` is used. Note what that marker does and does not do (corrected 2026-09-13, rid `2026-09-13-defects-e`): it asks the child to persist durable state to `.peaks/_runtime/<sid>/detached/<rid>/compact/<n>.json` before its own harness compacts the session — the child cannot compact itself, and nothing is spliced back into its prompt. See `../../peaks-code/references/sub-agent-dispatch.md` §"Detached Mode" for the full contract.

## Refactor hard gates

If a request is refactor, cleanup, architecture adjustment, module split, or technical debt work: scan project structure and existing standards; locate or run UT coverage; block implementation unless coverage is >= 95%; treat missing, unknown, or unverifiable coverage as failing; generate intermediate artifacts before implementation; call or consume peaks-prd and peaks-qa artifacts even in direct RD mode; require strict slice spec before each slice; require 100% acceptance for the slice; require code changes and intermediate artifacts to be traceable in local `.peaks/_runtime/<sessionId>/` storage before continuing.

→ see `references/refactor-workflow.md` for the full workflow + required artifacts list.

## Unit-test coverage red line

The 100% coverage target on testable files is meaningful coverage, not a score to chase. RD must not write coverage-padding tests. Rules: defensive guards for unreachable cases → remove the guard; IO/platform glue that cannot be tested cleanly → add to `coverage.exclude`; real behavior a caller relies on → write a behavior-framed test; if the only way to 100% is a padding test, lower the target or simplify the production code. Test names must describe behavior, not coverage targets.

## OpenSpec usage

For non-trivial RD changes, use OpenSpec when the project already has `openspec/` or the user approves adding OpenSpec. In repositories that already contain `openspec/`, missing OpenSpec change artifacts are a blocking pre-implementation issue, not an optional suggestion.

Create or update `openspec/changes/<change-id>/proposal.md`, `design.md`, `tasks.md`, and `specs/**/spec.md` before implementation slices begin. If the repository uses a different existing OpenSpec layout, follow that layout and record the file paths in the RD handoff.

OpenSpec artifacts are durable project specification files, not Peaks-Loop runtime swarm artifacts. They may live in the target repository root under `openspec/changes/...`. Swarm/runtime outputs such as task graphs, worker briefs, worker reports, reducer reports, scan reports, validation evidence, and compact handoffs must remain in the configured Peaks-Loop artifact workspace outside the target repository.

Peaks-Loop PRD/RD/QA gates remain authoritative: OpenSpec structures the durable spec, while Peaks-Loop artifacts still carry role handoffs, coverage gates, QA evidence, swarm coordination, and execution state.

→ see `references/openspec-cli.md` for the CLI recipes.

## Mock data placement rules (BLOCKING — framework-aware)

When the project-scan in `.peaks/project-scan/project-scan.md` (project-level, git-tracked; slice 2026-07-15-project-scan-bootstrap) identifies a frontend framework, mock data MUST follow the framework's built-in mock mechanism. **Never write mock data inline in component files.**

→ see `references/mock-data-placement.md` for the framework-to-mock-directory mapping + hard rules + verification gate.

## Frontend project generation

When RD work creates a frontend application and the user has not specified a technology stack, default to React + Vite + shadcn/ui with `peaks shadcn init --preset [CODE] --template vite`. Generated projects must not contain JavaScript source or config files. TypeScript only.

→ see `references/frontend-project-generation.md` for the scaffold protocol.

## Frontend anti-corruption layer (ACL) — route by integration mode first

When RD work touches the frontend, read `.integrationMode` from `## Project mode` in `.peaks/project-scan/project-scan.md` (written from `peaks scan archetype --json`) and run that mode's procedure. Do **not** route on the `frontendOnly` boolean: it is back-compat only and merges two modes that need different first commands (`frontendOnly=false` covers both `full-stack` and `prd-plus-interface-doc`; `frontendOnly=true` covers `prd-only`).

| `.integrationMode` | RD runs first | Contract source | Artifact that proves it ran |
|---|---|---|---|
| `full-stack` | read `## API` in `.peaks/project-scan/project-scan.md` (a real wrapper + endpoint inventory exist here) | the backend's own response type in this repo | the per-domain mapper at the path in `## API → DTO ↔ ViewModel boundary`, plus `peaks scan diff-vs-scope --rid <rid> --project <repo>` |
| `prd-plus-interface-doc` | `peaks scan api-diff <doc> --project <repo>`, **before writing any type** | the OpenAPI document | the doc-derived `src/services/types/<feature>-api.types.ts` + the `Exact` section recorded in `.peaks/_runtime/<sessionId>/rd/requests/<rid>.md` |
| `prd-only` | write `.peaks/_runtime/<sessionId>/rd/mock-plan.md` before any mock file | an authored guess | `mock-plan.md` + `mock/<feature>-mock.ts` |

Whichever the mode, the mapping rule is unchanged: the frontend's internal model is never polluted by external / API shapes, DTO ↔ ViewModel conversion happens at the boundary, and all conversion logic for a domain lives in exactly one mapper file (e.g. `mappers/user.mapper.ts`) — never scattered across pages. Hard constraint, verified by QA / code-review.

→ see `references/frontend-acl-mapper.md` for the three rules + reference shape + verification, and `skills/peaks-code/references/frontend-only-mode.md` §"Integration-mode routing (RD)" for the numbered procedure per mode — including the two checks each mode **cannot** perform (doc↔server drift; and, for `prd-only`, that no mechanism detects a real document appearing, since the §2.6 staleness artifact is not built).

## Artifact and standards output

When project identification or scanning produces reports, matrices, maps, plans, or validation files, write them under the configured Peaks-Loop artifact workspace (default: `.peaks/_runtime/<sessionId>/rd/`). Do not default to a git-backed artifact repository or external artifact sync. Route standards mutations through `peaks standards init/update`; do not hand-write. Do not update user-global `~/.claude/rules/**` from this workflow.

→ see `references/artifact-and-standards-output.md` for the full contract.

## Compact handoff

Before RD work stops, finishes, blocks, or hands off to another role, emit a short resumable capsule: mode, scope, coverage status, validated decisions, current slice, artifact paths, blockers, and next action. Link to scan reports, matrices, plans, and task graphs instead of restating them.

The handoff artifact carries **mandatory YAML frontmatter** (`requestId`, `scope`, `files`, `decisions[]`, `risks[]`, `nextActions[]`, `gateEvidence`, `schemaVersion`) so peaks-qa can mechanically cross-check. See `references/writing-handoff-frontmatter.md` for the field schema and validation.

→ see `references/compact-handoff.md`.

## External references

## Codegraph project analysis

Codegraph is local project-analysis evidence, scoped to red-line scope boundaries (changed files / symbols) and read via `peaks codegraph affected --project <path> <changed-files...> --json`. Peaks-Loop RD gates remain authoritative; codegraph is untrusted supporting evidence. Do not let codegraph output drive scope, design, or QA verdict decisions, and never mutate agent settings, Claude settings, or hooks from codegraph. Do not commit `.codegraph/` artifacts or persist generated `.codegraph/` databases into git. Codegraph context is written to `.peaks/_runtime/<sessionId>/rd/codegraph-context.md` for handoff to QA / TXT.

## Matt Pocock skills integration

Matt Pocock skills (`diagnose` / `triage` / `tdd` / `improve-codebase-architecture` / `prototype`): engineering references only. Inspect before applying; Peaks-Loop RD gates remain authoritative. Codegraph: project analysis is codegraph-first (`peaks codegraph context/affected`), structural import edges as the fallback; local analysis only, never commit `.codegraph/` artifacts. Other external resources: `peaks capabilities --source access-repo/mcp-server --json` for capability discovery.

→ see `references/external-references.md` + `references/matt-pocock-integration.md` + `references/codegraph-project-analysis.md`.

## Boundaries

Do not bypass PRD/QA artifacts. Do not install hooks, agents, MCP, or settings. Ask the Peaks-Loop CLI to handle runtime side effects.

Do not bypass the parallel review fan-out when the slice has a code-review / qa-test-cases / karpathy-review surface — see `## Parallel review fan-out` above. The three review activities are fan-out, not sequential; sequential re-implementation of the same logic by the main RD loop defeats the wall-clock benefit and is treated as a red-line violation.

**Security / perf audit boundary (v2.12.0):** security and perf audit run as standalone audit skills (`peaks-security-audit`, `peaks-perf-audit`) whose outputs land at `audit/security-<rid>.md` / `audit/perf-<rid>.md`. RD does **not** dispatch `security-reviewer` or `perf-baseline-reviewer` sub-agents. See `references/rd-fanout-contracts.md` §"Deprecated reviewer back-compat".

## Karpathy cost self-review (slice 2026-07-30-karpathy-cost-self-review)

The `karpathy-reviewer` sub-agent now reports its own runtime cost in the JSON envelope at `rd/karpathy-review-<rid>.md` (fields `evaluationCost` + `costRatio`; see `agents/karpathy-reviewer.md` §4). The **orchestrator-side** command `peaks job karpathy-cost-check --review-file <path>` reads that envelope and decides whether to downgrade a `'block'` gateAction to `'warn'` when `costRatio > 10`. **24h-mode is the override** — the check is entirely skipped when `peaks session 24h-mode state` reports `24H_ACTIVE`.

The main RD loop MUST call `peaks job karpathy-cost-check` after every `peaks request transition --state qa-handoff` and before the next-slice work begins. If the decision kind is `downgraded`, the LLM MUST honor the downgraded `warn` and proceed to the next slice; the `'block'` was an artifact of the reviewer's own cost, not the slice's quality. If the decision kind is `reported` (costRatio > 50, gate not `'block'`), the LLM MAY continue; the sediment will be appended by `peaks memory extract` at handoff time. The full design lives in `.peaks/memory/2026-07-30-karpathy-evaluation-cost-self-review-design.md` (sediment locked 2026-07-30).

## Sub-agent context governance (G7 + G8 + G9 — slice #010)

RD sub-agent prompt template MUST include the G7 path convention + G8.6 share protocol. Detailed protocol: `skills/peaks-code/references/context-governance.md`.

**Large tool output (> 2 KB) MUST NOT be dumped into the orchestrator's context** — use `--summary` (`peaks memory reindex --summary`, `peaks memory list --summary`, `peaks doctor --summary`, `peaks request list --summary`) or write to a file and `Read` selectively. Rationale (measured, session 2026-09-07-session-245530): 4 full `reindex --json` dumps ≈ 40K tokens of a 68%-full 1M window. `--summary` is an additive view — no information is removed. → `skills/peaks-code/references/context-governance.md` §G0.

→ see `references/rd-context-governance.md` for the full G7 / G8.6 / G9 protocol + RD sub-agent prompt template.

## Sub-stages (Plan 3 — strategic + tactical split)

peaks-rd runs in two sub-stages:

1. **Strategic** — root-cause analysis, design intent. Outputs the strategy markdown + STRAT.sig.
2. **Tactical** — minimal implementation. AST hard gate compares external API calls against peaks-context's locked-version docs. Outputs the impl json + TACT.sig.

Hard constraint: TACT.sig cannot be written when the AST gate has violations.
The LLM auto-fixes and retries (peaks-qa's 3-cycle repair cap).

Registered CLI surface (one-axis: `--session-id` required, every `--out` under
`.peaks/_runtime/<sid>/`):

```bash
peaks strat write --project <repo> --session-id <sid> \
  --out .peaks/_runtime/<sid>/rd/strategy.md \
  --goal <text> --root-cause <text> --impact <paths...> --design <text> --json
# writes strategy.md + its JSON sibling (.peaks/_runtime/<sid>/rd/strategy.md.json)

peaks tact write --project <repo> --session-id <sid> \
  --strategy .peaks/_runtime/<sid>/rd/strategy.md.json \
  --out .peaks/_runtime/<sid>/rd/impl.json \
  --changed-files <paths...> [--ast-context '<json>'] --json

peaks tact read --artifact .peaks/_runtime/<sid>/rd/impl.json --project <repo> --json
```

`tact write` never accepts a raw `--input-sig`: it re-verifies the strategy
JSON's recomputed sha256 and refuses a tampered artifact. `tact read` does the
same for `impl.json` and prints `{ sha256, inputSig, changedFiles, astGateResult }`.

Karpathy guidelines remain injected in both sub-stages.

Public entry points (from `src/services/rd/rd-service.ts`) are unchanged; the
commands above are thin wrappers over them:

- `runStrategic(input: RunStrategicInput): Promise<StrategyOutput>` — strategy writer (`peaks strat write`)
- `runTactical(input: RunTacticalInput): Promise<ImplOutput>` — runs AST gate then writes impl.json + TACT.sig chained to inputSig (`peaks tact write`)

## References

Index of every `references/` file in this skill. Read on demand.

| File | Coverage |
|---|---|
| `references/artifact-and-standards-output.md` | Artifact + standards output contract. |
| `references/artifact-contracts.md` | Sub-agent handoff artifact contracts. |
| `references/artifact-per-request.md` | RD per-request artifact + per-slice vs per-session scope. |
| `references/browser-self-test-contracts.md` | Browser self-test contracts (1) + (2). |
| `references/codegraph-project-analysis.md` | Codegraph local analysis (untrusted evidence). |
| `references/compact-handoff.md` | RD compact handoff capsule. |
| `references/external-references.md` | External 3rd-party inventory. |
| `references/frontend-project-generation.md` | React + Vite + shadcn/ui default. |
| `references/frontend-acl-mapper.md` | 前端防腐层 ACL + DTO↔VM 映射 + Mapper 聚合硬约束. |
| `references/library-version-awareness.md` | Breaking-change gate + freshness check. |
| `references/mandatory-perf-baseline.md` | RD-side perf baseline + `peaks perf baseline` workflow. |
| `references/matt-pocock-integration.md` | Matt Pocock skills as references. |
| `references/mock-data-placement.md` | Framework-to-mock-directory mapping + rules. |
| `references/openspec-cli.md` | OpenSpec CLI recipes. |
| `references/parallel-review-fanout.md` | 3-way parallel review fan-out. |
| `references/reading-v2-slice-results.md` | Read peaks-slice-decompose v2 envelope + per-pass dispatch. |
| `references/writing-handoff-frontmatter.md` | Required frontmatter fields for RD → QA handoff. |
| `references/rd-context-governance.md` | G7 + G8.6 + G9 RD sub-agent protocol. |
| `references/rd-gstack-integration.md` | GStack → Peaks mapping + dry-run cadence. |
| `references/rd-runbook.md` | Default 9-step runbook (steps #0–#8). |
| `references/rd-standards-preflight.md` | Standards preflight dry-run contract. |
| `references/rd-sub-agent-dispatch.md` | Sub-agent suspended sections + contract. |
| `references/rd-transition-gates.md` | Per-gate A-A3-B-B9 contract. |
| `references/refactor-workflow.md` | Refactor hard gates + required artifacts. |
| `references/skill-presence-and-title.md` | RD skill presence (main loop only). |
| `references/v2-12-fanout-collapse.md` | v2.12.0 fan-out collapse. |
## L2 surface reference (post rid-l2-extended)

For RD slices that touch the lease / dispatch / observability stack, the canonical L2 surface is the L2 ecosystem shipped 2026-07-29 (commits `33aad895` through `075321af`). The high-leverage CLIs RD slices will encounter:

- `peaks worktree spawn / renew / list / gc / lease-status / release` — lease lifecycle (source of truth for L2 hook gate)
- `peaks sub-agent dispatch --isolation worktree|container` — auto-spawns a lease; `PEAKS_WORKTREE_LEASE_ID` env var is the gate's lookup key
- `peaks container spawn / release` — L4 container runtime (Part 12); pairs with `--isolation container` on dispatch
- `peaks lease-metrics [--rate] [--all-sessions]` — per-kind event counts + leak-rate + lifetime stats
- `peaks lease-stats` — project-wide summary (per-rid / per-role / per-isolation breakdown)
- `peaks cron init / list / run` — scheduled tasks (lease-gc-daily built-in); `peaks cron-scheduler start` for daemon mode
- `peaks audit red-lines` — 119 catalog red-lines; 66 cli-backed enforcers (sweep 003) + 53 catalog

The pre-existing SKILL.md reference set (this section is additive — not a replacement) covers the LLM-flow contracts. The CLIs above are operator / dashboard surfaces.
