Decisions — AtelierBID
The architectural decisions on record and what they mean for you.
AtelierBID records architectural decisions as ADRs (Architecture Decision Records). Each ADR captures one non-obvious decision: the context that forced it, the choice made, the alternatives rejected, and the consequences. ADRs are immutable once accepted — a later decision supersedes an earlier one rather than editing it. The full ADR texts live in the private development repository; the summaries below are the record for adopters.
Read an ADR when you want to understand why something is the way it is, not just what it is. The decisions below are the ones most relevant to adopters and users of the plugin.
Decisions that affect how you use AtelierBID#
Offline floor (ADR-0002)#
The offline file-first path is the default and floor — zero auth, zero network, zero cost. Live read + validate is an optional, user-selected Tier-1 so generation can ground against a real model. Publish and refresh stay manual — instructions only, never executed via APIs.
This means: you can use AtelierBID with no internet connection for all generation and validation. You opt into live schema validation when you need it, and you always publish to Power BI Service yourself.
Export out of scope#
Outputs are file-first text and HTML previews: PBIP/TMDL/PBIR/theme.json, SQL, Mermaid, HTML mockups, and interactive prototypes. PNG, PDF, and PPTX export are out of scope; the generated HTML files are the shareable preview format.
Optional live connectivity (ADR-0008)#
The Tier-1 live override (lifecycle.js --override tier1) flips connectivity for that invocation only and is never persisted. The offline floor is the persistent default; a garbage override fails safe back to offline.
All decisions on record#
All 41 shipped ADRs are accepted. The table is sorted most-recent-first.
| ADR | Title | Date | Summary |
|---|---|---|---|
| ADR-0042 | Fabric-agent grounds from either a JSON model or a TMDL directory, failing loudly | 2026-06-30 | fabric-agent.js --model accepts both a .json model file and a directory of *.tmdl; a missing / empty / invalid model fails loudly rather than silently emitting generic defaults. |
| ADR-0041 | fabric-agent runs its CLI on require and scans argv position-independently for the offline harness | 2026-06-30 | fabric-agent.js calls main() on module load and parses flags position-independently, so a no-egress harness can require() it to prove zero live calls. |
| ADR-0040 | Fabric data-agent config asset is a single deterministic agent-config.json | 2026-06-30 | One agent-config.json with a stable, versioned top-level shape (schemaVersion, kind, dataSources, grounding, scope, guardrails, instructions), byte-order sorted and deterministic. |
| ADR-0039 | Verified-answer mappings are measure-grounded with a target-must-resolve guard | 2026-06-30 | verified-answers pins templated questions to Table[Measure] targets only when the target resolves in the model; de-duped by question so re-runs regenerate cleanly. |
| ADR-0038 | Hygiene hides keys via isHidden and disambiguates via displayName (never renames the physical column) | 2026-06-30 | Surface hygiene sets isHidden: true on key columns and adds a qualified displayName to cross-table name clashes without renaming the physical column, so relationship-referenced keys keep resolving. |
| ADR-0037 | Linguistic-schema shape (entities[] with bindings + terms), Q&A-scoped to exclude keys | 2026-06-30 | One entity per table / non-key column / measure, each with a binding to an existing surface plus lowercased terms; key columns excluded to avoid Q&A bloat. |
| ADR-0036 | Enrich adds descriptions/synonyms as additive column props; validate-pbip --model accepts a directory | 2026-06-30 | enrich injects description:/synonyms: property lines additively and idempotently; validate-pbip.js --model extended to accept a directory of *.tmdl. |
| ADR-0035 | AI-readiness reads a model as a TMDL directory and reports gaps in artefact content, not exit code | 2026-06-30 | A "model" is a directory of *.tmdl; every sub-command exits 0 and records gaps in artefact content so audit && grep chains keep running. |
| ADR-0034 | IR → PBIR conversion targets the PBIR-enhanced format with offline structural fidelity | 2026-06-30 | Convert the mockup IR to the PBIR-enhanced format; map visual types via VISUAL_TYPE_MAP (unmapped = warn-and-skip); guard overwrites on a _atelierBidGeneratedBy ownership sentinel; deterministic GUIDs. |
| ADR-0033 | Shared mockup-IR schema and floor+remainder grid tiling | 2026-06-29 | The mockup IR is self-describing JSON (schemaVersion 1.0, kind atelierbid/mockup-ir), embedded in a script block with </-injection escaping, and additive-only. Floor+remainder grid tiling eliminates visual overlap. |
| ADR-0032 | Background descriptor schema + offline PBIP static-resource wiring | 2026-06-29 | The background descriptor carries width/height/grid/styleTrace/zones; --pbip writes the resource into StaticResources and references it from report.json. |
| ADR-0031 | RAG-separation reserved set is the status roles only; informational excluded | 2026-06-29 | The ΔE-guard reserved set is {positive, negative, neutral}; informational (brand-accent blue) is excluded so blue-brand palettes pass the ΔE ≥ 15 guard without false-clashing. |
| ADR-0030 | Design-token contract — additive schema, consumers resolve, in-memory parameterisation | 2026-06-29 | A formal token schema lives in an additive tokens map; --resolve --set overlays brand params in memory only — the base file is never mutated. |
| ADR-0029 | DAX query — emit-only, metadata-in-comments, two-block equivalence pair | 2026-06-29 | EVALUATE queries carry human metadata in // comment lines; offline structural validation; an equivalence pair is two labelled EVALUATE blocks. |
| ADR-0028 | Offline time-intelligence numeric proxy + partial/prior-period semantics | 2026-06-29 | Validate time-intelligence offline against a hand-calculable constant-amount sample. |
| ADR-0027 | Fiscal-year naming and week-calendar semantics | 2026-06-29 | Fiscal year is named by its ending calendar year; ISO-8601 Monday-start is the default week calendar. |
| ADR-0026 | Marked date table as a calculated CALENDAR() table, contiguity proven offline | 2026-06-29 | The date table is emitted as a calculated CALENDAR() table marked dataCategory: Time; contiguity proven offline by a leap-day-aware UTC day-walk. |
| ADR-0025 | DAX write-back safety gate + offline equivalence verdict | 2026-06-29 | Write-back gated behind an explicit --apply (dry-run by default); the offline verdict reports engine: none rather than claiming false equivalence. |
| ADR-0024 | Equivalence-preserving DAX rewrite set + equivalence-id tagging | 2026-06-29 | Only a closed set of transforms that are equivalence-preserving by construction are applied; every rewrite is tagged with an equivalence id. |
| ADR-0023 | Marked-date-table resolution precedence for time-intelligence binding | 2026-06-29 | Precedence: contract + exactly one marked table → bind; contract + zero/many marked → fail loudly; absent → fall back to the convention 'Date'[Date]. |
| ADR-0022 | Measure/calc-group TMDL emit shape + measure-aware validator | 2026-06-29 | A sibling emitter writes measure and calculationGroup TMDL blocks; the measure-aware validator requires tab indentation, correct nesting, and non-empty expressions. |
| ADR-0021 | Optimiser auto-fix — safe fix set + offline before/after equivalence gate | 2026-06-29 | Only autofix: safe findings are written, via deterministic idempotent text edits, behind a result-preservation gate. |
| ADR-0020 | Model optimiser — read-only static scan + numeric severity ranking | 2026-06-29 | The optimiser scans TMDL read-only and ranks findings by a numeric severity with a stable tie-break. |
| ADR-0019 | Incremental refresh — emit-only refreshPolicy + M-fold heuristic | 2026-06-29 | Emits refreshPolicy, RangeStart/RangeEnd params and a foldable filter; a static M-text fold heuristic flags bare-vs-wrapped columns. |
| ADR-0018 | Partitioning — row-threshold recommendation, IR-template partition | 2026-06-29 | A deterministic recommendation (1M+ rows + a date-like grain) drives partitioning; the date range is emitted as an IR-template partition. |
| ADR-0017 | Uniform column grouping — name-inferred kinds + catalogue fallback | 2026-06-29 | Column grouping kind is inferred from the column name; the member list comes from a --tables dir or a built-in catalogue fallback; an unknown group fails loudly. |
| ADR-0016 | Role-playing dimensions — one active relationship + USERELATIONSHIP hint | 2026-06-26 | Exactly one active relationship per (fact, dimension) pair is emitted, with inactive relationships carrying USERELATIONSHIP hints. |
| ADR-0015 | Relationships inferred by shared-key naming, star-safe defaults | 2026-06-26 | Relationships are inferred from shared-key naming with star-safe many→one defaults; bidirectional is opt-in and warned. |
| ADR-0014 | Star-schema modelling — emit-only, heuristic NL parser, structural TMDL | 2026-06-26 | A heuristic NL parser (closed grammar) emits star/flat/dimension-only TMDL; offline structural TMDL validation proxies "opens in Desktop". |
| ADR-0013 | M authoring — emit-only, structural validation, fold heuristic, Value.NativeQuery IR wrapping | 2026-06-26 | author-m.js writes review-only M with no mashup engine; fold-breaks are flagged (warn-don't-fail). |
| ADR-0012 | SQL authoring — emit-only, context-selects-emitter, offline static parse | 2026-06-26 | author-sql.js writes review-only SQL with no DB driver and no execution path. |
| ADR-0011 | Discovery gap detection — additive gaps[] + stdout, non-fatal exit | 2026-06-25 | --check-gaps reports holes as an additive gaps[] field and exits 0 — a gap is a warning, not a failure. |
| ADR-0010 | Discovery trace ids — additive REQ-NNN array, opt-in and deterministic | 2026-06-25 | --trace stamps every captured item with a stable REQ-NNN id, assigned in fixed bucket-walk order so re-runs are byte-identical. |
| ADR-0009 | Discovery requirements spec — fixed-order JSON schema, deterministic | 2026-06-25 | The discovery spec is a fixed-key-order JSON document serialised deterministically; identical inputs yield byte-identical specs. |
| ADR-0008 | Tier-1 connectivity override is per-invocation, never persisted | 2026-06-25 | lifecycle.js --override tier1 flips connectivity for that run only; the offline floor is the persistent default. |
| ADR-0007 | Sanitise unsafe characters but refuse path traversal in project names | 2026-06-25 | new-project.js sanitises unsafe characters into a safe folder token but refuses .. path traversal. |
| ADR-0006 | Merged measures host in a dedicated _Measures table | 2026-06-19 | Generated measures are hosted in a dedicated _Measures table, never a table named after the measure. |
| ADR-0005 | Ship a minimal inline TMDL bootstrap early to unblock schema grounding | 2026-06-19 | A minimal inline TMDL bootstrap was shipped early in ground-schema.js before the full extraction bootstrap; the full version followed subsequently. |
| ADR-0004 | PBIP structural baseline, offline determinism, validator-as-Desktop-proxy | 2026-06-19 | A single requiredParts list drives both scaffolder and validator; emission is deterministic; the structural validator proxies "opens in Power BI Desktop". |
| ADR-0003 | XL build phases kept un-split; each phase delivered feature-by-feature | 2026-06-18 | The larger build phases (01, 03, 05) are kept as single units delivered feature-by-feature — each feature is the 1–2-week deliverable — rather than further sub-divided. |
| ADR-0002 | Optional live connectivity as Tier-1 above an offline floor; publish stays manual | 2026-06-18 | The offline file-first path is the default and floor. Live read + validate is an optional Tier-1. Publish / refresh stay manual. |
See Architecture for how these decisions shape the system, and Features for the capabilities they govern.