feat(core): raise MAX_CATEGORIES from 12 to 24, with one home (improvise-felo.1)

The wizard's private copy of the limit is gone; it reads the model's
now-public constant. Tests that fill to the cap derive it. Why 12 was
chosen and what 24 costs: context/code/core.md section 9.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
Edward Langley
2026-09-24 19:16:04 -07:00
parent bb01cd1957
commit 7d1f90dbf9
17 changed files with 240 additions and 42 deletions
+3 -2
View File
@@ -69,7 +69,7 @@ same effect without the early return.
three shapes; dispatch pattern-matches exhaustively.
- `CategoryKind` is `Regular | VirtualIndex | VirtualDim | VirtualMeasure | Label`.
Business rules (e.g., the 12-category limit counts only `Regular`) are
Business rules (e.g., the 24-category limit counts only `Regular`) are
enforced by matching on the enum, not by checking name prefixes. Virtual
categories (`_Index`, `_Dim`, `_Measure`) always exist: `_Index` and `_Dim`
support drill-down/records mode; `_Measure` holds numeric data fields and
@@ -99,7 +99,8 @@ sort. Property tests verify this invariant.
- `CellKey::new()` is the only way to build a key — it always sorts.
- `Category::add_item()` deduplicates by name and auto-assigns IDs via a private
counter. External code cannot fabricate an `ItemId`.
- `Model::add_category()` checks the 12-category limit before insertion.
- `Model::add_category()` checks the category limit (`MAX_CATEGORIES`, 24)
before insertion.
- `Formula::new()` takes all required fields; there is no default/empty formula
to accidentally leave half-initialized.