> ## Documentation Index
> Fetch the complete documentation index at: https://api-documentation.kare-app.fr/llms.txt
> Use this file to discover all available pages before exploring further.

# Claude Code — module porting flow

> How we port the legacy AkorD API to @kare/api, one module at a time, with Claude Code. The commands, the gates, the conditional branching, the side-effects — everything that happens, without reading the .claude internals.

<Note>
  **Spec-Driven Development.** One legacy module → **three commands you run in order**.
  You drive and validate at every gate; agents do the heavy reading and writing.
  When that sequence is done, the module is shipped.
</Note>

## The three commands

<CardGroup cols={3}>
  <Card title="/port-domain" icon="cube">
    Co-build the module's `domain/` (fields + business rules) from the legacy + your product calls. **Interactive.**
  </Card>

  <Card title="/port-routes" icon="list-check">
    A drafter writes `routes.md` (the build contract); **you edit it**. Draft + review.
  </Card>

  <Card title="/port-build" icon="robot">
    Autonomously builds **every route + its tests** from `routes.md`. A Workflow.
  </Card>
</CardGroup>

Utilities: `/qa` (typecheck · lint · test · build) and `/audit-module` (conformity check).

## High-level pipeline

```mermaid theme={null}
flowchart LR
  M(["module<br/>rs/anomaly"]) --> D1["/port-domain<br/>build domain/"]
  D1 -->|"domain/ ✓ GATE"| R1["/port-routes<br/>write routes.md"]
  R1 -->|"routes.md ✓ GATE"| B1["/port-build<br/>build routes + tests"]
  B1 -->|"QA ✓ GATE"| HP["build:human<br/>routes in pair"]
  HP --> OK(["MODULE 100%"])
```

`⛔ GATE` = **you stop and validate**. Anything ambiguous → the agent asks you
(multiple-choice), never guesses.

***

## FLOW 1 — `/port-domain` (interactive, pair)

Build the `domain/` — the source of truth for the module. There is **no** intermediate
spec file; the implemented domain *is* the spec.

<Steps>
  <Step title="Analyze (delegated, read-only)">
    `legacy-analyst` reads the legacy module; in parallel the new Prisma model is mapped.
  </Step>

  <Step title="⛔ GATE 1 — design review">
    A real design review (not a rubber-stamp): for every questionable point, *keep vs change*
    — fields, code-enums, scoping, soft-delete, operations. Driven by multiple-choice questions.
  </Step>

  <Step title="Implement (fields first)">
    Prisma schema (if needed) → `@db/fields/<entity>` → `domain/`. `/qa` until green.
  </Step>

  <Step title="⛔ GATE 2 — validate the domain">
    Facade shape, errors, code-enums, scoping. Iterate on your feedback.
  </Step>
</Steps>

**Out:** `domain/` code (green). **Next:** `/port-routes`.

***

## FLOW 2 — `/port-routes` (draft + you edit)

Produce `routes.md` — the **contract** the autonomous build consumes.

<Steps>
  <Step title="Draft">
    `routes-drafter` reads the legacy routes + the built domain and fills one block per
    operation: maps each route to an **archetype**, fills 12 fixed keys
    (method/path · scope · auth · input · output · domain calls · audit · errors · tests …).
  </Step>

  <Step title="Mark, never guess">
    Anything ambiguous → `[NEEDS CLARIFICATION: …]`. Anything that doesn't fit an archetype
    (custom auth, aggregation, async, mobile) → `build: human` + a reason.
  </Step>

  <Step title="⛔ GATE — you edit the contract">
    You add/remove/rename ops, adjust I/O, and **resolve every `[NEEDS CLARIFICATION]`**.
  </Step>
</Steps>

<Warning>
  After `/port-build`, the **code is the source of truth** — `routes.md` is the one-time
  contract, never re-generated from. (Avoids the "spec drifts from code" trap.)
</Warning>

**Out:** `routes.md`. **Next:** `/port-build`.

***

## FLOW 3 — `/port-build` (autonomous Workflow)

Reads `routes.md` and builds every `build: auto` route. This is where the conditional
branching lives.

