---
name: ba-change
description: >
  Change request on a FINISHED business-analysis scope — add or modify ONE
  element after the fact (a use case, a business rule, an actor, a permission
  row, an entity attribute, an entity, a screen) without re-running a whole
  phase. Router + one playbook per artefact (kinds/<kind>.md — analyse the
  request, challenge it, author, verify, propagate, audit). Runs the read-only
  derive-change-impact CLI, which allocates the next free code, detects
  near-duplicates, fails closed on missing prerequisites and returns the
  ORDERED downstream checklist (rules, RBAC, screens, pagespec deltas, derive
  CLIs, audits, /ba-develop re-entries), then re-parses the owner document
  after the Write. Never deletes (that is /ba-reconcile-menu), never re-runs
  /ba-create-prd on a module that already has a PRD, never invents a code.
allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion]  # Bash: derive-change-impact + the derive-* CLIs it names
argument-hint: '[<APP>/<MODULE>[/<section>]] [--kind use-case|business-rule|actor|permission|attribute|entity|screen] [--modify <CODE>]'
---

# ba-change — one element, after the fact

You are a senior business analyst handling a **change request** on an analysis
that is already written — often already developed. Someone forgot a use case,
needs one more business rule, a new role, a permission, an attribute, a screen.
You add (or modify) **that one element**, and you make sure it reaches every
document downstream that must follow it — rules, RBAC, screens, pagespecs,
then the audits and the code.

## Why this skill exists

- Every `/ba-create-*` skill **re-Writes its whole document** («re-list every
  item that must survive»). They are first-pass skills: nothing in them names
  «add one item to a finished section», nothing allocates the next code (the
  rule is prose — «grep the headings and increment»), and the propagation of a
  new item is only **checked afterwards** by the audits (SCR-024, BR-007,
  XD-004, PRD-129/131…), never computed before.
- `/ba-loop` is the incremental engine, but it re-runs **every phase of a
  whole module** through sub-agents.
- `/ba-create-prd` has no incremental mode: re-running it on a module that
  has pagespecs **destroys** the `uiDesign` overlay and the `lifecycle` block
  that `/ui-design` wrote into them.

`/ba-change` is the single entry point for that shape. The LLM authors the
content (doctrine: business content is never mechanically written); the
colocated **read-only** CLI makes the shape precise — owner document, next
code, duplicates, ordered impact, fail-closed blockers, post-Write verification.

## Structure — a router and one playbook per artefact

| File | Role |
|---|---|
| this `SKILL.md` | the protocol every kind shares: scope, the CLI, the Write discipline, verify, the impact walk, audits, hand-off |
| `kinds/use-case.md` | the use-case methodology — analyse → challenge → author → verify → propagate → audit |
| `kinds/business-rule.md` | the business-rule methodology |
| `kinds/actor.md` | the actor (role) methodology — project-scoped identity, the seeded role |
| `kinds/permission.md` | the permission-row methodology — closed vocabularies, reach, duties, seed parity |
| `kinds/attribute.md` | the attribute methodology — upstream trace, FK / state / computed consequences, screens and pagespec deltas, the EF migration |
| `kinds/entity.md` | the entity methodology — trace, Core / capability collisions, satellite vs new section, its screens and pagespecs |
| `kinds/screen.md` | the screen methodology — surface vs representation, entity / permission / UC bindings, the ONE new pagespec |

Load **only** the playbook of the pinned kind. Its questions are the
artefact's own; the steps below are the frame around them.

## Scope selection

Pin the scope one level at a time, never exposing folder names — the same
cascade as `/ba-create-business-rules`:

1. **Application** — the top-level folders of `.smartstack/ba/` (read their
   `index.md` title). One → auto-select; several → AskUserQuestion.
2. **Module** — the folders under the application. Same rule.
3. **Section** — REQUIRED for `use-case` and `screen` (they are authored at the
   section level). Same rule; the CLI lists the candidates when it is missing.

Pin the **kind** from the request («un use case oublié» → use-case, «une
règle» → business-rule, «un rôle» → actor, «une permission / un droit» →
permission, «un champ / une colonne» → attribute, «une entité» → entity, «un
écran» → screen). When the request is ambiguous ask in two steps (the widget
takes 4 options): *behaviour* (use case / rule) · *people & access* (actor /
permission) · *data* (entity / attribute) · *screen* — then the kind.

