oficina / sheets Public

core

The sealed spreadsheet core: storage, sealing, the formula engine, number formatting, XLSX both ways — plus CI, migrations, and an independent cross-check of the formula engine. 44 commits implementing docs/superpowers/specs/2026-08-30-sheets-design.md via docs/superpowers/plans/2026-08-30-sheets-core.md.

Everything here is design-system-independent and testable without a browser. The web surface — auth screens, the grid, sharing, live sync, charts — is plan 2.

What it does

Cells are sparse rows keyed by stable row and column identity, with A1 derived at render. An append-only event log stores input events and valueless recalc markers, so it grows with the number of edits rather than each edit's fan-out. Opening a tab decrypts it into a refcounted in-memory handle holding a precedent graph. A formula engine — lexer, precedence-climbing parser, evaluator, dirty-set propagation, cycle detection — owns all calculation. excelize is confined to the XLSX package.

The one rule holds end to end

Verified structurally rather than by luck: sealing happens before any database call, so even GORM's own SQL logging can only ever emit ciphertext.

The plaintext gate has been watched to fail on purpose four times — against a raw file, a real uncheckpointed WAL write through the actual driver, the busiest writer, and the XLSX import boundary.

Both merge blockers are closed

CI exists. Six steps under .amadan/ci.d/, each a three-line script execing a Makefile target, so make test and CI are one definition. Five rules that previously lived only in AGENTS.md prose are now guards inside the test binary — the 300-line cap, forbidden cgo SQLite drivers, excelize confinement, calc isolation, sealtest containment. Every guard was deliberately broken and watched fail.

Migrations exist. migrate.Apply at boot, ledgered. Tests and production share one BootSchema — no AutoMigrate anywhere. rastrillo migration check is a CI gate, watched to fail via a drift canary. The generated SQL was read before committing and verified to carry the composite primary key on cells, both unique (tab_id, position) indexes, and the unique formats.digest index.

The verification ceiling, raised but not removed

The corpus is still hand-authored — LibreOffice cannot be installed on this machine (no sudo, no flatpak, no snap), and tools/gencorpus has still never run.

But every corpus expression is now cross-checked against excelize's own formula engine — a different codebase by different authors, ~530 functions. Result: 60 compared, 59 agree, 1 divergence, 0 unavailable. The divergence is excelize's bug: its TRIM is literally strings.TrimSpace, contradicting its own doc comment and real Excel. Ours is right.

That is two independent implementations agreeing, which is materially stronger than one implementation agreeing with itself. It is not conformance testing against a reference spreadsheet, and nothing has confirmed our XLSX opens in real Excel.

Performance liability closed

Blanking a cell marks its dependents dirty unconditionally — the cap bounds the recompute, never the marking, because capping the marking is what allowed silent permanent staleness. Both per-cell transaction loops are now batched.

Measured at N=199,999, near the 200,000 cell ceiling:

| | setBlank lock hold | Open recovery | |---|---:|---:| | Before | 6.728s | 32m2.04s | | After | 2.779s | 8.818s |

Real measurements, taken by reverting to pre-fix code and back — not extrapolations.

Commits 0
Files changed 0 +0 −0
Discussions 1 1 open
Tasks 0/0 done

Activity