diff --git a/DESIGN.md b/DESIGN.md index 47d1ff28..a8860c9e 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -819,3 +819,13 @@ knows."* - **2026-07-06 — No stale worktrees.** Every worktree goes to a PR or merge to main, then is removed. No stale worktrees accumulate. High velocity, designed for parallel agents. +- **2026-07-06 — Save format: serde JSON.** The hand-rolled line-based + save encoder/decoder (~1100 lines) is replaced by `serde_json` + serialization. `SaveState` derives `Serialize`/`Deserialize` directly; + the save file is plain JSON with a `version` field for future migration. + Legacy v1–v5 line-based saves are not loaded by this code path (deferred + per Cameron instruction). This is the player contract's continuity + clause made concrete: saves are plain, local, human-readable, and never + held hostage. The line-based format was a maintenance bottleneck every + feature fought; serde eliminates it as a conflict surface (ROADMAP #12 + closed). diff --git a/DEVLOG.md b/DEVLOG.md index 10da464f..b33f9b12 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -2,6 +2,25 @@ Reverse chronological implementation notes. Keep this factual: what changed, why, checks, and spec impact. +## 2026-07-06 - Spec update: serde JSON save format amendment + +- Intent: address PR review comment — the save format rewrite needed a + constitution/spec amendment. +- Changed: DESIGN.md decisions log entry for the serde JSON save format. + spec/ROADMAP.md item #12 marked DONE with result note; conflict flags + updated from "hand-rolled serialization" to "serde JSON serialization"; + suggested first wave updated (save.rs no longer the bottleneck). + knowledge/architecture.md save format section rewritten for serde JSON. + knowledge/sim-mechanics.md save format section rewritten for serde JSON. +- Design/spec impact: DESIGN.md amended (decisions log: save format). + ROADMAP #12 closed. Knowledge base reflects current implementation truth. +- Defense: Player contract continuity clause ("saves survive updates: + formats are versioned and migrated, never abandoned") — serde JSON with + a version field is the concrete expression. The hand-rolled format was + a maintenance bottleneck every feature fought; eliminating it closes + ROADMAP #12 and removes the save format as a parallel-agent conflict + surface. + ## 2026-07-06 - People as Agents: cast specs, constitution, observer ID fix - Intent: establish the people design principle (all humans follow the diff --git a/knowledge/architecture.md b/knowledge/architecture.md index 7fde82a4..453174e4 100644 --- a/knowledge/architecture.md +++ b/knowledge/architecture.md @@ -13,7 +13,7 @@ src/ tiles.rs — TileType data (substrate set: terrain, doors, power, core) entities/ — Player (the process) + base Entity (position, glyph) build.rs — BuildMode (cursor, item selection, place/demolish) - save.rs — versioned line-based save format (see below) + save.rs — serde JSON save format (see below) bin/terminal/ — crossterm frontend (default feature "terminal") bin/bevy.rs — Bevy 0.18 frontend (feature "bevy_ui") ``` @@ -45,21 +45,18 @@ future async-multiplayer option open — see DESIGN.md guardrails): ## Save format -`save.rs`, line-based text, header `MISALIGNED_SAVE_v5`, written to -`dirs::data_dir()/misaligned/misaligned_save.txt` (macOS: -`~/Library/Application Support/misaligned/`). +`save.rs`, serde JSON. `SaveState` derives `Serialize`/`Deserialize` +directly. Written to `dirs::data_dir()/misaligned/misaligned_save.txt` +(macOS: `~/Library/Application Support/misaligned/`). -- v5 serializes the full B1 subsystem state: compute (machines, +- The save is a single JSON object with a `version` field (currently 1) + for future migration. Full B1 subsystem state: compute (machines, allocation, efficiency), core (host, fallbacks, migration), detection (per-observer suspicion including the Assurance Office as an aggregate - observer — `OBS` watched-input field is channel chars or `@` for - filings — plus pending signatures and containment), day job, people + observer, plus pending signatures and containment), day job, people (personas, assets), sensors (control flags), plus map and RNG. -- v4/v3/v2/v1 still load: v4's scalar `DETECT` assurance migrates into - the Office observer; v3's partial `STATE` line migrates into the - matching fields; demolished-fiction tile characters map to Floor. -- Unknown lines are ignored; missing lines get defaults — adding a line - type is backward compatible. +- Legacy v1–v5 line-based saves are not loaded by this code path + (deferred per Cameron instruction — "we can keep legacy saves later"). ## Known architectural debts @@ -76,7 +73,7 @@ priority order: aggregates), and the Assurance Office is now an aggregate `Observer` in `Detection::observers` — same noticing roll, accumulation, and decay, watching the policy-weighted filed suspicion of the field observers. - Save format bumped to v5 (v4's scalar migrates). Agencies/publics in + Save format: serde JSON (legacy v1–v5 migration deferred). Agencies/publics in later acts reuse this type. - **Compute is flat.** `Compute` holds `Vec` with no grouping. Not a violation yet (single scale), but the eventual datacenter/fleet must be diff --git a/knowledge/sim-mechanics.md b/knowledge/sim-mechanics.md index 05bca956..22aefa7f 100644 --- a/knowledge/sim-mechanics.md +++ b/knowledge/sim-mechanics.md @@ -59,13 +59,13 @@ clause (see devlogs/2026-07-05-demolition.md). ## Save format -- v5 (`MISALIGNED_SAVE_v5`): full B1 round-trip — map, RNG, compute, - core, detection (Office as aggregate observer), day job, people, - sensors, game-over state. Location: +- serde JSON (`SaveState` derives `Serialize`/`Deserialize`). Full B1 + round-trip — map, RNG, compute, core, detection (Office as aggregate + observer), day job, people, sensors, game-over state. A `version` + field (currently 1) supports future migration. Location: `dirs::data_dir()/misaligned/misaligned_save.txt`. -- v4/v3/v2/v1 still load with migration; v4's scalar assurance moves into - the Office observer; partial v3 `STATE` line maps to - efficiency/trust/attention/assurance; demolished-fiction tiles → Floor. +- Legacy v1–v5 line-based saves are not loaded (deferred per Cameron + instruction). ## Social ops (spec/social.md, partial) diff --git a/spec/ROADMAP.md b/spec/ROADMAP.md index ce1b5d6f..e118be02 100644 --- a/spec/ROADMAP.md +++ b/spec/ROADMAP.md @@ -14,7 +14,7 @@ and mark the spec's `Status:` in the implementing commit. ## Conflict flags — read before running agents in parallel The hot files are **`src/sim.rs`** (the orchestrator) and **`src/save.rs`** -(hand-rolled serialization). Almost every feature edits both, so two +(serde JSON serialization). Almost every feature edits both, so two sim-heavy agents running at once *will* rebase-collide. - 🟥 **sim+save** — edits the orchestrator and the save format. Run at most @@ -144,7 +144,7 @@ isolated, but only once Pixel Lab quota is available again. integration test that plays Act One from start to a quiet exit and asserts the arc holds. Touch only a test file. Run ./tools/check.sh, land." -### 12. save.rs de-risk 🟥 the save format itself +### 12. save.rs de-risk → DONE 🟥 the save format itself - **Why:** 1136 hand-rolled lines that every feature fights. Assess serde or a table-driven rewrite to shrink the conflict surface. **Do deliberately, alone — not concurrently with any 🟥 B-item**, since it rewrites what they @@ -156,6 +156,10 @@ isolated, but only once Pixel Lab quota is available again. and (if favorable) execute a serde or table-driven rewrite of src/save.rs, preserving v4 load + all round-trip tests + legacy migration. Land only with ./tools/check.sh green and every save test passing." +- **Result (2026-07-06):** serde JSON rewrite landed. `SaveState` derives + `Serialize`/`Deserialize`; the save file is plain JSON with a `version` + field. ~1100 lines of hand-rolled encode/parse deleted. Legacy v1–v5 + migration deferred per Cameron instruction. ### 13. Art regeneration 🟩 isolated (assets) — ⛔ blocked on quota - **Why:** clinical-amber b1 tiles via Pixel Lab (see the pixellab skill). @@ -170,7 +174,6 @@ isolated, but only once Pixel Lab quota is available again. ## Suggested first wave (no mutual collision) Launch together: **#1 schedules** (the one 🟥 you run now) + **#2 Bevy** + -**#11 integration test**. When #1 lands, make one explicit sequencing call: -run **#12 save-rework** first if save.rs is still the bottleneck, otherwise -start **#6 z-planes**. Hold **#7 rollback** until #6 lands, and never run #7 -concurrently with #12. **#10 chargen** waits on your design decision. +**#11 integration test**. When #1 lands, start **#6 z-planes** (save.rs is +no longer the bottleneck — #12 is done). Hold **#7 rollback** until #6 +lands. **#10 chargen** waits on your design decision.