Done in this pass
- Done Insert from a grid selection. Insert → Table, Dictionary, or List on a multi-cell grid region moves those values into the new structure (top-left cell). Table keeps the rectangle; list is reading order; dictionary is Name/Value for two columns, or one entry per column when the range is two rows. Single cell and Insert → Grid are unchanged.
-
Done
Analysis loop.
FILTER/GROUPBY/ table-awareSORTandUNIQUEreturn nested tables. Stats: MEDIAN, STDEV, VAR, PERCENTILE, LARGE, SMALL, RANK, CORREL, SUMPRODUCT. Chart is a first-class cell (bar / line / pie SVG), not a dialog. Seed workbook is Orders → West → By region → chart. -
Done
Ribbon as a sheet + slash commands. The ribbon column uses the same sheet UI as the workbook (row numbers, Name, command cells). Type
/in a cell to push:/COPY,/CUT,/SET,/DELETE,/REFRESH,/EXPORT,/EMAIL,/TEXT, plus any ribbon id. The cell shows the name; Space runs it. Chain calls;/NAMEsets the label. -
Done
Directory path instead of crumbs. Top bar shows
Workbook.School.Teachers.Full Name.2— workbook name in place of Root, dots instead of pills, table cells as field.record (not “Full Name · rec 2”). Numeric field names are quoted ('12'.12) so they are not mistaken for records. Segments still jump up on click. - Done Type Toggles menu, shared nested types, delete, Ctrl+arrow. Type flags live under a Toggles submenu. A shared-schema table field also shares the types of its nested table fields. Delete removes a nested structure without switching Type to Any. Ctrl+arrow can land on row headers; Up from the top transposed field header goes to the back corner (not diagonally to the first record).
- Done Faster pivots, Pivot name, colors. Field changes aggregate the source in one pass (no per-cell SUMIFS). New pivots are named “{table} Pivot”. Lists red, dictionaries green, tables blue, pivots purple.
-
Done
Sheet scrollbars + inset. Vertical and horizontal bars sit on the grid edge and span the header panes so headers stay aligned with records.
#sheet-wrappadding is 0. -
Done
FIELDS / RECORDS.
FIELDS(table_or_dictionary)returns field headers.RECORDS(table_or_list)returns the record (or list-item) count. Deleting or inserting a record remaps positional path indexes (.Data.'5'→.Data.'4'). - Done Tall rows, field delete, filter search. Multiline / wrapped cells grow the matching header row. Deleting a field with nested structures or formula references asks first (same idea as nested-structure delete). Filter search accepts multi-character typing and narrows the checkbox list; Up/Left still reach headers when the first record is filtered out.
- Done Formula bar multi-line height. Auto-height counts #refval padding/border and soft-wrap so long values are not clipped mid-glyph (still snaps to whole lines; drag grip for more).
- Done Edit spacing, list fill, frame chrome. Multi-line cell edit no longer uses cell height as line-height. List/dictionary Value column autofills remaining viewport width. Outer structure border and “Dictionary — inside … Esc back up” frame tag removed (crumbs carry path; tag only for pointing / list pick).
- Done List from column + PDF package. Create list from column values inserts the list outside the table (field before the table). Space on a PDF opens a dictionary: Name, Template PDF, Smart Fields, Filled PDF (bindings are sheet cells, not a dialog panel).
- Done Linked fields + total record. Fields linked across records unions nested table schemas (no silent shrink). Unique identifier toggle (default first field). Structure ▸ Total record before headers (or left when transposed): numbers sum/avg/min/max; linked table fields stack into one table with Id.
- Done Type Any + structure insert. Insert list/table/dictionary into a table field no longer fills every record when Type is Any. Field ☰ → Type → Structures linked across records opts into field-wide fill; Type → Structure still binds the whole field.
- Done Field Type menu. No separator between Type and Format. Create dictionary removed; Create list only when all values are text. Type choices apply immediately (no Apply/Clear). Number/Text/Checkbox under Value. Autodetect type on first value; mismatch confirms switch to Any. Reject invalid uses a message box.
- Done Chrome layout & naming. Full-width top bar (crumbs, undo/redo, cloud); formula bar formula-only to the right of the ribbon (height snaps to whole lines, no fx/dock overlay). Named UI areas: Top bar, Tabs, Sections, Ribbon menu, Formula bar, Sheet/Frame, Field menu, Status bar — Settings → Show UI area labels + F1 help.
- Done Ribbon density. Sheet-redundant Ctrl-chord commands hideable in Settings. Insert is a flat section column (Grid, Table, List, Dictionary, …) — not one Insert ▸ menu. Contextual tab always labeled Structure (key S); Transform first except Grid. Tab keytips: Insert I, Data D, View V. Format removed from ribbon → field ☰ menus (Type T, Format submenus). Keytip badges only on ribbon; letter underlines only on field dropdowns. Arrows / Home / End exit keytips and move the selector.
-
Done
Dictionary naming. “Named list” → Dictionary (green; Name|Value). Numbered list stays List (red). Nested field type stores
dictionaryso column siblings fill as dictionaries, not numbered lists. Field menus on dictionary Name cells and on transposed table field gutters (multi-select fields with Shift). - Done Table transpose parity (structure vs data). Delete on data cells (including a full row/column of values) clears values only. Delete structure only on header or row gutter. Copy/paste of data ranges overwrites (no insert row/field). Structure insert on paste only from gutter copy or header-only copy. Convert-to-table honors “records as columns” pref. Field menus: create list/dictionary from field values with immediate toast + close.
- Done File data type & autofit. File kind (any / image / PDF / …) on Type menus. Header ☰ autofit width so menus aren’t clipped.
-
Done
Request a6526bf2. Ctrl+R refresh; Ctrl+/− insert/delete; sticky table/list headers; same-row nested refs
Address.City(not cell-value path segments); M/D dates; formula tables viaTABLE/ADDCOL. - Done List ≡ one-record table (transposed). Convert list ↔ 1-row table. Nested table/list columns always share field schema (headers or indexes). “Lock formulas” only shares column formulas. “From a list” validation navigates the sheet to pick the source list.
- Done Rename rewrites formulas. Renaming a table header or list index walks the workbook and updates path segments that resolve to that field. Nested column siblings rename together.
-
Done
Power operator.
^is exponentiation (right-associative). Parent climb is dots only — one meaning per symbol. - Done Formula edit modes. F2 → cursor mode. Pointing always re-homes at the formula cell. Autocomplete never steals arrows while pointing; Enter commits, Tab accepts functions; field names beat same-named functions.
-
Done
Docs as real pages. Hub at
/metagrid/docs; each topic is its own URL under/metagrid/docs/…— no hash TOC. -
Done
JSON paste. Ctrl+V of a JSON object/array builds nested lists, tables, and grids at the selection (objects → lists, arrays of objects → tables, 2D scalar arrays → grids). Spec-style JSON with comments, trailing commas, and
…placeholders still maps to those structures. Fullmetagrid-v2documents still replace the workbook. - Done Excel / CSV import. SheetJS on demand. Dictionary of sheets (indexes = sheet names); each sheet a grid by default. Table only when the sheet is purely tabular and formulas are calculated columns with table-safe refs. Any other file type imports into the selected cell.
- Done Docs rewritten around “simplicity is the best metric” — operators, edit modes, rename rules, import contract.
-
Done
Split the monolith. App logic is now
js/model.js,formula.js,format.js,app.jsloaded fromapp.html. Boundaries match the layers in Architecture. -
Done
Formalize
metagrid-v2. One current document shape. Alpha: no legacy migration path. Local keymetagrid:local-v2. -
Done
Column template rule stated in code.
applyLockedTemplateToTableis the apply path; migration fills missingcolStructHeaders/colStructFormulaswhen lock is set. Docs describe the single ownership rule. - Done Ribbon honesty. Removed Share-as-export alias. “Get data” → “Sample table”. “Copy app link” is real clipboard behavior. Recalc lives under View → Debug. Protect labeled as sheet protect (local).
- Done Calc invalidation. Formula evaluation records dependency edges; cache can invalidate along dependents. History push / F9 still full-clear for correctness.
- Done Site structure. Landing sections are separate pages (Features, Docs, Architecture, Revision, About) with real detail — not one long scroll of fluff.
-
Done
Display formats. Number/date formats (General, currency, percent, Excel serial dates, …) on field menus; stored as
cellFmt/colFormat/valueFormat; values stay raw. (No longer a ribbon Format tab.)
Still open
- High Transposed table parity (remaining). Field-axis “row” still diverges in places (fill, sort edge cases, paste of mixed chrome, formula bar on gutters). Rule of thumb is set: data selection never mutates structure; chrome selection does. Hunt remaining call sites that treat full-width data as “delete/insert row”.
-
High
Column-structure code volume. Rule is clearer; implementation still spreads across apply/sync/remap helpers (now
colStruct*androwStruct*for transposed). Next cut: one “field template” object instead of parallel maps, if that shortens call sites without losing features. -
Med
Incremental calc in steady state. Edges exist, but many edit paths still call full invalidate via history. Wire
invalidateCellon single-cell commit when history snapshot isn’t needed for that micro-edit, and measure on the 5k demo. - Med Formula language freeze. Docs list the subset. Resist new functions unless they earn a row in that table. Add a small conformance checklist test page later if regressions hurt.
- Med Protect / share semantics. Protect is local-only. Cloud sharing is not multi-user ACL. Don’t pretend otherwise in UI copy (current: Copy app link, not “share workbook”).
- Later Realtime collab. Blocked on versioned documents + modular engine. JSON blob replace is the correct cloud model until then.
- Later ES modules + tests. Globals are fine for static deploy. If the engine grows again, switch format/formula to modules with a zero-config test runner — not before it hurts.
Decision guide
- Does it strengthen the tree model? Prefer yes.
- Does it add a ribbon button without a real backend? Prefer no.
- Does it need a format change? Bump
version, document the delta here. Alpha: no multi-version migration layer. - Would Excel users expect different behavior? Document the difference; don’t silently fake parity.
Module map: Architecture. User-facing contracts: Docs.