Skip to content

bug: preserve the previous reconciliation snapshot when a state write fails #30

Description

@codeforester

Problem

Northstar overwrites last-reconciliation.json directly with Path.write_text. A short/failed write can destroy the last valid state, and concurrent readers can observe partial JSON. This is an unsafe persistence example for adopters copying the reference consumer.

Verified evidence

Reviewed on 2026-09-17 at 2de6b83f21ccacae04f8050f5691d0dd8159fda1 (local checkout matched GitHub main). Reproduced in isolated macOS environments with Python 3.14.6. Framework default probe environment: Click 8.5.0 and Typer 0.27.2. Demo probes used released base-cli 0.4.3 unless noted.

Ran a successful local reconcile, producing a valid 116-byte snapshot. On the next reconcile, a bounded test injected an OSError after the state write had stored its first 12 characters:

first reconcile: exit 0, valid previous state
second reconcile: exit 1
remaining state: '{"action": "'

The previous snapshot is lost. The probe patched only the named consumer state destination; all fixtures were under a temporary root. _persist_reconciliation() opens the destination in truncating write mode rather than staging and replacing it.

Sources:

Acceptance criteria

  • Stage the complete consumer JSON snapshot in the destination directory and atomically replace it only after a successful write; clean temporary staging files on failure.
  • Preserve previous valid state on serialization/write/replacement failures and report an actionable persistence failure.
  • Define a small concurrent writer/read policy (for example atomic last-completed snapshot) and assert readers never see partial JSON.
  • Keep dry-run side-effect free and demonstrate normal, failed and concurrent persistence through the public consumer entry point; avoid private framework imports.

Related work

Distinct from #21, which covers renderer availability before mutation. This covers integrity during the actual state write even with a working JSON renderer.

Project fields

  • Status: Backlog
  • Priority: P2
  • Area: Runtime
  • Initiative: Base-CLI Demo
  • Size: S
  • Assignee: @codeforester
  • Milestone: v0.1.0
  • Target date: unscheduled

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething is not working

Type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions