---
# GENERATED — DO NOT EDIT. Source: skills/forge-6-docs/SKILL.md. Regenerate: python3 scripts/build-adapters.py
description: Generate developer-focused architecture documentation for a forge pipeline feature. Use when user runs /feature-forge:forge-6-docs or asks to generate docs after implementation is complete. Do NOT trigger for general documentation writing, README creation, or doc generation outside the forge pipeline.
globs: []
alwaysApply: false
---

# forge-6-docs — Architecture Documentation Generator

Generate developer-focused architecture documentation for a feature, suitable for onboarding, reference, and maintenance.

## Prerequisites

Read and follow `references/shared-conventions.md` for feature name validation, configuration reading, and force mode handling before proceeding.

**Turn structure reminder:** Output analysis/context as text, then route ALL questions through the host's question mechanism. Never embed questions in text output — the user will not be prompted and the session will stall.

## Step 1: Read Context

Resolve the feature directory via the **Feature Directory Resolution** block in `references/shared-conventions.md` (so a standalone feature resolves to its flat `{specsDir}/{feature}/` path exactly as today, and an epic member resolves to its nested path). Use the resulting `{resolvedFeatureDir}` everywhere this skill previously wrote `{specsDir}/{feature}/`.

Read `{resolvedFeatureDir}/.pipeline-state.json` to understand what exists.

### Documentation Decision Gate

Documentation is valuable but not mandatory: a feature may close with docs deliberately skipped, recorded honestly as `skipped` (never as a false `complete`). This gate is configured by `docsStage` in `forge.config.json` (`"prompt"` | `"skip"`, default `"prompt"`; an unrecognized or absent value behaves as `"prompt"`):

- **`"prompt"`** — before gathering sources, use the host's question mechanism to ask: **Generate docs (recommended)** — proceed with this skill as written · **Skip documentation for this feature** — close the stage with no docs, recorded as `skipped`; docs can still be generated later by re-running this stage.
- **`"skip"`** — take the skip path below directly, with no question: say one line — "docsStage is configured to skip: recording forge-6-docs as deliberately skipped for {feature}." — and proceed to the `state-skip` write. The user opted out of the per-run prompt by setting the config; re-asking would defeat it.

On **Skip documentation**, persist the skip through the `state-skip` verb — never by hand, and never via `state-complete` (which would claim a completion that did not happen). Add `--epic "{epic}"` when this feature is an epic member — required, per the Pipeline State Protocol in `references/shared-conventions.md`:

```bash
R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
python3 "$R/scripts/forge-session.py" state-skip \
  --feature "{feature}" --stage forge-6-docs --specs-dir "{specsDir}"
```

If the verb exits 2, surface its plain `Error:` line verbatim — a refusal means the skip would erase a record of docs that already exist; do not force it. Ask the user how to proceed (typically: generate/refresh the docs normally).

After a successful skip write: if `gitCommitAfterStage` is true, commit the state change (`git add {resolvedFeatureDir}/`, message `"{commitPrefix}({feature}): skip architecture docs"`) — a plain single commit; there is no artifact commit, so the two-commit hash follow-up does not apply. Then go **directly to Step 6** with `{DocsOutcome}` = `skipped`. Steps 1 (rest), 2, 3, 4, and 5 are all skipped — including the Impl-Verify Backstop: skipping docs generates nothing over unverified code, and any outstanding verification stays visible in state and keeps being surfaced by the navigator.

On **Generate docs**, continue below.

### Gather Sources

Load into context:
1. **Specs**: PRD.md, tech-spec.md, all implementation specs
2. **Implementation**: Read the actual source code for this feature's package
3. **Existing docs**: Check `{docsDir}/` for other features' docs to match conventions
4. **README**: Check if the feature package has its own README.md

### Implementation Completeness Check

Check `{resolvedFeatureDir}/backlog.json` (or `{backlogDir}/{feature}/backlog.json` if configured). Count items with status `complete` vs total. If implementation is less than 80% complete, use the host's question mechanism to warn: "Implementation is only N% complete. Documentation will be based primarily on specs and may need updates after implementation. Proceed?" If user proceeds, add a `PRE-IMPLEMENTATION` notice at the top of each generated doc.

