72 lines
5.2 KiB
Markdown
72 lines
5.2 KiB
Markdown
# Architecture
|
||
|
||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (created from the code on main; supersedes the local-only plan/architecture.md for committed docs) · **Target:** Microsoft Excel (Microsoft 365)
|
||
|
||
How GridCraft is built today. Rules for contributors are in [`AGENTS.md`](../AGENTS.md).
|
||
|
||
## Workspace and layering
|
||
|
||
An engine-first Cargo workspace. Layering is enforced by `cargo xtask layers`; nothing below L6
|
||
depends on egui, eframe, winit or rfd, so the UI crate is swappable. Line counts are Rust lines
|
||
including tests, 2026-10-10.
|
||
|
||
| Layer | Crate | Lines | Job |
|
||
|---|---|---|---|
|
||
| L0 | `core` | ~1.3k | Cell and range addresses (A1, R1C1, sheet-qualified; 1,048,576 × 16,384), `Value`, `CellError`, Excel coercion, 1900/1904 date serials, typed-input parsing |
|
||
| L0 | `numfmt` | ~2.1k | Excel number-format codes (sections, conditions, colours, dates, elapsed time, fractions, scientific, fill), General, `TEXT()`; en-US only |
|
||
| L1 | `formula` | ~1.7k | Tokenizer, parser, AST, printer (A1 and R1C1), reference adjustment for copy, fill and structural edits |
|
||
| L1 | `functions` | ~13.4k | The function library: `FnSpec` registry (name, arity, category, scalar args, signature, description) and pure implementations; automatic array lifting |
|
||
| L2 | `model` | ~2.2k | Workbook, sheets, copy-on-write cell store (64-row bands behind `Arc`), interned styles, names, tables, CF, validation, comments, charts, shapes, images, sparklines, print settings, protection |
|
||
| L2 | `calc` | ~2.9k | Evaluator (references, names, tables, LET/LAMBDA, special forms like OFFSET/INDIRECT/SUBTOTAL) and dependency-graph recalculation with dynamic arrays, spills and cycle detection; single-threaded |
|
||
| L2 | `xlsx` | ~10.7k | XLSX read/write (transitional and strict read), CSV/TSV, XLSB and ODS data import, PivotTable caches, DrawingML charts and drawings; byte slices only (WASM-safe); lenient reader that reports warnings |
|
||
| L2 | `pdf` | ~1k | Small PDF 1.7 writer (14 standard fonts, vectors, images) for print and export |
|
||
| L3 | `chart` | ~2.9k | Toolkit-free chart layout to drawing primitives, a rasterizer, sparklines |
|
||
| L5 | `engine` | ~17.7k | `Session`: open workbooks, selection, history (COW snapshots), clipboard, fill, sort, filter, PivotTables, what-if, print, file I/O (`io.rs`), and the command registry (`cmd/*`, 313 commands) with the Excel ribbon catalog (`catalog.rs`) |
|
||
| L6 | `ui-egui` | ~11.6k | Excel-style UI (title bar, QAT, ribbon, formula bar, virtualised grid, editor, tabs, status bar, dialogs, task panes, chart view) and the control channel |
|
||
| L6 | `mcp` | ~1.4k | MCP server over stdio (hand-written JSON-RPC), headless or bridged to a running app |
|
||
| L7 | `apps/gridcraft`, `apps/gridcraft-cli`, `apps/gridcraft-web` | ~2.2k | Desktop (eframe/wgpu), CLI (`info`, `convert`, `eval`, `cat`, `run`, `commands`, `functions`, `mcp`, `send`), web (WASM via trunk) |
|
||
| — | `xtask` | — | `ci`, `parity`, `assets`, `layers`, `wasm`, `version`, `stats` |
|
||
|
||
## Data flow
|
||
|
||
1. **Every action is a command.** The UI, CLI, control channel and MCP call
|
||
`Session::execute(id, params)`. Commands are `CommandSpec { id, label, menu, shortcut, params,
|
||
enabled, run, journal, undoable }`; ids follow Excel's ribbon (`home.bold`, `insert.chart`,
|
||
`data.sortAscending`) plus primitives (`cell.set`, `selection.set`, `range.setValues`).
|
||
`Session::execute` catches escaped panics and restores the workbook (never-crash guard).
|
||
2. **Edits** change the model through copy-on-write bands; undo keeps the previous snapshot.
|
||
3. **Recalc** marks dependents of changed cells dirty through the dependency graph (with range
|
||
nodes for range dependents), evaluates in topological order, spills dynamic arrays and reports
|
||
`#SPILL!`/cycles. Volatile functions are always dirty.
|
||
4. **Rendering**: the egui grid reads display values (number formats applied in `engine/display.rs`)
|
||
for the visible window only; charts render through `crates/chart` primitives.
|
||
5. **Files**: `engine/io.rs` sniffs content (XLSX, XLSB, ODS) before trusting the extension and
|
||
dispatches to `crates/xlsx`; imports that lose data return warnings shown to the user.
|
||
|
||
## Agent control
|
||
|
||
- Desktop control channel: `gridcraft --control 7979`, JSON lines on localhost
|
||
(`engine.execute`, `ui.screenshot`, pointer and keyboard input…), see
|
||
[`control-protocol.md`](control-protocol.md).
|
||
- MCP: `gridcraft-cli mcp`, headless or `--connect` to a running app, see [`mcp.md`](mcp.md).
|
||
- CLI: [`cli.md`](cli.md).
|
||
|
||
## Platforms and builds
|
||
|
||
macOS universal, Windows x64/x86/arm64, Linux x86_64/aarch64/riscv64 (AppImage, Flatpak, deb,
|
||
rpm, tarball), FreeBSD, and web (WASM; WebGPU or WebGL2). Release workflows in
|
||
`.github/workflows/release.yml`; see [`releasing.md`](releasing.md).
|
||
|
||
## Known architectural gaps
|
||
|
||
- No threading in calc (see [hardware-parity.md](hardware-parity.md)).
|
||
- No string catalog or text shaping (see [localization-parity.md](localization-parity.md)).
|
||
- XLSX reader builds the whole workbook in memory; no streaming (#175).
|
||
- Unmodelled XLSX parts are not carried through a save.
|
||
|
||
## Revision history
|
||
|
||
| Date | Change | Summary |
|
||
|---|---|---|
|
||
| 2026-10-10 | major | Created from the code on main: crates, layers, data flow, agent control, known gaps |
|