DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path scoping-notes/loomworks-list-loading-scoping-note-v0_1.html

Loomworks list-loading (pagination) — scoping note v0.1

Document: loomworks-list-loading-scoping-note-v0_1 Version: v0.1 Status: working draft Date: 2026-06-27 Author: Claude.ai (scoping role) Queue item: Companion build queue Item 1 — list-loading (cross-cutting pagination concern) Two-role note: This chat scopes and drafts. CC runs Step 0 and executes. Nothing here is committed to the record until the Operator authorises.


Orientation gap to name first

This note was drafted from the manifest's two precedent entries (Axis 11 conversation pagination, Entry 109; personal-recall wholesale-with-backstop, CR-2026-100). The canonical running queue — loomworks-companion-build-queue-v0_3.md in loomworks-record/current-status/ — is not reachable from this chat; it is not in the project mirror. The mirror also carries a stale manifest (v0.56) and a stale seed (v0.8); the canonical seed is v0.12 and the canonical manifest is higher than v0.56 per current project state.

What this means for this note: the pattern below is grounded in precedent I can read in full and is reliable. The endpoint inventory — which listing endpoints exist and which already paginate — is the thing I cannot close from here. That is exactly what the Step-0 brief (companion document) is for: CC reads Item 1's full queue section and the live engine, and reports the real delta. Do not treat the endpoint list in §4 as authoritative; treat it as the hypothesis Step 0 confirms or corrects.


1. What this item is, and what it is not

Item 1 is the cross-cutting pagination concern for unbounded-growth lists across every surface. Not "loading states / skeletons" — that is a sub-item of the same queue entry, a different concern (perceived-latency polish), and is out of scope here.

The lists in scope are the ones that grow without bound as an engagement accumulates:

Lists that are held-type or structurally small (bounded sets that do not grow without bound — e.g. a fixed enumeration, a small per-engagement catalogue) stay wholesale: fetched complete, no paging. The wholesale path is not a lesser version of the paged path; it is the correct path for bounded sets, mirroring the personal-recall precedent.


2. The pattern (largely pre-decided from two precedents)

The pattern is not open for re-litigation. It is the settled composite of the two precedents the queue names. Stated as the conformance target:

  1. Explicit load-more, not infinite scroll. A control the Operator clicks to fetch the next page. This is the settled Axis 11 §6 Q2 decision. Infinite scroll is rejected.
  2. total_count always visible. The Operator always sees how large the full set is, paged or not — the personal-recall total_count-surfaced precedent generalised. "You are seeing 50 of 312."
  3. has_more-gated control. The load-more control appears only when more exists — "only show what is available" (seed). Absent at the end of the set; never a disabled/greyed control.
  4. Composite (created_at, id) cursor. The keyset cursor is the pair, not created_at alone. This is the Axis 11 R2 known limitation resolved: the created_at-only strict-< cursor can skip a turn that shares the boundary timestamp and sorts later by id. The composite cursor is the complete fix and was explicitly recorded as the one engine-side follow-on tail. This item is where that tail gets paid, generalised across listing endpoints.
  5. Held-type / small sets stay wholesale, with a visible backstop limit and total_count surfaced — the personal-recall shape (limit 500 as a visible backstop, complete set returned, no silent clip).

The conversation-history endpoint (/operator/conversation-history) already carries the read-side of this pattern (before cursor + has_more), and Axis 11 already consumes it on the frontend. The conversation endpoint is the reference implementation. The work of this item is extending the same shape to the room-listing and engagement-listing endpoints — and, where the composite cursor is not yet present even on conversation-history, landing it there too so one cursor shape governs everywhere.


3. Where the work actually sits (engine vs. frontend)

Axis 11 was frontend-only because the conversation endpoint already paged. The room and engagement listings are the open question: if they currently return wholesale, this item carries a real engine delta (adding keyset pagination — limit, composite cursor params, has_more, total_count — to those endpoints), unlike Axis 11.

So the honest shape of this item, before Step 0, is:

The reason Step 0 must run before the CR is drafted: the engine delta is the load-bearing unknown. We do not know which listings already page (zero engine work, frontend-only like Axis 11) and which return wholesale (real engine work). The CR's size, classification, and step plan all depend on that count.


4. Endpoint hypothesis (to be confirmed/corrected by Step 0 — NOT authoritative)

From the stale manifest, two listing endpoints are visible:

Not visible from here, to be enumerated by Step 0:

§4 is deliberately thin because closing it from a stale mirror would be guessing. Step 0 closes it against the live engine.


5. Open questions for the Operator (none blocking the Step-0 brief)

  1. Page size. Axis 11 used limit=50 for conversation turns. Default lean: 50 for room/engagement listings too, unless a surface has an obvious different natural page (e.g. a card grid). Confirm or set per-surface at CR time, after Step 0 shows the surfaces.
  2. Default sort per list. Conversation is newest-first with load-earlier at the older edge. Room and home lists may want newest-first or a different default (e.g. "Needs you" by urgency, not recency). Default lean: newest-first (created_at DESC) everywhere unless the surface's purpose dictates otherwise; the composite cursor is order-agnostic. Set per-surface at CR time.
  3. Wholesale boundary. Which "small" sets stay wholesale is a judgement per listing. Default lean: a set stays wholesale only if it is structurally bounded (cannot grow without bound); anything that grows with engagement life pages. Step 0's inventory makes this concrete per endpoint.

None of these block Step 0. They are resolved at CR-drafting time, with Step 0's inventory in hand.


6. What this note commits to, against the seed

No apparent conflict with the seed. The one caveat: this note is checked against seed v0.8 (stale mirror); the live seed is v0.12. Step 0 / CR drafting should re-verify against canonical v0.12 before the CR is approved. Flagged, not silent.


7. Next step

The companion Step-0 inspection brief (loomworks-list-loading-step-0-inspection-brief-v0_1) goes to CC. CC reads Item 1's full section in the canonical queue, enumerates the live listing endpoints, reports paging status per endpoint, and returns the real engine delta. The CR is drafted only after Step 0 is Operator-accepted.