# Feature documentation (docs/features/{feature}.md)

Truth document. Use for every feature in `docs/features/`: something a person points at, such as an address, a command family or a named control. One file per feature, cut by the objects it designs, never by the code's routers, tables, plans or packages. The file persists from design (`status: draft`) to live reference (`status: active`).

**A feature document is sharp, bulleted and actionable** (`references/style-guide.md` § Labels; § Shape — the model first, the detail after). A reader scans it rather than reads it:

- **Headings and bullet labels are noun phrases.** For example `Flows`, `Organization member`, `Dead grant` — never a clause like "How it works" or "You already belong to an organization".
- **Each bullet is a bold label, then one or two third-person sentences** saying what happens: "**Organization user:** user lands in their existing organization", never "you land…".
- **Flows carry the journey; Decisions carry the reasons; Promises run deepest.**

The frontmatter names the objects the feature designs; which files it speaks for is never listed in the body. The ownership scan reads its transitional `owns:` region glob, and each owned source file's header names this document, ready for when the scan switches (`references/frontmatter.md`). Every computable fact (columns, vocabularies, foreign keys, writers, routes, guards, files) is the code graph's (`docs/architecture/systems/knowledge-layer.md`), and a hand-typed copy is the defect this genre removes. Code is named only where a person types or sees it (a page, a command, a flag, an environment variable) or at a cross-cutting seam the graph would not lead a reader to.

**A feature document runs deepest toward its end.** Scope and Flows are the model and the journey. **Promises** goes as deep as the behaviour does: every state the surface can be in, every edge case, what a refusal tells the person, and the exact wording wherever the wording itself is promised. That depth is earned because a person or a test checks it and the code cannot state it as intent. It stops before mechanism. A promise reads "a removed membership shows a panel, not a redirect", never which route answers it.

**Sections:**

| Section | When |
| --- | --- |
| Frontmatter | required |
| Goal line | required |
| `Scope` | required |
| `Flows` | required once `status: active`; omitted at `draft`, before there is a shipped surface to describe |
| `Decisions` | once any choice was made that the code cannot explain |
| `Promises` | required |
| `Gaps` | only when there is one |
| `For the agent` | required |

Nothing else. `doc-lint` blocks the retired mechanism sections (`mechanism-section`), and warns on code identifiers in the body (`body-identifier`), on a heading or bullet label written as a clause (`clause-label`), and on "you" outside quoted copy (`second-person`).

```yaml
---
type: feature                                    # required tooling key — preserve, never narrate
description: "{at most 300 characters: what this document settles and where its boundary sits}" # required — the per-file account a folder is browsed by (references/frontmatter.md)
status: active                                   # required — active | draft | deprecated
objects: [device, credential grant]              # required — the product objects this document designs, by their graph names
module: identity                                 # optional — one bounded-context label
owns: ["packages/studio/src/server/devices/**"]   # transitional — one region glob, read only by the ownership scan until it switches to header pointers (references/frontmatter.md)
---
```

```
# {Feature name}

{One sentence: what this lets a person do.}

## Scope

- **In scope:** {the surfaces, commands and journeys this document owns}
- **Bound by:** {the doctrine documents it applies, each with what it settles}
- **Out of scope:** {the neighbouring features a reader might expect here, each linked}

## Flows

### {Entry point or situation, as a noun phrase — e.g. "Browser", "Terminal", "Landing", "Sign-out"}

- **{Noun-phrase label — e.g. "Signed-out visitor", "Claimed domain", "`nustack login`"}:** {what the user does or meets, and what happens. One or two sentences, third person, present tense — "user lands…", never "you land…".}
  - {a sub-case, only where the parent genuinely branches}

## Decisions

- **{The decision as a noun phrase — e.g. "Single entry, no sign-up", "Unsigned organization cookie"}:** {why, in one or two sentences, and the alternative a reader would reach for if it matters.}

## Promises

### {Theme as a noun phrase — e.g. "Sign-in failures", "Gate outcomes", "Terminal grant states"}

{A table where the cases are parallel states — | Situation | Outcome | — carrying the exact wording where the wording is promised. Bullets otherwise:}

- **{Noun-phrase label}:** {the guarantee or refusal, checkable by a person or a test.}

## Gaps

- **{Noun-phrase label}:** {what the code does not keep, and what closing it would take. The backlog row carries the rest.}

## For the agent

- **Objects:** {object}: {one plain line}; {object}: {…}
- **Pages:** {`/…`}
- **Commands:** {`nustack …`}
- **Code roots:** {`packages/…/src/…/`}, directories where the graph should start
- **Seams:** {`name`}, only where the roots would not lead to them
- **Checklist:** `docs/tests/{feature}.md`, once the verification gate has written it
- **See also:** {neighbour}: {why}

No tables, routes or symbol rosters — those are the graph's.
```

### Lifecycle

| When | What is written |
| --- | --- |
| `status: draft` (design) | goal, Scope, Decisions, Promises (with gaps named), For the agent; the LLD research goes to the plan |
| `status: active` | Flows written from the shipped surface; `objects:` confirmed against the register, and each owned source file's header names this document |

A feature whose code is gone is deleted, or `status: deprecated` with its footer pointing at what replaced it.
