Skip to content

M2.2 story entries store, actions#349

Open
failerko wants to merge 3 commits into
mainfrom
slice/M2.2
Open

M2.2 story entries store, actions#349
failerko wants to merge 3 commits into
mainfrom
slice/M2.2

Conversation

@failerko

@failerko failerko commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Edit story entry content, delete entries, and rollback to previous entries with counts of affected items.
  • Enhancements

    • Typed rejection codes for clearer error responses.
    • Stronger gating: edits blocked during in-flight generation and while rollbacks run; improved entry synchronization.
  • Tests

    • Expanded test coverage for entry updates, deletions, rollback behavior, and store hydration.
  • Documentation

    • Updated milestone and roadmap docs clarifying storage ownership and rollback semantics.

@coderabbitai

coderabbitai Bot commented Jun 13, 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: c5c21904-3b3f-4438-a209-62843cb0f583

📥 Commits

Reviewing files that changed from the base of the PR and between 767ffb1 and ec4f920.

📒 Files selected for processing (4)
  • lib/actions/story-entries/operational.ts
  • lib/actions/story-entries/register.ts
  • lib/pipeline/authoring/registry.ts
  • lib/pipeline/runtime/orchestrator.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/actions/story-entries/operational.ts
  • lib/actions/story-entries/register.ts

📝 Walkthrough

Walkthrough

This PR implements Milestone 2 Slice 2.2 (entry-arms), adding story entry mutation and rollback operations alongside a new working-set store for synchronization. Edit-blocking logic moves to the generation store to eliminate circular dependencies, and comprehensive rejection codes and type extensions enable structured error handling throughout.

Changes

Entry-arms and rollback core

Layer / File(s) Summary
Documentation and type contracts
docs/implementation/milestones/02-first-user-loop/milestone.md, docs/implementation/milestones/02-first-user-loop/slices/02-entry-arms.md, docs/implementation/roadmap.md, lib/actions/delta/registry.ts, lib/actions/types.ts
Milestone C8 contract documents store ownership (creation in Slice 2.2, consumption in Slice 2.5). Implementation notes resolve rollback-index concerns and detail survival-anchor semantics, opening invariants, and typed rejection codes. HandlerOutcome and MutationResult add optional code field to rejections.
Gate behavior refactor: move edit-blocking to generation store
lib/stores/generation/generation.ts, lib/pipeline/index.ts, lib/pipeline/runtime/orchestrator.ts, lib/stores/generation/generation.test.ts, lib/pipeline/runtime/concurrency.test.ts, lib/stores/__tests__/namespace-shape.test.ts, lib/pipeline/__tests__/chained-and-parallel.test.ts
RunState gains gateBehavior: 'hard-gate' | 'no-gate' initialized from pipeline config. New exported isUserEditBlocked(txState) returns true when reversal is in progress or any run has gateBehavior === 'hard-gate'. Tests and helpers updated to set/use gate behavior.
Working-set entries store creation
lib/stores/entries/entries.ts, lib/stores/entries/entries.test.ts
entriesStore instantiated via createWorkingSetStore<StoryEntry>() exposing hydrate, patch, getById, and React hooks. Tests verify branch hydration, patch application for create/update/delete, and branch isolation (non-held branches ignored).
Story entry handlers: create, update, delete with rejection codes
lib/actions/story-entries/register.ts, lib/actions/story-entries/register.test.ts
Rejection constants (STORY_ENTRY_REJECTION) and codes defined. Creation normalizes rows and enforces opening position === 1; create/update/delete handlers emit working-set patches. deleteStoryEntry blocks opening deletion and records undo payloads. Tests verify patcher synchronization, opening invariants, and delete/reverse round-trips.
Reverse-and-prune delta utility
lib/actions/delta/reverse-replay.ts
New exported reverseAndPruneDeltaRows(rows, ctx) builds undo SQL, executes undo + delta row deletions in a single transaction, applies patcher patches, and returns processed row count. Errors are wrapped with DeltaReplayError including an actionId.
Content update and rollback APIs
lib/actions/story-entries/operational.ts, lib/actions/story-entries/operational.test.ts
updateStoryEntryContent performs direct content updates (no delta rows), guards against edits when blocked, and patches entriesStore. resolveRollbackWindow/getRollbackCounts compute rollback targets and counts; rollbackToEntry sets reversalInProgress, selects deltas using a survival-anchor predicate (handles entryId IS NULL), calls reverseAndPruneDeltaRows, and clears the barrier in finally. Tests cover success and rejection scenarios.
Public API exports & registry ergonomics
lib/actions/index.ts, lib/stores/index.ts, lib/pipeline/authoring/registry.ts, lib/pipeline/runtime/orchestrator.ts
Re-exports added for rollback/content-update helpers, rejection types/codes, and entriesStore. resetAllStores() now resets entriesStore. getPipelineSafe introduced and used to tolerate missing chained pipeline targets during commit.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • #336: Story entry delete, content-update, opening-entry invariants, and rollback APIs (handlers, reverse-and-prune, entriesStore, types) implement the core Slice 2.2 entry-arm specification.

