Skip to content

ft. ENG-40#97

Merged
Connorbelez merged 11 commits intomainfrom
codex/eng40
Mar 17, 2026
Merged

ft. ENG-40#97
Connorbelez merged 11 commits intomainfrom
codex/eng40

Conversation

@Connorbelez
Copy link
Copy Markdown
Owner

No description provided.

@linear
Copy link
Copy Markdown

linear Bot commented Mar 17, 2026

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Sorry @Connorbelez, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 17, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f19ed88-615d-4ed5-9689-2c879016b9b7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/eng40
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link
Copy Markdown
Owner Author

Connorbelez commented Mar 17, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@Connorbelez Connorbelez marked this pull request as ready for review March 17, 2026 02:27
Copilot AI review requested due to automatic review settings March 17, 2026 02:27
Copy link
Copy Markdown
Owner Author

@copilot please review

Copy link
Copy Markdown

Copilot AI commented Mar 17, 2026

@Connorbelez I've opened a new pull request, #98, to work on those changes. Once the pull request is ready, I'll request review from you.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Mar 17, 2026

Greptile Summary

This PR implements ENG-40: the Consumer Cursor Infrastructure for the mortgage ownership ledger. It refactors convex/ledger/cursors.ts from adminQuery/adminMutation to the ledger-domain-standard ledgerQuery/ledgerMutation, adds registerCursor (idempotent, initialises at genesis) and getNewEntries (paginated polling over ledger_journal_entries.by_sequence), tightens advanceCursor to require an existing cursor and validate target sequence numbers, and migrates cursor tests into a dedicated cursors.test.ts file covering the full SPEC §6.7 polling contract.

Key changes:

  • registerCursor — idempotent upsert returning the cursor _id, initialised at lastProcessedSequence: 0n
  • getNewEntries — queries ledger_journal_entries via by_sequence index, respects batchSize, returns entries, cursorPosition, and hasMore
  • advanceCursor — now requires the cursor to exist first (no more upsert) and validates that the target sequence is present in the journal
  • resetCursor — now shares the getCursorByConsumerId helper and adds sequence validation for non-zero targets
  • Cursor tests moved to convex/ledger/__tests__/cursors.test.ts; the stale T-072 lifecycle test removed from ledger.test.ts

Issues found:

  • hasMore false positive (cursors.ts:101): entries.length === batchSize yields true when remaining entries exactly equal batchSize, causing a spurious empty poll round-trip. Fetch batchSize + 1 to detect this reliably.
  • advanceCursor allows backward movement (cursors.ts:106–127): No guard prevents lastProcessedSequence from being set to a value less than the current cursor position. In a financial ledger this could cause downstream consumers (accrual engine, dispersal engine) to reprocess already-handled entries.
  • Manifest status stale (specs/ENG-40/chunks/manifest.md): Both chunks still show planned while tasks.md records the majority of work as complete.

Confidence Score: 2/5

  • Not safe to merge as-is — two logic issues in the core cursor API could cause downstream financial consumers to receive incorrect signals or reprocess ledger entries.
  • The hasMore false positive and the missing backward-movement guard in advanceCursor are both correctness issues in a financial ledger context. Reprocessing journal entries due to an accidental cursor rewind could produce duplicate accrual or dispersal calculations. The hasMore issue adds noise to polling contracts that consumers may rely on to determine when to stop. Both issues require changes to cursors.ts before merging.
  • convex/ledger/cursors.ts requires fixes at lines 101 (hasMore predicate) and 111–126 (backward-movement guard in advanceCursor).

Important Files Changed

Filename Overview
convex/ledger/cursors.ts Core cursor API refactored from adminQuery/adminMutation to ledgerQuery/ledgerMutation; adds registerCursor, getNewEntries, and tightens advanceCursor — but hasMore uses a false-positive predicate and advanceCursor lacks a backward-movement guard, both of which are correctness issues in a financial ledger context.
convex/ledger/tests/cursors.test.ts New dedicated cursor test file; covers idempotent registration, SPEC §6.7 poll/advance/replay flow, batch limiting, and structured error codes — test suite is solid but the batch-size test avoids the exact-boundary case that would expose the hasMore false positive.
convex/ledger/tests/ledger.test.ts Removes the now-stale T-072 cursor lifecycle test (which assumed upsert-on-advance behavior); the rest of the ledger test suite is unaffected.
specs/ENG-40/chunks/manifest.md Chunk manifest added but both entries still show status "planned" while tasks.md marks most work as done; minor doc inconsistency.
specs/ENG-40/tasks.md Master task list correctly reflects the implementation state; T-006 and T-011 (codegen/test gate) are still open, consistent with the status notes.

Sequence Diagram

