DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path scoping-notes/loomworks-b5-manifestation-room-scoping-note-v0_2.html
LoomworksScoping NoteDUNIN72026-08-01

B-5 Manifestation Room — Scoping Note — v0.2

Version
0.2
Date
2026-08-01
Status
Scoping note. Six decisions for Operator settlement. Change request A's Step 0 is complete on all three items. No change request drafted.
Author
Claude.ai. Operator: Marvin Percival.
Filing
loomworks-record/scoping-notes/
Governing
scoping-notes/loomworks-completion-scoping-note-v0_2.md — the arc CR-A belongs to.
Supersedes
v0.1 (record 3635eda), which stands alongside as a sibling.

1What this is

B-5 builds the Manifestation room — the surface where an engagement's Memory appears organized at a moment in time. It is item five on the main line and the front of the queue.

Change request A's Step 0 had three items. Item one, the engine contract, ran on 2026-07-31. Items two and three, the Operator Layer reads, ran on 2026-08-01. Both are complete and both are anchored. Nothing in this note is reconstructed from session memory; every fact carries a file:line anchor in one of the two findings documents.

Change request A's Step 0 is now closed on all three items, per the completion scoping note §6:

Item Status Where settled
1. The status of W-2 — load-bearing on acceptance Resolved. The defect cannot fire; the broken route was removed on 2026-07-30 and the live path calls the same code directly. Engine findings §3, B-27
2. The real shape of the room components and their data fetching Complete. Operator Layer findings §2–§7
3. The vocabulary wall against the seed's plain-terms discipline Complete, and the anticipated conflict does not materialise. See D5. Operator Layer findings §8

One residue on item 1. The completion note §9 records W-2's status as unknown with the acceptance gate on top of it. The defect is resolved. What remains unread is whether creation doors 1 and 2 complete end to end — a live check the engine session's fences forbade, and which rests on CR-2026-158's own Checkpoint A verification rather than on this Step 0. The acceptance gate still wants that evidence; CR-A does not.

This note settles the build shape and surfaces six decisions. It does not draft the change request.


2Where B-5 actually stands — a correction to the queue framing

Prior position — build list v0.10, B-5. "READY — front of the queue, and smaller than we thought. The read found the engine already returns what the screen needs. The staleness marker is a wire, not a build."

That is true of the engine and false of the Operator Layer. Both halves are now read, and they point in opposite directions.

The engine is ready. All four Manifestation routes exist. Walk-audit W-16 was wrong when filed — the version pin exists as a query parameter on route 4, and was already there at the walk-audit engine. GET /engagements/{id}/memory-status returns both halves of the state contract in a single call, so staleness needs no computation built.

The Operator Layer has nothing. No ManifestationRoom.tsx. No src/lib/api/manifestations.ts. Zero occurrences of manifestations anywhere in src/ or tests/. Zero occurrences of memory-status in either tree. The wire exists and nothing is plugged into it.

The corrected framing. B-5 is small because its parts are individually simple and no migration is implicated — not because most of it is already built. It is greenfield client work against a ready engine: two new adapters, one new room component, one new fetch-state representation, one changed line in the dispatcher, one new test file. The build list entry should be amended when it next moves.


3What CR-A actually is — the scope dependency, resolved

v0.1 §8 flagged an open dependency: whether change request A is B-5 alone or B-5 with other items. The completion scoping note settles it, and the answer has two halves.

By build-list item, CR-A is B-5 alone. Its §4 heading reads CR-A — the surface-state contract and the Manifestation screen · B-5, and §4's opening records this as a deliberate mapping: five build-list items do not map onto five change requests. CR-C is B-6 and B-7; CR-D is B-8; CR-E is B-9; CR-B carries no build number.

By content, CR-A lands two things. Its body: "Establishes the typed state contract from §2 and lands the Manifestation room as its first consumer… The contract lands with a real consumer rather than as a standalone abstraction, because a contract with no user is a guess." CR-C and CR-D consume that contract downstream.

The consequence for this note. Any decision about the state representation is not a Manifestation-room-local choice. It binds B-6, B-7 and B-8. D4 is reframed at v0.2 for exactly this reason: v0.1 treated the fetch-state question as B-5's to invent, and it is not — the contract is already committed in the completion note §2, and B-5's job is to ground it against real components, not to design it.

And the contract is already written. Completion note §2, How the rule is enforced, commits five states:

State Meaning Carries
unloaded no read attempted
loading read in flight
failed read attempted and failed the reason
empty read completed, nothing found time of read, source version read at
populated read completed the data, time of read, the version it was derived from, and the current version of its source

The note names the load-bearing property: empty and populated both carry the read that produced them, so a component cannot render an empty-state string without holding a value that proves a read completed. That is face 2 enforced by construction. And populated carrying both versions is what makes face 3 computable rather than optional.

The completion note explicitly defers the exact form to Step 0 — "the exact form is grounded at Step 0 against the real components." Step 0 has now run. Grounding it is CR-A's work.


4What exists and what is new

Piece State Anchor
Four Manifestation engine routes Exists api/routers/manifestations.py:321, :396, :441, :490
Version pin on route 4 Exists — query parameter, not path segment manifestations.py:502; loader engagement/manifestation.py:688-697
memory-status engine route Exists, returns both state-contract halves api/routers/memory_status.py:45; schema :6899 and :6908
Room key, label and discriminator Exists — no change needed src/lib/room-labels.ts:26
Room dispatcher Exists — one line changes RoomView.tsx:56-62
Fetch wrapper and adapter pattern Exists — 26 hand-written adapters over one 113-line wrapper src/lib/api.ts; src/lib/api/memory.ts as canonical
List fetch-state hook Exists, three states, list-shaped src/hooks/usePagedList.ts:38-50, :62
Room-test pattern Exists, six steps, directly copyable RenderingRoom.test.tsx:1-60
ManifestationRoom.tsx New
src/lib/api/manifestations.ts New
src/lib/api/memory-status.ts (or folded into the above) New
Single-object fetch state New — nothing models it see D4
ManifestationRoom.test.tsx New

The structural model is the Rendering room, not the Memory room. The Operator Layer findings overturn the brief's own framing here: two rooms have real implementations, not one. RenderingRoom.tsx is 126 lines of read-only list with honest empty state; MemoryRoom.tsx is 645 lines dominated by five mutating Operator actions the Manifestation room does not need. B-5 copies the Rendering room.


5The build shape

Six pieces, in dependency order.

  1. src/lib/api/manifestations.ts — wire-boundary comment, Operator-vocabulary types, Wire* snake_case interfaces, projection functions, fetch functions. Surfaces the version pin deliberately from the first line rather than retrofitting it. Must be added to WIRE_BOUNDARY_FILES at tests/components/vocabulary-wall.test.ts:43-80, or the wall fails the moment a route-path string lands.
  2. The memory-status adapter — same pattern. Whether it lives in its own file or inside the manifestations adapter is a build-time call, not an Operator decision.
  3. The fetch-state representation — see D4.
  4. ManifestationRoom.tsx — reads a Manifestation and, if D1 lands that way, a memory-status. Renders per D3.
  5. RoomView.tsx:56-62 — replace the compose case's EmptyRoom with the component. One line of substance.
  6. ManifestationRoom.test.tsx — six-step pattern, mocking @/lib/api/manifestations, manifestation-* testids, empty-state coverage modelled on MemoryRoom.test.tsx:511.

6Decisions for Operator settlement

D1 — Which staleness measure the room displays. Reframed at v0.2. The contract settles the data side already: populated must carry both the version it was derived from and the current version of its source (completion note §2). Both come from one memory-status call. That is not optional and is not a decision.

What remains is a display decision, and it is real. The engine carries two measures and they can disagree. memory_has_changed is driven by whether any Memory-content category is non-zero, explicitly not by version comparison (engagement/memory_status.py:135-136). The raw version delta counts every event including non-content ones. A Manifestation can be twenty-five versions behind and correctly flagged current.