Suggested reviewers

  • a-frazier

Poem

🐰 hops excitedly
Stories roll back now with grace,
Entries pruned from their place,
Gates moved home to stores so wise,
Patches sync what's stored inside—
Rollback sweeps with careful pride! 📜✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.17% 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 accurately reflects the main changes: it introduces a story entries store and associated operational actions for M2.2, covering store creation, entry mutations, and rollback functionality.
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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request establishes the entries working-set store and implements the rollback-to-entry functionality, including delta reversal and pruning, along with moving the user-edit gating logic to the generation store to prevent dependency cycles. The review feedback suggests optimizing the rollback delta selection query by replacing a correlated subquery with a leftJoin for better database performance. Additionally, it recommends validating rollback targets before modifying the reversalInProgress state, transitioning to a distinct error state upon failure, and ensuring that the delete handler consistently returns the notFound rejection code when a target is missing.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread lib/actions/story-entries/operational.ts Outdated
Comment thread lib/actions/story-entries/operational.ts
Comment thread lib/actions/story-entries/register.ts Outdated

@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 `@lib/actions/delta/reverse-replay.ts`:
- Around line 103-114: The current catch lumps transaction failures and
post-commit patcher failures together; separate them so transaction errors (from
ctx.runInTransaction([...ops, ...pruneOps])) still throw
DeltaReplayError('Reverse-and-prune failed', ...) while errors thrown by the
subsequent patch loop (from patches and resolveByTable(...).patcher) are
reported distinctly to indicate the DB change committed already. Update
reverse-replay.ts to: run ctx.runInTransaction and catch/throw
DeltaReplayError('Reverse-and-prune failed', { cause, actionId }) for any
failure there; then execute the for (const p of patches) loop outside that
try/catch and if a patcher throws, throw a different DeltaReplayError (e.g.,
'Post-commit patch sync failed') that includes the original error as cause, the
actionId, and a flag/property (e.g., committed: true) so callers know the deltas
were pruned and should not retry unsafely; keep references to buildUndoOps,
pruneOps, ctx.runInTransaction, patches, resolveByTable, and DeltaReplayError
when making the changes.

In `@lib/pipeline/runtime/orchestrator.ts`:
- Line 55: newRunState can throw via getPipeline(kind) which may abort commitRun
before generationStore.finishRun runs and leave txState.runs in an inconsistent
state; fix by validating the pipeline kind before creating successor runs (move
the getPipeline(kind) lookup out of newRunState into commitRun or add a
non-throwing getPipelineSafe that returns undefined), and if the kind is
unknown, ensure you call generationStore.finishRun(...) / run cleanup (or abort
successor creation) before throwing or return a safe default gateBehavior;
update references newRunState, getPipeline, commitRun, generationStore.finishRun
and txState.runs accordingly so cleanup always executes prior to any thrown
error.
🪄 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: 595ef319-a347-458c-8278-592c9acd0956

📥 Commits

Reviewing files that changed from the base of the PR and between d99b9fc and 767ffb1.

📒 Files selected for processing (23)
  • docs/implementation/milestones/02-first-user-loop/milestone.md
  • docs/implementation/milestones/02-first-user-loop/slices/02-entry-arms.md
  • docs/implementation/roadmap.md
  • lib/actions/delta/registry.ts
  • lib/actions/delta/reverse-replay.ts
  • lib/actions/index.ts
  • lib/actions/story-entries/operational.test.ts
  • lib/actions/story-entries/operational.ts
  • lib/actions/story-entries/register.test.ts
  • lib/actions/story-entries/register.ts
  • lib/actions/types.ts
  • lib/pipeline/__tests__/chained-and-parallel.test.ts
  • lib/pipeline/index.ts
  • lib/pipeline/runtime/concurrency.test.ts
  • lib/pipeline/runtime/gate.test.ts
  • lib/pipeline/runtime/gate.ts
  • lib/pipeline/runtime/orchestrator.ts
  • lib/stores/__tests__/namespace-shape.test.ts
  • lib/stores/entries/entries.test.ts
  • lib/stores/entries/entries.ts
  • lib/stores/generation/generation.test.ts
  • lib/stores/generation/generation.ts
  • lib/stores/index.ts
💤 Files with no reviewable changes (3)
  • lib/pipeline/runtime/gate.test.ts
  • lib/pipeline/runtime/gate.ts
  • lib/pipeline/index.ts

Comment thread lib/actions/delta/reverse-replay.ts
Comment thread lib/pipeline/runtime/orchestrator.ts
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.

Slice 2.2 — Entry-arm completion: delete, content-update, opening invariants, rollback action

1 participant