From cf43a43477a7b963589ce1438522cddea4551231 Mon Sep 17 00:00:00 2001 From: Graham Barber Date: Wed, 15 Jul 2026 14:21:24 -0700 Subject: [PATCH] archive add-auto-compaction: sync compaction requirements into block-graph spec, move change to archive/2026-07-15-add-auto-compaction --- .../.openspec.yaml | 0 .../2026-07-15-add-auto-compaction}/design.md | 0 .../proposal.md | 0 .../specs/block-graph/spec.md | 0 .../2026-07-15-add-auto-compaction}/tasks.md | 0 openspec/specs/block-graph/spec.md | 66 +++++++++++++++++++ 6 files changed, 66 insertions(+) rename openspec/changes/{add-auto-compaction => archive/2026-07-15-add-auto-compaction}/.openspec.yaml (100%) rename openspec/changes/{add-auto-compaction => archive/2026-07-15-add-auto-compaction}/design.md (100%) rename openspec/changes/{add-auto-compaction => archive/2026-07-15-add-auto-compaction}/proposal.md (100%) rename openspec/changes/{add-auto-compaction => archive/2026-07-15-add-auto-compaction}/specs/block-graph/spec.md (100%) rename openspec/changes/{add-auto-compaction => archive/2026-07-15-add-auto-compaction}/tasks.md (100%) diff --git a/openspec/changes/add-auto-compaction/.openspec.yaml b/openspec/changes/archive/2026-07-15-add-auto-compaction/.openspec.yaml similarity index 100% rename from openspec/changes/add-auto-compaction/.openspec.yaml rename to openspec/changes/archive/2026-07-15-add-auto-compaction/.openspec.yaml diff --git a/openspec/changes/add-auto-compaction/design.md b/openspec/changes/archive/2026-07-15-add-auto-compaction/design.md similarity index 100% rename from openspec/changes/add-auto-compaction/design.md rename to openspec/changes/archive/2026-07-15-add-auto-compaction/design.md diff --git a/openspec/changes/add-auto-compaction/proposal.md b/openspec/changes/archive/2026-07-15-add-auto-compaction/proposal.md similarity index 100% rename from openspec/changes/add-auto-compaction/proposal.md rename to openspec/changes/archive/2026-07-15-add-auto-compaction/proposal.md diff --git a/openspec/changes/add-auto-compaction/specs/block-graph/spec.md b/openspec/changes/archive/2026-07-15-add-auto-compaction/specs/block-graph/spec.md similarity index 100% rename from openspec/changes/add-auto-compaction/specs/block-graph/spec.md rename to openspec/changes/archive/2026-07-15-add-auto-compaction/specs/block-graph/spec.md diff --git a/openspec/changes/add-auto-compaction/tasks.md b/openspec/changes/archive/2026-07-15-add-auto-compaction/tasks.md similarity index 100% rename from openspec/changes/add-auto-compaction/tasks.md rename to openspec/changes/archive/2026-07-15-add-auto-compaction/tasks.md diff --git a/openspec/specs/block-graph/spec.md b/openspec/specs/block-graph/spec.md index 4e497eb..3ff849e 100644 --- a/openspec/specs/block-graph/spec.md +++ b/openspec/specs/block-graph/spec.md @@ -108,3 +108,69 @@ regenerated only together with a deliberate format version bump. files are decoded - **THEN** the golden-graph test fails, forcing either a fix or an explicit format version bump with a migration + +### Requirement: Update log is bounded by automatic compaction +The system SHALL automatically fold the incremental update log into a fresh +snapshot so that the log cannot grow without bound. Compaction SHALL trigger +(a) when, after an edit has been durably persisted, the update log has reached +a size threshold, and (b) at application quit when the update log exceeds a +smaller quit-time threshold. Compaction MUST NOT be required for correctness: +it only trades log-replay time at open for a snapshot write. + +#### Scenario: Size threshold crossed during a session +- **WHEN** an acknowledged edit brings `updates.log` to or past the automatic + compaction threshold +- **THEN** the log is folded into `snapshot.loro` and emptied (or removed), and + a subsequent open of the graph directory yields the identical graph state + while replaying no pre-compaction updates + +#### Scenario: Quit-time compaction +- **WHEN** the application quits normally with a non-trivial `updates.log` + (at or past the quit-time threshold) +- **THEN** on the next launch the graph loads from the snapshot with the + pre-quit edits already folded in + +#### Scenario: Trivial sessions do not rewrite the snapshot +- **WHEN** the application quits after a session whose `updates.log` is below + the quit-time threshold +- **THEN** the snapshot file is not rewritten and the small log is simply + replayed on next open + +### Requirement: Compaction preserves the acknowledged-edit guarantee +Automatic compaction SHALL run only after the triggering edit is durable in the +update log, and a compaction failure or interruption at any point MUST NOT lose +an acknowledged edit, MUST NOT leave the graph directory unloadable, and MUST +NOT surface as a persistence failure for the edit itself. Before the update log +is removed, the newly written snapshot MUST be verified loadable, and the +previous snapshot MUST be retained (as `snapshot.loro.prev`) as a manual +recovery fallback. Opening a graph whose current snapshot fails to decode MUST +fail with an error identifying the retained fallback rather than silently +loading stale state. + +#### Scenario: Kill between snapshot replacement and log removal +- **WHEN** the process is killed after compaction has atomically replaced + `snapshot.loro` but before `updates.log` is removed +- **THEN** the next open loads the graph to the identical state (re-importing + updates already contained in the snapshot is harmless), and a later + compaction removes the stale log + +#### Scenario: Compaction failure is not an edit failure +- **WHEN** the snapshot write fails (e.g. disk error) after the triggering + edit was appended and fsync'd +- **THEN** the edit is still acknowledged as persisted, the previous snapshot + and the update log remain intact and loadable, and compaction is retried at + the next trigger + +#### Scenario: Unverifiable snapshot never replaces a good one +- **WHEN** the newly exported snapshot fails verification (its bytes do not + decode into a loadable document) +- **THEN** compaction aborts before touching the current snapshot or the + update log, both remain intact and loadable, and the failure is reported + without affecting the acknowledged edit + +#### Scenario: Prior snapshot survives as a recovery fallback +- **WHEN** a compaction completes successfully +- **THEN** the pre-compaction snapshot remains on disk as + `snapshot.loro.prev`, and a subsequent open that finds the current snapshot + undecodable fails with an error naming that fallback instead of silently + loading it -- 2.51.2