---
name: Scan - Extract via the extract-doc CLI
description: Run extract-doc to locate the real page, detect chart types, and extract endpoints / business rules / entity props
next_step: step-02-generate.md
---

## STEP 01: Scan — run the `extract-doc` CLI

### Purpose

Gather the data needed for generation **deterministically** via the colocated
`extract-doc` CLI, instead of parsing controllers/entities by hand. The CLI is
read-only (writes nothing) and returns a JSON report.

### Run it

```bash
npx --prefer-offline tsx skills/documentation/cli/extract-doc/index.ts \
  --spec '{"type":"user","target":"<module>","application":"<app>","projectPath":"<project-root>"}'
```

- Optional `"pagePath":"<relative .tsx>"` — force a specific page (skip auto-detection) when you already know which page to document.
- `<project-root>` is the SmartStack project being documented (its layers are auto-detected — no hardcoded `SmartStack.*` paths).

> **Windows note:** PowerShell mangles the inline JSON quotes when calling `npx`.
> Invoke through the Bash tool (single-quoted JSON passes literally) or escape
> every `"` as `\"`.

### Read the `report`

| Field | Use |
|-------|-----|
| `resolved.pageTsxPath` | **READ this file** and reproduce it faithfully as annotated Mock UI (do NOT invent a generic table/KPI layout). If `null`, author from the live app / pagespec. |
| `resolved.pageCandidatesTried` | Other pages that matched — pick a different one via `pagePath` if the auto-pick is wrong. |
| `charts[]` | For each chart, `mockUiPattern` tells you the faithful Mock UI shape (recharts type → histogram / donut / line / area). `rechartsType: null` = inspect the source yourself. |
| `apiEndpoints[]` | Real endpoints (method, path, handler, resolved permission) — feed the header stats always, and the Technical Reference section when `--tech`. |
| `accessRoles` | **The Section 2 « Accès & rôles » join** (code permissions × core-seed state roles × rbac.md portée — the code is the source of truth). `source: 'state+ba' \| 'state' \| 'ba' \| 'none'`; `rows[]` = `{ role, roleCode, actions[], portee, porteeByAction }` — author the role table from these rows ONLY (never invent a grant). `source==='ba'` → render the `access.unverified` caveat. `unmappedCodePermissions[]` → render as a caveat. `warnings[]` (drift, unmatched actors) → REPORT to the user verbatim, never publish. `source==='none'` → keep the plain access card (URL + permissions list). |
| `businessRules[]` | Domain guard rules (deduped) — raw material; **curate**, don't dump verbatim. |
| `entity.properties[]` | Drives realistic form fields / table columns / mock records. |
| `namespace`, `navRoute`, `suggestedRoutes` | Feed these into `scaffold-doc` in step-03. **`namespace` is mode-dependent**: camelCase on the source monorepo (`docsAdministrationUsers`), KEBAB on a client project (`docs-administration-users` — the page must `useTranslation()` this exact string). |
| `resolved.frontendMode`, `resolved.packageVersion` | `source` \| `client` \| `unknown` — drives the whole wiring strategy (see step-02 §D). `unknown` → fix the project or pass `mode` explicitly to scaffold-doc. |
| `namespaceStyle`, `suggestedRegistryFile` | Client mode: confirms the kebab convention + where scaffold-doc will emit the `docs.*` PageRegistry registration. |
| `existingDoc.forbiddenSections[]` | **Forbidden "sales" framing already in the EXISTING doc** (problème/solution, Bénéfices, Avant/Après) — each `{ file, line, token }`. **Non-empty → you MUST strip these while regenerating** (step-02). The step-03 gate re-runs this scan and blocks until empty. |
| `existingDoc.missingRequired[]` | **Mandatory elements ABSENT from the EXISTING doc** (the mirror check). `"objective"` = no Objectif Section 1; `"summary"` (user) = no header accent tagline. **Non-empty → you MUST add them while regenerating** (step-02). The step-03 gate blocks until empty. |
| `existingDoc.adviseRolesTable` | **NON-blocking advice**: the existing `user` doc predates the « Accès & rôles » table while a roles source exists — add the Section 2 table at this regeneration. Never part of the step-03 gate. |
| `existingDoc.overflowRisks[]` | **NON-blocking**: `<code>`/`font-mono` elements without a break utility in the existing doc (`{ file, line, token }`) — add `break-all`/`break-words` (DocPanel 480px). Never part of the step-03 gate. |

### developer / database / testing types

`extract-doc` returns a thin report for these (they are authored from tool /
schema knowledge, not project code). Gather as before:
- **database** — read `…/Persistence/Configurations/*.cs` + the model snapshot for tables/relationships.
- **developer / testing** — tool docs (WebSearch for current versions), integration points, commands.

### Success metrics

- [x] `extract-doc` ran and returned `success: true`
- [x] (user) real page located and **read** before any Mock UI is written
- [x] (user) each chart's recharts type noted for faithful reproduction
- [x] endpoints + business rules + entity props captured as raw material to curate
- [x] (user) `accessRoles` read: rows → Section 2 table; warnings → reported to the user; `source` noted (caveat if `'ba'`, fallback card if `'none'`)

### Next step

→ **step-02-generate.md** — author the doc content, then run `scaffold-doc`.
