State Management
Relevant source files
The following files were used as context for generating this wiki page:
State Management in Marginalia coordinates information between a background poller, a local API server, and a web-based Studio. The system tracks the lifecycle of GitLab Merge Requests (MRs), including their review status, pending comments, and local triage fixes. It ensures that the Studio reflects the most recent bot runs and user interactions without requiring a central database.
Sources: README.md:1-20, studio/public/openapi.yaml:4-15
Persistent Storage Layers
The application persists state using several JSON files and local browser storage. This decentralized approach allows the bot to operate headlessly while the Studio provides a reactive interface.
| Storage Component | Location | Description |
|---|---|---|
state.json | Project Root | Tracks the last reviewed SHA for others' MRs and the last peer-comment timestamp for the user's MRs. |
status.json | Project Root | Stores the live status of the poller (idle, polling, reviewing) and progress of active runs. |
settings.json | Project Root | Stores runtime configuration overrides like poll intervals and branch filters. |
posted.json | Project Root | Records comments already added to GitLab to prevent duplicate postings. |
localStorage | Browser | Tracks "Read" state by mapping review slugs to reviewedAt timestamps. |
Sources: README.md:144-148, README.md:183-187, studio/src/lib/api.ts:213-228, studio/src/App.tsx:57-69
Bot Execution State
The poller manages execution state by tracking GitLab MR activity. It decides whether to trigger a new review based on changes to the head SHA or new peer comments.
Review vs. Triage Logic
The system differentiates state tracking based on MR authorship:
- Other's MRs: Tracking is SHA-based. A review triggers if the head SHA changes.
- User's MRs: Tracking is timestamp-based. A triage triggers if a new peer comment appears.
Studio Synchronisation
The Studio maintains a live view of the bot's state using Server-Sent Events (SSE) and specialized React hooks.
Live Updates via SSE
The server sends a data: changed event whenever status.json, settings.json, or the reviews directory changes. The Studio listens for these events to trigger a refresh of the review list.
Hook-Based Data Management
useReviews(): Manages the global state of all reviews, bot status, and settings. It handles reconnection and periodic polling (every 30 seconds) as a fallback to SSE.useReview(slug): Fetches the specific Markdown content and structured "shape" for a single review.useSeen(current): Manages local "read/unread" state by comparing the current review's timestamp againstlocalStorage.
Sources: studio/src/lib/api.ts:285-330, studio/src/App.tsx:57-69
Configuration State
Configuration is managed hierarchically. Environment variables in .env serve as the base defaults, while settings.json provides runtime overrides that the bot picks up without a restart.
Settings Update Flow
- User modifies values in
SettingsPage.tsx. saveSettingscall executes aPUT /api/settingsrequest.- The server updates
settings.json. - The poller reads the updated file before its next execution cycle.
Sources: studio/src/components/SettingsPage.tsx:43-55, studio/public/openapi.yaml:157-170
Review Verdict and Shape
The bot generates a structured state for each review, referred to as the "shape." This normalization allows the Studio to display consistent UI elements regardless of which command generated the report.
{
"verdict": "REQUEST_CHANGES",
"summary": "One or two sentences.",
"risk": { "level": "high", "rationale": "Changes totals...", "factors": ["payments"] },
"findings": [
{
"id": "neg-total",
"severity": "important",
"title": "Total can go negative",
"path": "src/lib/pricing.ts",
"line": 42,
"comment": "Fix suggestion..."
}
]
}
Sources: skills/marginalia-review/SKILL.md:120-136, studio/src/lib/api.ts:133-144
Triage and Fixes State
For MRs authored by the user, the system manages a local git state for automated fixes.
- Local Branch: Fixes are committed to
marginalia/<branch-slug>. - State Comparisons: The system compares the local fix branch against the remote MR branch to determine if fixes are
ready,pushed, oroutdated. - Fast-Forward Only: Pushing fixes from the Studio is restricted to fast-forward operations to prevent accidental overwrites.
Sources: README.md:167-175, studio/public/openapi.yaml:450-465, studio/src/lib/api.ts:446-453
The state management system prioritizes local control and visibility, ensuring that the user remains the final authority before any state changes are pushed to the remote GitLab repository.