Chapter 6 of 8

Architecture — AtelierBID

How the package is structured and how data flows through it.

AtelierBID has a deliberately simple shape: skills orchestrate, subagents do the reasoning, Node scripts do the deterministic work, and file-first artefacts are the output. Nothing runs outside the Claude Code session.


1 · The runtime model#

The plugin has zero backend and zero marginal cost. Every capability is a Claude Code primitive:

RoleImplementation
User-facing entry pointa skill in skills/
AI reasoning unita subagent in agents/
Deterministic computationNode scripts in scripts/ (+ scripts/lib/ libraries)
Design constantsdata/design-system.json
Per-run statea per-run output/<run-id>/ folder

Top-level layout#

PathResponsibility
skills/User-facing entry points (/AtelierBID:<skill>). Each SKILL.md defines the workflow steps.
agents/Single-purpose reasoning subagents dispatched by skills (21 in total).
scripts/32 deterministic Node CLIs across all lifecycle phases — foundation, discovery, model, calculation, design, AI, and documentation.
scripts/lib/Pure libraries: grounding/lifecycle helpers; design libs colorMath / themeBuilder / designSystem; pipeline libs mockupIr / composeLayout / chooseVisualType / irToPbir / applyTokens.
data/design-system.jsonMachine-readable constants: audience archetypes, layout patterns, colour roles, canvas sizes, theme defaults. data/canonical-sample.schema.json is the grounding fallback sample.
.claude-plugin/plugin.json + marketplace.json manifests.
output/<run-id>/Generated artefacts and step checkpoints (gitignored).

The core design principle — deterministic vs. AI split#

Two subagents serve the calculation and metadata phases. measure-author turns a batch of requested measures into DAX bound strictly to the columns present in the supplied model, factoring shared base measures across the batch and marking anything off-schema as a proposal rather than inventing a column. metadata-enricher writes descriptions and synonyms that beat the deterministic fallback — ai-readiness.js can only template ("Amount on the Sales table."), which restates the column name and helps nobody. Neither agent writes files: both return JSON, and the skills and CLIs perform all I/O, so the write path stays byte-reproducible.

Structure is computed; taste is delegated. Scripts are deterministic and AI-free — they consume no tokens and produce reproducible output: building/validating theme JSON, colour distances, sanitising SVG/HTML, rendering DDL/Mermaid, scaffolding a PBIP, capturing a requirements spec, emitting review-only SQL/M/DAX, composing a report layout, and converting a mockup IR into PBIR. Subagents are stateless reasoning units that handle the judgment calls (brand → palette, layout composition, schema design). The skill is the only coordinator; agents never call each other. No deterministic script uses the clock, randomness, or the network.

Data flow (a design-pipeline run)#

flowchart TD
    U[User brief] --> S[Skill: design-report]
    S --> R["new-run.js → output/<run-id>/"]
    R --> A1[orchestrator agent]
    A1 --> A2[brand → data-model → dummy-data agents]
    A2 --> A3[composer → visual-fill agents]
    A3 --> SC["deterministic compose / token / IR checks"]
    SC --> A4[validator → narrative agents]
    A4 --> O[mockup HTML + IR in run folder]
    A1 -. checkpoint .-> R
    A3 -. checkpoint .-> R
Diagram — shown as source if the renderer is unavailable.

Each step checkpoints into the run folder before the next begins, so an interrupted run resumes from the last completed step.

The mockup → PBIR bridge (Phase E)#

The design phase's headline structure is a single shared mockup IR read by both the human previews and the PBIR converter, so an approved mockup becomes a report page without re-authoring:

flowchart LR
    CMP["design-report.js --compose<br/>(composeLayout + chooseVisualType)"] --> IR["mockup IR<br/>(mockupIr.js — schemaVersion 1.0)"]
    IR --> TOK["--apply-tokens (applyTokens.js)<br/>resolve tokens + background zones"]
    TOK --> MH["--emit-mockup → HTML mockup"]
    TOK --> PRO["prototype-report.js --ir<br/>interactive Chart.js prototype"]
    PRO --> EIR["--emit-ir → approved IR (byte-identical)"]
    EIR --> PBIR["design-report.js --from-ir --pbip<br/>(irToPbir.js → PBIR-enhanced page)"]
    TOK --> PBIR
Diagram — shown as source if the renderer is unavailable.

The IR is a self-describing JSON contract (kind atelierbid/mockup-ir, additive-only — ADR-0033) carrying the grid, KPI strip, and per-visual type + rationale on a floor+remainder grid tiling that guarantees no overlap. Conversion (irToPbir.js) targets the PBIR-enhanced format, maps visual types through a fixed VISUAL_TYPE_MAP (unmapped → warn-and-skip), emits deterministic GUIDs, and guards existing files behind a _atelierBidGeneratedBy ownership sentinel (ADR-0034).

The foundation & data-acquisition CLIs (Phases A + B)#

The grounding/lifecycle spine plus discovery, SQL and Power Query/M authoring compose into one coherent starting flow:

flowchart LR
    NP["new-project.js"] --> PBIP["scaffold-pbip.js / validate-pbip.js"]
    NP --> BP["best-practice.js (seed _00-Best-Practice/)"]
    GC["ground-schema.js (load gate · propose-don't-invent · re-ground)"] --> GEN[generation]
    LC["lifecycle.js (offline floor · Tier-1 opt-in · bind-gate · manual publish)"] -. wraps .-> GEN
    DR["discover-requirements.js"] --> AS["author-sql.js (emit-only)"]
    AS --> AM["author-m.js (emit-only)"]
Diagram — shown as source if the renderer is unavailable.

2 · The full-package architecture#