sequenceDiagram
    participant C as Consumer (e.g. accrual_engine)
    participant R as registerCursor
    participant G as getNewEntries
    participant A as advanceCursor
    participant DB as ledger_journal_entries

    C->>R: registerCursor(consumerId)
    R-->>C: cursorId (idempotent, lastProcessedSequence=0n)

    loop Poll cycle
        C->>G: getNewEntries(consumerId, batchSize?)
        G->>DB: query by_sequence > lastProcessedSequence, take(batchSize)
        DB-->>G: entries[]
        G-->>C: { entries, cursorPosition, hasMore }

        alt entries.length > 0
            C->>C: process entries
            C->>A: advanceCursor(consumerId, lastProcessedSequence)
            A->>DB: validate sequence exists
            A-->>C: cursor patched
        else no new entries
            C->>C: wait / backoff
        end
    end
Loading

Last reviewed commit: 226b476

Comment thread convex/ledger/cursors.ts Outdated
Comment thread convex/ledger/cursors.ts
Comment thread specs/ENG-40/chunks/manifest.md Outdated
@Connorbelez Connorbelez changed the base branch from ENG-27 to graphite-base/97 March 17, 2026 02:31
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds the ENG-40 “consumer cursor” infrastructure to the ledger domain so downstream consumers can register a cursor, poll new journal entries in sequence order, and advance their cursor position, with dedicated test coverage and accompanying spec/task docs.

Changes:

  • Refactors convex/ledger/cursors.ts to use shared helpers, adds registerCursor + getNewEntries, and tightens cursor mutation validation.
  • Moves cursor contract tests into a new focused cursors.test.ts and removes the legacy cursor lifecycle assertions from ledger.test.ts.
  • Adds ENG-40 planning/status/spec documentation (task lists, chunk contexts/statuses, manifest).

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
specs/ENG-40/tasks.md Master checklist for ENG-40 work across chunks.
specs/ENG-40/chunks/manifest.md Chunk manifest table and status summary.
specs/ENG-40/chunks/chunk-01-cursor-api/tasks.md Chunk 01 task breakdown (cursor API refactor).
specs/ENG-40/chunks/chunk-01-cursor-api/status.md Chunk 01 implementation + quality gate notes.
specs/ENG-40/chunks/chunk-01-cursor-api/context.md Chunk 01 scope/acceptance criteria/context.
specs/ENG-40/chunks/chunk-02-cursor-tests/tasks.md Chunk 02 task breakdown (cursor tests).
specs/ENG-40/chunks/chunk-02-cursor-tests/status.md Chunk 02 implementation + quality gate notes.
specs/ENG-40/chunks/chunk-02-cursor-tests/context.md Chunk 02 test plan/context.
convex/ledger/cursors.ts Implements consumer cursor API (register, poll, advance/reset) with validation + structured errors.
convex/ledger/tests/ledger.test.ts Removes old cursor lifecycle test block (cursor contract moved to dedicated file).
convex/ledger/tests/cursors.test.ts New dedicated cursor contract tests (SPEC 6.7 flow + edge cases).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread convex/ledger/cursors.ts
Comment thread specs/ENG-40/chunks/manifest.md Outdated
Comment thread specs/ENG-40/chunks/manifest.md Outdated
Comment thread specs/ENG-40/chunks/chunk-01-cursor-api/tasks.md Outdated
Comment thread specs/ENG-40/chunks/chunk-02-cursor-tests/tasks.md Outdated
Connorbelez and others added 11 commits March 17, 2026 00:31
…alMutation

These three convenience mutations are called by GT effects (Deal Closing,
discharge pipeline), not by users directly. Converting them from
ledgerMutation.public() to internalMutation enforces this at the Convex
level. Also converts mintMortgage/burnMortgage to adminMutation per spec.

Key changes:
- Extract handler functions (issueSharesHandler, transferSharesHandler,
  redeemSharesHandler) for reuse across auth boundaries
- Add belt-and-suspenders same-mortgage check to transferShares
- Update getPositionAccount to throw ConvexError (structured errors)
- Add demo wrappers in convex/demo/ledger.ts for the demo UI
- Update all test files from api.* to internal.* namespace
- Add 21 dedicated unit tests covering happy paths, min fraction
  violations, sell-all exceptions, insufficient balance, idempotency

All 132 ledger tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…alMutation

These three convenience mutations are called by GT effects (Deal Closing,
discharge pipeline), not by users directly. Converting them from
ledgerMutation.public() to internalMutation enforces this at the Convex
level. Also converts mintMortgage/burnMortgage to adminMutation per spec.

Key changes:
- Extract handler functions (issueSharesHandler, transferSharesHandler,
  redeemSharesHandler) for reuse across auth boundaries
- Add belt-and-suspenders same-mortgage check to transferShares
- Update getPositionAccount to throw ConvexError (structured errors)
- Add demo wrappers in convex/demo/ledger.ts for the demo UI
- Update all test files from api.* to internal.* namespace
- Add 21 dedicated unit tests covering happy paths, min fraction
  violations, sell-all exceptions, insufficient balance, idempotency

All 132 ledger tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Connorbelez Connorbelez changed the base branch from graphite-base/97 to main March 17, 2026 04:43
@Connorbelez Connorbelez merged commit 495371d into main Mar 17, 2026
1 check passed
Connorbelez added a commit that referenced this pull request Apr 20, 2026
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.

3 participants