Skip to main content

Module review

Module review 

Source
Expand description

Review-thread persistence on the redb review_threads table.

The /diff overlay’s line comments persist here per (project, branch) so a review round survives closing the overlay and forge restarts. Keyed by (project, branch) - the whole set for a branch is one serde-json blob. project is the forge.toml project NAME (worktree-agnostic), never the directory-hash key.

Re-exports§

use anyhow::Context; 🔒
use forge_primitives::review::ReviewAuthor; 🔒
use forge_primitives::review::ReviewComment; 🔒
use forge_primitives::review::ReviewSet; 🔒
use forge_primitives::review::ReviewStatus; 🔒
use forge_primitives::review::ReviewThread; 🔒
use redb::ReadableTable; 🔒
use redb::TableDefinition; 🔒
use super::Db; 🔒

Structs§

ThreadMembership 🔒
Membership a row carries on the thread rather than its turns - the shape stored while a thread could only belong to one review.

Constants§

REVIEWS 🔒
Submitted reviews per (project, branch) - the sealed groupings a thread’s turns point into. Sibling of REVIEW_THREADS; the whole set for a branch is one serde-json blob.
REVIEW_THREADS 🔒

Functions§

append_reply
Append an agent reply to the thread id in (project, branch): push a ReviewComment authored by Agent { label: author_label }, flip an Open thread to Addressed (a Resolved / Outdated / already-Addressed thread keeps its state), bump updated_at, and persist in one write transaction. Returns the thread’s status after the append. Errors when no thread carries id, so a stale comment_id surfaces rather than silently no-op’ing. An empty at is stamped with the current instant.
decode 🔒
Decode a stored blob into threads, mapping a decode failure to an error tagged with the owning (project, branch) so a corrupt row is diagnosable rather than a bare serde message. Lifts membership off any row still carrying it on the thread (see lift_thread_membership).
decode_reviews 🔒
Decode a stored blob into reviews, tagged with the owning (project, branch) on failure so a corrupt row is diagnosable.
delete
Delete the whole thread set for (project, branch). Returns whether a row existed.
delete_branch_state
Drop both of (project, branch)’s rows in one write transaction.
find_thread_by_id
Look up one thread by its globally-unique id in (project, branch). None when the branch has no such thread (or no row). comment_id in the review MCP maps to this id.
lift_thread_membership 🔒
Attribute a pre-per-turn row’s history: a thread filed as a whole has its user turns stamped with that review, so they read as the round they were actually part of instead of as unfiled. Positional - the mirror decode ignores every other key, so it aligns with threads. Only applies where no turn is filed yet, leaving a re-saved row’s own membership alone; the new shape persists on the thread’s next write.
load
Load every thread for (project, branch). Empty when the branch has no row (or the table doesn’t exist yet).
load_reviews
Load every submitted review for (project, branch), oldest first. Empty when the branch has no row (or the table doesn’t exist yet).
remove_thread
Remove the single thread id from (project, branch), dropping the row entirely when it was the last one. Returns whether a thread was removed. Used when the user clears a reopened comment’s text to delete it, so it doesn’t resurrect on the next hydrate.
review_branches
The branches under project that hold at least one submitted review, in key order. Seeks straight to the project’s first key and stops at its last, so the review__list empty path can ask “is this review filed against another branch?” without scanning the table.
rfc3339_now 🔒
RFC3339 timestamp for the current instant, matching the mcp::peers helper’s shape.
save
Overwrite the whole thread set for (project, branch). An empty slice removes the row rather than storing an empty blob.
set_status
Set the status of the thread id in (project, branch), bumping its updated_at. Returns whether a matching thread was found.
stored_branches
Every branch under project holding review state of either kind, deduped, in key order. Same per-project seek as review_branches, run over both tables: a branch can carry drafted threads and no submitted review, so a sweep consulting only the reviews table would leave its threads row behind.
submit_review
Seal a new review for (project, branch): mint its number (existing count + 1), stamp every still-unfiled user turn on each listed thread with the new review id, and append the ReviewSet. Turns already filed never move, so a thread whose earlier turns went into review 1 and whose reply goes into review 2 belongs to both. A thread that gains a turn this way is Addressed no longer - the agent owes an answer again - so it flips back to Open; a Resolved / Outdated thread keeps its state. Agent replies are answers to a round rather than part of one and are never stamped. One write transaction spans both tables so the stamp and the append land together.
upsert
Insert thread, replacing any existing thread with the same id in the branch’s set; appends when the id is new. Stamps updated_at to now and fills created_at (preserved from the existing row on replace, set to now when the caller left it empty) so a view need not carry a clock.
write_corrupt_reviews_row_for_test
Test-only sibling of write_corrupt_row_for_test for the reviews table, so a caller can exercise the reviews load-error path.
write_corrupt_row_for_test
Test-only: write undecodable bytes into the (project, branch) row so a caller can exercise the load-error path (a corrupt / partially written redb row). Feature-gated for cross-crate test access.