Item 3 complete and verified live on both surfaces. Closes the 2026-05-28/29 arc.
This session opened on the 2026-05-28 evening handoff's five-item list and closes it. The headline result: item 3 — file upload through the in-engagement composer — is complete and verified on the live system, on both the new surface (CenterPane) and the old one (ChatView), across upload success and fallback paths. The work shipped as Shape 2 (a shared upload hook both surfaces consume) in five build steps plus one gap-closing test, each its own commit, with frontend behaviour preserved and proven.
Along the way the session paid down record debt: it filed queued-directions §15.3 (the upload assertion-grain gap plus two documentation corrections), and corrected the current-status manifest, which had mislabeled Phase 60 as "Upload pathway v1" when Phase 60 is actually Companion-as-Operator-system-interface. Both landed and pushed before the build began.
What is left: a short tracked follow-up list — none blocking, all named so they survive the session. The decision this handoff records is that item 3 is done; the action it carries forward is the batch push of the build commits and this handoff, and the tag composer-upload-port-v0_1.
| # | Item | State |
|---|---|---|
| 1 | Configuration-drift remediation | Closed (engine b793aef, 427c446). Prior session. |
| 2 | Test-override audit | Closed (engine d5d57ee). Prior session. |
| 3 | File upload through the in-engagement composer | Complete this session. Shape 2; built, tested, verified live on both surfaces. |
| 4 | Route-redisposition finding | Resolved into queued-directions §15.1 (v0.21 methodology candidate). No build action. |
| 5 | Operator real-passkey registration (dev RP-ID) | Tracked, deferred (§13.3). Not sequenced. Unchanged. |
Shape 2. The upload orchestration (~100 lines, formerly inlined in ChatView's handleUpload) was extracted into a shared, turn-type-agnostic hook, src/hooks/useEngagementUpload.ts. Both ChatView and CenterPane consume it.
The seam, resolved on evidence. The composer's upload goes direct to the engine (/engagements/{id}/uploads) via the existing postUpload, because the Operator Layer has no backend tier — it is a pure frontend; every call already terminates at the engine. The "gateway" alternative had no spec or code basis (architecture spec v0.4 names no gateway/chokepoint; OVA/FORAY are the governed boundary, both engine-side and seam-and-stub).
Draft persistence added (CR v0.2 amendment). Step 0 surfaced that CenterPane lost typed drafts on navigation while ChatView preserved them. The parity gap was closed in-scope: CenterPane now uses the same proven composer-draft.ts mechanism, keyed per engagement. The two surfaces are now symmetric.
DisplayTurn types under one name (handled by the hook staying turn-type-agnostic); CenterPane has no persisted-draft (→ draft-persistence scope added); src/hooks/ did not exist (→ created).d67173c) — extract useEngagementUpload; ChatView consumes it. Behaviour preserved exactly; 388 tests unchanged, none modified.002be2e) — draft persistence on CenterPane, alone. Used ChatView's render-phase-reset idiom rather than its setState-in-effect restore, to avoid propagating a pre-existing lint defect into clean code. Same behaviour; lint baseline held. +4 tests.74e1d26) — mount the live upload affordance on CenterPane; remove the disabled "Attachments coming soon" placeholder. +4 tests. Draft persistence and upload deliberately separated into Steps 2 and 3 so a regression would be attributable to one.2e938a7) — consolidated test pass; filled CenterPane upload error and 401 coverage. +2 tests.c2ca4db) — added a ChatView upload 401-silent test (a pre-existing coverage gap, not a regression); it passes, confirming ChatView's 401 handling is correct. +1 test.Final code head: c2ca4db. Test suite: 399 passing, typecheck and lint at baseline throughout.
Run against the live engine + MinIO + browser stack (the exercise that originally surfaced the transaction bug; green tests alone are not sufficient evidence). All passed:
.md rendered its extracted content) and the fallback path (.json/.html showed "couldn't read this file directly" with the manual-content affordance) rendered correctly..md extracted and rendered. ChatView's refactored path is unbroken.Both pushed to loomworks-record origin before the build:
b3ec366) — added §15.3 (upload content does not reach assertion grain; assertions_drafted hardcoded empty, no downstream promoter), folding in two independently-timed documentation corrections. Archived v0.19, v0.20.8f57ff3) — corrected Entry 101's Phase 60 mislabel (Phase 60 is Companion-as-Operator-system-interface, not Upload pathway v1), fixed stale upload-pathway framings, added Entry 105 absorbing this arc, recorded the upload-pathway phase-identifier as unreconciled in §5. Archived v0.42.The CR documents are in the record but not yet pushed (see batch push): the scoping note v0.1 (822a75a) and Change Request v0.2 (09876d0), both in change-requests/.
Named so they survive the session. None gate item 3's completion.
.md is canonical and correct.onClarificationPick not wired. On CenterPane, an upload that returns a clarification card renders it, but its buttons have no wired action — CenterPane has no chip-to-reconverse path like ChatView's. Observed live. A small follow-up; the manual-content fallback does work..json and .html. Surfaced clearly by live testing: the engine extracts .md, images, and others, but not .json/.html, which fall back to manual-content. Engine work (upload-facility-extension, queued-directions §4), not a frontend defect.record.dunin7.com/operations/discipline-mechanisms/ editor page serves editor.js/site.css as text/html, so the browser refuses them. A record-site serving issue, unrelated to this work, surfaced incidentally during testing.Recorded in full at queued-directions §15.3. Upload writes a UploadEventReceived Memory event with full provenance, but drafts no individually-affirmable Assertions (assertions_drafted hardcoded empty; no downstream promoter). Upload content is searchable and provenance-attributable but does not reach the assertion grain the rest of the Memory pipeline operates on. Independent of item 3; present on the path ChatView used before this work; a real engine work item, unsequenced.
loomworks (code): push c2ca4db and the tag composer-upload-port-v0_1. loomworks-record: push 09876d0 (CR v0.2) plus this handoff.composer-upload-port-v0_1, Operator-Layer-only (no engine tag — no engine change). Annotated.| Repository | Head | State |
|---|---|---|
Engine (loomworks-engine) | d5d57ee | Unchanged this session. |
Operator Layer (loomworks) | c2ca4db | Steps 1–4 + 401 test. Unpushed until batch push; tag composer-upload-port-v0_1 to apply. |
Record (loomworks-record) | 09876d0 | v0.21, v0.43 pushed; scoping note, CR v0.2, and this handoff unpushed until batch push. |