plan — parity with Microsoft Fabric IQ Plan / Anaplan-style EPM/CPM¶
Source UI: - Fabric IQ Plan (preview) overview — https://learn.microsoft.com/fabric/iq/plan/overview - Planning sheets (key capabilities) — https://learn.microsoft.com/fabric/iq/plan/planning-overview#key-capabilities - Set up scenarios — https://learn.microsoft.com/fabric/iq/plan/planning-how-to-set-up-scenarios - Writeback / persist data — https://learn.microsoft.com/fabric/iq/plan/planning-writeback/planning-how-to-persist-data - Intelligence sheets — https://learn.microsoft.com/fabric/iq/plan/intelligence-overview - Roles in plan — https://learn.microsoft.com/fabric/iq/plan/overview-roles - Anaplan connected-planning (drivers, breakback, versions) — https://www.anaplan.com/
No-Fabric rule. Everything below is the Azure-native default. Planning cells persist to Cosmos; governed writeback MERGEs into Azure SQL; actuals come from a Loom semantic model (AAS/XMLA) or Synapse/ADX. A real Fabric capacity is never required (
.claude/rules/no-fabric-dependency.md).Honest re-grade (2026-06-29). The prior version of this doc graded the editor "A, zero ❌" against an 18-row inventory that mostly enumerated what Loom already built. Measured against the full Fabric IQ Plan + Anaplan inventory below, the structural EPM core (multidimensional cube, hierarchies/roll-ups, user formulas, breakback/spreading, drivers, versions/snapshots) is absent and several polish surfaces (Intelligence gallery, comments, export, writeback logs) are thin or missing. Real grade today: C+ / B-. This doc is the roadmap to true parity.
Last verified: 2026-07-01 against current code (
apps/fiab-console/lib/editors/phase4/plan-editor.tsx+_plan-model.ts). The P0 structural-EPM core has since landed: a Model tab (dimensions + user measures), member hierarchies with roll-up/drill-down, and a guided Formula builder over a no-evaltoken AST — so those rows flip ❌→✅ below. Breakback/spreading, drivers, versions/snapshots, and AI Copilot remain ❌.
Real feature inventory¶
A. Planning sheet — data model¶
- Multi-dimensional cube — rows AND columns can each carry one or more dimensions (Account, Department, Product, Entity, Time), not a fixed "line item × period" grid.
- Hierarchies + roll-up / drill-down — members nest (Region → Country → Store); parents auto-aggregate children; expand/collapse; drill to leaf.
- Member management — add/rename/reorder/indent members; template rows across a hierarchy level.
- Measures — reusable measures (SUM/AVG/COUNT/min/max) over the cube.
B. Planning sheet — business logic¶
- Formula rows — Excel-style expressions referencing other rows/cells.
- Calculated columns — per-period computed columns (growth %, YoY, run-rate).
- Quick formulas — one-click common calcs (% of total, cumulative, growth).
- Driver-based planning — a driver row feeds dependent rows through a formula.
- Spreading / allocation — distribute a value down to cells evenly, by weight, by growth %, or by an existing distribution.
- Breakback (top-down) — edit a parent/subtotal; the delta pushes back to children proportionally.
C. Planning sheet — exploration¶
- Filtering & sorting; Top N ranking; grouping rows/columns; adjustable column widths/layout; hierarchy navigation.
D. Scenarios & versions¶
- Scenarios — create multiple what-if scenarios; compare; per-scenario writeback (all / selected); close scenario.
- Versions & snapshots — snapshot a plan state; version management; compare A↔B; rolling forecast (lock actuals, forecast the tail).
- Scenario security — per-scenario access control.
E. Forecasting & analytics¶
- Forecast management; what-if simulations; rolling forecasts.
- Variance (plan vs actuals vs forecast) with Δ and Δ%.
- Trend analysis.
F. PowerTable¶
- Large dimensional grid bound 1:1 to SQL; sort/filter/inline-edit.
- Import from CSV / Excel / JSON; export.
- Two-way writeback.
G. Intelligence sheets¶
- 100+ chart types, Gantt, KPI cards, tables on a storyboard canvas.
- IBCS formatting; pixel-perfect export to Excel / PDF.
- Canvas- and data-point-level annotations; threaded comments;
@mentions. - Compare actuals vs plans; reusable measures across sheets.
H. InfoBridge (data integration)¶
- Consolidate from multiple sources; transformations (merge/append/pivot/ group); real-time integration; data mapping between sheets.
I. Writeback & persistence¶
- Multiple destinations; add/manage; decimal precision + text length config; autowriteback.
- Writeback logs — milestones, payload size, duration, per-run detail; export.
J. Collaboration¶
- Notes/annotations; comment threads;
@mentions; email notifications; comment digests; comments column + comments pane.
K. Governance¶
- Roles — Planner / Stakeholder / Viewer capability matrix.
- Approval workflows — define flow, assign approvers, review/approve, request adjustments.
L. AI¶
- AI-assisted planning / Copilot ("AI-ready foundation", AI-assisted decisions).
Loom coverage¶
| # | Capability | Status | Notes / backend |
|---|---|---|---|
| 1 | Multi-dimensional cube (row AND column dimensions) | ✅ built (caveat) | PlanModelPanel Model tab + addDimension (plan-editor.tsx:1713/1735); PlanDimension.axis (_plan-model.ts:523); column-axis members validated/persisted but the grid still pivots periods as columns |
| ⅔ | Hierarchies, roll-up/drill-down, member mgmt | ✅ built | roll-up lineItemValueAt sums children (_plan-model.ts:817); expand/collapse toggleCollapse (plan-editor.tsx:752); indent/outdent + DimensionMembersEditor (:1650) |
| 4 | Measures (user-defined, SUM/AVG/COUNT/MIN/MAX + scope) | ✅ built (caveat) | PlanMeasure/addMeasure (_plan-model.ts:534, plan-editor.tsx:1740); defined/validated/persisted, not yet evaluated into a cube-output surface |
| 5/7 | Formula rows + quick formulas | ✅ built | FormulaBuilderDialog guided palette (plan-editor.tsx:1462) over evalFormula recursive-descent AST, no eval (_plan-model.ts:664); quick formulas qf* (:765-792) |
| 12 | Scenarios (branch/rename/delete, per-scenario cells) | ✅ built | PlanningSheetPanel; cloneScenarioCells/dropScenarioCells; Cosmos |
| 16 | Variance plan vs actuals (Δ, Δ%) | ✅ built | computeVariance; variance overlay + Intelligence report |
| 15/17 | Forecast (OLS) + trend | ✅ built | forecastPeriods/linearFit; PlanTrendChart |
| 18 | PowerTable: flat SQL-bound grid, sort/filter/inline-edit | ✅ built | PlanPowerTablePanel; flattenPlanCells |
| 20 | Two-way writeback (MERGE) + load-from-SQL | ✅ built | /api/items/plan/[id]/writeback; plan-backing-store (real Azure SQL) |
| 25 (partial) | InfoBridge line-item→source mapping, push to actuals | ✅ built | PlanInfoBridgePanel; applyMappingsToActuals (no merge/append/pivot/group transforms) |
| 30 | Approval workflow (real Office365 Logic App + callback) | ✅ built | /approval + /approval-callback; plan-approval-client |
| — | Semantic-model bind for actuals + Azure SQL provisioning | ✅ built | PlanSettingsFlyout; /binding |
| 21 (partial) | Intelligence: KPI cards + trend chart + variance table + Gantt | ⚠️ thin | KPI cards + one visual each; no chart gallery/storyboard |
| 11 | Top N / grouping / hierarchy nav / column width | ⚠️ partial | hierarchy nav built (expand/collapse/indent); Top N, grouping UI, column width missing |
| 6 | Calculated columns | ❌ MISSING | only built-in Total column + formula rows (no user calc-column construct) |
| 8 | Driver-based planning | ❌ MISSING | no named-driver primitive |
| 9/10 | Spreading/allocation + breakback | ❌ MISSING | no spread()/breakback() in _plan-model.ts |
| 13 | Versions & snapshots, compare, rolling forecast | ❌ MISSING | no snapshot route/container, no compare A↔B |
| 14/29 | Scenario security + roles (Planner/Stakeholder/Viewer) | ❌ MISSING | — |
| 19 | Import CSV/Excel/JSON | ❌ MISSING | — |
| 22 | Export to Excel / PDF | ❌ MISSING | — |
| 23/28 | Comments, annotations, @mentions, comments pane | ❌ MISSING | — |
| 26/27 | Multiple destinations, decimal/text config, autowriteback, writeback logs | ❌ MISSING | single hard-coded dbo.loom_plan_cells, no logs |
| 25 (rest) | InfoBridge transforms (merge/append/pivot/group), sheet-to-sheet | ❌ MISSING | mapping only |
| 31 | AI-assisted planning / Copilot | ❌ MISSING | computed (non-AI) planInsights only; DataAgent* imports are unrendered dead leftovers |
Build plan¶
P0 — structural EPM core (this is most of the "basic" complaint)¶
- Multi-dimensional cube + hierarchies + roll-ups (#1,#2,#3,#4).
- UI: extend
PlanningSheetPanelinto a dimension-aware grid. Add a "Model" left rail listing row and column dimensions as chips; a FluentTreefirst column with expand/collapse carets for nested members; indent/outdent + reorder; parent rows bold + read-only (auto roll-up).TileGridfor the dimension-manager dialog. Loom tokens,EmptyState, elevation. -
Backend: extend
_plan-model.tswithPlanDimension/PlanMember {id,label,parentId,level}and a purerollup(sheet,scenario)aggregating leaf cells up the parent chain (vitest-covered). Cosmos state growsdimensions[]; SQL writeback gainsdimension_pathcolumns — sameplan-backing-storeMERGE, no new Azure service. -
Formula rows + calculated columns + quick formulas (#5,#6,#7).
- UI: a "Formula" line-item kind whose editor opens a guided Formula builder dialog (function palette + row/measure token picker + live preview, mirroring the ADF/Synapse expression-builder pattern — NOT freeform per
loom_no_freeform_config). A "Quick formula"Menuper row (% of total, cumulative, growth %, YoY). -
Backend: a safe token-AST evaluator in
_plan-model.ts(row refs + arithmetic + SUM/AVG/IF, noeval), evaluated client-side and re-validated server-side in the writeback route. Pure, vitest-covered. -
Model editor (cube) tab + validation (#4 dimensions/measures/hierarchies).
- UI: new Model (6th) tab —
TileGridof dimension + measure cards; "Validate model" →MessageBarsummary; section headers (Title3/Caption1), Fluent icons,shadow4→shadow16hover per web3-ui. - Backend: new
POST /api/items/plan/[id]/modelvalidates member-parent integrity, measure refs, and formula cycles over Cosmos state — no external service.
P1 — planning depth + polish¶
- Spreading / allocation + breakback (#9,#10).
- UI: cell/total right-click
Menu→ "Spread evenly / by growth % / by weight"; editing a parent opens a breakbackDialog(proportional vs even). -
Backend:
spread()+breakback()pure helpers in_plan-model.ts, vitest-covered; Cosmos persist. -
Driver-based planning (#8).
- UI: mark a row Driver (
Badge); dependents reference it in the Formula builder; a "Drivers" mini-panel lists drivers + dependents. -
Backend: reuse the formula evaluator; topological recompute on driver edit.
-
Versions & snapshots + rolling forecast (#13).
- UI: Versions flyout — "Snapshot now", list (timestamp/author/total), "Compare A↔B" diff table, "Restore"; rolling-forecast toggle locking periods ≤ today as actuals.
-
Backend: snapshots = immutable state copies in a Cosmos
plan-snapshotscontainer (createIfNotExists); compare is a pure diff. -
Intelligence gallery (#21,#22,#24) — uplift the thin Intelligence tab.
- UI: a visual gallery (
TileGridof line/bar/area/KPI-card/waterfall/ Gantt/table) + a storyboard canvas reusing the report-editorcanvas-node-kit; extend the existing KPI strip into a card gallery; IBCS number-format toggle. -
Backend: all client-computed from plan cells (
periodSeries,forecastPeriods); export below. -
Export to Excel / PDF / CSV (#22).
- UI: ribbon "Export"
SplitButton. -
Backend:
GET /api/items/plan/[id]/export?format=xlsx|pdf|csv—exceljsfor xlsx, print-HTML→PDF (orpdf-lib), streamed download. Real bytes. -
Writeback logs + destinations + decimal/text config + autowriteback (#26,#27).
- UI: Settings flyout gains a Destinations table (target db, table, decimal precision, text length) + a Writeback logs table (run id, ts, rows, duration, status) with a detail
Drawer. -
Backend:
plan-backing-storerecords each run intodbo.loom_plan_writeback_log;GET /writeback?logs=1returns runs; autowriteback = persisted flag firing writeback on save. -
Comments / annotations / @mentions (#23,#28).
- UI: a Comments pane (
Drawer) + comments-column toggle; threaded replies;@mentioncombobox over tenant users;Badgecount. - Backend: Cosmos
plan-commentscontainer;@mentionvia the existing user/graph lookup; optional email via the approval Logic App.
- UI: a Comments pane (
-
Import CSV/Excel/JSON into PowerTable (#19).
- UI: PowerTable "Import"
Button→ fileDialog+ column-mapping step. - Backend:
POST /api/items/plan/[id]/importparses withpapaparse/exceljs, maps to cells, MERGEs. Honest errors.
- UI: PowerTable "Import"
P2 — governance + AI¶
-
Roles + scenario security (#14,#29).
- UI: a Sharing/Roles dialog (Planner/Stakeholder/Viewer) + per-scenario access list, reusing
share-dialog.tsx. - Backend: role grants on the item; enforced in the BFF routes per the roles capability matrix.
- UI: a Sharing/Roles dialog (Planner/Stakeholder/Viewer) + per-scenario access list, reusing
-
AI-assisted planning / Copilot (#31).
- UI: a collapsible side Plan Copilot (reuse the console side-Copilot) — "explain this variance", "draft next-quarter forecast", "what drives the OpEx jump".
- Backend: Azure OpenAI via the shared
aoai-chat-client(single AOAI client per EH Phase-0), grounded on plan cells/variance. No Fabric Copilot.
-
Top N / grouping / hierarchy nav / column layout (#11) — folded into the P0 cube grid work.
-
InfoBridge transformations (#25 rest) — merge/append/pivot/group + sheet-to-sheet mapping via a dropdown-driven transform-step builder (no freeform).
Backend per control (existing, preserved)¶
- Plan CRUD + cell/scenario/sheet edits → PATCH
/api/items/plan/[id](Cosmos). - Semantic-model picker + backing provision → GET/POST
/api/items/plan/[id]/binding. - Writeback / read-back → POST/GET
/api/items/plan/[id]/writeback→plan-backing-store(Azure SQL MERGE/SELECT; honest 503 gate onLOOM_PLAN_BACKING_SQL_*). - Intelligence → pure client compute over plan cells/tasks (
_plan-model). - Approval → POST
/api/items/plan/[id]/approval(Azure-native Logic App). No Fabric / Power Automate.