diff --git a/.claude/skills/alignment/SKILL.md b/.claude/skills/alignment/SKILL.md index 5a3b28e..8abb28d 100644 --- a/.claude/skills/alignment/SKILL.md +++ b/.claude/skills/alignment/SKILL.md @@ -37,8 +37,11 @@ Review all changes in scope. If changes span multiple patterns below, apply all 3. **Fix directly; don't ask first.** When you find an issue covered by these instructions, fix it in place rather than reporting it and waiting. Ask the user only when the fix is genuinely ambiguous or several valid approaches exist with real trade-offs. When guidelines - conflict, prefer in this order: **SOUL.md philosophy > `docs/spec/` behavioral contract > - `docs/architecture/` patterns > local cleanup**. These instructions are not strictly + conflict, prefer in this order: **SOUL.md philosophy > `docs/spec/` behavioral record > + `docs/architecture/` patterns > local cleanup**. (The spec is descriptive — the code + leads. A spec/code mismatch is fixed by updating the stale spec section, not by + reverting the code; only flag the code when it contradicts recorded _rationale_, not + merely an unrewritten section.) These instructions are not strictly prohibitive — if a guideline has a valid reason to be bypassed, mention it in the summary. ### Code Quality @@ -178,12 +181,15 @@ role`) or the rule it demonstrates. - **Positional sub-section cross-refs.** Cit (whole-spec drag/simplify) — never re-inlining the model/parse/writeBack prologue. The family has grown by copy-paste twice (eng-council; arch 08). -17. **Spec tracks the surfaces it mandates** (`docs/spec/`): a diff that **removes, moves, or - renames a user-facing surface** — where a message, control, or affordance lives — updates the - `docs/spec/` section describing it, not only the `docs/architecture/` pattern doc. The spec is - the behavioral contract; an arch-doc-only update leaves it describing a surface that no longer - exists. An arch-only update once left spec §03E mandating an editor-pane error message after it - had moved to the preview (eng-council). +17. **Spec tracks the surfaces it describes** (`docs/spec/`): a diff that **adds, removes, + moves, or renames a user-facing surface** — a feature, message, control, or affordance — + updates the `docs/spec/` section describing it (adding a section for new behavior), not + only the `docs/architecture/` pattern doc. The spec is the behavioral record and the code + leads; an arch-doc-only update leaves the spec describing a product that no longer exists. + An arch-only update once left spec §03E mandating an editor-pane error message after it had + moved to the preview (eng-council); a run of feature commits (2026-06-25 → 06-30: the + /learn/ section, the composition wireframe, editor scaffolds) once landed with zero spec + coverage (eng-council, 2026-07). ### Output @@ -206,7 +212,7 @@ role`) or the rule it demonstrates. - **Positional sub-section cross-refs.** Cit Update relevant docs if the feature is significant: -- **`docs/spec/`** — if product behavior changed (this is a contract; change deliberately). +- **`docs/spec/`** — if product behavior changed (descriptive record; update it to match what shipped — see #17). - **`docs/architecture/`** — if a new pattern, navigation map, or decision rule emerged. - **`docs/IMPLEMENTATION-PLAN.md`** — mark milestone progress. Use the `/doc-update` skill for session-discovered gaps. The list is not exclusive. @@ -226,7 +232,7 @@ If `package.json` changed: ### Alignment Check - **SOUL.md** — philosophy (must not violate without good reason). -- **`docs/spec/`** — behavioral contract. +- **`docs/spec/`** — behavioral record. - **`docs/architecture/`** — the relevant pattern doc. --- @@ -245,7 +251,7 @@ Usually not required unless the bug revealed incorrect docs, or the fix changes ### Alignment Check -- **SOUL.md** philosophy; **`docs/spec/`** behavioral contract; **`docs/architecture/`** patterns. +- **SOUL.md** philosophy; **`docs/spec/`** behavioral record; **`docs/architecture/`** patterns. --- @@ -286,10 +292,10 @@ Update JSDoc/inline comments if signatures or behavior changed. ## Reference Documents -| Document | Purpose | -| ------------------------------------------------------------------- | ----------------------------------------- | -| [SOUL.md](../../../SOUL.md) | Project philosophy and core values | -| [AGENTS.md](../../../AGENTS.md) | AI onboarding and project context | -| [docs/spec/](../../../docs/spec/) | Behavioral contract — _what_ the app does | -| [docs/architecture/](../../../docs/architecture/00-overview.md) | Architecture playbook — _how_ it's built | -| [docs/IMPLEMENTATION-PLAN.md](../../../docs/IMPLEMENTATION-PLAN.md) | Milestone sequence and scope | +| Document | Purpose | +| ------------------------------------------------------------------- | ---------------------------------------- | +| [SOUL.md](../../../SOUL.md) | Project philosophy and core values | +| [AGENTS.md](../../../AGENTS.md) | AI onboarding and project context | +| [docs/spec/](../../../docs/spec/) | Behavioral record — _what_ the app does | +| [docs/architecture/](../../../docs/architecture/00-overview.md) | Architecture playbook — _how_ it's built | +| [docs/IMPLEMENTATION-PLAN.md](../../../docs/IMPLEMENTATION-PLAN.md) | Milestone sequence and scope | diff --git a/.claude/skills/doc-update/SKILL.md b/.claude/skills/doc-update/SKILL.md index fef6086..81aca1a 100644 --- a/.claude/skills/doc-update/SKILL.md +++ b/.claude/skills/doc-update/SKILL.md @@ -30,9 +30,10 @@ For documentation organization, see **[CLAUDE.md](../../../CLAUDE.md)** and the ## The three documentation layers (know which one a gap belongs to) -- **`docs/spec/`** — the _what_: behavioral contract (what the app does, acceptance points). - This is a **contract**. Only change it when product behavior genuinely changes, and do so - deliberately — never as a casual "fill a doc gap" edit. A how-detail does NOT belong here. +- **`docs/spec/`** — the _what_: behavioral record (what the app does, acceptance points). + The code leads; the spec is kept rewritten to match what shipped. If the session added or + changed user-facing behavior, name the spec section that describes it — or write it — as + part of this pass. A how-detail does NOT belong here. - **`docs/architecture/`** — the _how_: the patterns behind each layer (state, persistence, modals, routing, rendering, inference, relationships). Most navigation maps and decision rules land here. @@ -59,19 +60,19 @@ not do Y"). If you can't state it concisely, it may be too implementation-specif Map each gap to the right document: -| Gap type | Target document | -| ------------------------------------------------- | ----------------------------------------------------------------------------- | -| Product behavior, capabilities, acceptance points | `docs/spec/` (the relevant 00–10 section) — **contract; change deliberately** | -| State / Zustand stores | `docs/architecture/01-state-and-stores.md` | -| Persistence, IndexedDB, localStorage, migrations | `docs/architecture/02-persistence.md` | -| Modals, dialog lifecycle | `docs/architecture/03-modal-system.md` | -| URL routing, keyboard/events | `docs/architecture/04-routing-and-events.md` | -| Rendering, theming, vega-embed, preview | `docs/architecture/05-rendering-theming-preview.md` | -| Type inference, dataset profiling | `docs/architecture/06-type-inference.md` | -| Names, snippet↔dataset links, rename propagation | `docs/architecture/07-naming-and-relationships.md` | -| Milestone scope, build order | `docs/IMPLEMENTATION-PLAN.md` | -| Project philosophy / identity | `SOUL.md` | -| Onboarding, conventions, stack | `AGENTS.md` / `CLAUDE.md` | +| Gap type | Target document | +| ------------------------------------------------- | --------------------------------------------------------------------------------- | +| Product behavior, capabilities, acceptance points | `docs/spec/` (the relevant 00–10 section) — **record; keep it matching the code** | +| State / Zustand stores | `docs/architecture/01-state-and-stores.md` | +| Persistence, IndexedDB, localStorage, migrations | `docs/architecture/02-persistence.md` | +| Modals, dialog lifecycle | `docs/architecture/03-modal-system.md` | +| URL routing, keyboard/events | `docs/architecture/04-routing-and-events.md` | +| Rendering, theming, vega-embed, preview | `docs/architecture/05-rendering-theming-preview.md` | +| Type inference, dataset profiling | `docs/architecture/06-type-inference.md` | +| Names, snippet↔dataset links, rename propagation | `docs/architecture/07-naming-and-relationships.md` | +| Milestone scope, build order | `docs/IMPLEMENTATION-PLAN.md` | +| Project philosophy / identity | `SOUL.md` | +| Onboarding, conventions, stack | `AGENTS.md` / `CLAUDE.md` | If a gap fits no existing document, consider a new section in the closest one; prefer extending over creating. A brand-new architecture topic can become `docs/architecture/08-*.md` diff --git a/AGENTS.md b/AGENTS.md index f4230da..f5aa3c8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,9 +11,10 @@ a local library of **snippets** (saved Vega-Lite specs), edits each as JSON with validation and a live chart preview, and reuses **datasets** across many snippets. Fully local, offline-capable, no account. -It is a **spec-driven rebuild** on an architecture adapted from its sibling project Syto. -The authoritative behavioral contract is **`docs/spec/`** (sections 00–10). Implement _to -the spec_; do not port legacy code. +It is a rebuild on an architecture adapted from its sibling project Syto. **`docs/spec/`** +(sections 00–10) is the behavioral record: the code leads and the spec is kept rewritten +to match — a user-facing change isn't done until its spec section describes it. Do not +port legacy code. ### Technical Stack @@ -74,7 +75,7 @@ src/ │ └── infrastructure/ # IndexedDB, localStorage, Monaco, settings adapters styles/ # Global CSS (tokens, base) docs/ -├── spec/ # Authoritative behavioral specification (00–10) — the WHAT +├── spec/ # Behavioral specification (00–10) — the WHAT (record; code leads) ├── architecture/ # Architecture playbook (00–11) — the HOW (self-contained) │ └── visual-specimen.html # Standalone token sandbox + reusable-primitive catalog ├── exploration/ # Point-in-time records (research, reviews, scope memos) — not maintained @@ -116,8 +117,10 @@ npm run format # Prettier trimming IBM Plex to the latin subsets dropped Cyrillic — capability for an internationally-usable app. We ship every script subset and precache them for offline; `unicode-range` means the browser only downloads what a glyph needs anyway.) -- **Spec is the contract** — when in doubt, read `docs/spec/`. If the spec is wrong or - silent, raise it; change the spec deliberately rather than drifting from it. +- **Spec follows code** — `docs/spec/` is the descriptive record of behavior; the code + leads. When in doubt about existing behavior, read the spec. When you ship user-facing + behavior, update the matching spec section in the same session; if spec and app + disagree, the spec is stale — rewrite it deliberately, never drift silently. - **Core-first** — for each feature, build the pure `src/core/` logic with tests before UI. - **Session wrap-up** — when the user signals the session is wrapping, run the review pass before any commit: `/doc-update` in-session first (flush unrecorded rationale), diff --git a/CLAUDE.md b/CLAUDE.md index f239be4..fa42c37 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,8 +5,9 @@ See @AGENTS.md for project overview, architecture rules, and the AI developer pr ## Documentation Index - **[SOUL.md](SOUL.md)** — project philosophy and identity. _Read first._ -- **[docs/spec/](docs/spec/)** — authoritative behavioral specification (sections 00–10): - the **what**. This is the contract; implement to it. +- **[docs/spec/](docs/spec/)** — behavioral specification (sections 00–10): the **what**. + Descriptive, kept current with the code: the code leads; on conflict amend the spec, + never drift silently. User-facing behavior ships with its spec section. - **[docs/architecture/](docs/architecture/00-overview.md)** — architecture playbook (00–11): the **how** (state, persistence, modals, routing, rendering, inference, relationships, vega-editor techniques, visual design, interaction & feedback, learning @@ -31,8 +32,9 @@ See @AGENTS.md for project overview, architecture rules, and the AI developer pr ## Quick Orientation -- Astrolabe is a **spec-driven rebuild** — the behavior is fixed in `docs/spec/`; the - architecture is adapted from Syto. Implement to the spec; don't port legacy code. +- Astrolabe is a **spec-recorded rebuild** — the architecture is adapted from Syto, and + `docs/spec/` records the behavior as built. Build deliberately, record in the spec; + don't port legacy code. - **`src/core/` is portable and tested hardest.** Browser specifics live in `src/app/infrastructure/`. UI is React + Zustand. - **Editor is Monaco**, charts render via **vega-embed**, storage is **IndexedDB**. diff --git a/README.md b/README.md index 22f501a..8887daa 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,9 @@ A browser-based **snippet manager for [Vega-Lite](https://vega.github.io/vega-li visualizations**. Author chart specs as JSON, watch them render live, and keep a personal, searchable library — local, offline-capable, no account. -> Astrolabe is a **spec-driven rebuild** on an architecture adapted from its sibling -> project Syto. The authoritative behavioral contract lives in [`docs/spec/`](docs/spec/). +> Astrolabe is a rebuild on an architecture adapted from its sibling project Syto. The +> behavioral record lives in [`docs/spec/`](docs/spec/) — the code leads; the spec is +> kept rewritten to match. > See [SOUL.md](SOUL.md) for the philosophy and [docs/IMPLEMENTATION-PLAN.md](docs/IMPLEMENTATION-PLAN.md) > for the build sequence. diff --git a/SOUL.md b/SOUL.md index 388e957..b57890f 100644 --- a/SOUL.md +++ b/SOUL.md @@ -79,12 +79,12 @@ clever. ## Technical Philosophy -### Spec-Driven, Clean Implementation +### Spec-Recorded, Clean Implementation -The behavioral contract lives in `docs/spec/`. Astrolabe is a deliberate rebuild on a -robust architecture (adapted from Syto): we implement _to the spec_, not by porting old -code. When the spec and convenience conflict, the spec wins or the spec changes — never -silent drift. +The behavioral record lives in `docs/spec/`. Astrolabe is a deliberate rebuild on a +robust architecture (adapted from Syto): behavior is designed deliberately and recorded +in the spec, not ported from old code. The code leads; the spec is rewritten to match +what ships — never silent drift. ### Portable Core, Thin Browser Shell diff --git a/docs/IMPLEMENTATION-PLAN.md b/docs/IMPLEMENTATION-PLAN.md index 7f47e71..d236d50 100644 --- a/docs/IMPLEMENTATION-PLAN.md +++ b/docs/IMPLEMENTATION-PLAN.md @@ -1,7 +1,8 @@ # Astrolabe — Incremental Implementation Plan -> A spec-driven rebuild of Astrolabe on Syto's architecture. The authoritative -> behavioral contract is `docs/spec/` (sections 00–10). +> A rebuild of Astrolabe on Syto's architecture. The behavioral record is +> `docs/spec/` (sections 00–10) — the code leads, and the spec is kept +> rewritten to match. > > **The M0–M6 build is complete** — the milestone map below is the record. Remaining > work is post-M6 enhancement, tracked in the **live backlog** and owned in detail by diff --git a/docs/architecture/00-overview.md b/docs/architecture/00-overview.md index 19b2778..25cfcc4 100644 --- a/docs/architecture/00-overview.md +++ b/docs/architecture/00-overview.md @@ -22,7 +22,9 @@ about user-facing widgets. At that overlap, one rule keeps them from drifting: and never contradict it.** A playbook bullet may _name_ the behavior in one clause and cite the spec, then spend its words on the _how_ (the role, the keys, the focus move) and the _why_ (the council/canon citation). When a playbook bullet and the spec disagree, the - **spec wins** and the bullet is the bug. Restatement is the leak: two docs describing the + **spec wins** and the bullet is the bug — both describe the shipped code, so if the spec + section is itself stale, rewrite it to match the app, then cite it (the code leads; the + spec records). Restatement is the leak: two docs describing the same behavior in their own words drift into contradiction; one cites the other instead. ## How to use this playbook diff --git a/docs/architecture/02-persistence.md b/docs/architecture/02-persistence.md index 3e0f5ed..b81d189 100644 --- a/docs/architecture/02-persistence.md +++ b/docs/architecture/02-persistence.md @@ -284,8 +284,8 @@ export interface UserSettings { formatting: { dateFormat: 'smart' | 'iso' | 'custom'; customDateFormat: string }; } -// Defaults must match the authoritative spec §07 table exactly — that is the -// contract; this is just where it's encoded. +// The spec §07 table records these defaults — keep the two matching; this is +// just where they're encoded. const DEFAULTS: UserSettings = { version: CURRENT_SETTINGS_VERSION, editor: { diff --git a/docs/architecture/07-naming-and-relationships.md b/docs/architecture/07-naming-and-relationships.md index b5546f9..c45b1ff 100644 --- a/docs/architecture/07-naming-and-relationships.md +++ b/docs/architecture/07-naming-and-relationships.md @@ -351,7 +351,7 @@ detection + normalization + the dedupe/rename/id-reassign helpers; `core/export- - browser IO (`infrastructure/file-transfer.ts`). The pure helpers are unit-tested hardest; `transfer.ts` only orchestrates (read stores → call core → commit → - notify). The behavioral contract is spec §08. + notify). The behavior is recorded in spec §08. Three rules a future change must keep: diff --git a/docs/architecture/08-vega-editor-techniques.md b/docs/architecture/08-vega-editor-techniques.md index c4dba1b..0e5b63b 100644 --- a/docs/architecture/08-vega-editor-techniques.md +++ b/docs/architecture/08-vega-editor-techniques.md @@ -6,7 +6,7 @@ > borrowing and the gotchas worth avoiding, so we don't rediscover them from scratch in > M1/M2. > -> It is a **reference**, not a contract. The behavioral contract is still [`docs/spec/`](../spec/); +> It is a **reference**, not a contract. The behavioral record is still [`docs/spec/`](../spec/); > the patterns are still docs [01](01-state-and-stores.md)–[07](07-naming-and-relationships.md). > This doc is the bridge: "here is how the canonical implementation does the editor/renderer > plumbing, and here is what we keep vs. improve." diff --git a/docs/spec/09-data-model.md b/docs/spec/09-data-model.md index c49e638..1cfc462 100644 --- a/docs/spec/09-data-model.md +++ b/docs/spec/09-data-model.md @@ -1,6 +1,6 @@ # 09 · Data Model & Persistence -This section defines the persistent entities of Astrolabe and how they relate. It is the authoritative data contract: an implementer recreating the app should store equivalent records with these fields and meanings. Types are given abstractly (string, number, boolean, ISO-timestamp string, string[], object, "JSON value") so they map onto any stack. "JSON value" means any valid JSON shape — object, array, string, number, boolean, or null. +This section defines the persistent entities of Astrolabe and how they relate. It is the data record of the shipped app: an implementer recreating the app should store equivalent records with these fields and meanings. Types are given abstractly (string, number, boolean, ISO-timestamp string, string[], object, "JSON value") so they map onto any stack. "JSON value" means any valid JSON shape — object, array, string, number, boolean, or null. All data lives entirely in the browser. There is no server, account, or sync. Records survive page reload and remain available offline (see _Application Shell & Navigation_). To move data between browsers or devices, use _Import & Export_. diff --git a/docs/spec/README.md b/docs/spec/README.md index 5ec08de..3b24ac0 100644 --- a/docs/spec/README.md +++ b/docs/spec/README.md @@ -8,6 +8,7 @@ A UX/behavioral specification of **Astrolabe**, a browser-based snippet manager - Each subsequent file is one feature area and can be read on its own; they cross-reference each other by title. - Every section describes intended behavior plus testable acceptance points ("The user can…", "When X, the system…"). - Section numbers and lettered headings (e.g. `§03G`, `§09B`) are **stable anchors** — code comments reference them. Extend by appending the next letter/number; never renumber existing ones. +- The spec is **descriptive**: it records what the shipped app does. The code leads — when the app and a section here disagree, the section is stale; rewrite it to match (deliberately) rather than treating it as a veto on the code. ## What this spec deliberately omits