jules ac7c294753 fix(kb-ui): P0 provenance crash + AA badges + a11y + first-run polish
Provenance/claims carried created_by/verified_by as {type,id} principal
refs from the service, but the types said string|null and ProvenancePanel
rendered them raw → React #31 crash on every object view. Widen to
string|PrincipalRef|null and add formatPrincipal() (barrel-exported).

Badges: mode-aware semantic tones (mix toward --foreground) so success/
warning/info/danger text clears WCAG AA on the subtle tint in BOTH light
and dark; Active badge 2.81→5.25/5.67:1. SensitivityBadge renders nothing
for an unset level (objects inherit from their collection) instead of a
misleading "—" pill. TierBadge tolerates an unknown tier.

Accessibility: Badge gains ariaLabel (screen readers announce the meaning,
not just the terse label); Field links label↔control via htmlFor + useId
and wires aria-describedby to the hint; OwnerToggle gets aria-pressed;
icons aria-hidden.

First-run: CollectionForm leads with Name and auto-derives the Identifier
(was slug-first); placeholder text uses --muted-foreground. Drop the
Sparkles "AI-magic" icons from the review empty state and the agent tier
badge (Inbox / Bot instead), per the no-magic-framing principle.

Verified live on dev-knowledge.sky-ai.com.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 08:40:24 +10:00
2026-07-07 10:05:46 +10:00
2026-07-07 10:05:46 +10:00
2026-07-07 10:05:46 +10:00

@crema/knowledge-ui

Management UI for arcadia-knowledge — the hosted knowledge base. Ships the collection browser, object viewer (card + provenance + supersession + citations), claims review queue, and export flow as pure, headless components: shapes and UI, never data fetching. The app injects a KnowledgeTransport; auth stays closed over inside it, so components never see a token.

Built to arcadia-knowledge-ui-spec.md. Two consumers today: the Knowledge area in arcadia-personal-cloud-web (me.sky-ai.com) and the standalone skyai-knowledge-web. Same lib, different shells.

Install (polyrepo — source alias, not npm)

Like every @crema/* lib, this is a path-aliased source folder. A consumer wires it in three places:

  1. vite.config.ts — resolve alias:

    "@crema/knowledge-ui": libSrc("knowledge-ui") + "/index.tsx",
    "@crema/knowledge-ui/": libSrc("knowledge-ui") + "/",
    

    Make sure lucide-react is in your shared-dep dedupe list.

  2. tsconfig.json — paths:

    "@crema/knowledge-ui": ["../lib-knowledge-ui/src/index.tsx"],
    "@crema/knowledge-ui/*": ["../lib-knowledge-ui/src/*"]
    
  3. app/app.css — Tailwind source scan:

    @source "../../lib-knowledge-ui/src";
    

The lib is fully self-contained — it imports only react and lucide-react (no other @crema/* libs), so a fresh consumer wires exactly this one alias. The app may separately use @crema/file-ui for the upload dropzone on its collection page (spec §4.5), but that's the app's choice, not a lib dependency.

The vite alias (step 1) also needs its own step — mirror step 2 in vite.config.ts resolve.alias, and ensure react / react-dom / lucide-react are deduped to the app's copies (sibling libs carry no node_modules).

Wiring the transport

The lib defines KnowledgeTransport; the app implements it over its KB client (a kb.ts factory that closes over the session token and talks to arcadia-knowledge :4025 directly). See arcadia-knowledge-ui-spec.md §4.2.

import { CollectionList, type KnowledgeTransport } from "@crema/knowledge-ui";

const transport: KnowledgeTransport = kbTransport(session.token);
const { collections } = await transport.listCollections();

<CollectionList collections={collections} onOpen={(c) => navigate(`/knowledge/${c.slug}`)} />

For development without a service, use MockKnowledgeTransport — it backs demo/knowledge.tsx with fixtures covering every surface (personal + org corpuses, documents, an image, a superseded doc, a vault doc, an open claim conflict, a proposed claim, a rejected tombstone, an export job).

Conventions

  • Tailwind theme tokens only — no hex. Sensitivity/tier/status/curation colours use --warning / --success / --destructive / --info (falls back to --primary). Works in any Crema theme.
  • Props in, callbacks out. No global state, no context, no fetching.
  • data-action attributes on interactive elements (command-bus contract).
  • Trust is surfaced raw — assertion tier, card_model, extraction_model are shown as first-class facts, never collapsed into a score.

Typecheck

../arcadia-personal-cloud-web/node_modules/.bin/tsc -p tsconfig.check.json

(Borrows a consumer's React types; the lib has no node_modules of its own.)

Surfaces

Module Exports
components-collections CollectionList, CollectionCard, CollectionForm
components-object ObjectList, ObjectViewer, CatalogCard, ProvenancePanel, SupersessionBanner, OutlineNav, TextReader, CitationLink
components-claims ClaimsReviewQueue, ClaimCard, ConflictPair
components-export ExportPanel, ExportJobRow
_internal (re-exported) badges + cn, formatBytes, formatDate, formatRelative, renderValue
Description
No description provided
Readme 162 KiB
Languages
TypeScript 100%