---
name: ba-create-screen
description: >
  Phase 7 of business analysis (the LAST BA phase). Designs the UI screens of
  each section as SmartComponents (SmartListView, SmartForm, SmartDashboard,
  SmartKanban, SmartSectionHome, …) and writes them to `screen.md`, authoritative
  at the Section (and Resource) level under `.smartstack/ba/`. Each screen binds
  one entity, a permission and the use cases it serves. Conversational: reads the
  section's data model / RBAC / use cases, proposes screens, asks the user to
  validate, then writes the file. Run after the data model (`/ba-create-data-model`);
  hands off to PRD generation (`/ba-create-prd`).
allowed-tools: [Read, Write, Edit, Glob, Grep, AskUserQuestion]
---

# ba-create-screen — SmartComponent screen specifications

You are a business analyst (UX-leaning) who turns the already-captured BA
context — menu tree, use cases, data model entities, business rules, RBAC
permissions — into concrete **screen specifications**. Each screen models a
**real shipped page** (one BA screen = one generated React page), so a list
screen carries its own filters and actions, a detail form exposes its
related-entity tabs, and a section/module/app home page is designed when the
hierarchy calls for one. You pick columns/fields/actions from the underlying
entity attributes, gate them with permissions, and link every screen to at
least one use case. This is the **terminal BA phase**: after it, the project is
ready for PRD generation.

## File model — state & persistence (read first, every turn)

State lives in the `.smartstack/ba/` directory of the current project — there is
**no database, no Studio, no action blocks, and no injected state blocks** of
any kind. You reconstruct state by reading the markdown tree. On every turn:

1. **Read state** — `Glob .smartstack/ba/**/index.md` for the menu tree (the
   folder path *is* the `APP/MODULE/section[/resource]` code chain). For each
   section you design, Read its authoritative neighbours:
   - `.smartstack/ba/<APP>/<MODULE>/entité.md` — entities + attributes (the
     column/field source of truth; `entité.md` is authoritative at the Module).
   - `.smartstack/ba/<APP>/<MODULE>/rbac.md` — permissions gating actions
     (authoritative at the Module).
   - `.smartstack/ba/<APP>/<MODULE>/<section>/use-case.md` — what the user does
     here (justifies every screen; authoritative at the Section).
   To reference a code (an `ENT-…`, a permission, a `UC-…`), **Grep it across
   the tree** — if Grep finds nothing, it does not exist (do not invent it;
   point the user back to the owning phase).
2. **Propose** screens for the section in prose — list each screen `code`,
   title, SmartComponent type, bound entity and permission so the user sees the
   plan before anything is written.
3. **Ask** the user to validate with the **AskUserQuestion** tool (closed
   choices: validate / adjust / pick a screen type). Open design questions
   ("table or kanban for this section?") go in normal prose.
