Persistence: share entity write-through helper; normalize quota at db.put

This commit is contained in:
2026-06-16 23:06:37 +03:00
parent 778b4d848a
commit 2ed9db3792
18 changed files with 422 additions and 205 deletions
+26 -22
View File
@@ -51,7 +51,7 @@ doc before implementing.
| **M3** | Datasets ✅ | Named reusable data + reference resolution in preview | §05, §03F, §09B |
| **M4** | Chart Builder ✅ | No-JSON chart composition from a dataset | §06 |
| **M5** | Settings + Import/Export ✅ | Preferences + workspace backup/transfer | §07, §08, §09C |
| **M6** | Shell polish | Resize/toggle panes, routing, shortcuts, toasts, a11y, offline | §01, §10 |
| **M6** | Shell polish | Resize/toggle panes, routing, shortcuts, toasts, a11y, offline | §01, §10 |
**MVP boundary = end of M1** (a genuinely usable single-user chart authoring loop).
M1.5 makes it _look right_; M2 makes it _robust_; M3M6 make it _complete_.
@@ -428,10 +428,15 @@ through `services/transfer.ts` (→ `normalizeImport` / envelope build), no moda
---
## M6 · Shell polish & non-functional
## M6 · Shell polish & non-functional ✅ (done)
**Goal:** the workspace feels finished and meets §10.
**Scope note — desktop/tablet, not phone.** Astrolabe is a desktop and (at best)
tablet tool; phones are out of scope. So the touch/installable surface we target is
**iPad add-to-home-screen**, not iPhone — which is why the one PNG icon is a 180×180
`apple-touch-icon` and we don't chase phone-specific viewport/layout work.
- **Panes:** ~~drag-resize handles with min widths; widths persist~~ ✅ (pulled
forward after M2). ~~Per-pane show/hide **toggle strip** + visibility persist +
proportional redistribution on hide (§01A, §09D)~~ ✅.
@@ -454,13 +459,13 @@ through `services/transfer.ts` (→ `normalizeImport` / envelope build), no moda
IDB-transaction atomicity would require exposing a raw transaction from `db.ts` — see
[arch 02](architecture/02-persistence.md)).
- **A11y:** modal focus trap + return, labelled icon buttons, contrast in both themes (§10) — ✅ in place.
- **About** and **Donate** modals ~~(§01)~~ (Donate URL is a placeholder
`DONATE_URL` pending the real link).
- **Offline/installable:** the manifest now ships a full SVG icon set (favicon / maskable /
monochrome) + `theme_color`, and the SW precaches the shell — the app is **installable**.
**⏳ Remaining** — manual verification in a running/installed app (checklist:
[manual-verification.md](manual-verification.md)); iOS home-screen still wants a PNG
`apple-touch-icon` (logged residual).
- **About** and **Donate** modals ~~(§01)~~. The project solicits nothing for
itself — **Donate** redirects to Ukraine's defense (`savelife.in.ua`, the Come Back
Alive foundation), where the author forwards any project donations anyway.
- **Offline/installable:** the manifest ships a full SVG icon set (favicon / maskable /
monochrome) + a 180×180 `apple-touch-icon.png` (iPad add-to-home-screen) + `theme_color`,
and the SW precaches the shell — the app is **installable**. ✅ Manual verification in a
running/installed app passed (checklist: [manual-verification.md](manual-verification.md)).
- **Council** — ~~seat **web.dev** for the PWA/offline/storage surfaces none of the seated
members cover: the service-worker **update-available** prompt (`registerType: 'prompt'`),
storage **persistence** (`navigator.storage.persist()`), and the quota **estimate**
@@ -470,9 +475,10 @@ through `services/transfer.ts` (→ `normalizeImport` / envelope build), no moda
[`/council`](../.claude/skills/council/SKILL.md) and
[arch 10](architecture/10-interaction-and-feedback.md).
**Manual checks:** keyboard-only run-through; reload restores view from URL;
offline reload works; install as standalone; reduced-motion honored. **⏳ Still owed**
(plus visual verification of the new library/monitor/modals/busy-indicator surfaces).
**Manual checks:** keyboard-only run-through; reload restores view from URL;
offline reload works; install as standalone; reduced-motion honored — all verified in a
running/installed app, plus visual verification of the library/monitor/modals/busy-indicator
surfaces.
---
@@ -487,7 +493,9 @@ offline reload works; install as standalone; reduced-motion honored. **⏳ Still
boundary. M1M6 can ship English-only with date formatting locale-aware (§10).
Don't retrofit later if avoidable — keep user-facing strings centralized from M1.
- **Versioning:** simplified semver `0.x.y`, `package.json``__APP_VERSION__`
(already wired). Bump per shippable milestone.
(already wired). **Not yet released publicly** — the working version stays pre-1.0 through
M0M6; the **first public release will be `1.0.0`**, cut on the maintainer's signal (don't
auto-bump in the meantime).
- **Docs trio:** keep `SOUL.md` / `AGENTS.md` / `CLAUDE.md` current as the app grows.
---
@@ -528,20 +536,16 @@ is in the maintained plan, not the archive.
**Chart Builder** (`exploration/chart-builder-enhancement-scope.md`):
- **Starter examples + open-in-builder (3B/3C)** — the next builder slice in the scope doc:
a starter-example front door that hydrates the builder from an existing spec (strict).
- **Open-in-builder + builder starter examples (3B/3C)** — the next builder slice in the
scope doc: hydrate the **builder** from an existing spec (strict spec→config parse), behind
a starter-example front door. Distinct from the shipped onboarding gallery
(`core/examples.ts``Onboarding.tsx`), which seeds a snippet straight into the editor, not
the builder — there is no spec→builder-config path yet.
- **Transform-aware data inspector** — show resolved post-transform rows
(`exploration/data-inspector-exploration.md`).
- **Field-chip drag-and-drop** — click/keyboard-first shipped; drag deferred.
- **Calculated-field autocomplete popup** — Monaco-style completion for expressions.
**Engineering follow-ups** (refactor candidates, not features):
- **Entity-persistence subscriber consolidation** — snippet/dataset/theme/font each carry a
near-identical diff-prev/next write-through subscriber (`orchestration/*-persistence.ts`);
a generic `wireEntityPersistence(store, { save, delete })` would replace the four. Earned
by the four call sites; hold only if per-entity clarity is judged to outweigh the dedupe.
---
## Architecture reference