Skip to content

Persist stacks to bounded JSONL - #568

Merged
season179 merged 2 commits into
mainfrom
feat/stack-jsonl-persistence
Jun 1, 2026
Merged

Persist stacks to bounded JSONL#568
season179 merged 2 commits into
mainfrom
feat/stack-jsonl-persistence

Conversation

@season179

@season179 season179 commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • persist model-call stack snapshots to a bounded JSONL file instead of keeping full stacks only in session memory
  • add lazy stack availability checks so Electron only shows the Stacks tab when retained records exist
  • show a clear empty state if retained stack records are trimmed before the user opens them
  • document which stack details cannot be reconstructed from DB replay

Validation

  • rtk cargo fmt --all --check
  • rtk cargo test
  • rtk cargo clippy --all-targets -- -D warnings
  • rtk bun lint
  • rtk bun run renderer:build
  • rtk bun test passed outside sandbox after sandbox backend-startup permission errors

Summary by CodeRabbit

  • New Features

    • Stacks are persisted to disk and retained across restarts.
    • Per-session stack availability is checked and the Stacks tab/button is shown only when available.
    • Stack availability is refreshed on session lifecycle events to keep UI in sync.
  • Documentation

    • Added guidance on what stack data can be reconstructed vs. what is intentionally not persisted.
  • Tests

    • Added coverage for stack persistence, availability, trimming, and compaction behavior.

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 74c1af18-31c9-40f3-83f3-073c93d30f50

📥 Commits

Reviewing files that changed from the base of the PR and between 8a113ce and 6e7f2cc.

📒 Files selected for processing (2)
  • src/stack_store.rs
  • tests/stack_store.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/stack_store.rs
  • src/stack_store.rs

📝 Walkthrough

Walkthrough

This PR implements persistent JSONL-based stack storage, exposes RPCs and IPCs for stacks and availability, integrates StackStore into SessionStore and run sinks, updates renderer contracts, and conditionally shows the Stacks UI based on availability.

Changes

Stack Persistence and Availability

Layer / File(s) Summary
Persistence specification and deserialization support
research/stack-persistence.md, src/stacks.rs
Research doc defines replay boundary constraints; stack snapshot types gain Deserialize derives for JSONL persistence.
JSONL stack store implementation
src/stack_store.rs
New StackStore implements append-only JSONL persistence with per-record size checks, compaction to newest valid records within a byte cap, availability and stacks queries, and durable rewrite/replace helpers.
Session store and sink integration
src/session.rs
SessionStore gains optional stack_store and with_stack_store() builder; Session uses a monotonic next_stack_sequence; SessionRunSink::model_call_stack appends snapshots to the store; new stack_availability() and stacks() APIs return store-backed results and unavailable reasons.
Backend RPC handlers and service initialization
src/lib.rs, src/bin/nav-local-backend.rs
Library declares and re-exports stack_store types; JSON-RPC session.stacks now returns the store result directly; nav-local-backend reads NAV_STACKS_PATH, opens StackStore at startup, and wires it into SessionStore when available.
IPC bridge contracts
desktop/electron/main.cjs, desktop/electron/preload.cjs, desktop/electron/renderer/window.d.ts
nav:session-stacks returns response.result directly; new nav:session-stack-availability handler added; preload exposes nav.sessionStackAvailability(sessionId); TypeScript types updated for new return shapes.
Frontend availability state machine
desktop/electron/renderer/src/App.jsx
Adds stackAvailable state, a race-safe refreshStackAvailability() using a request id ref, triggers on backend connection, run terminal events, session activation/switch, and provides markStacksUnavailable() helper.
UI conditional rendering
desktop/electron/renderer/src/App.jsx, desktop/electron/renderer/src/components/StacksPage.jsx
SessionToolbar accepts showStacks and conditionally renders the Stacks tab; StacksPage accepts onUnavailable, tracks unavailableReason, invokes callback when stacks empty with a reason, and maps reasons to empty-state messages.
Test infrastructure
tests/stack_store.rs, tests/session.rs, tests/local_backend.rs
New and updated tests validate StackStore append/availability/compaction, TestBackend wiring to a temp StackStore, and RPC behaviors including available and unavailableReason.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • season179/nav#560: Updates IPC/preload plumbing and renderer stacks display; this PR extends that work with persistent StackStore and availability handling.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.51% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Persist stacks to bounded JSONL' accurately and concisely captures the main feature: persisting model-call stack snapshots to a bounded JSONL file, which is the primary objective of this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/stack-jsonl-persistence

Comment @coderabbitai help to get the list of available commands and usage tips.

@season179
season179 force-pushed the feat/stack-jsonl-persistence branch from 3be82ec to 8a113ce Compare June 1, 2026 03:20

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/stack_store.rs`:
- Around line 149-153: The stacks() method needs an explicit guard for limit ==
0 to avoid the current indirect behavior that clears the buffer and sets
trimmed_or_missing incorrectly; add an early return at the top of stacks() that
when limit == 0 returns Ok(StackQueryResult { records: Vec::new(),
trimmed_or_missing: false }) (or the repository's chosen sentinel for "no
trimming") so the boundary is deterministic and later logic never runs for this
case; update any tests or callers if they expect a different trimmed_or_missing
convention.
- Around line 262-263: The call to fs::rename(temp_path, &self.path) in
compaction can behave non-atomically or fail on Windows/other filesystems;
update the compaction code that uses fs::rename(temp_path, &self.path) to first
ensure temp_path and self.path are on the same filesystem (or document that
requirement), and implement a robust fallback: on rename error, perform an
atomic-safe copy (copy file contents from temp_path to self.path, fsync the
destination directory if possible), verify write success, then remove temp_path;
also add a clear error log including the rename error to help debugging and
retry/propagate the error as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 239cfee4-d279-4dcd-a185-ca58279bb222

📥 Commits

Reviewing files that changed from the base of the PR and between 6dbbdb8 and 8a113ce.

📒 Files selected for processing (14)
  • desktop/electron/main.cjs
  • desktop/electron/preload.cjs
  • desktop/electron/renderer/src/App.jsx
  • desktop/electron/renderer/src/components/StacksPage.jsx
  • desktop/electron/renderer/window.d.ts
  • research/stack-persistence.md
  • src/bin/nav-local-backend.rs
  • src/lib.rs
  • src/session.rs
  • src/stack_store.rs
  • src/stacks.rs
  • tests/local_backend.rs
  • tests/session.rs
  • tests/stack_store.rs

Comment thread src/stack_store.rs
Comment thread src/stack_store.rs Outdated
@season179
season179 merged commit dc316e0 into main Jun 1, 2026
1 check passed
@season179
season179 deleted the feat/stack-jsonl-persistence branch June 1, 2026 04:46
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.

1 participant