06 — CX.33 source-document explorer option scan
06 — CX.33 source-document explorer option scan
Section titled “06 — CX.33 source-document explorer option scan”Status: Findings (S232 Wave 1B). Foreground investigation per 09-decision-graph-feedback-actions.md §3 (“Platform UI Source-document explorer — investigate options”) and 0.9-context.md §7.5 (“3rd-party tool for source-document explorer (TBD which)”) + Liam’s golden-source-update crossover ask.
Audit date: 12/05/2026
Branch: content-items-investigation
Scope: evaluate browse / preview / (optional) edit-back surface for binary golden-source documents (DOCX, PDF, XLSX, MD) held in Supabase Storage. Not the content_items editor — Tiptap+Yjs already covers that per 0.9-edit-flow-investigation.md §6.1 + §9.8.
1. TL;DR
Section titled “1. TL;DR”- The KH stack already ships every primitive an explorer needs for the markdown + DOCX + PDF paths: Tiptap 3.22 (read + edit),
mammoth1.11 (DOCX → HTML),react-pdf10.4 +@react-pdf/renderer4.5 (PDF preview, used incomponents/reader/pdf-viewer.tsx),docx9.6 +exceljs4.4 (write-back for DOCX and XLSX),turndown7.2 +turndown-plugin-gfm(HTML → markdown).yjs13.6 +y-prosemirror1.3 are installed but the collaboration extension isn’t yet wired to a liveY.Doc. - No file in
lib/,components/,app/imports@tiptap/extension-collaborationory-prosemirroras a Tiptap extension — these deps are queued for the §9.8 enable, not active. Source-doc-history UI also has no consumer of a “preview the binary” affordance yet — only diff + history list. - Primary recommendation for the v1 explorer: a per-mime-type viewer surface that reuses the in-stack components, mounted from a new
app/documents/[id]index page (not the existing[id]/diffsub-route).- Markdown → Tiptap (existing
ContentEditorincomponents/item-detail/content-editor.tsx, withreadOnly=truefor preview, editable for golden-source edit). - DOCX →
mammoth.convertToHtml+ Turndown → mount in Tiptap; edit-back via TiptapgetMarkdown()→ optional server-side DOCX regen (see §6). - PDF → existing
PdfViewer/PdfReaderView(read-only — PDF round-trip is out of scope; flag at UI). - XLSX → defer past v1 (form-data shape: handle via structured form UI per
09 §1 Q3.5, not a binary viewer).
- Markdown → Tiptap (existing
- Secondary recommendation (fallback if Tiptap-as-DOCX-viewer surface proves insufficient):
docx-previewas a read-only DOCX renderer (preserves layout fidelity better than mammoth+Tiptap), paired with the existing Tiptap surface for edit-mode. Adds ~150-200 KB minified. - Golden-source-update crossover (Liam’s specific ask): the chosen surface handles markdown trivially (Tiptap → write to Storage at
storage_path). DOCX round-trip via mammoth-in / Tiptap-edit /docxlibrary-out is feasible but lossy on complex formatting; gates on Wave 1B-2’s Q&A write-back decision. PDF round-trip is out of scope. XLSX edit-back uses the structured form UI path (not a viewer). The explorer’s surface and the edit-flow UC1/UC4/UC6 candidates already converge on Tiptap+Yjs — the explorer is a binary-source viewer that hands off to the same editor for markdown. - Net new dependencies if primary recommendation taken: zero. All capability exists in stack; secondary adds
docx-previewonly if explicit DOCX fidelity is required.
2. What’s already in stack (verified versions, 12/05/2026)
Section titled “2. What’s already in stack (verified versions, 12/05/2026)”| Capability | Package | Version | Active consumer | Notes |
|---|---|---|---|---|
| Rich-text editor (markdown) | @tiptap/react + @tiptap/starter-kit + @tiptap/markdown | 3.22.0 | components/item-detail/content-editor.tsx:42-58 (buildExtensions) | Markdown-in/markdown-out via editor.getMarkdown(). Used in Q&A answer display, response editor, bid context, item detail. |
| Tiptap collab plumbing | @tiptap/extension-collaboration, yjs, y-prosemirror | 3.22 / 13.6 / 1.3 | None — installed but no Y.Doc wiring yet | Per 0.9-edit-flow-investigation.md §9.8: “REUSE — one plugin enable away.” |
| PDF preview | react-pdf + @react-pdf/renderer | 10.4.1 / 4.5.1 | components/reader/pdf-viewer.tsx:4, components/reader/pdf-reader-view.tsx:4 | Already supports filePath → signed-URL → <Document><Page/></Document>. Includes page nav, zoom, fit-width, keyboard navigation. |
| PDF text extraction | unpdf | 1.4.0 | lib/extraction/pdf.ts (used by app/api/upload/route.ts:467) | Server-side; not a viewer. |
| DOCX → HTML | mammoth | 1.11.0 | app/api/upload/route.ts:13, lib/bid-library-ingest/docx-to-markdown.ts:12, lib/ai/extract-questions.ts:231, lib/bid-library-ingest/extract-qa-pairs.ts:475, app/api/bids/[id]/questions/extract/route.ts:241 | Verified two-step convertToHtml → Turndown pattern in use (per CLAUDE.md gotcha — convertToMarkdown drops tables). |
| HTML → markdown | turndown + turndown-plugin-gfm | 7.2.4 / 1.0.2 | lib/bid-library-ingest/docx-to-markdown.ts:13-14 | Same pipeline above. |
| DOCX writer (round-trip-out) | docx | 9.6.0 | lib/bid/bid-export-docx.ts:10-22 | Generates .docx from in-memory structure via Packer.toBuffer(). Server-side. |
| XLSX read/write | exceljs | 4.4.0 | lib/bid/bid-export-xlsx.ts:10 | Existing server-side write path; same package handles read. |
| Storage bucket | Supabase Storage documents bucket | n/a | app/api/upload/route.ts:375 (insert), components/reader/pdf-viewer.tsx:63-65 (signed URL read) | storage_path column on source_documents points here. |
source_documents row + history UI | KH schema | n/a | components/source-document/source-document-info.tsx, source-document-history.tsx | History timeline + version-chain link exist; no preview-the-binary affordance currently surfaced (gap CX.33 fills). |
Interpretation: the explorer is a UI-assembly job over existing primitives, not a tool-selection job. The “TBD which third-party tool” framing in 0.9-context.md §7.5 overstates the gap — all read-side primitives are already deployed.
3. Candidate comparison
Section titled “3. Candidate comparison”Scoring scale: yes / partial / no / n/a. “In-stack” means already in package.json with at least one active consumer.
3.1 Tiptap viewer (read-only) — already in stack
Section titled “3.1 Tiptap viewer (read-only) — already in stack”| Axis | Result |
|---|---|
| 1. Markdown preview | yes — ContentEditor readOnly={true} (line 78 of content-editor.tsx) renders markdown via the existing extension set. |
| 2. DOCX preview | partial — needs mammoth.convertToHtml → Turndown → Tiptap (see §3.5). Loses page layout, headers/footers, comments, tracked changes (though has_tracked_changes() detection exists at scripts/docx_utils.py). |
| 3. PDF preview | no — PDF is not a markdown shape. |
| 4. XLSX preview | no — table semantics drop; Tiptap’s table extensions are GFM-shaped, not spreadsheet-shaped. |
| 5. Edit-back capability | yes for markdown (native getMarkdown()); partial for DOCX (round-trip via docx library — lossy on complex formatting); no for PDF / XLSX. |
| 6. Tiptap+Yjs integration | yes — same editor instance; collab extension is the §9.8 enable. |
| 7. Workspace_id scoping | yes — access control attaches at the source_documents row + Storage signed-URL layer (existing pattern at components/reader/pdf-viewer.tsx:63-65). |
| 8. Golden-source update | yes (markdown), partial (DOCX), no (PDF/XLSX). Markdown writes back to Storage at storage_path; DOCX requires regen step. |
| 9. Bundle impact | 0 KB — already shipped. |
| 10. Licence | MIT (Tiptap), MIT (mammoth), MIT (Turndown). |
3.2 ProseMirror viewer (raw, no Tiptap wrapper)
Section titled “3.2 ProseMirror viewer (raw, no Tiptap wrapper)”| Axis | Result |
|---|---|
| 1. Markdown preview | yes but requires re-implementing the markdown serialiser Tiptap already provides. |
| 2-4. DOCX / PDF / XLSX | no — same constraint as Tiptap; no shape advantage. |
| 5. Edit-back | yes for markdown (more work than Tiptap to wire). |
| 6. Tiptap+Yjs integration | n/a — Tiptap IS the ProseMirror wrapper. Using raw ProseMirror means dropping the existing buildExtensions pipeline and re-implementing schema parity. |
| 7-10. Workspace / golden-source / bundle / licence | Identical to Tiptap (smaller bundle by ~20 KB; not material). MIT. |
Verdict: strictly worse than Tiptap — same capability surface, more bespoke code. Discount.
3.3 react-pdf — already in stack
Section titled “3.3 react-pdf — already in stack”| Axis | Result |
|---|---|
| 1. Markdown preview | no. |
| 2. DOCX preview | no. |
| 3. PDF preview | yes — production-deployed at components/reader/pdf-viewer.tsx (Dialog + toolbar + nav + zoom + keyboard) and pdf-reader-view.tsx (inline variant). Already reads from Supabase Storage signed URLs. |
| 4. XLSX preview | no. |
| 5. Edit-back | no — react-pdf is render-only. Form-field PDFs aren’t in scope per the corpus shape. |
| 6. Tiptap+Yjs integration | n/a. |
| 7. Workspace_id scoping | yes — signed-URL pattern verified at line 63-65. |
| 8. Golden-source update | no — flag as one-way preview. |
| 9. Bundle impact | 0 KB — already shipped. |
| 10. Licence | MIT. |
3.4 docx-preview — not in stack
Section titled “3.4 docx-preview — not in stack”| Axis | Result |
|---|---|
| 1. Markdown preview | no. |
| 2. DOCX preview | yes — renders .docx natively in-browser, preserving styles, headers/footers, footnotes, images. Higher fidelity than mammoth+Tiptap. |
| 3. PDF preview | no. |
| 4. XLSX preview | no. |
| 5. Edit-back | no — render-only. Edit-back stays in Tiptap (so this is paired with §3.5, not replacement). |
| 6. Tiptap+Yjs integration | n/a — separate surface. |
| 7. Workspace_id scoping | yes — signed-URL → ArrayBuffer pattern works identically to react-pdf. |
| 8. Golden-source update | no on the preview path — edit-back delegates to the Tiptap surface. |
| 9. Bundle impact | ~150-200 KB minified (pulls in jszip + DOM rendering). |
| 10. Licence | Apache 2.0. |
3.5 mammoth.js → Tiptap (composed) — already in stack
Section titled “3.5 mammoth.js → Tiptap (composed) — already in stack”This is the production-realistic markdown-as-canonical pathway: mammoth.convertToHtml → Turndown → Tiptap mount. Identical pipeline to lib/bid-library-ingest/docx-to-markdown.ts:38-44 (docxBufferToMarkdown). KH already normalises DOCX uploads to markdown at ingest time (app/api/upload/route.ts:476-477), so this is internally-consistent with the rest of the platform.
| Axis | Result |
|---|---|
| 1. Markdown preview | yes — Tiptap handles. |
| 2. DOCX preview | yes, as markdown — meaningful loss of formatting fidelity (tables preserved per CLAUDE.md gotcha + GFM plugin; headers/footers / page-layout / comments / tracked-changes / footnotes degrade). |
| 3. PDF preview | no. |
| 4. XLSX preview | no. |
| 5. Edit-back | yes (markdown-canonical) — Tiptap edit → getMarkdown() → write to Storage. For golden-source DOCX edit-back: add server-side step to convert markdown → DOCX via existing docx 9.6 package (the inverse of bid-export-docx.ts). Round-trip is lossy by design (markdown is the canonical layer). |
| 6. Tiptap+Yjs integration | yes — same editor; collab via §9.8 enable. |
| 7. Workspace_id scoping | yes. |
| 8. Golden-source update | partial-yes — see §6. |
| 9. Bundle impact | 0 KB — already shipped. Server-side conversion runs in existing upload-route environment. |
| 10. Licence | MIT (Tiptap), MIT (mammoth), MIT (Turndown), MIT (docx writer). |
3.6 Lexical (Facebook) — not in stack
Section titled “3.6 Lexical (Facebook) — not in stack”| Axis | Result |
|---|---|
| 1. Markdown preview | partial — has a markdown plugin but maturity lower than Tiptap’s. |
| 2-4. DOCX / PDF / XLSX | no — no first-party plugins. |
| 5. Edit-back | yes for markdown (after wiring). |
| 6. Tiptap+Yjs integration | n/a — different framework. Lexical has its own Yjs adapter (@lexical/yjs) but doesn’t reuse the existing @tiptap/extension-collaboration plumbing. |
| 7. Workspace_id scoping | yes (storage-layer concern, framework-agnostic). |
| 8. Golden-source update | Same as Tiptap shape, but reimplemented. |
| 9. Bundle impact | ~100-150 KB. |
| 10. Licence | MIT. |
Verdict: discounting per 0.9-context.md §8 anti-pattern (“don’t fall into ‘extend the existing infrastructure’ trap” cuts both ways — also “don’t introduce a new framework where existing one suffices”). Lexical adds zero capability over Tiptap for KH’s markdown-canonical model.
3.7 Adobe PDF Embed API — not in stack
Section titled “3.7 Adobe PDF Embed API — not in stack”| Axis | Result |
|---|---|
| 1. Markdown preview | no. |
| 2. DOCX preview | no. |
| 3. PDF preview | yes — Adobe-hosted; supports annotation, form-fill, comments. |
| 4. XLSX preview | no. |
| 5. Edit-back | partial — Adobe-hosted annotation layer, not raw PDF mutation. |
| 6. Tiptap+Yjs integration | n/a. |
| 7. Workspace_id scoping | partial — requires Adobe-hosted credential per workspace; introduces an external dependency on document URLs reachable by Adobe’s servers. |
| 8. Golden-source update | no (annotation overlays, not source mutation). |
| 9. Bundle impact | Small JS shim (~30 KB); load deferred to Adobe-hosted iframe. |
| 10. Licence | Proprietary — free tier with attribution; commercial use needs Adobe terms. |
Verdict: discounting. Strictly inferior to react-pdf for KH’s needs (no annotation requirement surfaced in 09-decision-graph-feedback-actions.md), and introduces an external-services dependency that conflicts with the “binary stays in Supabase Storage” assumption.
3.8 Slate — not in stack
Section titled “3.8 Slate — not in stack”Functionally equivalent surface to Tiptap with weaker ecosystem and no first-party Yjs. Discount on same grounds as Lexical.
4. Recommendation for v1
Section titled “4. Recommendation for v1”4.1 Primary: per-mime-type viewer composed from in-stack primitives
Section titled “4.1 Primary: per-mime-type viewer composed from in-stack primitives”Route: new app/documents/[id]/page.tsx (today the only [id]/ content is /diff/).
Behaviour by MIME type (taken from source_documents.mime_type):
| MIME | Component | Mode |
|---|---|---|
text/markdown, text/plain | ContentEditor (existing components/item-detail/content-editor.tsx) | readOnly toggle. Edit → onSave writes to Storage at storage_path. |
application/vnd.openxmlformats-officedocument.wordprocessingml.document (DOCX) | server-side mammoth.convertToHtml → Turndown → ContentEditor | readOnly for preview; edit-mode persists markdown; optional DOCX regen via docx 9.6 on save (gates on §6). |
application/pdf | PdfReaderView (existing components/reader/pdf-reader-view.tsx) | read-only. Banner reads “PDF source — preview only. Edit-back not supported (extract Q&A pairs or re-upload a revised binary).” |
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (XLSX) | defer past v1 — render an “Open in spreadsheet form UI” affordance pointing at the structured-form path (Wave 1B-3 forms / coverage). |
Workspace_id scoping: the page is gated on source_documents.workspace_id lookup with the existing role-based RLS; signed-URL pattern from pdf-viewer.tsx:63-65 reused. No new access-control surface needed.
Existing infrastructure reused:
source_documents.storage_path→ Supabase Storagedocumentsbucket (already wired).source_documents.mime_type→ drives component selection.source_documents.workspace_id→ drives RLS (per Option α in finding 01 §1).- Tiptap + Yjs collab via §9.8 enable (deferred to v1.1 per
0.9-edit-flow-investigation.md§6.1 Q4 ratification). - Existing
SourceDocumentInfo(components/source-document/source-document-info.tsx) andSourceDocumentHistorysidebar. - Existing diff UI at
app/documents/[id]/diff/page.tsxlinked from the new page (the explorer page becomes the index that the diff page hangs off).
Justifications:
- Reuse over introduction (
0.9-context.md §8): every read-side primitive is already shipped and has at least one prod consumer. Adding a framework or new viewer is unjustified spend. - Markdown-first ingestion (per
0.9-context.md §7.2): KH normalises DOCX to markdown at ingest. Surfacing a markdown view of the source is internally-consistent and trivially round-trippable. - Convergence with edit-flow §6.1 Candidate A: the explorer’s edit mode IS the UC1 / UC4 / UC6 in-platform-edit surface. Two affordances, one editor.
- Per-MIME selection rather than “one viewer for everything” is the only honest answer — DOCX / PDF / XLSX have genuinely different semantics, and pretending otherwise produces a worse UX.
4.2 Secondary: add docx-preview ONLY if mammoth+Tiptap loses critical fidelity
Section titled “4.2 Secondary: add docx-preview ONLY if mammoth+Tiptap loses critical fidelity”Trigger: user-feedback during v1 that the markdown-flattened DOCX preview loses information the user needs to see (headers / footers / styling cues / footnote anchors). Most likely surfaced from the docs/client-documentation-base/binary/ corpus — particularly long-form prose docs with heavy formatting.
Shape: view-mode toggles between “Markdown view” (Tiptap, default) and “Original layout” (docx-preview read-only iframe / shadow-DOM mount). Edit always uses the Tiptap surface.
Cost: ~150-200 KB minified bundle on top of react-pdf’s existing ~80 KB. Apache 2.0.
Don’t install pre-emptively — recommendation is to wire the per-MIME page first, observe whether the markdown-view fidelity is sufficient, and add docx-preview only on confirmed gap. This matches the 0.9-context.md §7.1 principle of avoiding speculative dep additions.
5. Golden-source-update crossover (Liam’s specific ask)
Section titled “5. Golden-source-update crossover (Liam’s specific ask)”The explorer needs to enable “seamlessly updating underlying golden-source knowledge hub documents” per Liam’s note in 09-decision-graph-feedback-actions.md §3. Handling per MIME:
5.1 Markdown (.md) — trivial
Section titled “5.1 Markdown (.md) — trivial”- User clicks “Edit” on the explorer page.
ContentEditormounts in editable mode against the markdown loaded fromstorage_path.- User edits →
onSavewrites the modified markdown back to Storage at the samestorage_path(or to a new versioned path under finding 01 Option α slim-and-keep). - Cocoindex source binding observes the file change on next scan (per
0.9-edit-flow-investigation.md§6.1 Candidate A) — the same write-back primitive UC1 / UC4 / UC6 use. content_itemsderived from the source re-flow through the pipeline;content_historyrecords the edit via existing DB trigger.
5.2 DOCX (.docx) — feasible but lossy
Section titled “5.2 DOCX (.docx) — feasible but lossy”- Read path:
mammoth.convertToHtml(server-side) → Turndown → markdown → Tiptap mount. - Edit path: Tiptap edit →
getMarkdown(). - Write-back path: TWO options:
- Markdown-canonical (recommended for v1): write the edited markdown back as a sidecar
.mdalongside the.docx(or replace the.docxstorage_path with the.mdif the workspace policy allows). The original DOCX becomes the “frozen original”; the markdown is the live editable surface. This matches0.9-edit-flow-investigation.md§6.1.1 Q6 ratification (“Prompted on first edit; silent thereafter per record”). - DOCX-canonical (deferred to v1.1): server-side regen via
docx9.6 package. Markdown → AST → DOCX-paragraph-tree →Packer.toBuffer()→ upload to Storage. Lossy: lacks the original styles / templates / numbering / images bundled in the source DOCX. Not worth the implementation cost in v1 when the markdown-canonical sidecar covers the workflow.
- Markdown-canonical (recommended for v1): write the edited markdown back as a sidecar
- The Q&A-write-back investigation (
02-q29-q32-q111-q112-qa-write-back.md, Wave 1B-2) covers a structurally identical decision for Q&A pair sources. Whatever shape that lands with should be carried forward here.
5.3 PDF — out of scope for edit-back
Section titled “5.3 PDF — out of scope for edit-back”- PDFs are not round-trippable through markdown without information loss; even Adobe-grade tooling (PDF Embed API) only adds annotation overlays rather than mutating the binary.
- Recommendation: the explorer renders PDFs read-only with a banner directing the user to either (a) re-upload a revised PDF (engages the UC7+UC10 binary re-upload flow per
0.9-edit-flow-investigation.md§6.7), or (b) extract Q&A pairs and edit those via the standard UC6 surface.
5.4 XLSX (form-data) — not a viewer concern
Section titled “5.4 XLSX (form-data) — not a viewer concern”- The cited example (Cloud Security Principles Checklist) is form-data per
09-decision-graph-feedback-actions.md§1 Q3.5: it’s a structured questionnaire, not free-form prose. - A spreadsheet viewer would be the wrong primitive — the user needs the form-fill UI from the Wave 1B-3 forms / coverage stream (
docs/plans/phase-0-investigation/10-feedback-investigation-findings/future doc), not a cell-grid. - The explorer’s XLSX affordance should be a one-line CTA: “Open in form view →” linking to the form-fill route once that work lands.
5.5 The cocoindex re-flow question
Section titled “5.5 The cocoindex re-flow question”If the user edits a markdown source through the explorer, does cocoindex (when wired) re-extract the content_items downstream? Per 0.9-edit-flow-investigation.md §6.1 Candidate A:
- Cocoindex source binding observes the file change on next scan.
- Engine compares content-hash; mismatched → re-runs the binary-shape adapter for that source-key.
- Resulting content_items are UPSERTed (not duplicated);
content_historyv2/v3 lands via existing DB trigger. - §6.1 Q3 ratification: cocoindex idempotency on equal-hash gates on S9 spike result — but the explorer’s edit path is the same path as UC1’s, so it inherits whatever resolution S9 produces.
Open question raised by this scan: does cocoindex re-extract on a user-initiated edit-back? Gates on Wave 1B-2’s resolution of the WP3 ledger query pattern (see 0.9-edit-flow-investigation.md §6.1 + Q3 / Q4 carry-forward).
6. Recommended shape for the v1 page
Section titled “6. Recommended shape for the v1 page”Sketch (not binding on implementation):
- Route:
app/documents/[id]/page.tsx(the document[id]issource_documents.id). - Layout: main content area + right-rail metadata sidebar.
- Main content: mounts
<DocumentViewer mimeType={...} storagePath={...} editable={...} />— a thin dispatcher that picks<MarkdownViewer />/<DocxViewer />/<PdfViewer />/<XlsxFormCta />. - Sidebar: existing
<SourceDocumentInfo />(filename, version, file size, hash, uploaded by, created at) +<SourceDocumentHistory />(version chain, if Option α retains it; see finding 01 §3.4). - Toolbar:
view-only/editmode toggle (subject to permission per0.9-edit-flow-investigation.md§6.0.4); “Download original” link; “View diff vs previous” ifparent_idset; “Re-upload as new version” CTA. - Edit-save flow:
- Markdown: direct Storage
update()atstorage_path; cocoindex re-flow follows. - DOCX (v1 markdown-canonical): write sidecar
.md; mark DOCX as “frozen original”.
- Markdown: direct Storage
- Concurrent-edit handling: Yjs collab via §9.8 enable (deferred to v1.1 per
0.9-edit-flow-investigation.md§6.1 Q4).
This page is also the natural home for the existing app/documents/[id]/diff/page.tsx sub-route to hang off — the explorer page becomes the index (“you’re looking at v3 of policy-v2.docx — see v2-vs-v3 diff →“).
7. Implications for adjacent decisions
Section titled “7. Implications for adjacent decisions”| Adjacent area | Implication |
|---|---|
| Finding 01 Option α vs β | A v1 explorer surface needs SOME row to dispatch from. If Option β (drop source_documents entirely) lands, the explorer dispatches from cocoindex source-key + Storage path lookups (more indirection; tolerable). Option α (slim-and-keep) is the cleaner host. Either way the explorer’s viability isn’t blocked. |
| Edit-flow §6.1 (UC1) Candidate A | The explorer’s “Edit” mode IS UC1’s write-back surface. No new architectural decision; this is the per-MIME UI face of the same write-back primitive. |
| §6.1.1 Q6 (binary source sidecar prompt) | Liam’s ratification “Prompted on first edit; silent thereafter per record” applies directly. The explorer’s first DOCX edit triggers the prompt. |
| §9.8 Tiptap+Yjs enable | Concurrent-user editing on the explorer page benefits from the same enable. Not a blocker for v1 read-mode. |
| Wave 1B-2 (Q&A write-back) | The DOCX-canonical-vs-markdown-canonical decision recurs there for Q&A pair sources. Whatever shape lands should propagate here. |
| Wave 1B-3 (forms / coverage) | The XLSX CTA depends on the forms-UI shape. Until that lands, the explorer’s XLSX path is a stub. |
| CX.33 → decision-graph status | Move to RESOLVED with implementation seed once this finding is reviewed: primary recommendation is “compose from in-stack primitives, no new deps required.” |
0.9-context.md §7.5 “3rd-party tool TBD” | The framing is partially obsolete — the third-party tools (react-pdf, mammoth, docx, Tiptap, exceljs) are already in stack. Update §7.5 to note “Composed from in-stack primitives per finding 06; docx-preview provisional if fidelity gap surfaces.” |
8. Open questions / follow-ups
Section titled “8. Open questions / follow-ups”| Q | For |
|---|---|
| OQ-CX33-A | Does cocoindex re-extract content_items on user-initiated edit-back through the explorer? — gates on WP3 ledger query pattern (0.9-edit-flow-investigation.md §6.1 Q3 / Q4 carry-forward). |
| OQ-CX33-B | DOCX write-back canonical: markdown-sidecar (v1 recommendation) vs full DOCX regen via docx 9.6 (v1.1 candidate) — confirm against Wave 1B-2 Q&A write-back outcome. |
| OQ-CX33-C | Does the explorer page need a “preview only” affordance for non-editor users (per 0.9-edit-flow-investigation.md §6.0.4 role matrix), or does the existing readOnly toggle on ContentEditor cover it? Confirm with role-matrix walkthrough. |
| OQ-CX33-D | XLSX explorer affordance — render a placeholder CTA in v1, or hide the explorer entirely for XLSX MIME until Wave 1B-3 lands? Recommendation: render a CTA so the user isn’t blocked from seeing the source row exists. |
| OQ-CX33-E | If source_documents retires under finding 01 Option β, what becomes the canonical “show me all extractions from this one upload” query the explorer needs? Cocoindex ops-DB query? Wave 1B-2’s q_a_extractions join? Resolve before implementation. |
| OQ-CX33-F | docx-preview add-or-defer trigger — define what “critical fidelity loss” means concretely (specific corpus examples from docs/client-documentation-base/binary/) so the decision isn’t perpetually deferred. |
| OQ-CX33-G | Annotation / highlight overlay on PDF preview — out of scope for v1 per §3.7 discount of Adobe PDF Embed API, but reconfirm against any sector-intelligence read-mode requirements that may surface. |
End of finding 06.