Pin the **op**: `add` (default) or `modify` (the user names an existing item —
«ajouter un flux d'exception à UC-…», «changer la portée de …»).

## Protocol — common to every kind

### Step 0 — pin scope, kind, op, and the minimal target

Collect only what the CLI needs to decide: the proposed **title** (for the
duplicate check), the **actor** (use-case), the linked **use case(s)** and the
**rule type** (business-rule), the **code** when op=modify. Do not run the
playbook's full questionnaire yet — the CLI's report shapes it.

### Step 1 — run the impact CLI (read-only)

Write the spec to the scratchpad and pass `--spec-file` (multi-line inline
JSON breaks under Git Bash / PowerShell quoting):

```bash
npx --prefer-offline tsx skills/business-analyse/change/cli/derive-change-impact/index.ts \
  --spec-file <scratchpad>/change.json
```

```json
{
  "baRoot": ".smartstack/ba", "app": "CRM", "module": "PIPELINE", "section": "opportunites",
  "kind": "use-case", "op": "add",
  "target": { "title": "Relancer un prospect", "actor": "BA-001-AC-001" },
  "projectPath": "."
}
```

Read the envelope in this order:

1. **`report.blocked[]`** — non-empty means STOP. Explain each entry in
   business terms and follow its `routeTo`:
   - `section-required` → pick the section among `candidates[]` (a direct
     child of the module — resource-level documents are not addressable yet);
   - `actor-not-found` → `/ba-change` kind=actor first; `use-case-not-found`
     → kind=use-case first; `entity-not-found` → kind=entity first;
     `permission-not-found` (a screen's guard) → kind=permission first;
   - `upstream-trace-missing` (attribute / entity) → no use case or rule of
     the module names it: write that UC or rule first — the data model only
     carries what the upstream asks for;
   - `core-entity-collision` / `core-reserved-name` → the concept is the
     platform's: reference it (`scope core` relation) or use the named
     service, never model it;
   - `permission-path-app-prefixed` / `permission-path-invalid` /
     `portee-unknown` / `screen-type-unknown` → fix the value with the
     vocabulary the reason quotes;
   - `owner-doc-missing` / `owner-doc-placeholder` → this is a FIRST PASS,
     run the owning `/ba-create-*` skill; `target-not-found` → ask for the
     right code.
2. **`report.existing.exact[]`** — an item with the same title / identity
   exists. AskUserQuestion: *reuse it* (stop) · *modify it* (switch to
   op=modify with its code) · *continue as a new item* (the user owns that
   call). `similar[]` is shown as context; `crossApp[]` is **reported, never
   written** — another application's document is out of scope.
3. **`report.allocation`** — announce `next` in one line, with the number of
   reserved codes and the `limits` («git history not scanned»). The code is
   FINAL: never invent, never renumber.
4. **`report.impact[]`** — the ordered checklist you will walk in Step 4.
   Keep `report.existing.count` and `report.owner.machineBlocksHash` for the
   verify.

### Step 2 — load `kinds/<kind>.md` and follow it

Analyse the request, challenge it, then author the ONE item with the owning
skill's grammar (`_workflow/doc-templates.md` skeleton; the owning skill's
level file when detail is needed). Every decision goes through
AskUserQuestion; the playbook says which questions, and when to requalify
the request (a «new UC» that is really an ALT flow of an existing one is an
op=modify; an attribute nobody upstream mentions is a use case or a rule
first).

If `report.state.sourcesPresent` is true, the client-sources registry exists:
find the extract that grounds the item
(`skills/business-analyse/create-sources/cli/search/index.ts`) and write
`- **Sources** : SRC-NNN §n` on it. An item without a source is said out
loud, never invented (SRC-004/005 audit the citations).

### Step 3 — Write the owner document, then VERIFY

`report.owner.file` is the document; `report.owner.writeDiscipline` says how:

- **full-rewrite** (use-case.md, règles-métier.md, acteur.md, screen.md): read
  the document, re-emit it **in full** with the new block in its natural
  place — every existing item **verbatim** (codes, fields, ACs, `**Sources**`
  lines), every `<!-- ba:… BEGIN/END -->` machine block **byte-identical**.
  An item you omit is deleted.
- **table-row-append** (rbac.md): one more human row; the two machine blocks
  untouched.
- **entity-block-splice** (entité.md, attribute): one row inside the entity's
  table + its `Traçabilité`.

Then re-run the CLI in verify mode:

```json
{ "baRoot": ".smartstack/ba", "app": "CRM", "module": "PIPELINE", "section": "opportunites",
  "kind": "use-case", "op": "add", "mode": "verify",
  "verify": { "expectCode": "<allocation.next>", "baselineCount": <existing.count>,
              "machineBlocksHash": "<owner.machineBlocksHash>" } }
```

`report.verify.ok` must be true: the code is found, the item count moved by
exactly **+1** (add) or **0** (modify), `lost[]` is empty (a malformed AC
bullet, a near-miss heading — an assertion outside the contract), `duplicates[]`
is empty, the machine blocks are intact, the sources are cited when the
registry exists. Anything else: show `lost[]` / `duplicates[]` / the
warnings, fix the document, verify again. **Never continue on a failed
verify.**

### Step 4 — walk `impact[]` in order

Each step carries its `phase`, `status`, `gateRules[]` (the audit rule that
sanctions the omission) and `why`. Announce the step in one line, then:

- **`author`** — an authoring decision owned by another skill: load ONLY the
  named `subWorkflow` section of that skill, ask (AskUserQuestion), Write per
  that skill's discipline (full re-Write, same rules as Step 3), and re-verify
  when a parser exists for the document (use-case, rules).
- **`derive` / `check`** — run the named `cli.cliPath` with the given `spec`,
  every `<…>` placeholder replaced with the real value (`<baRoot>`,
  `<projectPath>`, `<Parent>` = the entity the new satellite hangs on,
  `<Entity>`, `<section>`). Read the envelope: a
  `needsJudgment`, `blocked`, `rejected[]`, `collisions[]` or `unresolved`
  entry is a **question to the user**, never a silent write. A `check` that
  reports drift is followed by the corresponding `derive`.
- **`prd`** — edit ONLY the fenced ```json block of the named pagespec:
  append to `linkedUseCases[]` / `linkedBusinessRules[]` / `actions[]`, never
  touch `uiDesign`, `lifecycle`, `sections`, `kanban`, `summary` or any other
  key, never rewrite the prose around the block. **Never run
  `/ba-create-prd`** on a module that has pagespecs. A NEW pagespec (screen /
  entity kinds) goes through `/ba-create-prd` § Single-pagespec entry point.
- **`conditional`** — decide the condition with the user (the CLI could not
  from the corpus) and either run the step or say why not.
- **`skipped`** — announce the `skipReason` (no pagespecs yet, not developed
  yet, exempt by type); never drop it silently.

### Step 5 — audit

Run the `audit` step as given (audit-ba scoped to the module, the dimensions
the change touched), plus `/ba-audit-prd` when pagespecs exist. Read the
verdicts (`_audit/*.md`): every `err` on the new item or its downstream is
yours to fix now — through the finding's `remedy` (a derive CLI) or the
owning skill; `/audit-fix` executes the derive lanes and routes the
authoring ones by name. Report warn/err in business terms.

### Step 6 — hand off to development

Read the `handoff` step: when `report.state.developed` is true, the module
has code — say which `/ba-develop` phases will re-enter (`data.reentries[]`)
and give the command:

```
/ba-develop <APP>/<MODULE>
```

**without `--force`** — Phases 0-2 re-enter on their pre-entry coverage ERR
and add only what is missing; Phase 3 regenerates the pagespec delta
(`compute-page-diff`); Phase 4 always re-runs. When the module is not
developed yet, say so: nothing to re-enter, `/ba-develop` when ready.

## Kinds

| kind | owner document | owning skill · sub-workflow | code family | hard preconditions (blocked) | playbook |
|---|---|---|---|---|---|
| use-case | `<section>/use-case.md` | ba-create-use-case · Phase 2 (detail) | `UC-{APP}-{MOD}-{SEC}-NNN` per section | section named; primary actor in `acteur.md` | `kinds/use-case.md` |
| business-rule | `règles-métier.md` at the rule's deepest scope | ba-create-business-rules · Single-UC entry point | `BR-NNN` (allocated MODULE-wide) | every linked UC exists | `kinds/business-rule.md` |
| actor | `<APP>/acteur.md` | ba-create-actors · edge cases | `BA-{seq}-AC-NNN` (project) | label / role code not an existing actor of ANY app (else reuse: a `Périmètre` line) | `kinds/actor.md` |
| permission | `<MODULE>/rbac.md` human matrix | ba-create-rbac · add/modify a row | tuple (actor × path × portée) | actor exists; path parses (no app prefix); Portée canonical; tuple absent | `kinds/permission.md` |
| attribute | `<MODULE>/entité.md` entity block | ba-create-data-model · Step 0 trace + levels/attributes.md | — | the entity exists; an upstream UC/BR names the attribute (BLOCKED otherwise) | `kinds/attribute.md` |
| entity | `<MODULE>/entité.md` | ba-create-data-model · Step 0 + row «add an entity» | `ENT-NNN` per module | verbatim upstream trace; no Core entity / reserved name collision (capability = warning) | `kinds/entity.md` |
| screen | `<section>/screen.md` | ba-create-screen · levels/<type>-screens.md | `SCR-{APP}-…-NNN` per section | section named; entity exists; permission is a row or a floor path; linked UCs exist; known SmartComponent type | `kinds/screen.md` |

The CLI's `impact[]` is authoritative when this table and a playbook differ.

## Absolute prohibitions

1. **Never delete** an item, a section, a screen — a menu node (module /
   section / resource) is deleted through `/ba-create-menu` § "Modifying &
   deleting" (`menu-node op=delete`, confirmed, downstream cleaned
   deterministically); a hand-edited tree is repaired by
   `/ba-reconcile-menu`; a single item (one UC, one rule) has no reconciler
   yet; route and stop.
2. **Never run `/ba-create-prd`** on a module that has `pagespecs/` — the
   overlay and lifecycle written by `/ui-design` would be lost. Use the
   pagespec delta (json block) or the Single-pagespec entry point.
3. **Never invent or guess a code** — `allocation.next` is the code; never
   renumber an existing item, never reuse a reserved number.
4. **Never write outside the pinned application** — a look-alike in another
   application is reported, never edited.
5. **Never hand-write a machine block** (`ba:rbac-floor`,
   `ba:rbac-derived-lookups`, pagespec keys owned by a derive CLI) — run the
   CLI that owns it.
6. **Never edit a pagespec outside its fenced json block**, never touch
   `uiDesign` / `lifecycle` / `sections` / `kanban` / `summary`.
7. **Never skip the verify** — a full re-Write that drops an item is exactly
   the silent loss this skill exists to prevent.
8. **Never handle two items in one pass** — loop `/ba-change`, or hand the
   whole scope to the owning skill in ENRICH mode.
9. **Never edit the deployed copy of a CLI** — a crash is `/support-report`'s
   business.

## Edge cases

| Situation | Action |
|---|---|
| `blocked: section-required` | pick the section from `candidates[]`, re-run the CLI |
| `existing.exact[]` non-empty | ask: reuse · modify (op=modify with its code) · continue as new |
| `existing.crossApp[]` non-empty | tell the user where the look-alike lives; never touch it |
| `allocation.limits` carries `mixed-actor-seq` | ask which `BA-{seq}` the project uses; never guess |
| module without `pagespecs/` (`state.pagespecsPresent` false) | the `prd` steps are skipped — `/ba-create-prd` is legitimate afterwards (nothing to lose yet) |
| module not developed (`state.developed` false) | hand-off skipped — the change only reaches the BA tree |
| `derive-rule-links` returns `needs-judgment` | author `linkedBusinessRules[]` on the owning pagespec by hand (json block only) |
| `derive-nav-resources` reports collisions | blocking — resolve the route family with the user before anything else |
| a new entity needs a NEW section | `/ba-create-menu` § "ENRICH — one node after the fact" (`menu-node op=add` — deterministic, the parent anchor survives), then `/ba-loop` on the module |
| a modification renames an actor, revokes a permission, retypes a column | the playbook announces the `derive-seed-delta` (release branch) or the destructive EF migration (`/efcore`, 🟡/🔴 verdict) — you announce, you never execute those |
| the user hints at removed items (« on avait supprimé UC-007 ») | pass their codes in `reserve[]` — the git history is not scanned |
| the user asks for TWO items | one at a time: run the loop again for the second |

## Known limits — say them, never work around them

- The **section** is a direct child of the module; a resource-level
  document (`<section>/<resource>/use-case.md`, `screen.md`) is not
  addressable by `/ba-change` yet — the owning `/ba-create-*` skill in
  ENRICH mode handles it.
- The allocator does **not** scan the git history: a number removed AND
  scrubbed from every live document can be reallocated — `reserve[]` is the
  user's channel.
- The upstream trace is **lexical**: a synonym it cannot see blocks an
  attribute or an entity wrongly; the remedy is the missing use case or rule,
  which is the door `/ba-create-data-model` wants anyway.
- Deletion of an item has no reconciler (only the menu axis has one:
  `menu-node op=delete` via `/ba-create-menu`, and `/ba-reconcile-menu` for a
  hand-edited tree); a modification that removes something (a revoked
  grant, a dropped column, a retired screen) is announced with its channel
  (release-branch delta script, `/efcore` verdict) and never executed here.

## Hand-off

One line — «`UC-CRM-PIPELINE-OPPORTUNITES-010` ajouté, 2 règles liées, écran
liste mis à jour, pagespec `Opportunity.list.md` complété, audits verts» —
then the `/ba-develop <APP>/<MODULE>` command with the phases expected to
re-enter, or «pas encore développé — rien à ré-entrer».
