[codex] Centralize review session storage and history - #45
Conversation
Documents the GitHub PR review and local Redpen review workflows, shared infrastructure, tech stack, and build commands. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds prek.toml with local pre-push hooks for cargo fmt, cargo clippy, tsc typecheck, tauri version parity, and AGENTS.md/CLAUDE.md sync check. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add dir: {{.TASKFILE_DIR}}/.. so check-markdown runs from repo root
- Remove check-tauri-versions hook (uses grep -P, GNU grep only)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Centralizes Redpen’s review session persistence and history by moving session lookup/resume flows to a shared SQLite state DB under ~/.config/redpen, and updates the GUI/CLI/server integration to use the new session storage and in-memory session tracking.
Changes:
- Add SQLite-backed state storage (
state.db) and wire it into the Tauri app state for review sessions, session files, activity, and recents. - Introduce review history + resume/cleanup commands and surface them in the GitHub inbox UI.
- Replace legacy session/signal plumbing in CLI/server flows with server-managed session IDs and persisted completion state.
Reviewed changes
Copilot reviewed 36 out of 37 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src-tauri/src/storage.rs | New SQLite schema + session storage APIs under centralized app home. |
| src-tauri/src/state.rs | Adds shared StateDb and shared in-memory ReviewSessions to app state. |
| src-tauri/src/commands/review_history.rs | New Tauri commands for history, resume, and stale cleanup. |
| src-tauri/src/commands/github_review.rs | Persist GitHub PR review sessions + session-file indexing into SQLite. |
| src-tauri/src/commands/annotations.rs | Updates “review done” signaling to include optional session ID and persist completion. |
| crates/redpen-server/src/lib.rs | Extends bridge API, persists session start/complete, and adds persisted wait fallback. |
| crates/redpen-cli/src/main.rs | Removes signal-file fallback; uses server start/wait and reads annotations from sidecars. |
| src/components/GitHubInbox.svelte | Adds History UI (recent, resume, stale cleanup) backed by new Tauri commands. |
| src/lib/types.ts / src/lib/tauri.ts | Adds TS types + Tauri invoke wrappers for history/resume/cleanup. |
| src/lib/stores/review.svelte.ts / src/lib/review.ts | Tracks session ID in the review store and passes it when signaling completion. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let stale_sessions = sessions | ||
| .iter() | ||
| .filter(|session| { | ||
| session.status == ReviewSessionStatus::Stale || is_stale_timestamp(&session.updated_at) |
There was a problem hiding this comment.
stale_sessions currently includes any session whose updated_at is older than the stale cutoff, regardless of status. That means long-completed sessions will be shown as “stale” purely due to age. It seems more correct to only apply is_stale_timestamp() to active sessions (and/or rely on mark_stale_sessions()), e.g. status == Stale || (status == Active && is_stale_timestamp(...)).
| session.status == ReviewSessionStatus::Stale || is_stale_timestamp(&session.updated_at) | |
| session.status == ReviewSessionStatus::Stale | |
| || (session.status == ReviewSessionStatus::Active | |
| && is_stale_timestamp(&session.updated_at)) |
| export interface ReviewHistoryItem { | ||
| id: string; | ||
| kind: string; | ||
| status: string; | ||
| title: string; | ||
| subtitle: string; | ||
| updatedAt: string; | ||
| primaryFilePath?: string | null; | ||
| fileCount: number; | ||
| verdict?: string | null; | ||
| } | ||
|
|
||
| export interface ReviewHistory { | ||
| activeSession?: ReviewHistoryItem | null; | ||
| recentPullRequests: ReviewHistoryItem[]; | ||
| recentFiles: ReviewHistoryItem[]; | ||
| staleSessions: ReviewHistoryItem[]; | ||
| } | ||
|
|
||
| export interface ResumeReviewSessionResult { | ||
| kind: string; | ||
| sessionId: string; | ||
| projectRoot?: string | null; | ||
| files: string[]; | ||
| githubSession?: GitHubPrSession | null; | ||
| } | ||
|
|
||
| export interface CleanupReviewSessionsResult { | ||
| removedSessions: number; | ||
| } | ||
|
|
There was a problem hiding this comment.
This file claims “All types are generated from Rust via ts-rs”, but the newly added ReviewHistory*/ResumeReviewSessionResult/CleanupReviewSessionsResult types duplicate Rust structs that are already annotated with #[ts(export)] in src-tauri/src/commands/review_history.rs. To avoid drift between backend and frontend types, consider committing the generated binding files and re-exporting them from src/lib/bindings/index.ts (or updating the header comment if these are intentionally TS-only).
| fn state_db() -> CommandResult<StateDb> { | ||
| StateDb::new().map_err(storage_error) | ||
| } |
There was a problem hiding this comment.
state_db() constructs a new StateDb (and runs initialization/migrations) each time it’s called. This file calls state_db() in multiple hot paths (session load, sidecar save, session lookup), which can add overhead and increases the chance of contention/locking on the SQLite file. Since AppState already owns a StateDb (state.storage), consider threading a &StateDb through these helpers or passing State<'_, AppState> where needed so the shared instance is reused.
Add a Map-based cache in the diff store keyed on (directory, filePath, baseRef, targetRef, algorithm) with per-key request counters to prevent stale-write races. Cache is invalidated on file save, GitHub session change, and diff exit. Review page now uses the shared cachedInvokeDiff instead of direct Rust invoke. Also fixes all pre-existing type errors across the codebase: - Remove unused fileName function in ReviewSession - Fix unused params in Editor selection callback - Fix view possibly-null in Editor effect - Add non-null assertions in GitHubInbox template - Remove unused highlightsModeExtensions import in EditorPane - Prefix unused handleWindowClick param - Align EditorRef types across App/EditorPane/Editor - Add rightDiffEditor cursor/visual method types - Add missing Button import in AnnotationSidebar Closes #40 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Summary
~/.config/redpenand add a migration-backedstate.dbfor repos, review sessions, indexed files, activity, and recent items.redpen/commentsfor file annotation sidecarsprek,AGENTS.md,CLAUDE.md)Why
Validation
cargo check -p red-pen-tauri -p redpen-cli -p redpen-server -p redpen-runtime -p redpen-corecargo check -p red-pen-tauricargo clippy -- -D warningsnpm run buildnpm run test:runnpx tsc --noEmit