Claude's lean: carry both, as the contract requires, but display memory_has_changed as the marker with changes_since_derivation as the detail. Do not surface the raw version delta. The delta counts things that are not Memory content, so it is not an Operator-meaningful number, and showing it is what manufactures the apparent contradiction the build list warns about. This resolves the problem by not introducing it.

D2 — Per-object Manifestation history. Assertions have a /history route; Manifestations do not. Building one is small. But the client has no caller for the assertion-side history route either, so there is no existing history-display pattern in the surface to extend — this would be new on both sides.

Claude's lean: out of B-5. Route 3 already lists an engagement's Manifestations filtered by state, newest first, which gives "what came before" at the engagement level. Per-object history is a different axis and no evidence yet shows the room needs it. Deferring costs nothing and it can be added later without rework.

D3 — What the room renders: fan-out, inlining, or organization-only. organized_groups carries assertion references — identifier and version — not text. Three options:

Claude's lean: C. The room's job per the seed is Memory organized at a moment in time. The organization is the product; assertion text is a drill-down. C ships now, needs no engine work, introduces no unprecedented fetch pattern, and does not block A or B later. If the room proves thin in use, B is the better follow-on than A — it keeps the fetch pattern uniform.

D4 — Where a Manifestation with no organized grouping sits in the contract. Substantially reframed at v0.2. v0.1's framing is withdrawn — see Section 10.

Prior framing (v0.1). The Operator Layer has no representation for fetched successfully, and the value is legitimately null for a structural reason, so B-5 needs a new state. Lean was four states — loading, error, organized, unorganized.

Why that was wrong. It treated the state question as B-5's to invent. The contract is already committed in the completion note §2, at five states, and CR-A's job is to ground it against real components rather than design it. Proposing a competing four-state shape would have put CR-A in conflict with the arc it belongs to.

The real question, which is narrower. organized_groups is null on pre-Phase-19 Manifestations, where only counts survive. Under the contract this is populated, not empty — the read completed and a Manifestation exists. Empty means no Manifestation was found at all. So the question is whether populated needs an internal distinction for the unorganized case, or whether the room simply renders what the populated value carries.

Claude's lean: no sixth state and no sub-state. The room renders the organization when organized_groups is present and an honest explanation with the surviving counts when it is null. Both are populated. Adding a state for a data condition inside a successfully-read object would weaken the contract, whose whole point is distinguishing read conditions, not content shapes.

What is genuinely new build work regardless. usePagedList is list-shaped and models three of the five states; there is no single-object fetch representation in the Operator Layer at all (src/hooks/usePagedList.ts:38-50, :62). CR-A builds the five-state contract as a first-class type. That is the contract landing, and the Manifestation room is its first consumer — exactly as the completion note describes.

D5 — The vocabulary wall's case-sensitivity. Reframed at v0.2, because the completion note anticipated a conflict that the read does not find.

What the completion note expected. Its §6, CR-A Step 0 item 3: "RoomView.tsx carries a header referring to forbidden room-key literals. The seed's plain-terms discipline protects Memory, Manifestation, Shaping and Rendering on operator-facing surfaces. One of the two gives… if the wall is deliberate at the level of the methodology nouns, it conflicts with the seed and the Operator decides which moves."

What the read found. No conflict. The wall restricts lowercase code literals; the seed requires plain terms on operator-facing surfaces. Both hold at once, and the Operator Layer findings report zero offenders — every operator-visible string in the room surfaces is in plain terms and centralised in strings.ts. The anticipated ruling is not needed. Completion note §6 item 3 closes without an Operator decision.

What the read found instead. The wall does not enforce what its own comment claims. Matching is case-sensitive (vocabulary-wall.test.ts:128) against lowercase terms (:29-30), so the capitalized forms Manifestation and Shaping — the operator-facing forms — pass in every file. The carve-out declares itself a tight distinction, not a blanket exception; as implemented it binds only the lowercase spellings. Live instances already sit outside the sanctioned file: strings.ts:372, :588, SpendPausePreferenceSection.tsx:12-13.

