ID-135 {135.1} RESEARCH — OKF human search/browse + source_document provenance UI (reuse-or-rebuild reconciliation)
ID-135 {135.1} RESEARCH — OKF human search/browse + source_document provenance UI
Section titled “ID-135 {135.1} RESEARCH — OKF human search/browse + source_document provenance UI”Status: RESEARCH artefact — not self-ratified. Authored 28/06/2026, fresh Planner dispatch (Q-PLANNER-2). British English throughout; dates DD/MM/YYYY.
Task: ID-135 — two net-new human-facing UI surfaces over the OKF L-records model. Surface A (was bl-386): human search/browse/filter over
q_a_pairs+source_documents, filling the gap left by the deleted IMS browse/item UI. Surface B (was bl-387):source_documentdetail/provenance viewer — version chain, citations, and whichq_a_pairsderive from each document.The load-bearing job of {135.1} (owner note, S429): bl-386/387 were authored possibly unaware of id-117 and the id-110/111/118 reference-item UI/UX work. This RESEARCH gives an explicit reuse-or-rebuild verdict per surface against each of id-110/111/117/118, with the concrete component/route/hook each verdict maps to. HARD RULE honoured: no net-new component is proposed without first checking the reference-item / diff-surface equivalent and stating why it cannot be reused/extended.
1. Context
Section titled “1. Context”1.1 Code-intelligence orientation (cited verbatim, not paraphrased)
Section titled “1.1 Code-intelligence orientation (cited verbatim, not paraphrased)”Tools run against the indexed main repo /Users/liamj/Documents/development/canonical
(the repo: 'canonical' name was ambiguous — two registered repos match; the absolute path
disambiguates). On-disk existence re-verified in the id-135 worktree at HEAD
3a222eac feat(id-131 {131.9}): G-SD-COLS M3 classification cols.
gitnexus_query({query: 'reference item browse detail search list page'})→ top processesproc_155_referencedetailpage(ReferenceDetailPage → Cn) andproc_160_browsecontent(BrowseContent → UseBrowseFilters). Definitions surfaced the shipped id-111 reference stack:Function:app/reference/reference-content.tsx:ReferenceContent(44–165),Function:app/reference/reference-content.tsx:ReferenceSearchBox(173–225),Function:hooks/reference/use-reference-data.ts:useReferenceData(146–369),Interface:hooks/reference/use-reference-data.ts:ReferenceListPage(62–66),Function:app/reference/[id]/reference-detail-client.tsx:ReferenceDetailError(205–221), plus the query-key factoriesFunction:lib/query/query-keys.ts:browse(20–21) /library(23–24) /list(41–42). The IMS browse stack (app/browse/browse-content.tsx:BrowseContent58–672,hooks/browse/use-browse-data.tsBrowsePage/UseBrowseDataReturn) also surfaced — present but slated for BI-12 deletion (§1.3).gitnexus_query({query: 'source document provenance version chain revision diff viewer'})→ surfaced the shipped id-117 diff stack:Interface:lib/diff/unified-revision.ts:UnifiedRevision(99–147) /:UnifiedDiff(162–167),Function:lib/diff/adapters/source-document-revision.ts:sourceDocumentRevisionToUnified(53–83),Function:components/diff/binary-diff-pane.tsx:BinarySide(112–231),Function:app/documents/[id]/diff/page.tsx:DocumentDiffPage(83–208),Function:components/item-detail/version-history.tsx:VersionHistory(166–473),Function:components/qa/qa-revision-history.tsx:QARevisionHistory(62–140),Function:lib/source-documents/source-document-impact.ts:analyseDocumentImpact(46–146), and the q_a_pair history routeFunction:app/api/q-a-pairs/[id]/history/route.ts:GET(31–92).gitnexus_query({query: 'hybrid search api route web search hook results'})→ top processes are the homepageSearchBar(components/browse/search-bar.tsx:SearchBar39–568) and the MCPlib/mcp/tools/search.ts:registerSearchTools(76–819) /findSimilarItemsImpl(267–383). The human web search surface is the loosely-coupledSearchBar→/api/search→hooks/use-search.tspass-through (§2.3), distinct from the AI MCPfind.gitnexus_context({name: 'useReferenceData'})→hooks/reference/use-reference-data.ts146–369; incoming.calls: exactly ONE —ReferenceContent(app/reference/reference-content.tsx); outgoing accessesisLoading/error; processes: []. The Surface-A reuse base is a single-caller list+search hook.gitnexus_context({name: 'UnifiedDiffContainer'})→components/diff/unified-diff-container.tsx74–105; incoming.calls: exactly ONE —DocumentDiffPage(app/documents/[id]/diff/page.tsx); outgoing.calls:BinaryDiffPane,toRevisionBlob,RevisionDiffView(components/item-detail/revision-diff-view.tsx),deriveRenderMode(lib/diff/unified-revision.ts); processes: []. The Surface-B version/diff reuse base is a single-caller composition over the landed engine.ccc searchfallback: attempted for both greenfield claims (ccc search "source document detail provenance viewer page ..."andccc search "q_a_pair human search browse filter list page"). The cocoindex-code daemon errored in this environment (DaemonStartErrortraceback — same failure id-111’s TECH recorded). The greenfield claims below therefore rest on the definitive gitnexus + on-diskls/findevidence, which is conclusive for the two specific gaps.
1.2 The greenfield gaps (verified absent on disk)
Section titled “1.2 The greenfield gaps (verified absent on disk)”- No human
q_a_pairsearch/browse page.find app -path '*q-a-pairs*' -name page.tsxreturns only admin surfaces (app/admin/q-a-pairs/dedup-proposals/...); the rest ofapp/api/q-a-pairs/*is API/promotion/dedup. There is no reader-facing q_a_pair browse/search/list page. Surface A is genuinely net-new as a page. - No
source_documentdetail/provenance page.app/documents/[id]/contains onlydiff/(page.tsx+error.tsx+loading.tsx) — id-117 shipped the version-compare route but noapp/documents/[id]/page.tsxdetail landing. Surface B is net-new as a page, but composes shipped id-117 pieces (§4).
1.3 The L-records read schema these surfaces read (id-131 PRODUCT/TECH)
Section titled “1.3 The L-records read schema these surfaces read (id-131 PRODUCT/TECH)”q_a_pairs— the answer grain. Carries the hot lifecycle subset inline (publication_status, superseded_by, valid_from, valid_to— BI-20; q_a_search filterspublication_statuson every query),answer_standard/answer_advanced,scope_tag[],source_document_id(nullable provenance — BI-15/BI-33), opaquegen_random_uuid()PK (BI-5),origin_kind(incl. new'manually_authored', BI-33). Question-embedded in EMB-STORE. Primary match grain for Surface A.source_documents— the provenance/citation anchor. NO embedding (BI-29) — never a direct vector-match target. {131.9} (shipped on this HEAD) added the classification family (primary_domain, primary_subtopic, secondary_domain, secondary_subtopic, ai_keywords, summary, classification_confidence, classification_reasoning, classified_at, …— BI-11) plus a M3 domain-sync trigger, so SD now carries the metadata both surfaces render. Identity seedsd:{rel_path}(BI-3);content_hashaudit;version/parent_idversion chain (id-117);storage_path/mime_typefor the binary leg.reference_items— external evidence; flat, workspace-less, write-once,UNIQUE(source_url)(BI-6); no version chain / history (id-117 OQ-117-6 confirmed out). Owned by id-111/id-118; explicitly out of Surface A/B scope as a primary grain (§9 of the design routes reference surfaces elsewhere), but reference results DO appear in the §9 search-ALL default (Surface A renders them as one of three result kinds).record_lifecyclefacet (BI-18/BI-20/BI-22) — cold governance/freshness, polymorphic(owner_kind, owner_id); freshness axis ={source_document}only, review axis ={source_document, q_a_pair}. Surface B may surface SD freshness/review state from here.- EMB-STORE (BI-17) — polymorphic
(owner_kind, owner_id, model)vector store; the substrate Surface A’s search reads through. In flight (§3).S438 {135.19} reconcile: “EMB-STORE” was the design codename; the shipped store is
record_embeddings. Per {131.11} (G-SEARCH, implemented-to-commit oncmux-worker-subo-search-13111),hybrid_searchis a 4-arm polymorphic UNION overrecord_embeddings(source_documenttext-only,content_chunk→SD collapse+dedup,q_a_pair×1.1 profile,reference_item) — see §1.4. - Citations (BI-23 CITE-EXT) —
cited_target_kindextended to{content_item→removed, q_a_pair, reference_item, source_document, concept}; Surface B’s “citations” panel reads these. In flight (§3).
1.4 The {131.20} §9 ratified search/sourcing contract (target Surface A designs against)
Section titled “1.4 The {131.20} §9 ratified search/sourcing contract (target Surface A designs against)”The owner-ratified ({131.20} §9, S428) search redesign that {131.11} G-SEARCH implements — the target contract Surface A’s behaviour must assume (not the legacy content_items path):
- Default scope = ALL owner_kinds (
q_a_pair+content_chunk→source_document+reference_item), retrieved per-grain, normalised, then merged — NOT a flat 4-way cosine UNION, and NOT scope-narrowed to q_a_pairs. - Answer-first is a bounded boost (~×1.1), applied after per-grain normalisation, living
in a named ranking PROFILE selected by
application_type(derived fromworkspace_id). One profile ships now (answer-first default; procurement is q_a_pair-primary — sales-proposals/sector-intelligence profiles are later config). content_chunkhits collapse up to theirsource_documentfor result identity + citation (one underlying fact → one hit; de-dup by provenance). SD is reached via chunks, never embedded directly.- Result
content_typefield now carriesowner_kind/record-kind (BI-27 semantic change, owner-approved §7.3) so the two-step preview→fetch resolves a polymorphic id. type/scopeparam NARROWS only (type=q_a_pair= prior-answer match + forms path).find_related_items+filter_by_keywordsare DROPPED (§9 §7.4/§7.5). Related-records and a keyword facet are future backlog, co-designed with these surfaces — so a “related records” affordance and a keyword pre-filter are explicitly NOT Surface A v1 features (they are flagged here as the co-design seam).
1.5 Reuse-prohibited: the IMS browse/item stack (id-131 BI-12)
Section titled “1.5 Reuse-prohibited: the IMS browse/item stack (id-131 BI-12)”On this HEAD ({131.9}) the legacy IMS stack is still present (components/content/*:
content-card.tsx, content-grid.tsx, content-list.tsx, …; app/browse/, app/item/,
app/library/) because id-131 sequences drops last and {131.11}+ are in flight. id-131
BI-12 / design §6 delete this stack (it binds dropped IMS columns). Therefore it is
reuse-PROHIBITED for Surfaces A/B — Surface A exists precisely to replace the eliminated IMS
/browse. The reuse base is the id-111 reference stack + the id-117 diff stack, never
the IMS content stack. (/library is the one exception — BI-33 repoints it to q_a_pairs
inside id-131; its relationship to Surface A is the single biggest reuse question — §6, OQ-1.)
S438 {135.19} reconcile (D7): the BI-33
/library→q_a_pairsrepoint was DEFERRED out of id-131 (at the {131.2} ratification) to the id-71 AI-tooling family ({71.16}/ID-59/ID-69);/librarystill readscontent_itemstoday. Surface A’s/librarylink target is therefore not an id-131 guarantee — it is an open owner decision (NO-1); see OQ-1 and the §6 handoff.
2. Per-surface reuse-or-rebuild verdict matrix
Section titled “2. Per-surface reuse-or-rebuild verdict matrix”Each cell: {reuse as-is | extend | rebuild | n/a} + mapped artefact + one-line justification. “n/a” = the effort is not a UI analogue for that surface (orthogonal), recorded so the HARD RULE check is explicit, not skipped.
S438 {135.19} reconcile (DR-013): the “EXTEND / HARD RULE” reuse framing below is superseded. Per DR-013 the id-135 surfaces are net-new-by-design: Surface A reuses the id-111 stack only at the leaf/pattern level (its single-grain, non-paginated
useReferenceDataforces the polymorphic abstraction), and Surface B reuses id-117’s version-chain data leg only (RPC +/versionsroute + diff link-out) — NOTUnifiedDiffContainer. Read the verdict cells below as reuse evidence, not as an extend-in-place mandate.
Surface A — human search/browse/filter over q_a_pairs + source_documents
Section titled “Surface A — human search/browse/filter over q_a_pairs + source_documents”| vs | Verdict | Maps to | Justification |
|---|---|---|---|
| id-110 (url_import→reference_items, backend re-point) | n/a (no UI reuse) | — (backend write-path; IngestionSuccessCard only) | id-110 is a backend re-point + a success-card link; it ships no browse/search UI. Only carry is the evidence-vs-knowledge framing, irrelevant to a read surface. |
| id-111 (reference browse/detail UI) | EXTEND | app/reference/reference-content.tsx (ReferenceContent, ReferenceSearchBox), hooks/reference/use-reference-data.ts (useReferenceData, ReferenceListPage), lib/query/query-keys.ts (list/browse factories) | Closest analogue. Page shell, search box, list/card, empty/loading/error states, reduced-filter UX (domain/subtopic/date), URL-driven search state, infinite-list pattern are directly reusable. But grain differs: id-111 is single-RPC reference-scoped (reference_list/reference_search, one ReferenceListItem shape); Surface A is polymorphic multi-grain over the §9 search-ALL contract (per-grain normalise + merge + answer-first profile, result card rendered per owner_kind). So copy-and-generalise the shell/hook/card to a polymorphic result type — EXTEND, not reuse-as-is. |
| id-117 (diff/version surface) | n/a (orthogonal) | — | Search/browse has no diff/version need. id-117 reuse is Surface B’s. |
| id-118 (reference nav + corpus IA) | EXTEND | components/shell/site-header.tsx NAV_LINKS, components/shell/command-palette.tsx; id-118’s option-B “Knowledge Base” corpus grouping | Surface A is a new corpus-layer surface replacing the eliminated IMS /browse. Its nav slot must be co-decided under the same corpus-vs-application IA decision id-118 frames (don’t ship a divergent nav). Reuse id-118’s placement/role-uniform/active-state machinery. |
Surface B — source_document detail/provenance viewer (version chain + citations + derived q_a_pairs)
Section titled “Surface B — source_document detail/provenance viewer (version chain + citations + derived q_a_pairs)”| vs | Verdict | Maps to | Justification |
|---|---|---|---|
| id-110 (url_import provenance pair) | reuse as-is (field set, no component) | id-111 detail-page B-28 SD-join (tryQuery over source_documents.select('original_filename, filename, mime_type, extraction_method, source_url, created_at'), plain-language extraction_method) | id-110 lands the sd+ri provenance pair; the SD provenance field set + plain-language rendering id-111 already built (B-28) is the direct template for Surface B’s provenance panel. Reuse the field set + rendering verbatim; no new component. |
| id-111 (reference detail page) | EXTEND | app/reference/[id]/reference-detail-client.tsx + app/reference/[id]/page.tsx (read-only detail shell: notFound(), loading/error, markdown body, metadata badges, provenance affordance) | The reference detail page shape is the template for the SD detail page shell. But SD is richer: it is the provenance anchor itself, with a version chain (id-117), citations (BI-23), and derived q_a_pairs — features a flat reference lacks. So EXTEND the id-111 detail shell with the version/citation/derived-pairs sections. |
| id-117 (unified diff/version surface) | REUSE-AS-IS (version/diff leg) + EXTEND (add detail page) | components/diff/unified-diff-container.tsx (UnifiedDiffContainer), lib/diff/adapters/source-document-revision.ts (sourceDocumentRevisionToUnified), app/api/source-documents/[id]/versions/route.ts (get_document_version_chain RPC), app/documents/[id]/diff/page.tsx, app/api/source-documents/[id]/send-to-review/route.ts | Material overlap — the load-bearing reuse. The SD version chain + diff Surface B needs is already shipped by id-117 (version-chain RPC + route + UnifiedDiffContainer + SD adapter + re-ingest review). REUSE-AS-IS: the SD detail page links to / embeds the existing /documents/[id]/diff and renders the version list from get_document_version_chain. EXTEND: id-117 deliberately built no app/documents/[id]/page.tsx detail landing — Surface B ADDS that missing sibling page in the same route tree. HARD RULE: do NOT build a net-new version-diff component — UnifiedDiffContainer is reused. |
| id-118 (corpus IA) | EXTEND | app/documents/[id] route tree; site-header (no own nav slot) | id-118 frames /documents as a homeless corpus route. Surface B (/documents/[id]) is a detail destination reachable from Surface A’s SD search results, not a top-nav entry. Fold its IA into id-118’s corpus grouping; no standalone nav link. |
HARD-RULE audit (net-new components proposed): Surface A’s polymorphic result card +
generalised list/search hook is the only genuinely net-new component — and it is an EXTEND
of useReferenceData + ReferenceContent’s ReferenceListItem card, justified by the
single-RPC→multi-grain grain change (§9). Surface B’s SD detail page is net-new as a
page but composes id-111’s detail shell + id-117’s UnifiedDiffContainer/version chain +
id-111’s B-28 provenance field set — no net-new version/diff/detail-shell component.
3. Read-contract dependency list (shipped vs in-flight → OQ)
Section titled “3. Read-contract dependency list (shipped vs in-flight → OQ)”The id-131 search/API waves ({131.11} G-SEARCH / {131.19}) are still in flight. Surface A must design against the §9 target contract; anything {131.11}+ has not shipped is an OQ, never assumed present.
Surface A reads
Section titled “Surface A reads”| Read-contract | State | Note |
|---|---|---|
§9 polymorphic hybrid_search (per-grain normalise + merge, content_chunk→SD collapse, owner_kind in result) | IN FLIGHT ({131.11}) → OQ-2 | The whole Surface-A result model depends on this; design against §9 target, do not assume shipped. |
Typed polymorphic /api/search web result shape (replacing SearchResult extends ContentListItem, types/content.ts:135) | IN FLIGHT ({131.11} AC4) → OQ-3 | Today hooks/use-search.ts POSTs /api/search → {results, count} typed as content_items SearchResult. {131.11} must hand the web path a typed polymorphic shape; Surface A consumes that, not the legacy one. |
Per-application_type ranking profile (one shipped; answer-first default) | IN FLIGHT (§9) → OQ-4 | workspace_id→application_type threading into /api/search (§9 AC4). Surface A renders results under the one shipped profile. |
| EMB-STORE (BI-17) | IN FLIGHT ({131.11}) → OQ-2 | The retrieval substrate; gated before any RPC rewrite (id-131 AC11). |
q_a_pairs.publication_status (hot, inline) | SHIPPED (BI-20) | Surface A filters published pairs. |
source_documents classification cols (primary_domain, summary, …) | SHIPPED on this HEAD ({131.9}) | SD result cards + the SD detail page can render these now. |
record_lifecycle facet (SD freshness/review) | IN FLIGHT (id-131 F-cluster) | Optional for Surface A v1 (search need not show governance). |
Surface B reads
Section titled “Surface B reads”| Read-contract | State | Note |
|---|---|---|
get_document_version_chain RPC + app/api/source-documents/[id]/versions route | SHIPPED (id-117) | Version chain reuse is ready. |
UnifiedDiffContainer / source-document-revision adapter / /documents/[id]/diff | SHIPPED (id-117) | Diff leg reuse ready. |
app/api/source-documents/[id] GET (SD row + linked records) | SHIPPED but BREAKS → OQ-5 | The route currently joins content_items (select('id,title,content_type,...').eq('source_document_id', id)). id-131 BI-9 eliminates content_items — this read must re-point to q_a_pairs (the “derived pairs” the SD detail page renders). This is a dependency + a defect-in-waiting, not an assumption. |
Citations contract (BI-23 CITE-EXT: cited_target_kind incl. source_document, q_a_pair) | IN FLIGHT (id-131 G-cluster, atomic w/ WINRATE-FIX) → OQ-6 | Surface B’s “citations” panel reads these; citations is 0 rows today, so design against the extended contract, not the dormant one. |
”Which q_a_pairs derive from this SD” = q_a_pairs.source_document_id | SHIPPED (schema) | Filterable now; the route exposing it is OQ-5’s re-point. |
4. IA / nav placement findings (id-118 precedent)
Section titled “4. IA / nav placement findings (id-118 precedent)”- Current
NAV_LINKS(components/shell/site-header.tsx):/browse,/library,/coverage,/workspaces,/change-reports,/intelligence,/review,/settings. No/referenceentry — confirming id-118 (surface reference nav) is spec_needed / unbuilt (bun scripts/ledger-cli.ts show task 118:status: "spec_needed", dep[111]). - id-118 settled context (from its ledger record): standalone corpus surfaces are the ratified design (ID-75 BI-16 two-surface principle); References = corpus layer, peer to Browse + Q&A Library, not inside any application. Open decision (Liam): (A) top-level corpus nav entry now [recommended] → (B) “Knowledge Base” group collapsing Browse+Library+References [best long-term] → (C) contextual-only.
- Consequence for id-135: post-id-131 the corpus-nav set is reshaped —
/browse(IMS content_items) is eliminated (BI-12),/libraryis repointed toq_a_pairs(BI-33),/referenceis the id-111 surface (id-118 to surface). Surface A is the replacement for the eliminated/browse(cross-grain search/browse) and Surface B (/documents/[id]) is a detail destination, reachable from Surface A’s SD results, with no own nav slot. Recommendation: id-135’s nav placement must be co-decided with id-118, not shipped divergently — Surface A becomes the corpus search/browse entry (under id-118’s option-B “Knowledge Base” grouping), Surface B inherits the corpus IA without a top-nav link. (id-118’s own scope already flags/documentsas a homeless corpus route.)
5. Open Questions (numbered)
Section titled “5. Open Questions (numbered)”- Surface A vs the BI-33
/libraryq_a_pair viewer (the biggest reuse question). After id-131 BI-33,/library(app/library/library-content.tsx— a TanStack-virtualised list with search/filter/tag) becomes the q_a_pair viewer/editor. Surface A is a cross-grain search/browse. Are these one surface or two? Is Surface A a mode of the repointed/library, or a distinct corpus-search surface that links into/libraryfor single-pair read/edit? This materially shapes the whole of Surface A and overlaps two Tasks. PRODUCT must decide; may need Orchestrator Task-boundary input.S438 {135.19} reconcile (D7): the
/library→q_a_pairsrepoint this OQ assumes lands “inside id-131” was DEFERRED out of id-131 to the id-71 family ({71.16}/ID-59/ID-69) at {131.2};/librarystill readscontent_items. Surface A’s answer-result deep-link target is an open owner decision (NO-1) — not an id-131 deliverable. - Polymorphic
hybrid_search/ EMB-STORE result contract (§9) is in flight ({131.11}). Surface A cannot finalise its result model until the typed polymorphic result shape + owner_kind field + per-grain merge are shipped. Design against §9 target; flag the dependency on {131.11}/{131.19}. - Typed polymorphic
/api/searchweb shape. TheSearchResult extends ContentListItemcoupling (types/content.ts:135, consumed byhooks/use-search.ts) breaks under id-131. Surface A depends on {131.11} AC4 delivering the replacement typed shape — confirm its fields before Surface A’s card/hook are specified. - Ranking profile exposure. Does Surface A surface any profile/scope control to the
user (e.g. a “documents only” / “answers only”
typenarrow), or is the one shipped answer-first profile entirely implicit (AI-invisible-infrastructure)? §9 saystypenarrows only; the UX affordance is undecided. - SD detail route’s
content_itemsjoin breaks (OQ-5 above).app/api/source-documents/[id]/route.tsjoinscontent_items; id-131 eliminates that table. Surface B’s “derived records” panel must readq_a_pairsviasource_document_id. Is re-pointing this route an id-135 deliverable, or does it belong to id-131’s content_items-elimination sweep? Boundary question for the Orchestrator. - Citations panel contract. BI-23 CITE-EXT (extended
cited_target_kind) lands as one atomic slice in id-131 andcitationsis 0 rows today. Confirm the shipped contract shape before Surface B’s citations panel is specified; until then it is design-against-target. - Related-records + keyword facet are §9-DROPPED / future backlog. §9 §7.4/§7.5 drop
find_related_itemsandfilter_by_keywordsand route related-records (ontology-grounded)- a keyword facet param to future backlog co-designed with these surfaces. Confirm both are out of Surface A/B v1 (recommended) — they are the named co-design seam, not v1 features.
- Reference grain in Surface A’s results. §9 default scope includes
reference_itemresults, but reference surfaces are owned by id-111/id-118. Does Surface A render reference hits inline (as one of three result kinds, linking out to/reference/[id]), or exclude them? Recommended: render inline + link out (the §9 search-ALL intent), reusing id-111’s reference card. - Provenance depth on Surface B. id-111 B-28 surfaces SD
original_filename/extraction_method/ landed date. Surface B is the SD itself — does it additionally surfacerecord_lifecyclefreshness/review state,content_hashaudit, and the full version chain inline, or link out to/documents/[id]/difffor the chain? Recommended: inline version list + link-out to the diff route for pairwise compare. /documents/[id]/diffownership boundary. id-117 owns the diff route; Surface B adds the sibling/documents/[id]detail page and links to it. Confirm id-135 may add to the id-117 route tree (it should — same surface family) vs. coordinating a shared seam.
6. What PRODUCT ({135.2}) must decide — handoff list
Section titled “6. What PRODUCT ({135.2}) must decide — handoff list”- Resolve OQ-1 first — Surface A vs the BI-33
/libraryviewer: one surface or two. Everything else in Surface A’s scope follows from this. (May need an Orchestrator Task-boundary call before {135.2} proceeds.)S438 {135.19} reconcile (D7): the BI-33
/libraryq_a_pair viewer repoint is deferred out of id-131 (to the id-71 family); do not treat the/libraryanswer-link destination as an id-131 guarantee — it needs an owner decision (NO-1). - Fix the spec tier per surface. Surface A is behaviourally ambiguous (search ranking,
filters, polymorphic results, in-flight dependencies) → full PRODUCT + likely TECH.
Surface B is largely a composition of shipped id-111/id-117 pieces + one new page → PRODUCT
- a thin TECH for the OQ-5 route re-point and the version/citation embedding.
- Lock the reuse verdicts (§2) as the implementation spine: Surface A EXTENDs the id-111
reference stack (shell +
useReferenceData+ card → polymorphic); Surface B EXTENDs the id-111 detail shell + REUSEs id-117’sUnifiedDiffContainer/version chain + reuses id-111’s B-28 provenance field set. No net-new browse/detail/diff component. - State every in-flight dependency as an explicit assumption-against-target (OQ-2/3/4/6), not a present fact — Surface A’s behaviour invariants must reference the §9 contract, and the Checker must be able to see which reads are gated on {131.11}/{131.19}.
- Decide the §9-dropped affordances out (OQ-7): no related-records, no keyword pre-filter in v1; record them as the co-design backlog seam.
- Co-decide nav/IA with id-118 (§4): Surface A as the corpus search/browse entry under the “Knowledge Base” grouping; Surface B as a detail destination with no own nav slot.
- Carry the quality bars into every invariant: semantic Warm Meridian tokens only, UK
English, DD/MM/YYYY,
getAuthorisedClient()+authFailureResponse(auth),sb()/tryQuery(), TanStack Query only, no barrel re-exports,bun run test, behaviour-first tests. Both surfaces are read-only, authenticated, role-uniform (inherit id-111 B-21) and AI-invisible-infrastructure (no “AI search” chrome, no raw scores).
7. Empirical verification (OQ-3 / Q-EX2 scope)
Section titled “7. Empirical verification (OQ-3 / Q-EX2 scope)”This RESEARCH cites no external-library symbols. Every symbol referenced is internal
Canonical (useReferenceData, ReferenceContent, ReferenceSearchBox,
UnifiedDiffContainer, sourceDocumentRevisionToUnified, the reference/version-chain RPCs,
hybrid_search), Postgres/Supabase RPC surface (get_document_version_chain,
.from().select(), .rpc()), or Next.js/TanStack framework (notFound, useQuery,
useInfiniteQuery) — all out of the import-and-call verification scope (external-library
symbols only, per shared-discipline §Empirical verification). No verification block
required. The one runtime contract that will drift is the §9 polymorphic search shape and
the OQ-5 content_items route join — both carried as explicit OQs gated on {131.11}, not as
unverified assumptions.
End of {135.1} RESEARCH. Reuse-or-rebuild verdict given per surface against id-110/111/117/118 with mapped artefacts; read-contract dependencies split shipped/in-flight; IA folded into id-118; 10 OQs + a PRODUCT handoff list. No implementation, no DDL, no ledger writes, no commits.