```mermaid theme={null}
flowchart TD
  S(["routes.md validated"]) --> PF{"any NEEDS<br/>CLARIFICATION?"}
  PF -->|yes| RJ["REFUSE<br/>→ back to FLOW 2"]
  PF -->|no| PA["parse → work-items<br/>set aside build:human"]
  PA --> RB["route-builder<br/>tests-first · mirror exemplars"]
  RB --> EX{"folder<br/>already exists?"}
  EX -->|yes| SK["skip + report<br/>(idempotent)"]
  EX -->|no| RV["route-verifier<br/>ENFORCE coverage + conventions"]
  RV -->|PASS| NX["next route"]
  RV -->|FAIL| RT{"retries left?"}
  RT -->|yes| RB
  RT -->|no| BH["auto build:human<br/>+ CONTINUE (never blocks)"]
  NX --> IN["integrator · ONCE · serial<br/>4 registrations + audit keys + i18n"]
  BH --> IN
  SK --> IN
  IN --> GT["1 integration run<br/>+ /audit-module"]
  GT --> RP(["report:<br/>built / verified / build:human"])
```

**What each route-builder reads** (so it never invents): the archetype ref + the **shape
exemplar** (`template`) + the **auth exemplar** (`user`) + the constitution + the domain
facade + `@db/fields`. It writes **only its own folder** and the tests **first**.

**Out:** routes + tests wired, QA green. **Next:** the few `build: human` routes, in pair.

***

## Branching & side-effects — the rules

<CardGroup cols={2}>
  <Card title="⛔ Human gates" icon="hand">
    GATE 1 (design) · GATE 2 (domain) · contract gate · final report. You never get skipped.
  </Card>

  <Card title="[NEEDS CLARIFICATION]" icon="circle-question">
    Hard stop. The build **refuses** any route that still has one. Zero guessing.
  </Card>

  <Card title="build: human" icon="user-pen">
    Off-archetype routes (custom auth, aggregation, async, mobile) → done in pair, not auto.
  </Card>

  <Card title="verify FAIL → retry → build:human" icon="rotate">
    Bounded retries; if still failing, auto-flag `build: human` and **continue** — one bad route never blocks the batch.
  </Card>

  <Card title="Idempotent" icon="repeat">
    A folder that already exists is **skipped** — `/port-build` is safely re-runnable.
  </Card>

  <Card title="No worktrees · serial wiring" icon="layer-group">
    Each route writes its **own** folder (no conflict). Shared files (`routes/index`, module
    index, `app.ts`, action-keys, messages) are touched **only** by the integrator, in series.
  </Card>
</CardGroup>

<Warning>
  **Integration tests run exactly once**, by the orchestrator, after wiring — **never**
  concurrently (the global setup recreates the per-worker DBs; two runs destroy each other).
  Build agents *write* tests, never *run* them.
</Warning>

## Conventions baked in

| Area       | Rule                                                                                                                                                                                                                                         |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Enums**  | Int/String **codes** via `codeEnum(map)` — never Prisma enums.                                                                                                                                                                               |
| **Auth**   | Every route: `config.auth.capability` (named `<AUD>_CAPABILITIES` const) + `requireContext.<aud>(req)`. Org from auth, never the body; cross-tenant → 404.                                                                                   |
| **Errors** | `AppError` + per-module `<entity>Errs`; never a hand-built JSON body.                                                                                                                                                                        |
| **Writes** | `prisma.auditedTx`; semantic actions add an `AUDIT_ACTIONS` key.                                                                                                                                                                             |
| **Reads**  | `@kit/parse-query` extends machinery; soft-deleted excluded.                                                                                                                                                                                 |
| **Tests**  | Start from `rsFixture(app)` / `boFixture(app)` + factories; **mock external adapters** (email/storage/AI), Prisma + auth real; **1 test per where / orderBy / extend**; the `route-verifier` **enforces** the per-archetype coverage groups. |

## The cast

<CardGroup cols={2}>
  <Card title="Skills (knowledge)">
    `CONSTITUTION` · `porting-system` · `routes-spec` · `code-enum` · `route-tests` · `api-conventions` / `api-routes` / `api-parse-query` / `api-module-anatomy` / `api-layers` / `adapter-and-facade` · `legacy-api`
  </Card>

  <Card title="Agents (workers)">
    `legacy-analyst` (read legacy) · `routes-drafter` (draft routes.md) · `route-builder`
    (1 builder + 7 archetype refs) · `route-verifier` (enforce coverage) · `integrator`
    (wire, serial) · `module-auditor` (final gate) · `qa-runner`
  </Card>

  <Card title="References (templates)">
    `routes.template.md` · 7 archetype guides · `exemplar-registry` · `domain-review-checklist`
  </Card>

  <Card title="Shared helpers (built)">
    `codeEnum` (`@kit/fields`) · `rsFixture` / `boFixture` / `rs-auth` (`@tests/helpers`)
  </Card>
</CardGroup>
