---
name: ba-files
description: >
  The file-based persistence model for the BA workflow in native Claude Code.
  The `.smartstack/ba/` markdown tree IS the database — there is no Studio, no
  SQLite, no `[ACTION]` blocks. Read the tree as state, write `.md` with the
  Write tool. Replaces the Studio-era `output-schema.md`.
phase: '*'
kind: companion
mode_pinned: true
section_label: '_WORKFLOW — FILE MODEL (.smartstack/ba)'
---

# BA file model — the markdown tree is the database

In native Claude Code there is **no Studio, no SQLite, no backend route, no
`[ACTION]`/`[QUESTION]` block, no injected `--- CURRENT X ---` state**. Your
state is the `.smartstack/ba/` directory in the user's project. You:

1. **Read** the tree (Glob + Read) at the start of every task to know what exists.
2. **Propose** in prose; ask closed choices with the **AskUserQuestion** tool.
3. **Write** `.md` files with the **Write** tool once the user validates.

There is no watchdog and no input lock. A skill that "persists" simply writes a
file. A skill that "reads current state" simply reads files.

## Output root & layout

Everything lives under **`.smartstack/ba/`** in the current project
(`.smartstack/` is already SmartStack's project-local config dir). Each node of
the Application → Module → Section → Resource hierarchy is a **folder named by
its code**, and every node folder carries `index.md` + the six concept docs:

```
.smartstack/ba/
├─ index.md                      ← PROJECT metadata (name, context, global out-of-scope, app list)
└─ CRM/                          ← Application  (code UPPERCASE)
   ├─ index.md
   ├─ acteur.md
   ├─ entité.md
   ├─ use-case.md
   ├─ règles-métier.md
   ├─ screen.md
   ├─ rbac.md
   ├─ _audit/                    ← audit verdicts for this node (menu.md, actors.md, …)
   └─ PIPELINE/                  ← Module  (code UPPERCASE)
      ├─ index.md … (same 6 docs + _audit/)
      ├─ prd.md                  ← PRD synthesis (module level only — see create-prd)
      ├─ prd.entities.md / prd.api.md / prd.frontend.md
      ├─ pagespecs/<Entity>.<view>.md
      ├─ claude.md
      ├─ audit.json              ← dev-readiness gate (generated, see audit-prd)
      └─ opportunites/           ← Section  (folder = code, lower-kebab ASCII)
         ├─ index.md … (same 6 docs)
         └─ devis/               ← Resource (folder = code, lower-kebab ASCII)
            └─ index.md … (same 6 docs)
```

The **folder structure encodes the menu hierarchy**; each folder is named by its
**node code** and each `index.md` holds the node metadata (incl. the accented
label). Codes are ASCII (UPPERCASE apps/modules, lower-kebab sections/resources),
so `Opportunités` (label) lives in a folder named `opportunites` (code).
Generated doc CONTENT is in the user's language; this SKILL.md and all skill
files stay in English.

## Boundary — `.smartstack/ba/` is the SPECIFICATION, nothing else

`.smartstack/ba/` is the business specification: the seven `/ba-create-*`
skills write it, the audits read it, `/ba-create-prd` synthesises it,
`/ba-develop` consumes it. Nothing else belongs in it. **Execution traces do
NOT**: `/ba-develop` writes its run artefacts (`heal.log.json`,
`blockers.json`) to **`.smartstack/runs/<APP>/<MODULE>/`** — a sibling root,
appended to the project's `.gitignore` at run start (they date from one run
and are stale at the next; the UAT precedent gitignores its `runs/` the same
way). The historical `_dev/` folder inside the BA tree mixed two lifetimes and
two audiences, and the convention was propagating (editor feedback rounds were
filed there by analogy). The only generated files that legitimately live in
`ba/` are the SPEC-derived ones the audits/diffs read across runs: `_audit/`
verdicts, `_plan/`, `audit.json` and `.run-snapshot.json` (the page-diff
baseline — functional state, committed like `.smartstack/core-seed/`).

## Sibling root — `.smartstack/sources/` is the EVIDENCE, committed

Client-provided source material (cahiers des charges, PDF, Word/Excel, notes,
screenshots) and RETAINED web findings live in **`.smartstack/sources/`** — a
sibling root, never inside `ba/` (same reasoning as `runs/`: a client document
has a different lifetime and audience than the spec; filing it in the BA tree
would repeat the `_dev/` mistake). Unlike `runs/`, sources are **COMMITTED**:
a spec line `- **Sources** : SRC-002 §3` is a citation, and a citation must
stay verifiable and diffable after the client's original file is gone (the
`core-seed/` precedent). The registry is written ONLY by
`/ba-create-sources`' `cli/ingest`; its contract lives in `lib/ba-sources.ts`
and the `sources` audit dimension (SRC-001..007) keeps it honest.

**Context-bomb interdiction** (the 394M-token incident): no skill, no agent,
no audit ever reads `sources/` wholesale or opens `raw/`. Consumers read
`index.json`, then the few `source.md` whose `scopes`/`tags` cover their
pinned scope; anything finer goes through the deterministic
`cli/search`.

> The six **doc filenames** are intentionally French and accented (`acteur.md`,
> `entité.md`, `use-case.md`, `règles-métier.md`, `screen.md`) — keep them
> verbatim. Only the **folder names** are ASCII codes.

## The six docs + index — what each holds