Claude's lean: split it out as its own small build item and run it before B-5's room lands. B-5 is about to add a room dense with exactly those two words, and shipping it under a guard known to be blind is the wrong moment. Keeping it separate also protects CR-A's scope: normalising the comparison will surface the three known instances, and each needs a judgment — legitimate operator-facing label, or leak. That triage is a vocabulary question, not a Manifestation-room question.

Rejected alternative, recorded: fixing it inside B-5 by adding the known instances to the allowlist. That is patching a test green when its premise is false, which the project prohibits.

Unchanged obligation either way. The new src/lib/api/manifestations.ts must be added to WIRE_BOUNDARY_FILES (vocabulary-wall.test.ts:43-80), or the wall fails the moment a route-path string lands — the lowercase manifestation is caught.

D6 — Room linkability. Rooms are useState, not routes (InEngagementSurface.tsx:66). A room is not linkable, not bookmarkable, and not restored on reload; the Operator always lands in Memory.

Claude's lean: out of B-5. Making rooms linkable changes the shared surface for all four rooms and is not a Manifestation-room-local change. Worth a build-list item of its own if a staleness notice elsewhere should ever deep-link into the room.


7Build notes — not decisions

The shared-gate choice. The Memory room's two lists share one gate: either list's loading or error state governs the whole room (MemoryRoom.tsx:555, :558). If B-5 reads both a Manifestation and a memory-status, the same either/or presents itself. The Manifestation is the room's substance and staleness is an annotation on it, so they should not share a gate — a failed staleness read should not blank the room.

Load-more error collapse. usePagedList sets the same error flag for a first-page failure and a load-more failure (:136), so a failed second page replaces an already-rendered list with an error and the loaded items vanish. B-5 inherits this only if it uses the hook. Under D3 lean C it likely does not, and should not reproduce the behaviour.

Only show what is available. The established idiom is conditional rendering to null with a comment naming the principle — nine sites, zero greyed-out controls in any room component. A Manifestation room with no derivation yet shows an honest empty state, not a disabled Derive button.

W-16 should be struck from the walk-audit record, not scheduled. It was wrong when filed. The break list loses an entry. This is a record correction, not build work, and does not belong inside B-5.

The two disabled attributes at MemoryRoom.tsx:224/:241 are an open seed-interpretation question with the code's counter-reasoning recorded at :126-129. Not B-5's to fix either way; noted so it is not lost.


8What B-5 does not include


9Sequence

  1. Operator settles D1 through D6.
  2. If D5 lands as split, the vocabulary-wall item is allocated a build number and runs first. It is very small.
  3. Change request A is drafted in a fresh session from this note plus both findings documents.
  4. Build.

The dependency v0.1 flagged is closed. See Section 3. CR-A is B-5 by build-list item and the state contract by content.

A consequence for CR-B, outside this note's scope but caused by its inputs. The completion note §4 lists W-16 as one of CR-B's four items — "no route retrieves a Manifestation at the version a Shape was built from" — and sets the dependency "must complete before… CR-E (which needs the version route)." The engine findings overturned W-16 on 2026-07-31: the route exists as a query parameter and was present at the walk-audit engine. CR-B loses a bullet, and CR-E's dependency on CR-B for the version route evaporates. CR-B's other three items stand and CR-D still needs the title. This is a record correction for whoever next amends the completion note; it is not B-5's to make.


10Corrections preserved

"Smaller than we thought." Build list v0.10's B-5 entry, written from the engine half alone. True of the engine, false of the Operator Layer, where the room is greenfield. The entry stands; the framing is corrected here and should be amended when the list next moves.

"The one room believed to work." Asserted in the Operator Layer brief §4 V1 as the reason to detail the Memory room. Two rooms have real implementations. The Rendering room at 126 lines is the closer structural model for a read-only room than the Memory room at 645. Corrected by the read.