Also check `.pipeline-state.json` for `stages.forge-5-loop`. If it exists and has status `in-progress` (some items incomplete), include this in the warning: "The rauf loop has not fully completed — {done}/{total} items done. Documentation may need updates after remaining items are implemented."

### Impl-Verify Backstop

Read `stages.forge-verify-impl` from `.pipeline-state.json` and branch on its status — **five** cases, in this order (the pending case must be tested *before* the absent/`skipped` one, or owed-and-dropped debt gets reported as never-scheduled):

1. **`passed`** — verification ran and resolved clean (or advisory-only, report attached); proceed with no warning.
2. **`findings-reported`** — blocking findings are live and **unresolved**: docs generated over them can document known defects as intended behavior. Use the host's question mechanism to offer: **Apply the findings first (recommended)** (`/feature-forge:forge-fix {feature} --served-stage forge-5-loop`) · **Generate docs anyway**. Proceeding is an explicit deferral, persisted per the skip rule below — the findings documents stay on disk and the deferral is a recorded decision.
3. **`findings-applied`** — fixes landed but nothing re-verified them: this status deliberately clears freshness, so the implementation's verification is still outstanding, not silently satisfied. Use the host's question mechanism to offer: **Re-verify first (recommended)** (`/feature-forge:forge-verify {feature} impl`) · **Generate docs anyway**. On proceed, **write nothing to the verify entry** — the skip rule below does NOT apply to this case. `findings-applied` counts as complete-for-orchestration, so replacing it with `skipped` would demote the member out of its epic rollup and re-block dependents (`state-verify` refuses exactly that write — issue #203's 5/6 → 1/6 collapse). The recorded status already says re-verification is outstanding; proceeding is the deferral, and later gates keep surfacing it.
4. **`auto-verify-pending`** — automatic verification *was* scheduled for the implementation stage and the debt *was* durably recorded; it simply has not run. Say exactly that, naming the served stage and the retry command: *"{feature}: automatic verification is still pending for forge-5-loop; run `/feature-forge:forge-verify {feature} impl` to resolve it."* Then use the host's question mechanism to offer the same two choices as case 5. Never report this as "hasn't been verified yet" — an **absent** entry means verification was never scheduled, `auto-verify-pending` means it was scheduled and never ran, and the operator acts on those two facts differently.
5. **Absent, or `skipped`** — use the host's question mechanism to warn with the cost of skipping: "Implementation hasn't been verified yet. Recommended: run `/feature-forge:forge-verify {feature} impl` first to audit the loop's output — docs generated over unverified code can document bugs or gaps as if they were intended behavior, and readers will trust them. Generate docs anyway?"

Cases 2–5 all pair a recommended first action with **Generate docs anyway**. On **Verify first** / **Re-verify first**, invoke `feature-forge:forge-verify {feature} impl` with the literal `owner: nested` token in the dispatching prompt — this dispatch happens inside the docs stage, so **you** remain the sole terminal owner and the branch skill returns its structured result and prints no terminal block of its own (see "Branch ownership: the `owner:` token" in `references/stage-exit-protocol.md`); on **Apply the findings first**, dispatch `feature-forge:forge-fix` the same way (same token, same ownership). This mirrors `forge-4-backlog`'s pre-stage verification check and backstops a skipped or unresolved impl-verify regardless of how the loop ended.

**"Generate docs anyway" persists the skip before docs can complete — in cases 2, 4, and 5 only.** An explicit choice to proceed without verification is recorded as `skipped` through `state-verify` — never by hand — **before** Step 2, so an unresolved result cannot be bypassed by this stage's terminal wording. Case 3 (`findings-applied`) is the exception spelled out above: its deferral writes nothing, because the verb refuses to demote a complete-for-orchestration status (#203). Add `--epic "{epic}"` when this feature is an epic member — required, per the Pipeline State Protocol in `references/shared-conventions.md`:

```bash
R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
python3 "$R/scripts/forge-session.py" state-verify \
  --feature "{feature}" --stage forge-5-loop --status skipped --specs-dir "{specsDir}"
```

If that verb exits 2, surface its plain `Error:` line verbatim and stop — the skip is not persisted, so docs may not complete.

**Verification that is operationally unavailable is not an implicit skip.** If the user chose **Verify first** and the clean-room verifier could not be dispatched, returned `CLEAN_ROOM_UNAVAILABLE`, or returned a non-answer, then verification did **not** run: write nothing, follow the *Clean-room unavailable, or a non-answer* path in `references/stage-exit-protocol.md` (leave the debt unresolved and print the verify command for the user to run), and never read the failed attempt as consent to proceed. Docs may complete only after verification passes or after the user makes the explicit "Generate docs anyway" choice above, which persists `skipped` — an unavailable tool is neither.

### Epic-Level Documentation (epic members only)

If the resolved feature has an `epic` back-pointer in its `.pipeline-state.json`, run:

```bash
R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
```

If `render-status` fails, skip the epic-level offer and proceed with the per-feature docs only; surface the error per the exit-1/exit-2 split in the **Feature Directory Resolution** block of `references/shared-conventions.md` (exit 1 → parse `{findings[]}` from stdout; exit 2 → surface the plain `Error:` stderr line verbatim).

**Gate the offer on per-member DOCS state, not the orchestration rollup (#173).** `rollup.complete` counts loop-completeness, so in an epic implemented before any docs were written it reads full on the *first* member's docs run — offering an epic doc that would be sourced from a fraction of its inputs. Instead, read each member row's `docsStatus` from the same `render-status` payload and offer **only if**: `rollup.total > 0`, AND every member **other than {feature}** has `docsStatus` of `complete` or `skipped` (#197's deliberate skip satisfies — those members will contribute no per-feature docs by decision, not by omission). The current member counts as satisfied by this in-flight run. This fires exactly once per epic, on its final docs run:

"All {total} features in the '{epic}' epic now have their documentation settled. I can also generate an **epic-level architecture document** spanning the features, alongside {feature}'s per-feature docs — say the word and I'll add it."

If the user asks for it, synthesize a doc at **`{docsDir}/{epic}/`** sourced from: the `EPIC.md` narrative, each member's per-feature docs (members whose docs were deliberately skipped contribute their manifest charter/contracts only), and the manifest contracts (each feature's `exposes`/`consumes`). When the epic-level doc is written, the Step 5 commit also stages `{docsDir}/{epic}/`.

If any other member's `docsStatus` is neither `complete` nor `skipped` (or the feature has no `epic` back-pointer), **do not offer** — the per-feature doc flow proceeds unchanged.

Read `references/doc-conventions.md` for documentation standards.

## Step 2: Plan Documentation Structure

Based on feature complexity and existing doc conventions, propose a doc plan:

**Minimum (simple feature):**
```
{docsDir}/{feature}/
├── README.md          — Overview, quick start, key concepts
└── api-reference.md   — Exported APIs, types, configuration
```

**Standard (typical feature):**
```
{docsDir}/{feature}/
├── README.md          — Overview, quick start, key concepts
├── architecture.md    — Design decisions, data flow, component relationships
├── api-reference.md   — Exported APIs, types, configuration
└── guides/
    └── integration.md — How to integrate this feature into an app
```

**Comprehensive (complex feature):**
```
{docsDir}/{feature}/
├── README.md          — Overview, quick start, key concepts
├── architecture.md    — Design decisions, data flow, component relationships
├── api-reference.md   — Exported APIs, types, configuration
├── configuration.md   — All configuration options with examples
├── guides/
│   ├── getting-started.md  — Step-by-step setup
│   ├── integration.md      — How to integrate with other packages
│   └── troubleshooting.md  — Common issues and solutions
└── decisions/
    └── adr-001-*.md   — Architecture decision records (if significant decisions were made)
```

Present the plan as a statement and invite edits before writing — not a forced confirmation gate: "Here's the doc plan I'll generate. Tell me if you want to add, remove, or restructure any documents; otherwise I'll proceed." Write the docs unless the user asks for changes.

## Step 3: Write Documentation

### Key Principles

**Write for the reader, not the writer.**
- A developer encountering this feature for the first time should be able to understand it from the docs alone
- Lead with the "what" and "why" before the "how"
- Include code examples for every exported API
- Don't assume familiarity with the spec documents

**Be accurate to the implementation, not the spec.**
- If the implementation diverged from the spec, document the implementation
- Specs are the source of truth for design intent; code is the source of truth for behavior
- Read the actual source code to verify your documentation is correct

**Don't cite or link spec files in the generated docs.**
- Read the specs freely for context, but the docs you write are shipped implementation artifacts — they must be self-contained
- Never link or reference `PRD.md`, `tech-spec.md`, or the numbered implementation specs (`specs/{feature}/NN-*.md`); these are pre-implementation artifacts that may be archived or deleted
- Reference only the code, runtime contracts/configuration, and other generated docs. If you need to convey design intent, write it directly into the doc rather than pointing at a spec

**Match existing conventions.**
- If other features' docs use a specific heading structure, follow it
- If they include diagrams, include diagrams
- If they use a specific tone (formal, casual, tutorial-style), match it

### README.md Structure

```markdown
# {Feature Name}

{One-paragraph description of what this feature does and why it exists.}

## Quick Start

{Minimal code to get started — import, configure, use.}

## Key Concepts

{Explain the domain model and core abstractions in plain language.}

## Package Exports

{Table of subpath exports and what each contains.}

| Export / Entry Point | Description |
|---------------------|-------------|
| `{module}` | Shared types and utilities |
| `{module}/server` | Server-side functionality |
| ...    | ... |

Adapt export paths to match the project's module/package conventions.

## Configuration

{Key configuration options with defaults.}

## Further Reading

- [Architecture](./architecture.md) — Design decisions and data flow
- [API Reference](./api-reference.md) — Complete API documentation
- [Integration Guide](./guides/integration.md) — How to use with other packages
```

## Step 4: Review with User

Present the docs as text. Then use the host's question mechanism to collect feedback — do NOT include these questions in your text output:

"1. Does this accurately reflect the implementation? 2. Is the level of detail appropriate for your team? 3. Any areas that need more explanation?"

## Step 5: Update Pipeline State and Commit

Pipeline state is written by the `state-*` verbs — see the Pipeline State Protocol in `references/shared-conventions.md`. The `state-complete` call for item 1, with the portable plugin-root prelude. Add `--epic "{epic}"` when this feature is an epic member — required, per that same protocol:

```bash
R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
python3 "$R/scripts/forge-session.py" state-complete \
  --feature "{feature}" --stage forge-6-docs --version {n} \
  --based-on "forge-1-prd=<n>" --based-on "forge-2-tech=<n>" --based-on "forge-3-specs=<n>" \
  --artifact "<doc file>" --specs-dir "{specsDir}"
```

1. Record completion by running the `state-complete` call above with `--version`, one `--artifact` per doc file this stage produced, and one `--based-on STAGE=<version>` per completed upstream stage. Always include forge-1-prd, forge-2-tech, forge-3-specs. Include forge-4-backlog and forge-5-loop ONLY if they have status `complete`. The verb sets `status: "complete"`, `completedAt`, the version, `basedOnVersions` and `artifacts`, and refreshes `updatedAt`.
2. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files (`git add {docsDir}/{feature}/ {resolvedFeatureDir}/` — and **also** `{docsDir}/{epic}/` when an epic-level doc was written in Step 1), attempt commit with message `"{commitPrefix}({feature}): complete architecture docs"` (marking `stages.forge-6-docs.status` `complete` with `commitHash: null` in that commit), then record the artifact-commit hash via the protocol's two-commit follow-up (never `--amend`) only on success. If commit fails, leave status as `in-progress`.
3. Say that the docs are written — "Documentation complete for '{feature}'." — and stop there. The hand-off is Step 6's, and it is the script's to decide.

## Step 6: Close the Stage

Every docs run ends here, and ends here **exactly once** — standalone or epic member, complete or not.

Select `{DocsOutcome}` first, from what actually landed:

- **`complete`** — the docs were written and Step 5's state (and commit, when `gitCommitAfterStage` is true) succeeded.
- **`skipped`** — the user chose **Skip documentation** at the Documentation Decision Gate and the `state-skip` write succeeded. Routes exactly like `complete` (the pipeline still ends here), but the wording says the docs were deliberately skipped — never that they exist.
- **`blocked`** — docs work could not complete. Persist only valid partial state, then run the same call with `blocked`; it routes to navigator/recovery and never claims the pipeline is finished. If the failure happened **before** a safe state write, report the failure and its recovery and run **no** exit at all — there is nothing durable for an exit to close over.

**Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:

```bash
R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
python3 "$R/scripts/forge-session.py" stage-exit --feature "{feature}" --stage forge-6-docs --outcome "{DocsOutcome}" --specs-dir "{specsDir}" --host generic --verify-capability "{verify-capability}"
```

Obey the DIRECTIVES it prints, in the consumption order this protocol fixes: surface `invalidAutoVerifyKeys` and every `warnings` entry first; `runInStageVerify: true` → run the in-stage clean-room verify chain now (honoring `autoFixEligible`, and asking through the Standard Verify Gate first when you may not dispatch unsolicited); `verifyGate: "standard"` → present the Standard Verify Gate; `verifyGate: "manual-print"` → print the `verifyCommand` for the user and do **not** dispatch inline. Then, and only when `terminalOwnedBy` is `"self"`, **print the NEXT-STEPS block verbatim as your absolute last output — nothing after its sentinel line.** A `terminalOwnedBy: "outer"` payload carries `nextSteps: null`: return your structured result to the caller and print no terminal block at all.

Add `--epic "{epic}"` when this feature is an epic member — required, per the Pipeline State Protocol in `references/shared-conventions.md`. Determine `{verify-capability}` per the **Host and capability determination** section of `references/stage-exit-protocol.md`: `interactive` needs both a question mechanism and *permission* to dispatch the clean-room `forge-verifier`, and a session that merely needs consent first is still `interactive`.

The script owns the routing for both outcomes, so append nothing to its block — no hand-off paragraph, no "start a new feature" list, no second command:

- **Epic member** — the script reads live epic status **at exit time**, after this stage's own state write and commit. Do **not** reuse Step 1's `render-status` snapshot and do **not** pass a member you picked yourself: that snapshot predates the docs state it would be routing from. An actionable member gets its own live command fenced; nothing actionable routes to the epic dashboard; every member complete routes to the dashboard completion view.
- **Standalone** — `complete` fences `/feature-forge:forge {feature}` as the authoritative completion action, and leaves starting a new feature (or grouping several with `/feature-forge:forge-0-epic`) as secondary unfenced text.

## Gotchas

- Don't just rephrase the specs. Documentation should explain the implemented system, not the planned system. Read the actual code.
- Don't cite spec files (PRD.md, tech-spec.md, numbered specs) as sources or "further reading" in the generated docs — specs are pre-implementation artifacts that may not survive. Keep the docs self-contained; link only to code, configuration, and other docs.
- If the implementation doesn't exist yet (backlog hasn't been run), document based on specs but note prominently that docs are pre-implementation and may need updating.
- API reference should include actual function signatures from the code, not from the spec (they may differ).
- Don't generate docs that will immediately be stale. Focus on concepts, architecture, and patterns rather than line-by-line code walkthroughs.
- Include "When to use" and "When NOT to use" sections — they save developers more time than any other documentation pattern.

---

## Host execution notes

This skill was authored Claude-first; the body above refers to "the host's question mechanism", "the host's subagent mechanism", and "the host's background-execution mechanism". Use your runtime's equivalent for each — and if your runtime has no such tool:

- **User input:** ask the question directly and wait for the answer before proceeding. Do not skip a required question or assume an answer.
- **Subagents:** if your host cannot dispatch the named custom agent, run that step inline yourself.
- **Background / monitoring:** run long-lived commands in the foreground (or your host's background facility) and report progress as it arrives.
