ID-118 {118.1} RESEARCH — Product-wide IA map + ratifiable nav proposal (S454)
ID-118 {118.1} RESEARCH — Product-wide information architecture
Section titled “ID-118 {118.1} RESEARCH — Product-wide information architecture”Kind: RESEARCH ({118.1}) — feeds {118.2} PRODUCT, {118.3} TECH, {118.4} PLAN, and gates id-135 {135.10}.
Authored: 08/07/2026 · Task Planner (fresh dispatch, S454 owner reframe).
Status: DRAFT — not committed; owner reviews, ratifies labels + option, then parent commits.
Reframe provenance: S454 owner steer superseding the original “pick placement A/B/C” ask
(bun scripts/ledger-cli.ts get task 118.1). Owner chose “Option B in principle” (grouped nav)
but ruled that nav/label choices must first be grounded in a product-wide investigation of
how the platform fits together. This document IS that investigation.
Empirical-verification note. This spec cites internal Canonical routes/components and ratified docs only — no external-library symbols. The pre-ratification import-and-call check (
shared-discipline.md§Empirical verification) is therefore N/A for this artefact.
0. Code-intelligence orientation (verbatim)
Section titled “0. Code-intelligence orientation (verbatim)”Per the Planner code-intel binding rule. GitNexus was reachable (bl-422 intermittent, up at authoring time); outputs cited verbatim, cross-checked with direct file reads.
gitnexus_query({query: 'site header navigation links nav menu top-level routes', repo: 'canonical'})→ the single navigation definition isFunction:components/shell/site-header.tsx:SiteHeader(startLine 68, endLine 230, moduleUi). Test harness reads it viaFunction:e2e/helpers/responsive.ts:getVisibleNavLinks(125–141) andnavigateViaHeader(30–48). OKF bundle nav is a separate surface:Function:lib/okf/parse-index.ts:parseBundleNav(55–103) +Interface:…:BundleNavTheme. Settings sub-nav isFunction:components/settings/settings-sidebar.tsx:SidebarNav(163–220).- Direct reads confirm three independently-authored top-level navigation surfaces that must
move in lockstep:
components/shell/site-header.tsx(NAV_LINKS, desktop + mobile drawer), andcomponents/shell/command-palette.tsx(Cmd+KCommand.Group heading="Navigation", mounted inapp/layout.tsx). The global headerSearchBar(components/browse/search-bar.tsx) is a fourth, content-search, discovery surface.
Load-bearing finding: nav is a hardcoded NAV_LINKS array plus a hand-duplicated command-palette
list — there is no shared nav registry. Any IA change is a coordinated edit across three files,
and the command palette is already the most drifted of the three (see §1.3).
1. Current-state inventory
Section titled “1. Current-state inventory”1.1 What is navigable today (components/shell/site-header.tsx NAV_LINKS, lines 33–67)
Section titled “1.1 What is navigable today (components/shell/site-header.tsx NAV_LINKS, lines 33–67)”| Order | Route | Current label | requiresEdit | Icon | Conceptual home |
|---|---|---|---|---|---|
| logo | / | (brand logo) | — | BrandLogo | Home dashboard |
| 1 | /library | Q&A Library | false | Library | Corpus (q_a_pairs) |
| 2 | /coverage | Coverage | true | BarChart3 | Governance |
| 3 | /workspaces | Workspaces | false | Briefcase | Application launcher (legacy-shaped) |
| 4 | /change-reports | Change Reports | false | FileBarChart | Governance |
| 5 | /intelligence | Intelligence | true | Newspaper | Application (intelligence) |
| 6 | /review | Review | true | ShieldCheck | Governance |
| icon | /settings | Settings | — | Settings | Admin |
Plus a persistent header SearchBar (content search) and, in the mobile drawer, an explicit Home
link. Role-gating today: requiresEdit && !canEdit → link hidden (lines 100–101, 179–180).
1.2 Homeless routes — user-facing pages reachable only by deep-link or contextual link
Section titled “1.2 Homeless routes — user-facing pages reachable only by deep-link or contextual link”Enumerated from find app -name page.tsx, cross-checked against NAV_LINKS:
| Route | What it is | Conceptual home | Why homeless / status |
|---|---|---|---|
/search (net-new) | Surface A corpus search over the whole KB (answers + documents + references), answer-first boost | Corpus | id-135, being built now; nav entry is {135.10}, explicitly id-118-coupled and pending THIS decision (TECH BI-21) |
/reference, /reference/[id] | References — external evidence ingested from URL/RSS, “External evidence imported from URLs and RSS feeds” (app/reference/reference-content.tsx:74) | Corpus (reference_items, L-records) | id-111 shipped read-only + role-uniform (B-21); B-22 deliberately kept it OUT of nav pending id-118 |
/documents/[id], /documents/[id]/diff | Surface B source_document provenance/version/diff viewer | Corpus (source_documents, L-records) | id-135 — deliberately no top-level nav (PRODUCT §4, “no top-level navigation slot of its own”); contextual-only, linked from Surface A + citations |
/procurement, /procurement/[id], …/session, …/templates | Procurement application home + RFP instance surfaces | Application (procurement) | Reached today only via /workspaces or command palette (“Bids”); never a first-class nav entry |
/okf/[bundleId] | OKF bundle viewer — the L-concepts map (lib/okf/parse-index.ts:parseBundleNav) | Corpus (L-concepts, DR-025) | id-132; [bundleId]-scoped, no index/landing route; the “human-editable surface” candidate the owner named |
/guide, /guide/[slug] | Guides (reading paths / product guides) | Application seat (product_guide) or help | Managed via Settings › Guides; no reader nav entry |
/provenance | Provenance admin/audit tabs (model-name carve-out per AI-visibility policy) | Governance (admin) | Admin-only; reached via command palette (“Provenance › Audit”, canAdmin) |
/activity | Activity log/feed (audit) | Governance | Homeless; overlaps the home-dashboard activity feed |
/admin/q-a-pairs/dedup-proposals, /admin/refinement | Admin dedup/refinement tools | Admin | Deep-link only |
/item/new, /item/new/batch | Content-item creation | Legacy/IMS | content_items eliminated (id-131 BI-12); candidate for retirement — flag, do not adopt into IA |
Auth chrome (not user content, correctly out of nav): /login, /auth/callback, /oauth/consent,
/.well-known/*, /coverage API-only siblings.
1.3 The command palette is separately drifted (components/shell/command-palette.tsx)
Section titled “1.3 The command palette is separately drifted (components/shell/command-palette.tsx)”Its “Navigation” group lists: Home, Review, Workspaces, Bids (→ /procurement, stale label —
bid is a form_type, not an application, per DR-038 + 01-vision §4.4), Change Reports, Settings,
and (admin) a Settings/Provenance fan-out. It has no Search, no References, no Q&A/Answers, no
Intelligence, no Coverage. So the three nav surfaces already disagree with each other — the IA change
is also a de-drift of the command palette.
2. Planned-state inventory (what the IA must accommodate)
Section titled “2. Planned-state inventory (what the IA must accommodate)”Sourced from 01-vision.md, platform-direction.md, deployment-architecture.md, and the ledger.
2.1 Applications on the horizon (01-vision.md §4.2; platform-direction.md core-entity glossary)
Section titled “2.1 Applications on the horizon (01-vision.md §4.2; platform-direction.md core-entity glossary)”Six core application_types are schema-seated in v1:
| application_type | Status | Nav implication |
|---|---|---|
| procurement | Live (first application) | First-class application entry now |
| intelligence | In-flight (second application) | First-class application entry now |
| sales_proposal | Next-after-procurement (planned) | Appears when it comes online |
| product_guide | Baseline seat (planned) | /guide reader is the likely surface |
| competitor_research | Baseline seat (planned) | Appears when online |
| training_onboarding | Baseline seat (planned) | Appears when online |
The owner also names Research as an incoming application (references feed it). Whether “Research”
is competitor_research re-labelled or a new core row is an owner/product call (OQ-A, §7).
Containment (verbatim, platform-direction.md:56): tenant (one DB per client) ⊃ multiple
applications per client (application_type) ⊃ workspaces (multiple per application_type) ⊃ forms ⊃
form_responses; q_a_pairs are corpus-level (one client’s shared corpus), not workspace-partitioned.
The IA’s top axis must therefore be application, not workspace.
2.2 Corpus / knowledge surfaces (the shared canonical layer — deployment-architecture.md §3, DR-025)
Section titled “2.2 Corpus / knowledge surfaces (the shared canonical layer — deployment-architecture.md §3, DR-025)”The canonical layer is client DB (records) + OKF bundle (concepts) (DR-025). Its human surfaces:
| Surface | Backs | Layer | Status |
|---|---|---|---|
Search (/search, Surface A) | polymorphic search over q_a_pairs + content_chunk→SD collapse + reference_items | L-records | id-135, in build; nav = {135.10} (this decision) |
Answers (/library) | q_a_pairs (corpus-level reusable knowledge) | L-records | Live, but still reads content_items; the q_a_pair-viewer repoint (id-131 BI-33) is DEFERRED to the id-71 family / ID-59 / ID-69; deep-link target is owner-open NO-1 (id-135 {135.19}) |
References/Sources (/reference) | reference_items (external content: URL import + RSS) | L-records | id-111, shipped read-only + role-uniform |
Documents (/documents/[id], Surface B) | source_documents (provenance/versions/citations) | L-records | id-135, in build; contextual-only by design |
Concepts (/okf/[bundleId]) | OKF bundle (L-concepts) — the map agents traverse | L-concepts | id-132; human-editable review UI is a follow-on (DR-013 shape) |
2.3 Governance surfaces (01-vision.md §3.2 — the web UI is the governance/curation/visualisation tier)
Section titled “2.3 Governance surfaces (01-vision.md §3.2 — the web UI is the governance/curation/visualisation tier)”Review (/review), Coverage (/coverage — DR-034 retired the content_items-era coverage; only
template-completion + governance coverage survive), Change Reports (/change-reports), Provenance
(/provenance, admin), Activity (/activity).
2.4 AI tooling surface (id-71)
Section titled “2.4 AI tooling surface (id-71)”id-71 rationalises the AI-consumption layer (MCP tools/resources/prompts/plugins/skills/apps).
Per 01-vision.md §1.3 + §2.5, AI is invisible plumbing — it is NOT a human nav destination.
The only human-visible AI touchpoint is Claude as a destination (“Open in Claude”). Implication
for the IA: there is no “AI” nav group. MCP setup lives under Settings › Integrations (already so).
3. Terminology map — IMS-era terms → what each actually is → proposed label
Section titled “3. Terminology map — IMS-era terms → what each actually is → proposed label”The current nav config predates S246 (application abstraction), DR-025 (corpus reframe), and DR-038 (workspace ruling). Each stale term below is mapped to its post-ruling reality and a proposed user-facing label. Labels are proposals; the owner ratifies (label choice is owner-reserved).
| IMS-era term | What it ACTUALLY is now | Ruling | Owner’s stance | Proposed label(s) |
|---|---|---|---|---|
| Browse (verb) | The corpus Search surface (Surface A, /search) over the whole KB | id-135 TECH BI-7 (route /search, “search-first”) | Rejected (“verb, IMS-repo + content_item hangover”) | “Search” (primary) · “Explore” (alt) |
| Workspace | NOT a tenant. An application-specific instance/activity — e.g. an RFP being worked on within Procurement. Structured data scopes to the ACTIVITY, not a *_workspaces table | DR-038 (activity-carried ids); platform-direction.md:52 (workspace ≠ client) | Named as a “conflation and hangover from IMS” | Retire generic top-level “Workspaces”; surface instances inside each application (e.g. Procurement’s instances are its bids/RFPs). Group label if a launcher is kept: “Applications” |
| References | reference_items — external content ingested (URL/RSS) to expand sector-specific knowledge; consumed by Intelligence now, Research later | id-111 B-11..B-22; DR-025 (sources are evidence; authority earned at promotion) | Rejected (“would make no sense to a user”) | “Sources” (primary) · “External sources” (safe) · “Reading” (alt) — OQ-B, owner ratifies |
| Evidence | DR-025 internal term for raw source bytes flowing through the sieve (before promotion) | DR-025 | Rejected (“would make no sense to a user”) | Not user-facing at all — it is a backend concept; users see promoted/authoritative records, never “evidence” |
| Q&A Library | q_a_pairs — corpus-level reusable answers | 01-vision §2.2(1); platform-direction.md:54 | (not flagged) | “Answers” (primary) · “Q&A” (alt) — reframes the store as the thing a user wants (an answer) |
| OKF bundle / concepts | L-concepts — the distilled concept map agents traverse; the human-editable surface candidate | DR-025; DR-016/DR-013 | Named as needing “a human-editable surface" | "Concepts” (primary) · “Knowledge map” (alt) |
Bids (command-palette → /procurement) | The Procurement application; “bid” is one form_type within it | 01-vision §4.4; DR-038 | (rename already ratified) | “Procurement” |
Unifying frame the owner is reaching for: references, answers, documents and concepts are not four unrelated things — they are the four human-facing faces of one client’s shared corpus (the canonical layer). That is the natural grouping, and it is the platform’s own architecture, not a UI invention.
4. IA options
Section titled “4. IA options”All three options assume the load-bearing constraint from §0: whatever ships must be applied in
lockstep across site-header.tsx (desktop + mobile) and command-palette.tsx.
Design axis (shared by all options)
Section titled “Design axis (shared by all options)”The platform’s own architecture yields three functional zones (01-vision §1, §3.2; DR-025):
- Applications — where domain work happens (consume the corpus).
- Knowledge — the shared corpus / canonical layer (records + concepts).
- Governance — curate, review, audit the corpus (the web UI’s stated job).
Plus utilities: Home, global Search, Settings.
Option 1 — Zone-grouped nav (RECOMMENDED)
Section titled “Option 1 — Zone-grouped nav (RECOMMENDED)”Three grouped menus mirroring the architecture, degrading gracefully as applications multiply:
[Logo/Home] Search Applications ▾ Knowledge ▾ Governance ▾ [Search box] [Settings] [Theme] [Sign out] ├ Procurement ├ Search ├ Review ├ Intelligence ├ Answers ├ Coverage └ (future apps) ├ Sources ├ Change reports └ Concepts ├ Activity └ Provenance (admin)- Knowledge group = the corpus faces (Search, Answers, Sources, Concepts). Read-only, role-uniform.
- Applications group = live application_types (Procurement, Intelligence); new rows appear here as they come online — the group is the extensibility seam DR-038 + 01-vision §4.3 demand.
- Governance group = the web UI’s curation/audit tier; entries keep today’s
requiresEditgating. - Global Search stays promoted (top-level + persistent box + Cmd+K) because search is the primary corpus entry point (01-vision §1.2 “search returns one result”).
Trade-offs. (+) Matches the platform’s own mental model; scales to 6 applications without a
crowded bar; gives every homeless corpus surface a principled home; is exactly the owner’s “Option B
in principle” generalised across the whole product. (−) Introduces dropdown machinery (more
components, more a11y surface — keyboard/focus, aria-expanded); two clicks to reach a grouped leaf;
requires the command palette to grow matching groups.
Option 2 — Hybrid: flat primaries + two grouped menus
Section titled “Option 2 — Hybrid: flat primaries + two grouped menus”[Logo/Home] Search Procurement Intelligence Knowledge ▾ Governance ▾ [box][Settings]Applications stay flat (fine while only two are live); only Knowledge and Governance are grouped.
Trade-offs. (+) Less machinery than Option 1; keeps the two live applications one click away. (−) Two competing organising principles (some zones flat, some grouped) — the bar has to be re-architected the moment a third application ships, which the roadmap guarantees; postpones rather than answers the “how it all fits together” question the owner asked.
Option 3 — Flat relabel only (label fix, no grouping) (fallback)
Section titled “Option 3 — Flat relabel only (label fix, no grouping) (fallback)”Keep a flat bar; only fix labels and add the two homeless corpus surfaces:
Home Search Answers Sources Procurement Intelligence Review Coverage Change reportsTrade-offs. (+) Smallest change; unblocks {135.10} immediately. (−) Does not deliver the product-wide IA the owner explicitly asked for; the bar overflows as applications + corpus surfaces grow; leaves Concepts/Provenance/Activity homeless. Recommended only if the owner reverses the grouped-nav decision.
Recommendation
Section titled “Recommendation”Option 1. It is the owner’s stated “Option B in principle” taken to its grounded conclusion: the group is not an arbitrary “Knowledge Base” bucket but the platform’s own three-zone architecture (applications consume a shared corpus, governed by the web UI). It is the only option that stays coherent as the four planned application_types and the OKF concept surface come online.
5. Proposed invariants for {118.2} PRODUCT (numbered, testable)
Section titled “5. Proposed invariants for {118.2} PRODUCT (numbered, testable)”Research-stage invariants (IA-INV-N) the {118.2} PRODUCT slice formalises as behaviour invariants and the Checker gates {118.2}–{118.4} + id-135 {135.10} against. Written so a Checker can map each to nav behaviour.
Structure & placement
- IA-INV-1 The top-level nav is organised into the three ratified zones Applications, Knowledge, Governance (Option 1), plus utilities Home + global Search + Settings. No top-level entry sits outside a zone or a utility slot.
- IA-INV-2 The Knowledge zone contains exactly: Search (
/search), Answers (/library), Sources (/reference), Concepts (/okflanding). Nocontent_items-era surface (/item/new,/browse) appears. - IA-INV-3 The Applications zone lists only live application_types (v1: Procurement
/procurement, Intelligence/intelligence); it is the extension seam — a new live application_type adds one entry here and nowhere else (DR-038, 01-vision §4.3). - IA-INV-4 Generic top-level “Workspaces” is retired as a nav label; workspace/activity instances are reached inside their owning application, never as a product-wide peer entry (DR-038).
- IA-INV-5 Surface B (
/documents/[id]) and diff (/documents/[id]/diff) have no top-level nav slot; they are reached only contextually (from Search results + citations) — preserves id-135 PRODUCT §4.
Labels
- IA-INV-6 No nav label is a bare verb or IMS artefact: “Browse”, “Workspaces”, “Bids”, “Evidence” do not appear as user-facing labels anywhere in the three nav surfaces.
- IA-INV-7 Ratified labels are applied identically across
site-header.tsx(desktop + mobile drawer) andcommand-palette.tsx— the three surfaces never disagree (fixes §1.3 drift). The command palette’s stale “Bids”→/procurementbecomes “Procurement”. - IA-INV-8 The corpus-surface labels are the owner-ratified set (defaults pending: Search / Answers / Sources / Concepts). (Label strings are OQ-B; the invariant is that whatever is ratified is applied uniformly and matches the §3 map — not the specific string.)
Role-gating
- IA-INV-9 Every Knowledge-zone entry is read-only and role-uniform:
requiresEdit: false, visible identically to every authenticated user regardless of role — inherits id-111 B-21 and id-135 BI-2. No Knowledge entry is hidden bycanEdit. - IA-INV-10 Existing per-entry gating is preserved for Governance/Application entries (today:
Coverage/Intelligence/Review
requiresEdit: true); the IA change does not silently widen or narrow any entry’s audience except the deliberate IA-INV-9 uniformity for Knowledge surfaces.
Discovery set
- IA-INV-11 Each ratified nav entry is reachable from the full discovery set: desktop nav, mobile drawer, and the Cmd+K command palette; the persistent header search box remains; the home dashboard is reachable via logo + explicit mobile “Home”. (Command palette IS in scope — it is a real, mounted surface, not a future affordance.)
- IA-INV-12 The id-135 Surface A entry ({135.10}) is placed in the Knowledge zone at
/searchwithrequiresEdit: false, satisfying id-135 TECH BI-21 (“ship consistently with whatever id-118 ratifies, never a divergent slot”).
Active-state
- IA-INV-13 Active-state highlights the current entry via
pathname === href || pathname.startsWith(href + '/')(the existing machinery,site-header.tsx:102–103):/reference/[id]highlights Sources,/documents/[id]highlights nothing top-level (IA-INV-5),/searchhighlights Search, deep application routes (/procurement/[id]/…) highlight their application entry. - IA-INV-14 When a zone is a grouped menu, the group header shows an active affordance when any
descendant route is active (so a user on
/referencesees Knowledge marked active), andaria-current="page"is set on the specific active leaf (WCAG 2.1 AA, matching id-111 B-26).
6. Out-of-scope register (what this deliberately does NOT decide)
Section titled “6. Out-of-scope register (what this deliberately does NOT decide)”- Code implementation of the nav. {118.1} is research; the grouped-menu component, active-state wiring, and command-palette de-drift are {118.2}–{118.4} + the {135.10} executor.
- The
/library→ q_a_pair-viewer repoint and the answer deep-link destination (NO-1) — owned by the id-71 family / ID-59 / ID-69; the IA reserves the “Answers” slot but does not decide what/libraryrenders. - The workspace→activity data migration (DR-038). The IA retires the nav label and states the direction (instances live under applications); the schema/route migration is opportunistic per DR-038, not this Task.
- OKF human-editable review UI (accept/edit/reject concept edits — DR-013 shape). The IA reserves
the “Concepts” slot and a
/okflanding; the editing surface is id-132/id-138 follow-on work. - Retirement of
/item/new,/item/new/batch(content_items-era). Flagged as a likely dead-route cleanup; routed to the Orchestrator/Curator as a backlog candidate, not decided here. /activityvs the home-dashboard activity feed overlap — whether/activitysurvives as a distinct Governance entry or folds into the dashboard is a product call (OQ-C).- Whether “Research” is a new application_type or
competitor_researchrelabelled (OQ-A). - Final label strings (OQ-B) — owner-ratified; §3 gives justified proposals, not fait accompli.
- Public/anonymous surfaces &
proxy.ts publicRoutes— unchanged; every corpus surface here is authenticated (id-111 B-21, id-135 BI-1), so nopublicRoutesedit is implied.
7. Open questions requiring owner ratification
Section titled “7. Open questions requiring owner ratification”- OQ-A Is “Research” a seventh
application_type(newcorerow) or a relabelling of the seatedcompetitor_research? Affects the Applications-zone entry set. - OQ-B Ratify the corpus-surface labels: Search / Sources (vs “External sources” /
“Reading”) / Answers (vs “Q&A”) / Concepts (vs “Knowledge map”). “Sources” for
/referenceis the single most contested — owner explicitly rejected “References” and “Evidence”. - OQ-C Does
/activitysurvive as a distinct Governance nav entry, or fold into the home dashboard’s activity feed? - OQ-D Confirm Option 1 (zone-grouped) over Option 2 (hybrid) — i.e. group Applications now, or keep the two live apps flat until a third ships?
- OQ-E Group header labels: “Applications / Knowledge / Governance” — accept, or prefer “Apps / Library / Oversight” (or other)?