W-16 — "there is no at-version route for manifestations." Walk-audit report §5.3. Overturned by the engine half: the capability exists as a query parameter and was present at the walk-audit engine. What W-16 got right is its route enumeration; what failed is its method — it read an OpenAPI document for a path segment and concluded absence.

v0.1's D4 — "the fourth state." Asserted at v0.1 §5: the Operator Layer has no representation for a structurally-null value, so B-5 needs a new state, leaning to four — loading, error, organized, unorganized. Withdrawn at v0.2. The error was one of authority, not of observation: the observation was correct and the conclusion overstepped, because the state contract was already committed in the completion note §2 at five states and CR-A's job is to ground it, not design it. A Manifestation with null organized_groups is populated, not a new state. The prior wording stands at D4 as the surfacing event.

v0.1 §8's open dependency. "Whether A is now B-5 alone, or B-5 plus B-6 and B-7, is not settled by either findings document." Closed at v0.2 by reading the completion note. The framing was also imprecise — the real answer is neither of the two options offered: B-5 by build-list item, and the shared state contract by content. Recorded because the question as posed could not have produced the right answer.

The completion note's anticipated seed conflict. Its §6 CR-A item 3 expected the vocabulary wall and the seed's plain-terms discipline to be in conflict, with an Operator ruling on which moves. The read finds no conflict: the wall restricts lowercase code literals, the seed governs operator-facing strings, and there are zero offenders. The anticipated decision is not needed. What the read found instead is a different defect entirely — the guard is blind to capitalized forms.

W-16 inside CR-B. The completion note §4 still carries W-16 as a CR-B item and CR-E's dependency on it. Overturned by the engine findings on 2026-07-31; the note predates the read. Stale rather than wrong, and named here so it is not lost.

The vocabulary wall carve-out as described. vocabulary-wall.test.ts:82-88 claims a tight restriction. The implementation enforces it only for lowercase spellings. The comment describes an intent the code does not deliver.


11Provenance

Produced 2026-08-01 in the Claude.ai Loomworks project, from the two Step 0 findings documents and build list v0.10. No repository was inspected from this session; every anchor is quoted from a findings document, not read directly.

The trajectory worth preserving: the engine half arrived first and produced an optimistic framing that the build list absorbed. The Operator Layer half, run a day later, showed the optimism was half-correct and localised. Neither read was wrong; the framing error came from generalising one half to the whole before the other half ran. Worth naming as a pattern — a partial Step 0 absorbed into the queue reads as a complete one unless the gap is stated in the entry itself.

v0.2 came from reading the governing note that v0.1 had only cited. The same pattern repeated one level up: v0.1 was drafted from two findings documents and the build list, all of which are true, and none of which carries the state contract CR-A exists to land. Two of its six decisions were reframed and one was withdrawn. The lesson is narrower than read more — it is that a scoping note for a lettered change request must read the arc note that letters it, before the findings and not after.


12Version history

v0.2 (2026-08-01). Amendment following a read of loomworks-completion-scoping-note-v0_2. New Section 3 resolves v0.1's open dependency and reproduces the five-state contract the completion note §2 commits. Section 1 gains the Step 0 closure table for CR-A's three items. D1 is reframed to separate the contract's data requirement from the display choice. D4 is withdrawn and rewritten — v0.1 proposed a competing state shape where a contract already existed. D5 is reframed: the seed conflict the completion note anticipated does not materialise, and completion note §6 item 3 closes without an Operator ruling. Section 9 records that CR-B loses W-16 and CR-E loses its dependency on CR-B for the version route. Section 10 gains four entries. Leans on D1, D2, D3, D5 and D6 are unchanged in substance.

v0.1 (2026-08-01). Original, at record 3635eda. Corrected the queue's smaller than we thought framing, inventoried what exists against what is new, and posed six decisions.

DUNIN7 — Done In Seven LLC — Miami, Florida
Loomworks — B-5 Manifestation Room — Scoping Note — v0.2 — 2026-08-01