The package covers seven lifecycle phases, all writing into one PBIP project, all standing on the shared cross-cutting spine (Phase A).

flowchart TB
    subgraph SPINE["Cross-cutting spine — always on"]
        GC[Schema-grounding contract]
        BP[Best-practice rule library]
        LC[Hybrid lifecycle + conformance harness]
    end
    A[A · Start project + PBIP shell] --> B[B · Discovery + SQL/M text]
    B --> C[C · Model — star schema → TMDL]
    C --> D[D · Calculation — DAX]
    D --> E[E · Design — tokens → theme → IR → PBIR]
    E --> F[F · AI — readiness + Fabric data agent]
    F --> G[G · Documentation]
    SPINE -. grounds / guards / cites .-> A
    SPINE -. grounds / guards / cites .-> C
    SPINE -. grounds / guards / cites .-> D
    SPINE -. grounds / guards / cites .-> E
Diagram — shown as source if the renderer is unavailable.

Key components and responsibilities#

ComponentResponsibilityWhere
New Project + PBIP scaffoldCreate the project folder + conventions, and an openable PBIP container every downstream skill writes into; structural validator as a Desktop proxy.Phase A
Schema-grounding contractSingle authoritative schema-of-record; a load gate; propose-don't-invent (off-schema = a proposal); re-ground on change.Phase A
Best-practice rule libraryPer-project _00-Best-Practice/ rules + BPA JSON; the single source the model/DAX/settings skills cite by stable id.Phase A
Hybrid lifecycle + conformance harnessOffline floor + optional Tier-1; "bind live data?" gate; drift guard over canonical PBIR/TMDL fidelity; manual publish.Phase A
Discovery + source textDeterministic requirements spec with trace ids + gap detection; emit-only SQL and folding-aware Power Query/M.Phase B
Model engineEmit star-schema TMDL: tables, inferred safe relationships including role-playing, settings, partitions, incremental refresh, and a ranked read-only optimisation pass with safe auto-fix.Phase C
Calculation engineIdiomatic DAX + calc groups in a _Measures host; a time-intelligence family on a contiguous marked date table; equivalence-preserving rewrites with a write-back gate; EVALUATE validation queries.Phase D
Design pipelineToken contract, accessible theme with RAG separation, zoned PBIP-wired background, a shared mockup IR that converts into valid PBIR, and an interactive prototype.Phase E
AI layerModel AI-readiness (audit, descriptions+synonyms, linguistic schema, surface hygiene, verified answers) via one offline CLI; plus a Fabric data-agent generator emitting a grounded agent-config.json with scope + guardrails and an ordered provisioning runbook.Phase F
Documentation generatorDeterministic, regenerable data dictionary parsed straight from the TMDL.Phase G

The artefact model — one project that accretes#

All phases write into a single PBIP container, which grows but always stays Desktop-openable:

flowchart LR
    P0[Empty PBIP shell] --> P1[+ TMDL model]
    P1 --> P2[+ DAX measures]
    P2 --> P3[+ theme.json + PBIR report]
    P3 --> P4[+ AI-ready metadata]
    P4 --> P5[Openable, documented project]
Diagram — shown as source if the renderer is unavailable.

Data-flow / grounding tier model#

stateDiagram-v2
    [*] --> Offline
    Offline --> Offline: generate / validate (file-first, zero network)
    Offline --> Tier1: user opts in — "bind live data?"
    Tier1 --> Offline: read live schema · validate · drop back
    Tier1 --> Manual: publish / refresh
    Manual --> [*]: runs in the Power BI Service — instructions only, never via API
Diagram — shown as source if the renderer is unavailable.

Offline is the default and floor; live read/validate is opt-in Tier-1; publish/refresh are always a deliberate manual step (ADR-0002, ADR-0008).


External dependencies#

By design, there are almost none:

  • Runtime: Node.js (stdlib only — no npm dependencies).
  • Claude Code: provides the skill/subagent execution environment.
  • Chart.js (CDN): loaded only by the interactive prototype's output HTML, at view time — the one optional, preview-only network dependency. The IR → PBIR generation path is fully offline.
  • Power BI Desktop (optional): for the "opens without error" verification and the optional Tier-1 live read/validate. Never required for the offline floor.
  • No backend, database, auth, API key, or cloud service — the zero-backend stance is the defining constraint.

Decisions that shape the architecture#

  • ADR-0002 — optional live connectivity as Tier-1 above an offline floor; publish stays manual.
  • ADR-0004 — PBIP structural baseline + offline determinism; the validator is a Desktop proxy.
  • ADR-0012 / 0013 — SQL and Power Query/M authoring are emit-only with offline static validation.
  • ADR-0014–0021 — the model engine: emit-only TMDL, inferred star-safe relationships, settings, partitions, incremental refresh, and a read-only optimiser with a result-preservation gate.
  • ADR-0022–0029 — the calculation engine: TMDL measure shape, marked-date binding, contiguous date table, time-intelligence semantics, equivalence-preserving rewrites, and EVALUATE queries.
  • ADR-0030–0032 — the design token contract, RAG separation rule, and background wiring.
  • ADR-0033 — the shared mockup-IR schema + floor/remainder grid tiling.
  • ADR-0034 — IR → PBIR conversion to the PBIR-enhanced format with offline structural fidelity.
  • ADR-0035–0039 — the AI-readiness layer: model-as-TMDL-directory + exit-0-findings-in-content; additive enrich; linguistic-schema shape; hygiene via displayName without renaming; measure-grounded verified answers.
  • ADR-0040–0042 — the Fabric data agent: a single deterministic agent-config.json; an offline-floor CLI shape; a grounding-input contract accepting JSON model or TMDL directory.

See Decisions for the full digest.