Skip to content

Paginate Timeline by 30 roots and reconcile cross-page moves - #117

Merged
RCmerci merged 9 commits into
mainfrom
codex/timeline-initial-30-roots
Oct 26, 2026
Merged

RCmerci merged 9 commits into
mainfrom
codex/timeline-initial-30-roots

Conversation

@RCmerci

@RCmerci RCmerci commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Timeline's tree-node quota could spend the display budget on children, and future journals could fill the first batch while the unread Today section appeared empty. Initial loads and every continuation now share a 30-displayed-root scanner. The first batch prioritizes Today, then fills from descending journal dates; future journals remain reachable and final display keeps date/sibling order.

Read roots at depth zero, then fetch bounded direct-child previews and display asset metadata through existing Worker commands. Headers, children and assets do not consume the root quota; resource delivery remains asynchronous. The dbworker API is unchanged. Date packets remain seven metadata entries, without a seven-date stop condition.

App-local date continuation is independent of display order. Runtime retains each page's later-date traversal separately from disposable Worker structure cursors, so stale-cursor recovery, Retry and retained-page reconciliation cannot drop deferred future/older dates. Graph reset clears it. Keep a separate date continuation visible even when authoritative deletion/reconciliation removes the day's root continuation. Sync refresh treats Today and the chronological prefix separately, preserves loaded history and UUID anchors, and removes old copies of identities moved into a fresh prefix. Page invalidation epochs allow prefix reads and retained reconciliation to complete together.

A normal cross-day move could also blank Timeline: a point read combined the returned page ID with cached old date/parent context, then a contiguous page splice could leave duplicate UUIDs in retained history. Resolve point reads against their actual page (fetching unknown page metadata through the existing API), retire superseded point/context responses (including every observation started before a resync), and relocate changed root membership/order only inside loaded ranges. Authoritative page replacement removes the whole old page and old occurrences of incoming UUIDs across pages, updates date counts and preserves unread continuations and UUID anchors. Swift duplicate rejection is unchanged; this repairs the upstream model. Several implicated methods also existed in the release baseline, so the whole failure is not attributed solely to this PR's new quota.

Validation:

  • Final locked OCaml 5.5 full regression: Runtime 175, Application 148, sync 333, Timeline and all remaining suites.
  • Supported isolated Database API → real Runtime/Timeline → actual headless rendered text: nine future29/30/31 × populated/empty/absent Today cases. Baseline falsely rendered populated Today empty at future30/31; the fix includes Today in each populated initial 30 and preserves later roots. Standard journal creation/small inserts, canonical journal UUIDs, unchanged 256 KiB bound. Official Logseq future-navigation source establishes the normal user entry; deployed Web version/fresh server E2E were not verified.
  • All ten public Runtime+Timeline recovery combinations pass on the final code: nine RED→GREEN cases plus one always-GREEN control. The earlier eight combinations (Today31/61 × stale cursor, Retry, retained reconciliation and a calendar-sampler day transition/new priority prefix) each failed before the Runtime date-traversal correction. In the later deletion cases, Today31→30 failed before the separate date-entry-point correction and passed afterward; Today61→60 was already green and remains a control. Assertions cover exact complete UUID/date sets, no duplicates, chronological order and UUID anchors.
  • Owner regressions cover same-day/cross-date quotas, sparse/filtered dates, multiple future dates outside the first metadata packet, child/assets, byte splitting, partial/final Today refresh, both cross-date move directions, deletion/count cleanup, stale generations, reset and epoch interleavings.
  • Resync boundary regression: eight public Runtime combinations (push/pull × raw point/pending page metadata × moved destination/moved-back source) fail on the previous head and pass after retirement at resync admission. Fresh roots are published before the late response; it cannot restore the saved old block or start a lookup. New post-resync points still publish, and both graph-reset controls remain green. All ten combinations pass.
  • Cross-page owner regressions: eight Runtime point/context/old-response cases failed before correction and pass afterward. Timeline cases check each publication for unique UUIDs, coherent page/date/root-parent ownership and date/sibling order across all six point/source/target completion orders, root-to-child moves, same-day reorder, loaded suffixes, counts and anchors; source-first controls remain. A corrected reachable Today29+Future1 fixture verifies that a moved root outside the target prefix waits for its actual continuation.
  • Recompiled the preserved default30 real Worker/Overlay FIFO fixture (unchanged normal move transaction and production limits). The old head drained 143 requests to66 rows/65 UUIDs. The fix drains the same143 to64 valid rows/64 UUIDs plus one legitimately unread destination root; one public visible-range continuation reaches the exact65/65 UUID set (148 requests total). Every published state is checked for unique roots, correct page/date/parent and order. This is an isolated source-model execution, not a replay of the live graph or a native/server E2E test. Move alone is sufficient; the actual two-transaction Move→Edit native path remains for the acceptance owner.
  • Earlier native fixture XCTest and an authorized real-graph recording exercised loading and assets before the later corrections. No current-head Simulator acceptance is claimed; old recordings cannot validate this Today fix. Experimental native provenance retains cross_abi_validated=false.
  • The decision documents validate. Global document validation retains five untouched pre-existing format failures.

Limits: 30 is a displayed-root quota, not a hard bound on DB scanning, snapshots, bytes or parsing. The pre-existing change-window pagination and older-Feed loading/error presentation issues remain outside scope. No merge, release or real-graph mutation is part of this change.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-25T07:27:04.970634Z ee92650 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee92650611

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/journal_graph_runtime.ml Outdated
Comment on lines +1123 to +1124
let epoch = t.next_request in
Hashtbl.replace t.root_page_epochs page.id epoch;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep feed scans from cancelling full-page reconciliation

Inferred from the resync path: rehydrate_current_interests starts both a prefix feed scan and read_changed_roots for retained pages, but both owners overwrite this same page epoch. If the journal-list response starts the feed's root read while the changed-page read is still collecting previews or subsequent batches, its remaining completions are discarded by root_batch_current, and superseded_root_batch silently drops Changed_roots. For a day with more than 30 loaded roots, refresh_feed then preserves the old suffix without the cancelled reconciliation updating it, leaving remote edits or deletions beyond the refreshed prefix stale. Separate the owners' epochs or coordinate these reads so the prefix refresh cannot cancel the reconciliation responsible for that suffix.

Useful? React with 👍 / 👎.

@RCmerci RCmerci changed the title Paginate Timeline by 30 roots with independent child previews Load Timeline by 30 roots with Today first Oct 25, 2026
@RCmerci RCmerci changed the title Load Timeline by 30 roots with Today first Paginate Timeline by 30 roots and reconcile cross-page moves Oct 25, 2026
@RCmerci
RCmerci merged commit cf23f14 into main Oct 26, 2026
2 checks passed
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.

1 participant