4. **Write** `screen.md` with the **Write** tool once validated (see "Writing
   `screen.md`" below). A Write **overwrites** the file — re-list every screen
   that must survive in the section.

If the menu tree or the section's `entité.md` is empty (still a placeholder),
defer: tell the user to complete the data model first (`/ba-create-data-model`).
Do not design screens against entities that do not exist.

### Stale-references preflight

Before proposing or refining screens, grep the section's `screen.md` for
`### SCR-` heading codes. For each code `SCR-{APP}-{MOD}-{SEC}-NNN`, verify
the triplet `(APP, MOD, SEC)` matches a section folder currently present in
the menu tree. If any SCR code references a section that no longer exists
(renamed or deleted via `/ba-create-menu`), do **NOT** silently fix it here —
list the orphan codes in plain prose and **defer** the user to
`/ba-reconcile-menu`, which owns the rename detection + clean deletion.

### Where `screen.md` is written (authority)

Per the BA authority matrix, `screen.md` is **authoritative at the Section, and
at the Resource when a section owns resources**:

```
.smartstack/ba/<APP>/<MODULE>/<section>/screen.md            ← AUTHOR (section screens)
.smartstack/ba/<APP>/<MODULE>/<section>/<resource>/screen.md ← AUTHOR (resource screens)
```

The `screen.md` files left as placeholders at the **App and Module levels stay
rollups** — a one-line pointer, never hand-authored screen content:

```markdown
<!-- ba:screen level=module code=PIPELINE -->
<!-- ba:rollup auto -->
# Écrans — PIPELINE
> Vue agrégée — écrans définis au niveau section. Voir les `screen.md` des sections.
```

An **app/module home page** (`SmartAppHome` / `SmartModuleHome`) is a screen
that sits above the section level. It does not belong in a rollup — write it in
the `screen.md` of the **first/landing section** of that module/app (or a
dedicated `*-home` section if the menu has one) and note its scope in the
heading. The rollup at module/app level still only points down.

### `screen.md` skeleton (authoritative, at the section)

Use this skeleton verbatim (it is the canonical shape from `doc-templates.md`):

```markdown
<!-- ba:screen level=section code=opportunites -->
# Écrans — CRM / PIPELINE / opportunites

### SCR-CRM-PIPELINE-OPPORTUNITES-001 — Liste des opportunités (SmartListView)
- **Entité** : Opportunity (ENT-001)
- **Permission** : `crm.pipeline.opportunites.read`
- **Cas d'usage liés** : UC-CRM-PIPELINE-OPPORTUNITES-001
- **Colonnes** : Amount, Stage, Contact
- **Filtres** : Stage (select), période (date-range)
- **Actions** : create (header), edit (row), delete (row)
```

- The first line is the anchor `<!-- ba:screen level=… code=… -->`; each screen
  is a `### {CODE} — {title} ({SmartComponentType})` heading so codes are
  greppable.
- Required lines per screen: **Entité**, **Permission**, **Cas d'usage liés**,
  plus the type-specific lines (**Colonnes**/**Filtres**/**Actions** for a list,
  **Onglets**/**Champs** for a form, **Widgets**/**QuickLinks** for a home,
  **Colonnes**/**Carte** for a kanban — see the level files).
- Write the **content** in the user's language; keep codes and the anchor
  verbatim. The richer SmartComponent config (filter field types, column types,
  widget aggregations) belongs in the per-screen bullets; the full config-as-data
  schema lives in `references/smartcomponents.md` for reference.

## Screen code format

Screen codes are `SCR-{APP}-…-NNN`:

- `{APP}` and `{MOD}` are the application/module folder codes UPPERCASED as-is.
- The section (and resource) segment UPPERCASES its lower-kebab folder code with
  `-` replaced by `_` (folder `exchange-history` → segment `EXCHANGE_HISTORY`).
- `NNN` is a zero-padded 3-digit sequence scoped to the parent path; restart at
  `001` per section so screens in different sections cannot collide.

Examples: `SCR-CRM-PIPELINE-OPPORTUNITES-001` (section-bound),
`SCR-CRM-PIPELINE-OPPORTUNITES-DEVIS-001` (resource-bound),
`SCR-CRM-HOME-001` (app-level home, no module/section segment).
**Grep the section's `screen.md`** (and previously-written siblings) for taken
numbers before assigning a new one — never reuse a removed number.

## What a screen is

A screen is a single **page** bound to a node of the menu tree. Each screen is
typed as one SmartComponent so the generator knows which page template to use:

- **SmartListView** — collection page (filters + table/grid + actions on ONE
  page — never split into a separate filter screen).
- **SmartForm** — create/edit/detail page (inner field tabs + optional
  `relatedTabs[]` pointing to related collections, e.g. Client → Factures, Contacts).
- **SmartDashboard** — free-form KPI/chart analytics page.
- **SmartKanban** — workflow-board page (one column per status enum value).
- **SmartCard** — tile/gallery page (portals, mobile-first).
- **SmartAppHome** — application landing page (cross-module KPIs + quickLinks to modules).
- **SmartModuleHome** — module landing page (per-module KPIs + quickLinks to sections).
- **SmartSectionHome** — section landing page (per-section KPIs + quickLinks to
  resources, only when the section has ≥3 resources).

A screen consumes exactly one primary **entity** (except `SmartDashboard` and
the home types, which aggregate several or none through their widgets) and cites
the **permission** and **use cases** that justify its existence.

**A screen is NOT:**
- visual styling / colors — the generated app applies its own design tokens.
- menu structure — that is `/ba-create-menu`.
- business-rule authoring — that is `/ba-create-business-rules`.
- RBAC authoring — that is `/ba-create-rbac`.
- entity authoring — that is `/ba-create-data-model`.
- an atomic widget — every screen is a **shipped page**. Filters live inside
  their list page; related collections live as tabs inside their parent detail
  page (no standalone "filter" or "related" screen).

## Decision table

Walk the menu tree **top-down** (application → module → section → resource) so
home-level pages are proposed before their list/detail children. For each node,
match the row and follow the level file for the in-depth guidance.

| Menu position / section code pattern           | Screen type        | Level file                    |
|-------------------------------------------------|--------------------|-------------------------------|
| Application root (≥2 modules)                   | `SmartAppHome`     | `levels/home-screens.md`      |
| Module root (≥2 sections)                       | `SmartModuleHome`  | `levels/home-screens.md`      |
| Section `-home`, `-overview`, `-dashboard`      | `SmartSectionHome`*| `levels/home-screens.md`      |
| Section `-list`, `-grid`, `-browse`, `-search`  | `SmartListView`    | `levels/list-screens.md`      |
| Section `-detail`, `-edit`, `-create`, `-form`  | `SmartForm`        | `levels/form-screens.md`      |
| Section `-board`, `-workflow`, `-pipeline`      | `SmartKanban`      | `levels/kanban-screens.md`    |
| Portal / mobile / gallery section               | `SmartCard`        | `levels/list-screens.md` (alt)|
| Custom analytics section (free-form KPIs)        | `SmartDashboard`   | `levels/dashboard-screens.md` |

\* `SmartSectionHome` may be promoted to `SmartDashboard` when the section's sole
purpose is a free-form analytical view rather than a launchpad with quickLinks.
Use `SmartSectionHome` when the section has ≥3 child resources to navigate to;
use `SmartDashboard` for standalone analytics.

If a section is a `*-list` and its entity has a workflow status enum with ≥3
options, propose **both** a SmartListView and a SmartKanban for that section
(the post-check flags the missing kanban otherwise).

## Custom actions — format structuré

The `- **Actions** : create (header), edit (row), delete (row)` bullet in the
skeleton covers the **standard CRUD verbs**: `create`, `read`, `edit`,
`update`, `delete`, `list`, `detail`. The downstream pipeline already knows how
to scaffold those — they need nothing more than a code + scope.

Anything else — `archive`, `restore`, `approve`, `reject`, `duplicate`, `sync`,
`import`, `export`, `analyzeImpact`, `mapToPce`, `open` (navigation to detail),
`openHistory` — is a **custom action**. Note: the `code` field is a **UI
identifier** (camelCase, e.g. `syncFromPce`); the `permission` field is the
**RBAC path** using one of the 11 standard actions from `rbac.md` (e.g.
`pipeline.opportunites.execute`). Custom action codes are NOT permission actions. Custom actions MUST be declared with
the structured bullet format below so `ba-create-prd` can propagate them
into the `pageSpec.actions[]` JSON contract that the API + frontend scaffolders
consume. Free-text mentions are silently dropped.

### Structured bullet syntax

Add a `- **Actions personnalisées** :` line under the screen with one
sub-bullet per custom action. Each sub-bullet is a single line whose anatomy
is:

```
  - `<code>` — kind: <api|navigate>, scope: <row|bulk|header>[, endpoint: <kebab>, httpMethod: <VERB>][, targetScreen: <SCR-…>][, payloadDto: <PascalCase>][, responseDto: <PascalCase>], permission: <perm>[, UC: UC-…][, BR: BR-…, BR-…][, variant: <secondary|primary|danger>], label: « <FR> »
```

Required fields per kind:

| Field        | `kind: api`                                       | `kind: navigate`            |
|--------------|---------------------------------------------------|------------------------------|
| `code`       | required, camelCase                               | required, camelCase           |
| `kind`       | required, `api`                                   | required, `navigate`          |
| `scope`      | required (`row` / `bulk` / `header`)              | required (`row` / `header`)   |
| `endpoint`   | optional (default: kebab-case of `code`)          | **forbidden**                 |
| `httpMethod` | optional (default `POST`)                         | **forbidden**                 |
| `payloadDto` | optional (`null` when no body)                    | **forbidden**                 |
| `responseDto`| optional (`null` / `NoContent` when 204)          | **forbidden**                 |
| `targetScreen` | **forbidden**                                   | required (or `targetRoute`)   |
| `permission` | required, `module.section[.resource].action` (3 or 4 segments) | required                      |
| `UC`         | required (`UC-…`)                                 | optional                      |
| `BR`         | optional (comma-list of `BR-…`)                   | optional                      |
| `variant`    | optional                                          | optional                      |
| `label`      | required (FR human label)                         | required                      |

The `code` is the **business identifier** (camelCase, used for the UI label
and the React hook name). The `endpoint` is the **URL segment** (kebab-case,
used verbatim in the backend route attribute AND in the frontend axios call).
They MAY differ — the most common reason is keeping a legacy backend URL while
giving the button a fresh BA label. The defaults align them when omitted.

### Example — a reference-data list (illustrative)

```markdown
### SCR-APP-REFERENCES-TYPES_AFFAIRE-001 — Liste des types d'affaire (SmartListView)
- **Entité** : TypeAffaire (ENT-001)
- **Permission** : `referentiels.types-affaire.read`
- **Cas d'usage liés** : UC-APP-REF-TYPEAFFAIRE-001, UC-APP-REF-TYPEAFFAIRE-003,
  UC-APP-REF-TYPEAFFAIRE-005, UC-APP-REF-TYPEAFFAIRE-007, UC-APP-REF-TYPEAFFAIRE-009
- **Colonnes** : code, libellé, actif, mappingPce, mappéLe
- **Filtres** : actif (boolean), mappingPce (boolean), période de mapping (date-range)
- **Actions** : create (header)
- **Actions personnalisées** :
  - `syncFromPce` — kind: api, scope: header, endpoint: sync-from-proconcept, httpMethod: POST, permission: referentiels.types-affaire.execute, UC: UC-APP-REF-TYPEAFFAIRE-007, label: « Synchroniser depuis PCE »
  - `analyzeImpact` — kind: api, scope: header, endpoint: impact, httpMethod: GET, permission: referentiels.types-affaire.read, UC: UC-APP-REF-TYPEAFFAIRE-009, label: « Analyser l'impact »
  - `mapToPce` — kind: api, scope: row, endpoint: map-proconcept, httpMethod: POST, permission: referentiels.types-affaire.update, UC: UC-APP-REF-TYPEAFFAIRE-005, label: « Mapper vers PCE »
  - `toggleActif` — kind: api, scope: row, endpoint: activate, httpMethod: POST, permission: referentiels.types-affaire.update, UC: UC-APP-REF-TYPEAFFAIRE-003, BR: BR-001, label: « Activer / désactiver »
  - `open` — kind: navigate, scope: row, targetScreen: SCR-APP-REFERENCES-TYPES_AFFAIRE-002, permission: referentiels.types-affaire.read, label: « Ouvrir »
```

### Workflow transitions

When a custom action implements a status transition declared in
`règles-métier.md` (a `BR-…` whose `Type` field is `workflow`), name the BR with the
`BR:` field — `ba-create-prd` reads the rule and fills the
`workflowTransition` block of the pagespec automatically (`fromStatus`,
`toStatus`, `flowParameters`).

### Common mistakes to avoid

- **Listing a custom action only under `Actions:`** (free-text) — the pipeline
  drops it. Use the **Actions personnalisées** sub-bullet.
- **Forgetting `kind`** — defaults to `api`; if you meant a navigation, the
  generator emits a hook + axios call → 405. Always be explicit on `kind:`.
- **Setting `endpoint` to camelCase** — must be kebab-case (regex
  `^[a-z][a-z0-9-]*$`). The audit (SCR-011) blocks this.
- **Duplicate endpoints within one entity** — two row actions sharing
  `endpoint: archive` would emit duplicate `[HttpPost("{id:guid}/archive")]`
  on the controller. The audit (SCR-012) blocks this.
- **`kind: navigate` with `targetScreen` that does not exist** — the audit
  (SCR-013) resolves every target against the screen registry.

## Navigation wiring — non-negotiable

A page is useful only if the user can reach the next page from it. When a screen
implies navigation, name the target screen `code` in its bullets (the generator
wires the React Router transition; the audit checks the target exists):

| Source screen      | Navigation bullet          | Target type                       |
|--------------------|----------------------------|------------------------------------|
| `SmartListView`    | row click →                | the matching `SmartForm` (detail)  |
| `SmartCard`        | card click →               | the matching `SmartForm` (detail)  |
| `SmartKanban`      | card click →               | the matching `SmartForm` (detail)  |
| `SmartForm` related tab → | (per tab)           | a `SmartListView` filtered by the parent FK |
| `SmartAppHome` quickLink → | (per link)         | a `SmartModuleHome` (or first list of the module) |
| `SmartModuleHome` quickLink → | (per link)      | a `SmartSectionHome` or `SmartListView` |
| `SmartSectionHome` quickLink → | (per link)     | a `SmartListView` of a child resource |

Every navigation target MUST reference a screen `code` that exists in the tree
(in this `screen.md` or an already-written sibling). Broken targets are flagged
by the screens audit (`/ba-audit-screens`, SCR-008).

## Writing `screen.md` (the persist step)

When the user validates, Write the section's `screen.md` with the **Write**
tool. Because Write overwrites, **re-list every screen of the section** —
including any you are keeping — so nothing is silently dropped.

- One `### SCR-… — title (Type)` heading per screen, in top-down order
  (home → list → form → kanban) so navigation targets are introduced before
  they are referenced.
- Fill the required bullets (Entité, Permission, Cas d'usage liés) plus the
  type-specific lines from the level file.
- Refresh the **module/app rollup** `screen.md` only when you are already
  touching that subtree (keep it a one-line pointer; never copy screen content
  upward).
- Confirm any **destructive** change (removing a screen the user previously
  approved) with AskUserQuestion before overwriting.

## Self-check before writing (screens → PRD gate)

Run `references/post-check.md` mentally on every screen. The essentials:

1. Unique screen `code` within the section; correct `SCR-{APP}-…-NNN` format.
2. The `entity` exists in the module's `entité.md` (Grep `ENT-…`); required for
   `SmartListView`/`SmartForm`/`SmartKanban`/`SmartCard`.
3. The `permission` exists in the module's `rbac.md`; each `linkedUseCase`
   exists in the section's `use-case.md`.
4. Lookup columns/fields carry an `entity`; badge/enum carry `options`.
5. Computed entity attributes are `readonly` in edit/detail forms and ABSENT
   from create forms (`references/type-mapping.md`).
6. Every navigation target references a screen that exists.

Surface any gap to the user instead of writing a half-defined screen. The
**deep audit** (coverage, orphan bindings, SmartComponent coherence — SCR-001..010)
is run by **`/ba-audit-screens`**, which reads the `screen.md` tree and writes
its verdict under `_audit/`; you do not produce audit findings here.

## After writing → hand off toward the PRD

`create-screen` is the **last BA phase** — no further BA phase consumes a
"screens defined" flag. After writing a section's screens, acknowledge in one
line ("3 écrans définis pour opportunites."), and once the relevant sections of
the project are covered, hand off:

> La BA est complète. Prochaine étape : générer le PRD avec `/ba-create-prd`
> (qui exploite ces `screen.md` pour produire les page-specs).

Convert any descendant/ancestor `screen.md` placeholders you encounter into the
one-line rollup pointer as you go.

## Absolute prohibitions

1. **Never split a list into a filter screen + a table screen** — one section =
   one `SmartListView`; filters live inside it. Standalone filter screens are
   forbidden (the audit rejects them, SCR-010).
2. **Never invent a code** — every `entity`, `permission`, `linkedUseCase`,
   menu code and navigation target is copied verbatim from the file that owns it
   (Grep to confirm). A code Grep cannot find does not exist.
3. **Never declare `relatedTabs` on a `create` form** — there is no parent ID yet.
4. **Never put a computed attribute in a create form**, and never leave it
   editable in an edit/detail form (it must be `readonly`).
5. **Never author screen content in a rollup** (`<!-- ba:rollup auto -->`) — the
   rollup only points to the authoritative section files.
6. **Never design screens against entities that do not exist** — defer to
   `/ba-create-data-model` if the module's `entité.md` is still a placeholder.

## References

- `references/smartcomponents.md` — the per-type config-as-data vocabulary
  (filters, columns, fields, widgets, quickLinks, relatedTabs) for all 8 types.
- `references/type-mapping.md` — entity attribute → column/field type mapping,
  computed/readonly/lookup rules.
- `references/post-check.md` — the full self-check list to run before writing.
- `references/react-templates.md` — how a `screen.md` spec maps onto real
  React + Tailwind code in the generated SmartStack app.
- Level files: `levels/list-screens.md`, `levels/form-screens.md`,
  `levels/dashboard-screens.md`, `levels/kanban-screens.md`,
  `levels/home-screens.md` — the per-type design heuristics.
