Skip to content

Guarantee bounded-loss autosave durability across crashes and restarts #39

Closed

Description

@lastobelus

Outcome

An app crash or restart must never lose more than a few seconds of review work, regardless of whether a review is currently being edited or is inflight with an agent. Users should not need to drain reviews or ask agents to retrieve them before restarting Markover.

Why this is separate

This is a launch-reliability and data-durability change, not part of #12's loopback authorization boundary. Keep its implementation and PRs independent from credential propagation and adversarial API verification.

It is also not a backward-compatibility project: preserve historical review JSON and avoid speculative schema versions, adapters, or migration machinery unless a demonstrated data-format change requires one.

Current baseline

  • Managed-review autosaves are emitted on every input and relevant state change.
  • Review JSON is written through atomic, flushed replacement files.
  • Managed reviews are restored from disk after restart.
  • Every keystroke currently queues a separate full-file write rather than coalescing toward the latest snapshot.
  • Graceful shutdown does not explicitly await managed-review write queues.
  • No crash/restart test proves a maximum work-loss bound.

Accepted durability contract

  • The default maximum-loss window is 2 seconds under healthy local storage.
  • Advanced users may change autosaveMaximumDelayMs from 100–60000 ms in Markover's persisted settings file; the setting is not exposed in the UI, requires restart, and changes the guarantee.
  • Managed autosaves use independent per-review leading-and-trailing throttles. Intermediate snapshots are disposable; the newest pending snapshot is not.
  • Failed writes retain the newest snapshot, retry with bounded exponential backoff capped at 30 seconds, and produce a persistent in-app warning until recovery.
  • Graceful quit blocks new local mutations, snapshots every loaded editable review, drains attachment mutations and persistence queues, and closes the service before exiting.
  • A five-second shutdown failure presents Retry Quit and Quit Anyway rather than silently discarding work.
  • Attachment bytes are atomically flushed before a durable review may reference them. A crash may leave harmless orphan bytes but never a durable broken reference.
  • Handoff and reopen bypass autosave throttling and durably commit the exact snapshot and status before acknowledging success.
  • Power loss, unhealthy storage, and hardware or operating-system failure are outside the two-second process-crash guarantee.

Acceptance criteria

  • Adopt and document the two-second default maximum-loss window and encode that same bound in deterministic tests.
  • Coalesce queued writes toward the latest state so sustained typing cannot create an unbounded full-file persistence backlog or starve the newest snapshot.
  • Add a graceful-shutdown barrier that awaits pending managed-review persistence without requiring users to drain reviews or contact agent threads first.
  • Prove crash/restart recovery for reviews in editing and inflight agent states, including rapid edits around status transitions.
  • Prove multiple active reviews cannot block, overwrite, or confuse one another's latest durable state.
  • Preserve correct attachment bytes and metadata ordering where attachment work overlaps autosave or shutdown.
  • Preserve existing historical review JSON without speculative compatibility layers or migrations.
  • Update privacy, storage, recovery, and support guidance with the tested guarantee and honest limits.
  • Run the supported Node checks and tests plus relevant macOS packaged-app restart validation.

Intended PR stack

Bottom to top:

  1. Bounded autosave core — agent/autosave-bounded-core. Advanced configuration, per-review leading/trailing coalescing, latest-snapshot retention, retry state, and fake-time unit tests.
  2. Application durability barriers — agent/autosave-durability-barriers. Main/renderer integration, exact handoff and reopen barriers, attachment ordering, graceful shutdown, failure warning and retry-or-force quit UX.
  3. Crash evidence and claims — agent/autosave-crash-evidence. Compact killed-child recovery coverage, multi-review and inflight-agent scenarios, local packaged-app restart validation, and public durability guidance.

The ordinary CI additions target less than two seconds per Node lane. Packaged-app restart smoke remains local here and becomes clean-machine release evidence under #11.

Ordering and dependencies

Activity

  1. added this to the Focused preview milestone on Aug 3, 2026
  2. self-assigned this
    on Aug 3, 2026
  3. added
    releaseRelease engineering and distribution
    launch:blockerBlocks the next Markover announcement gate
    launchWork required for an announcement or release gate
    on Aug 3, 2026
  4. moved this from Todo to In Progress in Markover Announcement Readinesson Aug 6, 2026
  5. lastobelus commented on Aug 7, 2026

    @lastobelus
    OwnerAuthor

    Work intent

    phase: completed
    summary: "PR #82 proves the default autosave bound, accounts for flushed-write latency, restores editing and pending-agent work after a real killed-process crash, and publishes the tested durability claims"
    touch-points:
      - "deterministic sustained-edit, persistence-latency, and slow-write warning proofs in test/review-autosave.test.ts"
      - "compact killed-child crash/restart coverage in test/durability-crash.test.ts and test/fixtures/durability-crash-child.ts"
      - "editing and pending-agent restoration, rapid snapshots, multiple reviews, and attachment byte/reference ordering"
      - "README, user guide, developer override guidance, and the accepted issue #39 plan"
      - "existing packaged-app restart smoke remains graceful-restart evidence; no additional packaged CI lane"
    blocked-by: []
    may-block:
      - "#9"
      - "#10"
      - "#11"
      - "#17"
    branch: "agent/autosave-crash-evidence"
    pull-request: "https://github.com/lastobelus/markover/pull/82"
    head: "d9cc97a"
    merge: "8f1b153"
    validation:
      - "npm run ci:local (368 tests plus live Electron smoke)"
      - "npm run package:mac (hardened arm64 package and signed-app smoke)"
      - "GitHub CI: Node 22.13, Node 24, macOS arm64 package smoke, and macOS Intel package smoke"
      - "Codex final-head review: no major issues and thumbs-up"
      - "git diff --check"
    thread: "start-issue-39-20260807-cc1767de-crash-evidence"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

launchWork required for an announcement or release gatelaunch:blockerBlocks the next Markover announcement gatereleaseRelease engineering and distribution

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions