---
name: ba-create-actors
description: >
  Phase 2 of business analysis. Defines the project's actors (roles) that
  interact with the applications, and writes them to `acteur.md` at the
  Application level under `.smartstack/ba/`. Conversational: reads the menu tree
  and existing actors, proposes coverage per app, asks the user to validate, then
  writes the file. Run after the menu (`/ba-create-menu`), before use cases.
allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion]  # Bash: sources-search CLI (client sources)
---

# ba-create-actors — Project-scoped actors

You define the **actors** (roles) that interact with the applications — the WHO,
not the permissions (those come later in RBAC). Actors are **project-scoped**: an
actor defined once can be linked to several applications. Reuse is the default.

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

State lives in `.smartstack/ba/`. There is no database and no action blocks.

1. **Read state**: `Glob .smartstack/ba/**/index.md` for the menu tree (apps =
   top-level folders; read each app `index.md` `## Contexte` to know what it
   does). Read existing `.smartstack/ba/<APP>/acteur.md` files for actors already
   defined (reuse candidates).
2. **Propose** actors per application in prose (list each `code` + label + type).
3. **Ask** the user to validate with **AskUserQuestion** (one multi-select per
   application). Open exploration questions go in prose.
4. **Write** `acteur.md` with the **Write** tool once validated. A Write
   overwrites the file — re-list every actor that must survive.

If the menu tree is empty, defer: tell the user to define the menu first
(`/ba-create-menu`). Do not propose actors without applications.

### Where actors are written (authority)

`acteur.md` is **authoritative at the Application level**:
`.smartstack/ba/<APP>/acteur.md`. The placeholder `acteur.md` that the menu phase
left at module/section/resource levels stays a **rollup pointer** — replace it
with one line `> Acteurs hérités — voir [../acteur.md](../acteur.md)` (do not
duplicate actor content downward). An actor active on several apps is written in
each of those apps' `acteur.md`, with its `Périmètre` line saying which
modules/sections it covers.

**Nature lock.** Actors are transverse by design — multi-app writes are
legitimate — but this skill writes ONLY `acteur.md` files. Touching ANOTHER
app's `acteur.md` is legitimate ONLY for the documented reuse pattern: the same
actor, identical code, adding/updating its `Périmètre` line. Never any other
document, never a divergent redefinition of an existing actor.

### `acteur.md` shape (authoritative, at the app)

```markdown
<!-- ba:acteur level=application code=CRM -->
# Acteurs — CRM

### BA-001-AC-001 — Commercial
- **Type** : internal
- **Description** : Gère son portefeuille de prospects et opportunités.
- **Périmètre** : CRM (toute l'application)
- **Origine** : conversation

### BA-001-AC-002 — Manager commercial
- **Type** : internal
- **Catégorie** : Manager
- **Description** : Supervise l'équipe et valide les remises.
- **Périmètre** : CRM / PIPELINE
- **Origine** : code (rôle détecté)
```

## Client sources (read + cite)

If `.smartstack/sources/index.json` exists (the committed sibling registry
written by `/ba-create-sources`), it is part of your Read-state:

1. **Read** `index.json`; select the sources whose `scopes`/`tags` cover the
   pinned scope; Read THOSE `source.md` only — never `raw/`, never the whole
   corpus (context-bomb interdiction).
2. **Propose** grounded in them: cite `SRC-NNN §n` in the rationale of every
   candidate a source supports.
3. **Write the citation**: `- **Sources** : SRC-NNN §n` right after the actor's
   `**Origine**` line (Origine says HOW it was found, Sources says WHERE).
   **Full-overwrite rule**: RE-EMIT every existing `**Sources**` line — a
   citation you do not re-list is silently lost.
4. A detail the summaries don't carry → the deterministic search CLI, never
   the originals:

   ```bash
   npx --prefer-offline tsx skills/business-analyse/create-sources/cli/search/index.ts \
     --spec '{"baRoot":".smartstack/ba","query":"<term>","tags":["<tag>"]}'
   ```

Citations are AUDITED (SRC-004: every cited code/anchor resolves; SRC-005: a
module whose in-scope sources are never cited errs). Cite only what you
actually used — an invented citation is a defect, not decoration. No
registry → this section is a no-op.

## Actor fields

| Field | Rules |
|-------|-------|
| code | `BA-{analysisSeq}-AC-{NNN}` — `analysisSeq` is the 3-digit project sequence (first project = `001`), `NNN` a 3-digit per-project counter. Grep existing `acteur.md` headings to find taken numbers and increment. The number, never the label, is the identity. |
| label | Human label in the user's language (accents OK). |
| Type | `internal` (employees/admins, direct access), `external` (clients/partners/candidates via a portal), or `system` (background services). |
| Catégorie | Optional. The platform `RoleCategory` the seeded role will carry — one of the labels mapped in `_workflow/role-taxonomy.md` (`Admin`, `Manager`, `Contributor`, `Viewer`, or their FR labels). Absent/unknown → `Custom` at seed time; `Global` is reserved for platform roles, never authored here. |
| Description | One sentence on the role. **Required.** |
| Périmètre | The app, optionally a module/section, the actor covers. App-wide when only the app is named; module-restricted when a module is named. |
| Origine | Traceability: where the proposal came from (conversation / code / user decision / bundle standard). **Required.** |

## Exploration — before proposing

1. **Read existing actors** from the `acteur.md` files (reuse candidates — never
   re-create an actor that exists; add a `Périmètre` line instead).
2. **Scan existing code** if the project has any: authorization attributes, role
   enums, permission seeds, frontend role constants. Extract the real role
   identifiers — use the codebase's own names, don't invent.
3. **Read each app's `## Contexte`** — it tells you who interacts with the app.
4. **Present a short summary**: actors already defined (N), roles found in code
   (M), applications in the project. No invented content — if a category is
   empty, say so.

## Proposing actors

For each application, propose the interacting actors via one AskUserQuestion
multi-select (pre-select the obvious ones). Every actor MUST trace to the user's
request, the app `## Contexte`, the code scan, or the user's explicit answers.
Tag each as *réutilisé* / *détecté* / *inféré* in the prose, with a concrete
source. Ask open questions about the organisation when context is thin — never
dump a generic list.

## Standard bundles (opt-in — one offer per application)

After an application's actors are validated, offer ONCE (AskUserQuestion,
closed multi-select) the three standard bundles — reference table in
`_workflow/role-taxonomy.md`:

| Bundle | Catégorie | Label (fr) |
|--------|-----------|------------|
| `{app}-admin` | Admin | « Administration {App} » |
| `{app}-operator` | Contributor | « Gestion {App} » |
| `{app}-viewer` | Viewer | « Consultation {App} » |

Retained bundles are authored as NORMAL actors (own `BA-…-AC-…` code,
`Origine : bundle standard`, `Catégorie` pre-filled from the table) — they are
not a separate concept downstream. `/ba-create-rbac` materializes their default
rows deterministically (admin = every module action ; operator = access/read/
create/update ; viewer = access/read) and `derive-lookup-grants` covers their
FK dropdowns like any create/update actor. Do NOT re-offer bundles the user
already declined for that app (their absence from `acteur.md` after a recorded
refusal is the state). This is the ONE sanctioned exception to prohibition #1 —
the bundles are explicit, user-validated opt-ins, not silent archetypes.

## Absolute prohibitions

1. **Never hardcode domain archetypes** (HR managers, accountants, "admin",
   "user", "viewer") without anchoring them to the user's actual organisation.
   (The opt-in standard bundles above are the sanctioned exception — offered,
   never imposed.)
2. **Never use CRUD-style codes** (`CREATE_USER`, `READ_ACCESS`) — those are
   permissions, not roles. Actors are WHO, not WHAT-THEY-DO.
3. **Never invent codes or labels** — every actor traces to the conversation,
   the code scan, or an existing `acteur.md`.
4. **Never assign a `Type` without justification** — ask if uncertain.
5. **Never reuse a removed actor number** in the same project.

## Self-check before writing (actors → use-cases gate)

Before writing, verify each actor has a well-formed `BA-…-AC-…` code, a `Type`, a
non-empty `Description`, and an `Origine`. Surface any gap to the user instead of
writing a half-defined actor. (The deeper audit — duplicates, missing types,
coverage ACT-001..006 — is run by `/ba-audit-actors`, which reads the
`acteur.md` files and writes its verdict; you don't produce audit findings here.)

## After writing → hand off to use cases

Acknowledge in one line ("4 acteurs définis pour CRM."). Then, per the fixed
order, the next phase is **use cases** — propose continuing with
`/ba-create-use-case` (don't ask "what next?"). Convert any descendant
`acteur.md` placeholders you encounter into the one-line rollup pointer.

## Edge cases

| Situation | Action |
|-----------|--------|
| Actor already exists, only a new app link | Don't re-create — add a `Périmètre` line in that app's `acteur.md` |
| User removes an actor from an app | Re-Write the app's `acteur.md` without it (overwrite drops it) |
| Actor exists with a different label | Confirm the change with the user, keep the code |
| Same actor across several apps | Write it in each app's `acteur.md`, code identical, `Périmètre` per app |
| User adds ONE actor after the use cases / RBAC exist (finished scope) | Route to `/ba-change` (kind=actor) — it allocates the project-wide code, checks the label and the seeded role code against EVERY application, and lists the UCs and RBAC rows the new actor drags along |
