Purpose

This inventory is the analysis substrate used to decide the correct file-granularity standard BEFORE we port writing-system/webblockdata/apps/web. The objective is consistency in the new repo — fewer one-off files, clear primitive boundaries, and a defensible split/merge decision for every file — rather than a 1

copy of the legacy layout.

  • Closure denominator: 81 first-party files · 16,797 LOC (from closure.json, mode degraded — recursive import trace, dependency-cruiser not installed).
  • Entry route(s) (from current router + closure.json): the rendered surface is BlockdataWorkbenchPage.tsx for /app/blockdata/workbench, /app/blockdata/workbench/schemas, and /app/blockdata/workbench/jobs; /app/blockdata/workbench/database lazy-loads BlockdataSqlConnectionsRoute.tsx. The closure is the union of both entry components.
  • Analysis honesty: the four analysis columns (Primitive Level, Library Compliance, Foreign/Forbidden Includes, Consolidation/Port Action) are filled only from files that have a completed read-ledger entry. Every other file is marked ⏳ pending. Nothing in those columns is guessed.

Column definitions

  • # — row ordinal, 1..81.
  • Pathsrc-relative path from closure.json, sorted by path.
  • Type — structural role, inferred from path + closure entry data: Route (the actual route-entry components), Component (other .tsx under pages/ or components/), Hook (hooks/ + use*.ts), Context (*Context/Provider), Store (stores/*), Lib-API (lib/* that call backend endpoints), Lib-Util (other lib/*), Types (types-only files), Stylesheet (.css).
  • Routed? — whether the file is directly mounted by E:\writing-system\web\src\router.tsx. Yes means route-entry component; No means imported support code inside the workbench route closure.
  • LOC — lines of code, from closure.json. A size signal: a large LOC count means the file likely does too much and is a split candidate; a very small LOC count usually means a one-off that is a merge candidate. LOC is the primary lever for the file-granularity standard.
  • Primitive Level — where the file sits in the component hierarchy: Atom (button / input / icon), Molecule (chip / menu / field), Organism (pane / column / table / toolbar), Layout, Page/Route, Logic (hook / lib / api / util / store / types), Style (css).
  • Library Compliance — whether it uses the approved primitives (Ark UI, Tabler icons) properly, vs an ad-hoc / hand-rolled lookalike, vs n/a (no UI primitives in the file).
  • Foreign/Forbidden Includes — things it should NOT carry into the clean repo: @supabase/*, hardcoded hex / rgba instead of --ds-* tokens, non-Tabler icon libraries, cross-feature imports, and dead references.
  • Consolidation/Port Action — the recommended split / merge / lift action and any backend re-pointing required.
  • Analysis✓ read when covered by a read-ledger entry, else ⏳ pending.

Inventory (81 files)

#PathTypeRouted?LOCPrimitive LevelLibrary ComplianceForeign/Forbidden IncludesConsolidation/Port ActionAnalysis
1src/auth/AuthContext.tsxContextNo222LogicProper React context; auth backend hand-rolled directly on Supabase client (no abstraction)Supabase seam@supabase/supabase-js (Session/User types) + @/lib/supabase client; uses getSession/onAuthStateChange/signInWithPassword/signUp/resend/signOut/signInWithOAuthRefactor — replace all supabase.auth.* with Better-Auth; swap Session/User types; keep OAuth-attempt ledger + redirect-guard + profile-mirror helpers. Largest auth coupling point✓ read
2src/components/blockdata/PipelineBar.tsxComponentNo228OrganismProper Tabler icon use; buttons hand-rolled native <button> (no Ark), acceptable for toolbar railNone — all --ds-* tokens, Tabler-only, no Supabase/cross-featureKeep — self-contained launcher. Drop @deprecated WorkbenchJobLauncher/PipelineBarProps alias on port unless tests need them✓ read
3src/components/blockdata/RunJobConfigForm.tsxComponentNo223MoleculeAd-hoc/hand-rolled — native input/textarea/select/checkbox, no Ark UI Field/Select primitivesNone — --ds-* tokens throughout, no hex/icons/Supabase/cross-featureRefactor-to-primitive — replace native select/checkbox with Ark UI for a11y; keep schema-driven structure✓ read
4src/components/blockdata/runJobConfigValidation.tsLib-UtilNo37Logicn/a (pure logic)NoneKeep — pairs with RunJobConfigForm; port together. Type-only import keeps coupling clean✓ read
5src/components/common/ShellHeaderTitle.cssStylesheetNo38Stylen/aUses shadcn --foreground/--muted-foreground tokens (NOT --ds-*) — token-namespace mismatchKeep, reconcile token namespace (--foreground--ds-text etc.) during port✓ read
6src/components/common/useShellHeaderTitle.tsxHookNo171Logicn/a (logic hook); proper memo/effectNone forbidden — intra-shell @/components/shell/* imports expected; CSS uses --foreground/--muted-foregroundKeep — central breadcrumb logic; migrate nav-config + HeaderCenterContext together. Tight coupling to /app/blockdata/... route strings✓ read
7src/components/documents/CodePreview.tsxComponentNo49MoleculeProper Monaco wrapper; n/a for DS primitivesNone forbidden — uses shadcn text-muted-foreground in loading node (documents/ convention)Keep — thin stable preview; port useMonacoTheme + monacoPreviewConfig together✓ read
8src/components/documents/DocxPreview.tsxComponentNo128OrganismProper Tabler icon + shared blockdata toolbar primitiveNone forbidden — shadcn tokens (text-muted-foreground,hover:bg-accent); imports from @/pages/blockdata/* (toolbar seam, layering inversion)Keep — port with BlockdataPreviewToolbar/useIsDark/blockdataWorkbenchChrome; needs .parse-docx-* CSS✓ read
9src/components/documents/PdfPreview.tsxComponentNo144OrganismProper direct pdfjs-dist composition (intentionally no React wrapper)Hardcoded rgbargba(238,238,238,…), rgba(0,0,0,0.4), rgba(120,170,255,0.14) instead of --ds-*; imports @/pages/blockdata/* (toolbar seam)Refactor — replace rgba literals with tokens; port with ./pdf/* subcomponents✓ read
10src/components/documents/PdfResultsHighlighter.tsxComponentNo757OrganismProper react-pdf-highlighter use; ToggleSwitch hand-rolled but ARIA-correct (role=switch)shadcn tokens (text-destructive,bg-primary,bg-muted) not --ds-*; brittle deep relative path into nested node_modules/.../pdf.worker.min.mjs; needs .parse-docling-* CSSKeep — core results viewer; fix worker URL resolution; reconcile tokens; consider splitting pure JSON-pointer/docling-geometry helpers into tested lib✓ read
11src/components/documents/PptxPreview.tsxComponentNo324OrganismProper Tabler + cn; shared toolbar primitive; inputs/buttons hand-rolled nativeNone forbidden — dual token systems: --ds-* (hideToolbar branch) + shadcn (border-border,bg-background,focus:ring-ring); imports @/pages/blockdata/*Keep — merge duplicated inline/external toolbar control sets; reconcile tokens; needs .parse-pptx-* CSS✓ read
12src/components/documents/pdf/PdfPageCanvas.tsxComponentNo50Atomn/a — idiomatic pdfjs-dist direct renderNoneKeep — clean single-responsibility canvas primitive✓ read
13src/components/documents/pdf/PdfPreviewToolbar.tsxComponentNo86MoleculeProper Tabler use via shared BD_WB_TABLER_ICON conventionNone — divider uses --ds-border-subtle; note: imports presentational class consts from a pages/ module (mild layering smell)Keep — consider moving blockdataPreviewToolbar*Class out of pages/ into chrome lib to remove component→page dependency✓ read
14src/components/documents/pdf/PdfTextLayer.tsxComponentNo68Atomn/a — idiomatic pdfjs-dist TextLayerNone (depends on global .textLayer CSS from pdfjs, expected)Keep — real coordinate layer (not a stub)✓ read
15src/components/documents/pdf/pdfWorker.tsLib-UtilNo18Logicn/a — standard pdfjs-dist + Vite worker wiringNone — Vite-specific ?url import (bundler dependency)Keep — adapt ?url suffix under non-Vite bundler✓ read
16src/components/eval-designer/eval-designer-surface.cssStylesheetNo525Style/Layoutn/a — properly themes React Flow via class overridesUses --app-workspace-* namespace (THIRD token namespace); hardcoded rgba(0,0,0,0.12) box-shadow (L473)Keep — migrate --app-workspace-* token set; replace shadow rgba with token; confirm pm-flow-node/pm-reactflow-wrap contract✓ read
17src/components/shell/HeaderCenterContext.tsxContextNo48Logicn/a — plain React contextNoneKeep — standard slot-injection context for shell composition✓ read
18src/components/shell/nav-config.tsLib-UtilNo278LogicProper Tabler use (Icon type refs, not rendered)None — all blockdata namespace; note several consts (SHARED_STATIC_SECTIONS, BLOCKDATA_NAV_SECTIONS) possibly redundant (dead/unused breadth)Keep — central nav source of truth; audit unused exports to trim on port✓ read
19src/components/ui/checkbox.tsxComponentNo70AtomProper Ark UI Checkbox partsHardcoded hexborder-[#3a3a3a], focus #e2503f instead of --ds-*; inline non-Tabler <svg> checkmarkRefactor-to-primitive — replace hex with tokens; consider Tabler check icon✓ read
20src/components/ui/dialog.tsxComponentNo154OrganismProper Ark UI Dialog compositionNon-Tabler icon — Hugeicons Cancel01Icon; hardcoded hex #3a3a3a/#222221/#e2503f + raw rgb shadowRefactor-to-primitive — swap Hugeicons for Tabler IconX; replace hex with tokens. Canonical dialog✓ read
21src/components/ui/menu.tsxComponentNo184OrganismProper Ark UI Menu compositionNon-Tabler icon — Lucide ChevronDownIcon (third icon lib); hardcoded hex #3a3a3a/#222221/#e2503f; depends on global ui-menu-* CSSRefactor-to-primitive — replace Lucide chevron with Tabler IconChevronDown; tokenize hex; standardize icon lib✓ read
22src/components/ui/splitter.tsxComponentNo68MoleculeProper Ark UI Splitter partsHardcoded hex#3a3a3a (divider), #111110 (indicator bg) + raw rgb shadow vs --ds-*Refactor-to-primitive — replace hex/shadow with tokens✓ read
23src/hooks/useBlockTypeRegistry.tsHookNo111LogicAd-hoc/hand-rolled — bespoke module-singleton cache (not React Query)None (hex values are DB-sourced data, not styling literals)Keep — backend-agnostic if fetchParseRegistry ported; optionally merge into React Query✓ read
24src/hooks/useDropboxChooser.tsHookNo116LogicAd-hoc/hand-rolled — own script loader (does not reuse useExternalScript, needs data-app-key)None (Dropbox CDN script is feature-intrinsic)Keep — backend-agnostic browser integration; carries over unchanged✓ read
25src/hooks/useExternalScript.tsHookNo43LogicProper primitive — clean reusable utilityNoneKeep — backend-agnostic; carries over unchanged✓ read
26src/hooks/useGoogleDrivePicker.tsHookNo127LogicProper primitive — reuses useExternalScript; uses untyped (google.picker as any) castsNone (Google CDN scripts feature-intrinsic; ambient globals)Keep — backend-agnostic; carries over unchanged✓ read
27src/hooks/useMonacoTheme.tsHookNo23LogicProper primitive — textbook useSyncExternalStoreNone ('light'/'vs-dark' are Monaco theme ids, not hex)Keep — backend-agnostic; carries over unchanged✓ read
28src/hooks/useProjectFocus.tsHookNo389LogicAd-hoc/hand-rolled — bespoke module-singleton store via useSyncExternalStore + DOM CustomEvent bus (not React Query/Zustand)None direct — cross-feature: blends generic platform + blockdata-specific focus, /app/elt/:id route knowledge; auth-coupled indirectly via useAuth (Supabase session.access_token through requestKey)Refactor — requestKey depends on Supabase token shape; rederive from Better-Auth. Consider splitting blockdata vs global scope branches✓ read
29src/hooks/useStorageQuota.tsHookNo94LogicAd-hoc/hand-rolled — manual listener/singleton store + dedup (not React Query/useSyncExternalStore)NoneKeep — backend-agnostic via platformApiFetch; optionally migrate to React Query✓ read
30src/lib/accountProfileApi.tsLib-APINo25LogicProper primitive — delegates to platformApiJsonNone directly (Supabase coupling transitive via platformApi→authToken); doc comment references Supabase Auth updateUserKeep — /profile mirror is the post-updateUser sync hook for Better-Auth/Neon✓ read
31src/lib/authOAuthAttempts.tsLib-APINo183LogicAd-hoc/hand-rolled — raw fetch (NOT platformApiFetch), hardcoded /platform-api base, duplicates error parsingNone (no @supabase); hardcoded base path stringKeep, refactor — primary auth port seam; fronts Supabase OAuth callback flow; maps to Better-Auth callback hooks✓ read
32src/lib/authRedirects.tsLib-UtilNo19Logicn/a — pure utilNoneKeep — redirect origin handling carries to Better-Auth callback URLs✓ read
33src/lib/authToken.tsLib-APINo17Logicn/a — direct Supabase SDK useSupabase seam@/lib/supabase; calls supabase.auth.getSession() + refreshSession()Refactor — core seam; replace with Better-Auth session/token retrieval. Every authed call flows through here via platformApiFetch✓ read
34src/lib/bdPreviewRuntimeApi.tsLib-APINo28LogicProper primitive — via platformApiJsonNone directlyKeep — /blockdata/preview/renderer-bindings stable; auth via platformApi seam✓ read
35src/lib/blockdataProjectFocus.tsLib-UtilNo57Logicn/a — plain web-storage + event busNoneKeep — minimal cross-tab/intra-app focus sync; port verbatim✓ read
36src/lib/blockdataWorkbenchAssetDrag.tsLib-UtilNo41Logicn/a — framework-agnostic DnD utilityNoneKeep — small cohesive DnD contract; rename MIME namespace if app rebrands✓ read
37src/lib/blockdataWorkbenchAssetsApi.tsLib-APINo489LogicProper primitive — TanStack via shared query-policy + keys; uses platformApiFetchNone (no @supabase; goes through platformApiFetch)Keep — canonical asset data layer. Optionally split embedded useBlockdataWorkbenchAssets hook into hooks/ (low priority, cohesion high)✓ read
38src/lib/blockdataWorkbenchChrome.tsLib-UtilNo27StyleProper primitive — centralizes Tabler icon propsNone (pixel constants are geometry, not color hex)Keep — tiny shared constant module; merge into broader DS constants file only if one exists✓ read
39src/lib/blockdataWorkbenchJobs.tsLib-APINo579LogicProper primitive — shared keys + query policy + platformApiFetch; mock/integrated dual-path intentional A7 scaffoldingCross-feature up-import — type-only imports from components/blockdata/RunJobConfigForm, components/blockdata/PipelineBar, pages/blockdata/RunJobModal (lib importing up from components/pages, port hazard)Refactor — relocate shared job types into lib/types/ so lib no longer imports up; fix layering before port✓ read
40src/lib/blockdataWorkbenchLayout.tsLib-UtilNo373LogicProper primitive — pure math; sources AI width from styleTokensNone (router-outlet context type; no hardcoded hex)Keep — well-factored geometry engine; structural duplication across four derive fns extractable (optional)✓ read
41src/lib/blockdataWorkspaces.tsLib-APINo208LogicProper primitive — manual fetch+cache (intentionally pre-React-Query bootstrap); shared platformApiFetchNoneKeep — bootstrap singleton with cache/dedupe is deliberate; consider folding into TanStack later (optional)✓ read
42src/lib/doclingOverlayColors.tsLib-UtilNo78LogicAd-hoc/hand-rolled — color fallbacks are literal hex/rgba, NOT --ds-*Hardcoded hex/rgba#0ea5e9, rgba(14,165,233,0.14), #f59e0b, #d97706, #38bdf8 etc. instead of --ds-*Refactor — move overlay fallback colors to --ds-* CSS vars; keep label-resolution logic✓ read
43src/lib/dsWorkbenchClasses.tsLib-UtilNo21StyleProper primitive — uses --ds-* tokens via Tailwind arbitrary values, not raw hexNone (all colors are var(--ds-*) tokens)Keep — token-correct shared class strings; port as-is✓ read
44src/lib/extractionSchemaHelpers.tsLib-UtilNo203LogicProper primitive — standard useSyncExternalStore; Web Crypto hashingNone (no @supabase; Monaco theme via data-theme attr, no color literals)Keep — client-side, backend-agnostic; ports verbatim. Shared by Schemas page + Extract workbench✓ read
45src/lib/extractionSchemasApi.tsLib-APINo93LogicProper primitive — routes all I/O through platformApi helpers; sound hand-rolled in-flight dedupeNone (PostgREST/Supabase deliberately avoided per header)Keep — clean platform-api client; port as-is✓ read
46src/lib/monacoPreviewConfig.tsLib-UtilNo79LogicProper primitive — pure config/utilNone (@monaco-editor/react only a label string, not imported)Keep — pure, portable; copy as-is✓ read
47src/lib/operationalReadiness.tsLib-APINo560LogicProper primitive — strong runtime validation, no ad-hoc fetchsupabase_admin_connectivity appears only as a string literal in OperationalReadinessProbeKind (label, not an import) — flag for readiness-rename sweepKeep — blockdata SurfaceId + supabase_admin_connectivity probe-kind label are blockdata-specific; verify surface taxonomy on port✓ read
48src/lib/parseApi.tsLib-APINo335LogicProper primitive — all via platformApiFetchNone directly; admin/blockdata-settings/base control-plane+profiles are near-duplicate tripletsKeep, consider merge — endpoints stable; triplication is a server-driven refactor candidate✓ read
49src/lib/platformApi.tsLib-APINo228LogicProper primitive — THE canonical client primitive other api libs build onSupabase seam — imports @/lib/supabase, calls supabase.auth.refreshSession() (fetch + upload retry); Bearer JWT is Supabase-issuedRefactor — central seam; replace refreshSession + JWT semantics with Better-Auth token refresh; keep relative /platform-api proxy + retry-once-on-401✓ read
50src/lib/platformWorkspace.tsLib-APINo257LogicProper primitive — all via platformApiFetchNone directly (auth via platformApi seam); localStorage onlyKeep — orgs/membership/invites are platform-API concerns; user_id comes from Better-Auth post-port. Endpoints stable✓ read
51src/lib/projectDetailHelpers.tsLib-UtilNo353LogicProper primitive for the one API call; rest pure utilsNone (no hex/icons)Keep — /storage/download-url signed-URL is a storage seam (likely Supabase Storage); move off Supabase Storage on port. Pure classification utils port verbatim✓ read
52src/lib/projectFocus.tsLib-UtilNo32Logicn/a — pure utilNoneKeep — client-only state, no backend/auth dependency; ports verbatim✓ read
53src/lib/projectsApi.tsLib-APINo73LogicProper primitive — via platformApiFetchNone directlyKeep — endpoints stable; organization_id scoping ties to platform org identity; auth via platformApi/Supabase seam✓ read
54src/lib/queryClient.tsLib-UtilNo27LogicProper primitive — standard TanStack Query setup; testMode disables retriesNoneKeep — backend-agnostic; carries over unchanged✓ read
55src/lib/queryKeys/blockdataWorkbenchKeys.tsLib-UtilNo126LogicProper primitive — centralized key factory; all as constNoneKeep — required hub; do not inline keys at call sites; port verbatim✓ read
56src/lib/reactQuery/appQueryDefaults.tsLib-UtilNo7LogicProper primitive — centralizes query defaultsNoneKeep — base config constant; port as-is✓ read
57src/lib/reactQuery/blockdataWorkbenchQueryPolicy.tsLib-UtilNo17LogicProper primitive — derives gc from app defaultNoneKeep — central timing policy; port with appQueryDefaults✓ read
58src/lib/storageUploadService.tsLib-APINo265LogicProper primitive — server-proxied upload (avoids browser→storage CORS); @noble/hashes for hashingNone — no @supabase; uploads route through platform-api, not Supabase storage SDKKeep — core upload service; storage_surface:'assets' is blockdata-aware, confirm on port✓ read
59src/lib/styleTokens.tsLib-UtilNo109StyleAd-hoc/hand-rolled (partial) — most semantic colors are CSS-var tokens, but grid.light/dark + gradient rgba are hardcodedHardcoded hex/rgbagrid hex (#ffffff,#faf9f7,#1c1917,#d6d3d1,#78716c,#09090b,#fafafa,#27272a,#a1a1aa) + gradient rgba; blockdata-named dimsRefactor — migrate grid hex + gradient rgba to design tokens; review blockdata-specific dims; keep layout dims + CSS-var sections✓ read
60src/lib/supabase.tsLib-APINo10Logicn/a — direct vendor SDK; exactly what migration removesSupabase seam (PRIMARY removal target)@supabase/supabase-js createClient; two VITE_SUPABASE_* env vars; central coupling pointRefactor/remove — eliminate client; migrate all consumers to platform-api; track every importer of @/lib/supabase. Highest-priority decoupling target✓ read
61src/lib/types.tsTypesNo278Logicn/a — type declarations onlyNone (no Supabase import; comments reference writing-system/blockdata issues)Keep — audit each row vs target backend schema; Run/BlockOverlay vs Extraction* families may be legacy/dead, prune on port✓ read
62src/lib/uploadReservationRecovery.tsLib-APINo101LogicProper primitive — typed error class, single retry, idempotent cleanupNoneKeep — tightly coupled to storageUploadService; port together✓ read
63src/lib/useIsDark.tsHookNo30LogicProper primitive — idiomatic useSyncExternalStoreNoneKeep — clean, framework-portable theme hook✓ read
64src/lib/utils.tsLib-UtilNo7AtomProper primitive — canonical clsx + tailwind-merge cnNoneKeep — ubiquitous primitive; copy verbatim✓ read
65src/lib/workbenchCloudImport.tsLib-APINo46LogicProper primitive — reuses upload response parser + platformApiFetchNone (Google/Dropbox are own-backend endpoints, not client SDKs)Keep — thin provider clients; port with upload module✓ read
66src/lib/workbenchFolderCatalog.tsLib-UtilNo57Logicn/a — pure data transforms (time formatting injected)NoneKeep — clean pure helpers with cycle guard; port verbatim✓ read
67src/pages/BlockdataWorkbenchPage.cssStylesheetNo211Stylen/a (pure CSS)None — uses --ds-* tokens + color-mix(in oklab); no hex/rgba, no iconsDirect lift; ensure --ds-* tokens + blockdata-* classes (filter-chip, upload-progress, asset-filter-row) travel✓ read
68src/pages/BlockdataWorkbenchPage.tsxRouteYes — /app/blockdata/workbench, /app/blockdata/workbench/schemas, /app/blockdata/workbench/jobs1436Page/RouteCompliant — Ark UI Splitter, Tabler iconsNone — Supabase-free (all via abstracted API helpers); Tabler-onlySplit candidate (1,436 LOC; page + 8 internal components). Re-point upload + workbench API helpers to Neon/Better-Auth; keep Ark Splitter✓ read
69src/pages/blockdata-db-workbench/workbenchTypes.tsTypesNo65Logicn/aNone (hardcoded base path is a route literal, legitimate)Keep — canonical route-builder module; drop DB_WORKBENCH_BASE deprecated alias once callers migrate✓ read
70src/pages/blockdata/BlockdataAssetTablePane.tsxComponentNo1825Organism (whole assets column/table pane)Compliant — Ark UI checkbox/menu wrappers, Tabler iconsNone in-file (no Supabase/auth); Tabler-only; heavy --ds-* + blockdata-* class relianceSplit candidate (1,825 LOC — largest file). Re-point prop callbacks + hooks (useStorageQuota, useUploadsStore, cloud-import) to Neon/Better-Auth; ensure tokens/classes + cloud-import env vars travel✓ read
71src/pages/blockdata/BlockdataAssetsDockLayer.tsxComponentNo116Layout (detached/floating Assets window layer)n/a (dockview-driven; no Ark/Tabler)Hardcoded bg #111111 (not a --ds-* token) — tokenize on port; depends on dockview + its CSSDirect lift; tokenize the #111111 background; confirm dockview in target deps✓ read
72src/pages/blockdata/BlockdataPreviewToolbar.tsxComponentNo97Molecule (preview-toolbar slot system) + Logic (React context)n/a (no Ark/Tabler primitives; styling via class consts)None — uses --ds-* tokens + --bd-wb-preview-toolbar var; no icons, no auth/DBDirect lift; ensure --ds-* tokens + --bd-wb-preview-toolbar var travel✓ read
73src/pages/blockdata/BlockdataSchemaEditor.tsxComponentNo951Organism (Visual/Split/Code schema editor)Compliant — Ark UI Select/Splitter, Tabler iconsHardcoded hex/rgba (#0e0e0e, #3B82F6, rgba(120,170,255,…), #111111) instead of --ds-*; inline Monaco blockdata-dark theme; flagged cross-domain import of useMonacoTheme from legacy extractionSchemaHelpersSplit candidate (951 LOC). Tokenize hardcoded colors; relocate useMonacoTheme; confirm @monaco-editor/react + @ark-ui/react in target; CRUD delegated to props (indirect backend port)✓ read
74src/pages/blockdata/BlockdataSchemasModal.tsxComponentNo233Organism (modal master/detail shell)Compliant — Ark UI dialog + first-party dialog wrappers, Tabler iconsNone — uses --ds-* tokens; Tabler-only. Note non-functional per-schema IconDotsVertical actions placeholder (dead/stub ref)Direct lift of shell; port the useBlockdataSchemas hook (the data seam, likely Supabase today) to Neon/Better-Auth; preserve projectId single-source ownership✓ read
75src/pages/blockdata/BlockdataSqlConnectionsRoute.tsxRouteYes — /app/blockdata/workbench/database11Page/Route (redirect shim)n/a (no UI primitives — renders <Navigate>)None — no Supabase/auth, no icons, no state/effectsDirect lift (11 LOC redirect shim); merge candidate if a routing index consolidates redirects✓ read
76src/pages/blockdata/FolderNameEditor.tsxComponentNo94Molecule (inline rename/create field)n/a (plain controlled <input>; no Ark/Tabler)None — uses --ds-* tokens only; no icons; backend-agnosticDirect lift; ensure --ds-* tokens (border-strong, canvas, text, brand, brand-tint-faint) exist in target✓ read
77src/pages/blockdata/RunJobModal.tsxComponentNo285OrganismProper Ark UI dialog wrapper (Ark-backed); buttons raw <button> (hand-rolled, acceptable)None — no Supabase; all colors via --ds-* tokens; no icons; no cross-feature importsKeep — self-contained, API-injected modal; port as-is, swap raw buttons for shared Button primitive if standardized✓ read
78src/pages/blockdata/hooks/useBlockdataSchemas.tsHookNo106Logicn/a (pure hook, no UI primitives)None — explicitly platform-api only (no @supabase); all first-party importsKeep — clean injected data hook; minor refactor: make deleteSchema optimistic for parity with create/update✓ read
79src/pages/blockdata/lib/blockdataPreviewRegistry.tsxLib-UtilNo825Logic + OrganismProper Tabler (IconHash) + react-markdown/remark; mixed registry data + multiple React components in one file is structurally ad-hocHardcoded hex/rgba (intentional dark prose) — MARKDOWN_PROSE_DARK, #3B82F6 (link), #FFC470 (code), #0e0e0e (image bg), rgba(255,255,255,…); day/night split hand-managed via useIsDark instead of tokens. Light mode correctly uses --ds-*Split — separate registry table/resolver (Logic) from embedded preview components (Markdown/PlainText/Unsupported organisms); migrate hardcoded colors to --ds-* so one token set drives both themes✓ read
80src/pages/blockdata/lib/blockdataSchemaHelpers.tsLib-UtilNo188Logicn/a (no UI); Web Crypto APINone — zero imports, no Supabase/styling/cross-feature; self-contained forkKeep — clean self-contained domain util; port as-is. Future: canonical-JSON hashing for order-independent computeSchemaUid✓ read
81src/stores/uploadsStore.tsStoreNo143LogicProper primitive — idiomatic Zustand; integrates React Query via queryClient invalidationNone direct — cross-feature: imports blockdata-specific blockdataWorkbenchAssetsApi (generic store coupled to one feature's invalidation; acceptable)Keep — backend-agnostic; carries over if asset-invalidation API ported✓ read

Coverage

81 / 81 analyzed (✓ read). No ⚠ MISSING files — every file in closure.json maps to exactly one completed read-ledger entry (read-ledger.md for rows 67/68/75; ledger/01-pages-a.md … 08-lib-util-b.md for the other 78).

LOC reconciliation: canonical ΣLOC (closure.json, wc -l) = 16,797; ledger read-side ΣLOC ≈ 17,040; the ~243 delta is Read line-index vs wc -l counting variance (last-line / trailing-newline differences), not unread lines — every file has a full-read entry. The LOC column above uses the canonical closure.json value throughout.

Findings

Compiled strictly from the read-ledger entries (no inference beyond what each entry states).

Primitive-level distribution

LevelCountFiles
Atom3utils.ts; pdf/PdfPageCanvas.tsx; pdf/PdfTextLayer.tsx
Molecule5RunJobConfigForm.tsx; CodePreview.tsx; pdf/PdfPreviewToolbar.tsx; splitter.tsx; FolderNameEditor.tsx
Organism11PipelineBar.tsx; DocxPreview.tsx; PdfPreview.tsx; PdfResultsHighlighter.tsx; PptxPreview.tsx; dialog.tsx; menu.tsx; RunJobModal.tsx; BlockdataSchemaEditor.tsx; BlockdataSchemasModal.tsx; BlockdataAssetTablePane.tsx
Layout1BlockdataAssetsDockLayer.tsx
Page/Route3BlockdataWorkbenchPage.tsx; BlockdataSqlConnectionsRoute.tsx; (BlockdataPreviewToolbar.tsx = Molecule+Logic, counted under Molecule)
Logic53all Hooks/Contexts/Lib-API/Lib-Util/Store/Types entries marked Logic (AuthContext, useShellHeaderTitle, HeaderCenterContext, nav-config, all hooks, all lib/* non-Style, types.ts, uploadsStore, workbenchTypes, useBlockdataSchemas, blockdataPreviewRegistry [Logic+Organism], blockdataSchemaHelpers, runJobConfigValidation, etc.)
Style5ShellHeaderTitle.css; eval-designer-surface.css; BlockdataWorkbenchPage.css; blockdataWorkbenchChrome.ts; dsWorkbenchClasses.ts; styleTokens.ts

Note: two files carry dual levels per their ledger entry — BlockdataPreviewToolbar.tsx (Molecule + Logic) and blockdataPreviewRegistry.tsx (Logic + Organism). The eval-designer-surface.css is Style/Layout. Counted by primary level above; the Style row lists 6 token-bearing files (3 .css + 3 style-constant .ts).

Ad-hoc / hand-rolled (Library Compliance ≠ proper)

8 files:

  • RunJobConfigForm.tsx — native input/textarea/select/checkbox, no Ark UI Field/Select primitives.
  • useBlockTypeRegistry.ts — bespoke module-singleton cache instead of React Query.
  • useDropboxChooser.ts — own script loader; does not reuse useExternalScript (needs data-app-key).
  • useProjectFocus.ts — bespoke module-singleton store via useSyncExternalStore + DOM CustomEvent bus (not React Query/Zustand).
  • useStorageQuota.ts — manual listener/singleton store + dedup (not React Query/useSyncExternalStore).
  • authOAuthAttempts.ts — raw fetch (not platformApiFetch), hardcoded /platform-api base, duplicates error parsing.
  • doclingOverlayColors.ts — color fallbacks are literal hex/rgba, not --ds-* tokens.
  • styleTokens.ts — partial: grid.light/dark + gradient rgba hardcoded (rest are proper CSS-var tokens).

(AuthContext.tsx notes its auth backend is hand-rolled directly on the Supabase client, but its React-context primitive use is proper; tracked under the Supabase seam below.)

Forbidden / foreign includes

(a) Supabase seams — files touching @supabase/* or @/lib/supabase:

  • src/lib/supabase.ts@supabase/supabase-js createClient; the client singleton (PRIMARY removal target).
  • src/auth/AuthContext.tsx@supabase/supabase-js (Session/User types) + @/lib/supabase client; full auth lifecycle.
  • src/lib/authToken.ts@/lib/supabase; getSession()/refreshSession().
  • src/lib/platformApi.ts@/lib/supabase; refreshSession() on 401 retry (fetch + upload).

(Transitive-only, no direct import: accountProfileApi.ts, bdPreviewRuntimeApi.ts, platformWorkspace.ts, projectsApi.ts, projectDetailHelpers.ts, extractionSchemasApi.ts etc. authenticate through platformApi's Supabase seam but carry no @supabase import themselves. operationalReadiness.ts contains the string literal supabase_admin_connectivity as a probe-kind label only — not an import.)

(b) Hardcoded hex / rgba (vs --ds-*/--app-* tokens):

  • components/ui/checkbox.tsx#3a3a3a, focus #e2503f.
  • components/ui/dialog.tsx#3a3a3a, #222221, #e2503f, raw rgb shadow.
  • components/ui/menu.tsx#3a3a3a, #222221, #e2503f, raw rgb shadow.
  • components/ui/splitter.tsx#3a3a3a, #111110, raw rgb shadow.
  • documents/PdfPreview.tsxrgba(238,238,238,…), rgba(0,0,0,0.4), rgba(120,170,255,0.14).
  • BlockdataAssetsDockLayer.tsx#111111 panel bg.
  • BlockdataSchemaEditor.tsx#0e0e0e, #3B82F6, rgba(120,170,255,…), #111111; inline Monaco blockdata-dark theme.
  • blockdataPreviewRegistry.tsxMARKDOWN_PROSE_DARK block, #3B82F6, #FFC470, #0e0e0e, rgba(255,255,255,…) (intentional dark prose, day/night via useIsDark).
  • doclingOverlayColors.ts#0ea5e9, rgba(14,165,233,0.14), #f59e0b, #d97706, #38bdf8.
  • styleTokens.tsgrid hex (#ffffff,#faf9f7,#1c1917,#d6d3d1,#78716c,#09090b,#fafafa,#27272a,#a1a1aa) + gradient rgba.
  • eval-designer-surface.cssrgba(0,0,0,0.12) box-shadow (L473).

(c) Non-Tabler icons / cross-feature imports / dead refs:

  • Non-Tabler icons: dialog.tsx (Hugeicons Cancel01Icon); menu.tsx (Lucide ChevronDownIcon); checkbox.tsx (inline hand-rolled <svg> checkmark). Three icon libraries in play alongside Tabler.
  • Token-namespace foreign: ShellHeaderTitle.css + useShellHeaderTitle.tsx + CodePreview.tsx + DocxPreview.tsx + PptxPreview.tsx + PdfResultsHighlighter.tsx use shadcn --foreground/--muted-foreground/bg-primary/text-muted-foreground; eval-designer-surface.css uses a third --app-workspace-* namespace.
  • Cross-feature / layering inversions: blockdataWorkbenchJobs.ts (lib up-imports types from components/blockdata/* + pages/blockdata/RunJobModal); DocxPreview.tsx/PptxPreview.tsx/PdfPreview.tsx/pdf/PdfPreviewToolbar.tsx (components import from pages/blockdata/* toolbar seam); useProjectFocus.ts (blends generic platform + blockdata-specific concerns); uploadsStore.ts (generic store imports blockdata-specific assets API).
  • Dead / stub refs: BlockdataSchemasModal.tsx (non-functional per-schema IconDotsVertical actions placeholder); nav-config.ts (possibly-redundant SHARED_STATIC_SECTIONS/BLOCKDATA_NAV_SECTIONS breadth, empty BOTTOM_RAIL_NAV); types.ts (Run/BlockOverlay vs Extraction* families flagged possibly legacy/dead); PdfResultsHighlighter.tsx brittle deep node_modules/.../pdf.worker.min.mjs path.

Consolidation candidates

Split targets (too large / mixed concerns):

  • BlockdataAssetTablePane.tsx (1,825) — largest file; whole assets pane, split into sub-components.
  • BlockdataWorkbenchPage.tsx (1,436) — page + 8 internal components.
  • BlockdataSchemaEditor.tsx (951) — Visual/Split/Code editor; split + tokenize.
  • blockdataPreviewRegistry.tsx (825) — split registry table/resolver (Logic) from embedded preview components (organisms).
  • PdfResultsHighlighter.tsx (757) — extract pure JSON-pointer/docling-geometry helpers into a tested lib module.

Merge targets (one-offs / refactor-to-shared):

  • BlockdataSqlConnectionsRoute.tsx (11) — redirect shim; merge if a routing index consolidates redirects.
  • blockdataWorkbenchChrome.ts (27) — merge into a broader DS-constants file if one exists.
  • pdf/PdfPreviewToolbar.tsx — move blockdataPreviewToolbar*Class consts out of pages/ into the chrome lib (removes component→page dependency).
  • parseApi.ts — admin/blockdata-settings/base control-plane+profiles near-duplicate triplets; merge (server-driven).
  • blockdataWorkbenchJobs.ts — relocate shared job types into lib/types/ so lib stops up-importing from components/pages (fix layering, then types consumed downward).
  • RunJobConfigForm.tsx / checkbox.tsx / dialog.tsx / menu.tsx / splitter.tsx — refactor-to-primitive: standardize on Ark UI + Tabler, replace hex with tokens (consolidate icon library to Tabler).
  • doclingOverlayColors.ts / styleTokens.ts / BlockdataSchemaEditor.tsx / blockdataPreviewRegistry.tsx / PdfPreview.tsx — tokenize hardcoded colors into the single --ds-* set.

On this page