| File | Owner skill | Holds |
|------|-------------|-------|
| `index.md` | create-menu | node code, label, context, out_of_scope, list of children |
| `acteur.md` | create-actors | actors (`BA-{NNN}-AC-{NNN}`): label, type, description, scope |
| `use-case.md` | create-use-case | Cockburn UCs (`UC-{APP}-{MOD}-{SEC}-NNN`) |
| `règles-métier.md` | create-business-rules | rules (`BR-…`): condition, expression, valid/invalid examples, linked UCs |
| `rbac.md` | create-rbac | permission matrix: actor × action × scope |
| `entité.md` | create-data-model | MCD entities (`ENT-…`): attributes, relationships, indexes |
| `screen.md` | create-screen | screen specs (`SCR-…`): SmartComponent type, entity, config |
| `jeu-de-test.md` | create-test-data | OPTIONAL — the business TEST DATASET (`JT-…`): 5-8 fictitious rows per business entity, the second seed tier (dev/test/qual, never prod), the acceptance-test fixtures and a simulator's rows. ASCII name on purpose |

BA docs carry **no diagrams** — visual ERD / sequence rendering is a Studio
concern, not part of the file-based BA output.

## Authority matrix — single source of truth, no drift

The six docs **exist at every level** (uniform, predictable structure). To avoid
divergent duplication, **exactly one level is AUTHORITATIVE per concept**; the
other levels carry an **auto-generated rollup** — a short aggregated/filtered
view that links to the authoritative children and never contains hand-authored
prose.

| Doc | App | Module | Section | Resource | Authoritative level |
|-----|-----|--------|---------|----------|---------------------|
| `index.md` | author | author | author | author | every node (intrinsic metadata) |
| `acteur.md` | **author** | rollup | rollup | rollup | App (actors are app/project-scoped) |
| `rbac.md` | rollup | **author** | author | author | Module (perms attach to actor × target) |
| `use-case.md` | rollup | rollup | **author** | refine | Section (`UC-{APP}-{MOD}-{SEC}-NNN`) |
| `règles-métier.md` | author | author | author | author | the rule's deepest declared scope |
| `entité.md` | rollup | **author** | rollup | rollup | Module (MCD per module) |
| `screen.md` | rollup | rollup | **author** | author | Section / Resource (screen binds there) |
| `jeu-de-test.md` | — | **author** | — | — | Module, OPTIONAL, no rollup — cites other modules' rows by KEY, never copies them (`doc-templates.md` § Références entre modules) |

A rollup file starts with the marker `<!-- ba:rollup auto -->` immediately after
its anchor comment. **Never hand-edit a rollup** — it is regenerated from its
authoritative children. An authoritative file never carries the rollup marker.

## Anchor markers — how files are parsed back into state

Every doc starts with an HTML-comment anchor so a later turn (or an audit) can
reconstruct state by reading files:

```
<!-- ba:node kind=acteur level=application code=CRM -->
```

- `kind` ∈ `node | acteur | use-case | rules | rbac | entité | screen | prd | audit`
- `level` ∈ `project | application | module | section | resource`
- `code` = the node code this doc is scoped to
- `depends` (optional, module-level `index.md` only) = comma-separated `APP/MODULE`
  keys listing cross-module BA dependencies. Written by `/ba-create-ba-order`
  (Phase 1.5). Example: `depends=ERP/REFERENCES,ERP/CUSTOMERS`.
  Absent means "no dependencies declared yet" (not "none").

Individual items inside a doc use a `### {CODE} — {label}` heading so codes are
greppable. The code **prefixes are the functional identifiers** and are found by
Grep on the tree — not from any injected block:

| Identifier | Format | Found in |
|------------|--------|----------|
| application / module code | UPPERCASE | folder name + `index.md` anchor |
| section / resource code | lower-kebab | folder name + `index.md` anchor |
| actor code | `BA-{NNN}-AC-{NNN}` | `acteur.md` headings |
| use-case code | `UC-{APP}-{MOD}-{SEC}-NNN` | `use-case.md` headings |
| rule code | `BR-{NNN}` | `règles-métier.md` headings |
| entity code | `ENT-{NNN}` | `entité.md` headings |
| screen code | `SCR-{APP}-…-NNN` | `screen.md` headings |

## Reading the tree as state (do this first, every task)

1. `Glob .smartstack/ba/**/index.md` → the full node tree (folders = hierarchy).
2. Read the `index.md` of the node(s) in scope for metadata (label, context, out_of_scope).
3. For the concept you work on, Read the authoritative `<concept>.md` of the
   relevant node(s). To reference a code, Grep it across the tree — if it is not
   found, it does not exist (do not invent it; offer to create it).

If `.smartstack/ba/` does not exist, you are at project start: create it and
`index.md` as part of the first `create-menu` turn.

## Writing (Write tool — overwrite semantics)

- A persist = **Write the full authoritative doc** for the node. The Write
  **overwrites** the file, so any item you omit is removed — re-list every item
  that must survive (this replaces the old "orphan cleanup" discipline).
- The authoritative doc holds the real content. At every OTHER level the doc
  still exists (uniform structure) but as a **rollup**. The **minimal, preferred
  form of a rollup is a one-line pointer** to the authoritative doc
  (`> Voir [chemin](...)`) — keep rollups pointer-thin so they cannot drift. An
  aggregated list of child codes is optional, never required. Only refresh a
  rollup when you are already touching that subtree; do not fan out across the
  whole tree on every write.
- `create-menu` scaffolds each new node folder with `index.md` + six
  placeholder docs (anchor + `_À définir via /<skill>_`), so the structure is
  uniform from creation. Phase skills replace placeholders with real content at
  the authoritative level.
- Confirm destructive edits (removing a node, an actor, a permission) with
  AskUserQuestion before writing.

## Code discipline (carried over — still load-bearing)

The verbatim-copy rule survives, with the source of truth now being the `.md`
tree instead of injected blocks. Never translate, compose, or invent a code:
copy it verbatim from the file where it is authored. See `code-discipline.md`
for the seven historical drifts (label→SCREAMING_SNAKE, FR↔EN, dot-composition,
invented codes, …) — they all still apply.
