Skip to content

Checkpoint reading positions before lifecycle shutdown - #219

Merged
Renakoni merged 6 commits into
mainfrom
fix/resume-checkpoints
Sep 19, 2026
Merged

Renakoni merged 6 commits into
mainfrom
fix/resume-checkpoints

Conversation

@Renakoni

@Renakoni Renakoni commented Sep 19, 2026 •

Copy link
Copy Markdown
Owner

Summary

Reading positions previously depended on leaving the editor or delivering a lifecycle callback, then waiting for an asynchronous full-document SHA-256 digest. A task removal or process shutdown could interrupt that last operation. The editor now saves foreground checkpoints after activity settles and during continuous activity, so a completed position exists before shutdown begins.

Behavior

  • Scroll/edit activity saves after 500 ms of quiet. Continuous activity initiates a checkpoint at most 2.5 seconds after the first unsaved event; the quiet deadline cannot indefinitely postpone it.
  • Existing exit/lifecycle paths still capture the latest live viewport immediately and cancel the scheduled checkpoint.
  • Once a fingerprint has completed, unchanged Markdown reuses it and writes a fresh anchor synchronously, without another WebCrypto suspension.
  • While an unchanged-content fingerprint is still computing, newer captures share that digest and use their own latest anchor and capture time. A slow hash can complete even when continuous scrolling triggers more checkpoints.
  • Passive revisits do not overwrite the previous record. Source-mode suspension follows the capture-surface guard from Preserve reading positions across source mode #218.

Design and responsibility boundaries

The resume session controller owns the two bounded timers, one completed-capture cache, and one reference to pending fingerprint work. Scroll handlers only mark activity and schedule work; they do not read DOM geometry, serialize Markdown, or hash the document on every event. A checkpoint flushes pending editor operations, reads current Markdown, and then captures the current structural block/ratio anchor in the same JavaScript turn.

Fingerprint reuse requires exact equality with the cached or pending Markdown, including same-length edits. It reuses only identity metadata: the anchor, display text, and timestamp are captured anew. Cached synchronous writes and asynchronous hash completions share the existing per-document sequence tokens, so even an undo to cached content supersedes an older in-flight edited-content digest. Sharing the pending digest avoids repeatedly invalidating hashes that take longer than the checkpoint interval. Failed digests release the pending reference so a later capture can retry. Both references are session-local and reset with the editor; a late outgoing write cannot populate the next session's cache or clear its pending hash.

Document replacement and teardown cancel both timers. Explicit persistence also clears timers scheduled reentrantly by flushing pending editor operations. No new storage schema, dependency, setting, native service, or document-content save path is introduced. Resume-card presentation and exact-content validation remain unchanged.

Scope and integration

This PR targets main, which includes the source-mode safety fix from merged #218. Its diff and sole fix target are #216. The main-branch integration preserves the reviewed checkpoint implementation and regression coverage.

The timing bounds govern checkpoint initiation, not guaranteed disk durability or hash-completion deadlines. Abrupt termination can still lose activity newer than the last completed checkpoint, and changed content must complete a new digest. This does not change document autosave or promise recovery of unsaved Markdown.

Verification

  • Four scheduling/cache regressions failed against the original controller before implementation.
  • Web unit tests after self-review: 83 files / 721 tests passed, including quiet/max-wait scheduling, edit-only activity, timer cancellation, passive revisits, synchronous cached exits, changed-content hashing, cached-vs-in-flight ordering, slow shared hashes, hash-failure retry, reentrant flush notifications, and late outgoing-session completions. A new delayed-hash regression failed before the pending-work sharing fix.
  • Resume, source-mode, and local-draft lifecycle mobile browser E2E after self-review: 37/37 passed. New cases cover foreground persistence/reload with exit handlers suppressed, continuous scrolling, a same-turn lifecycle write with WebCrypto deliberately blocked after warming the cache, a 3-second digest during continuous checkpoints, and the parent PR's pending-offer cancellation across a source-mode round trip.
  • pnpm build (includes TypeScript typecheck), ESLint on all 259 tracked JavaScript/TypeScript/Vue files, changed-file ESLint, and git diff --check passed.
  • cap sync android and Android assembleDebug passed.
  • Dedicated API 35 emulator, installed debug APK: foreground checkpoint confirmed before leaving; real recent-task swipe confirmed task removal and restored scrollTop=3000; Android Home/resume in source mode preserved the WYSIWYG block; foreground am force-stop confirmed process termination, then cold restart restored scrollTop=5000 from the completed checkpoint. The swipe left a cached process alive, so process termination was tested separately rather than inferred from task removal.

The Android checks used a fresh isolated AVD. They do not establish behavior on every OEM or guarantee a final write during abrupt termination; recovery is from the last completed checkpoint. The unfiltered workstation pnpm lint sees pre-existing untracked archive files, so tracked-file lint was used without changing the lint rules.

Closes #216

Base automatically changed from fix/source-mode-resume to main September 19, 2026 11:04
@Renakoni

Copy link
Copy Markdown
Owner Author

@codex help me resolve the conflicts

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@Renakoni

Copy link
Copy Markdown
Owner Author

@codex help me resolve the conflicts

@chatgpt-codex-connector

Copy link
Copy Markdown

Summary

  • Resolved merge conflicts between the foreground checkpoint implementation and the base source-mode resume changes, preserving the current resume-position controller and its scheduling/cache behavior. src/features/editor/resumePosition.tsL1-L20
  • Preserved the expanded resume-position regression test suite while completing the merge resolution. src/features/editor/resumePosition.test.tsL1-L20
  • Created commit 298c3c1 and prepared the pull-request metadata with the title “Resolve merge conflicts with base resume-position changes.”

Testing

  • ✅ pnpm vitest run src/features/editor/resumePosition.test.ts — 1 test file and 35 tests passed.
  • ✅ git status --short — working tree clean after conflict resolution.

View task →

@Renakoni
Renakoni merged commit 7eff407 into main Sep 19, 2026
6 checks passed
@Renakoni
Renakoni deleted the fix/resume-checkpoints branch September 19, 2026 11:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Checkpoint reading positions before Android lifecycle shutdown

1 participant