Purpose
This inventory is the analysis substrate used to decide the correct
file-granularity standard BEFORE we port writing-system/web →
blockdata/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
- Closure denominator: 81 first-party files · 16,797 LOC (from
closure.json, modedegraded— recursive import trace, dependency-cruiser not installed). - Entry route(s) (from current router +
closure.json): the rendered surface isBlockdataWorkbenchPage.tsxfor/app/blockdata/workbench,/app/blockdata/workbench/schemas, and/app/blockdata/workbench/jobs;/app/blockdata/workbench/databaselazy-loadsBlockdataSqlConnectionsRoute.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.
- Path —
src-relative path fromclosure.json, sorted by path. - Type — structural role, inferred from path + closure entry data:
Route(the actual route-entry components),Component(other.tsxunderpages/orcomponents/),Hook(hooks/+use*.ts),Context(*Context/Provider),Store(stores/*),Lib-API(lib/*that call backend endpoints),Lib-Util(otherlib/*),Types(types-only files),Stylesheet(.css). - Routed? — whether the file is directly mounted by
E:\writing-system\web\src\router.tsx.Yesmeans route-entry component;Nomeans 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 —
✓ readwhen covered by a read-ledger entry, else⏳ pending.
Inventory (81 files)
| # | Path | Type | Routed? | LOC | Primitive Level | Library Compliance | Foreign/Forbidden Includes | Consolidation/Port Action | Analysis |
|---|---|---|---|---|---|---|---|---|---|
| 1 | src/auth/AuthContext.tsx | Context | No | 222 | Logic | Proper 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/signInWithOAuth | Refactor — 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 |
| 2 | src/components/blockdata/PipelineBar.tsx | Component | No | 228 | Organism | Proper Tabler icon use; buttons hand-rolled native <button> (no Ark), acceptable for toolbar rail | None — all --ds-* tokens, Tabler-only, no Supabase/cross-feature | Keep — self-contained launcher. Drop @deprecated WorkbenchJobLauncher/PipelineBarProps alias on port unless tests need them | ✓ read |
| 3 | src/components/blockdata/RunJobConfigForm.tsx | Component | No | 223 | Molecule | Ad-hoc/hand-rolled — native input/textarea/select/checkbox, no Ark UI Field/Select primitives | None — --ds-* tokens throughout, no hex/icons/Supabase/cross-feature | Refactor-to-primitive — replace native select/checkbox with Ark UI for a11y; keep schema-driven structure | ✓ read |
| 4 | src/components/blockdata/runJobConfigValidation.ts | Lib-Util | No | 37 | Logic | n/a (pure logic) | None | Keep — pairs with RunJobConfigForm; port together. Type-only import keeps coupling clean | ✓ read |
| 5 | src/components/common/ShellHeaderTitle.css | Stylesheet | No | 38 | Style | n/a | Uses shadcn --foreground/--muted-foreground tokens (NOT --ds-*) — token-namespace mismatch | Keep, reconcile token namespace (--foreground→--ds-text etc.) during port | ✓ read |
| 6 | src/components/common/useShellHeaderTitle.tsx | Hook | No | 171 | Logic | n/a (logic hook); proper memo/effect | None forbidden — intra-shell @/components/shell/* imports expected; CSS uses --foreground/--muted-foreground | Keep — central breadcrumb logic; migrate nav-config + HeaderCenterContext together. Tight coupling to /app/blockdata/... route strings | ✓ read |
| 7 | src/components/documents/CodePreview.tsx | Component | No | 49 | Molecule | Proper Monaco wrapper; n/a for DS primitives | None forbidden — uses shadcn text-muted-foreground in loading node (documents/ convention) | Keep — thin stable preview; port useMonacoTheme + monacoPreviewConfig together | ✓ read |
| 8 | src/components/documents/DocxPreview.tsx | Component | No | 128 | Organism | Proper Tabler icon + shared blockdata toolbar primitive | None 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 |
| 9 | src/components/documents/PdfPreview.tsx | Component | No | 144 | Organism | Proper direct pdfjs-dist composition (intentionally no React wrapper) | Hardcoded rgba — rgba(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 |
| 10 | src/components/documents/PdfResultsHighlighter.tsx | Component | No | 757 | Organism | Proper 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-* CSS | Keep — core results viewer; fix worker URL resolution; reconcile tokens; consider splitting pure JSON-pointer/docling-geometry helpers into tested lib | ✓ read |
| 11 | src/components/documents/PptxPreview.tsx | Component | No | 324 | Organism | Proper Tabler + cn; shared toolbar primitive; inputs/buttons hand-rolled native | None 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 |
| 12 | src/components/documents/pdf/PdfPageCanvas.tsx | Component | No | 50 | Atom | n/a — idiomatic pdfjs-dist direct render | None | Keep — clean single-responsibility canvas primitive | ✓ read |
| 13 | src/components/documents/pdf/PdfPreviewToolbar.tsx | Component | No | 86 | Molecule | Proper Tabler use via shared BD_WB_TABLER_ICON convention | None — 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 |
| 14 | src/components/documents/pdf/PdfTextLayer.tsx | Component | No | 68 | Atom | n/a — idiomatic pdfjs-dist TextLayer | None (depends on global .textLayer CSS from pdfjs, expected) | Keep — real coordinate layer (not a stub) | ✓ read |
| 15 | src/components/documents/pdf/pdfWorker.ts | Lib-Util | No | 18 | Logic | n/a — standard pdfjs-dist + Vite worker wiring | None — Vite-specific ?url import (bundler dependency) | Keep — adapt ?url suffix under non-Vite bundler | ✓ read |
| 16 | src/components/eval-designer/eval-designer-surface.css | Stylesheet | No | 525 | Style/Layout | n/a — properly themes React Flow via class overrides | Uses --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 |
| 17 | src/components/shell/HeaderCenterContext.tsx | Context | No | 48 | Logic | n/a — plain React context | None | Keep — standard slot-injection context for shell composition | ✓ read |
| 18 | src/components/shell/nav-config.ts | Lib-Util | No | 278 | Logic | Proper 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 |
| 19 | src/components/ui/checkbox.tsx | Component | No | 70 | Atom | Proper Ark UI Checkbox parts | Hardcoded hex — border-[#3a3a3a], focus #e2503f instead of --ds-*; inline non-Tabler <svg> checkmark | Refactor-to-primitive — replace hex with tokens; consider Tabler check icon | ✓ read |
| 20 | src/components/ui/dialog.tsx | Component | No | 154 | Organism | Proper Ark UI Dialog composition | Non-Tabler icon — Hugeicons Cancel01Icon; hardcoded hex #3a3a3a/#222221/#e2503f + raw rgb shadow | Refactor-to-primitive — swap Hugeicons for Tabler IconX; replace hex with tokens. Canonical dialog | ✓ read |
| 21 | src/components/ui/menu.tsx | Component | No | 184 | Organism | Proper Ark UI Menu composition | Non-Tabler icon — Lucide ChevronDownIcon (third icon lib); hardcoded hex #3a3a3a/#222221/#e2503f; depends on global ui-menu-* CSS | Refactor-to-primitive — replace Lucide chevron with Tabler IconChevronDown; tokenize hex; standardize icon lib | ✓ read |
| 22 | src/components/ui/splitter.tsx | Component | No | 68 | Molecule | Proper Ark UI Splitter parts | Hardcoded hex — #3a3a3a (divider), #111110 (indicator bg) + raw rgb shadow vs --ds-* | Refactor-to-primitive — replace hex/shadow with tokens | ✓ read |
| 23 | src/hooks/useBlockTypeRegistry.ts | Hook | No | 111 | Logic | Ad-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 |
| 24 | src/hooks/useDropboxChooser.ts | Hook | No | 116 | Logic | Ad-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 |
| 25 | src/hooks/useExternalScript.ts | Hook | No | 43 | Logic | Proper primitive — clean reusable utility | None | Keep — backend-agnostic; carries over unchanged | ✓ read |
| 26 | src/hooks/useGoogleDrivePicker.ts | Hook | No | 127 | Logic | Proper primitive — reuses useExternalScript; uses untyped (google.picker as any) casts | None (Google CDN scripts feature-intrinsic; ambient globals) | Keep — backend-agnostic; carries over unchanged | ✓ read |
| 27 | src/hooks/useMonacoTheme.ts | Hook | No | 23 | Logic | Proper primitive — textbook useSyncExternalStore | None ('light'/'vs-dark' are Monaco theme ids, not hex) | Keep — backend-agnostic; carries over unchanged | ✓ read |
| 28 | src/hooks/useProjectFocus.ts | Hook | No | 389 | Logic | Ad-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 |
| 29 | src/hooks/useStorageQuota.ts | Hook | No | 94 | Logic | Ad-hoc/hand-rolled — manual listener/singleton store + dedup (not React Query/useSyncExternalStore) | None | Keep — backend-agnostic via platformApiFetch; optionally migrate to React Query | ✓ read |
| 30 | src/lib/accountProfileApi.ts | Lib-API | No | 25 | Logic | Proper primitive — delegates to platformApiJson | None directly (Supabase coupling transitive via platformApi→authToken); doc comment references Supabase Auth updateUser | Keep — /profile mirror is the post-updateUser sync hook for Better-Auth/Neon | ✓ read |
| 31 | src/lib/authOAuthAttempts.ts | Lib-API | No | 183 | Logic | Ad-hoc/hand-rolled — raw fetch (NOT platformApiFetch), hardcoded /platform-api base, duplicates error parsing | None (no @supabase); hardcoded base path string | Keep, refactor — primary auth port seam; fronts Supabase OAuth callback flow; maps to Better-Auth callback hooks | ✓ read |
| 32 | src/lib/authRedirects.ts | Lib-Util | No | 19 | Logic | n/a — pure util | None | Keep — redirect origin handling carries to Better-Auth callback URLs | ✓ read |
| 33 | src/lib/authToken.ts | Lib-API | No | 17 | Logic | n/a — direct Supabase SDK use | Supabase 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 |
| 34 | src/lib/bdPreviewRuntimeApi.ts | Lib-API | No | 28 | Logic | Proper primitive — via platformApiJson | None directly | Keep — /blockdata/preview/renderer-bindings stable; auth via platformApi seam | ✓ read |
| 35 | src/lib/blockdataProjectFocus.ts | Lib-Util | No | 57 | Logic | n/a — plain web-storage + event bus | None | Keep — minimal cross-tab/intra-app focus sync; port verbatim | ✓ read |
| 36 | src/lib/blockdataWorkbenchAssetDrag.ts | Lib-Util | No | 41 | Logic | n/a — framework-agnostic DnD utility | None | Keep — small cohesive DnD contract; rename MIME namespace if app rebrands | ✓ read |
| 37 | src/lib/blockdataWorkbenchAssetsApi.ts | Lib-API | No | 489 | Logic | Proper primitive — TanStack via shared query-policy + keys; uses platformApiFetch | None (no @supabase; goes through platformApiFetch) | Keep — canonical asset data layer. Optionally split embedded useBlockdataWorkbenchAssets hook into hooks/ (low priority, cohesion high) | ✓ read |
| 38 | src/lib/blockdataWorkbenchChrome.ts | Lib-Util | No | 27 | Style | Proper primitive — centralizes Tabler icon props | None (pixel constants are geometry, not color hex) | Keep — tiny shared constant module; merge into broader DS constants file only if one exists | ✓ read |
| 39 | src/lib/blockdataWorkbenchJobs.ts | Lib-API | No | 579 | Logic | Proper primitive — shared keys + query policy + platformApiFetch; mock/integrated dual-path intentional A7 scaffolding | Cross-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 |
| 40 | src/lib/blockdataWorkbenchLayout.ts | Lib-Util | No | 373 | Logic | Proper primitive — pure math; sources AI width from styleTokens | None (router-outlet context type; no hardcoded hex) | Keep — well-factored geometry engine; structural duplication across four derive fns extractable (optional) | ✓ read |
| 41 | src/lib/blockdataWorkspaces.ts | Lib-API | No | 208 | Logic | Proper primitive — manual fetch+cache (intentionally pre-React-Query bootstrap); shared platformApiFetch | None | Keep — bootstrap singleton with cache/dedupe is deliberate; consider folding into TanStack later (optional) | ✓ read |
| 42 | src/lib/doclingOverlayColors.ts | Lib-Util | No | 78 | Logic | Ad-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 |
| 43 | src/lib/dsWorkbenchClasses.ts | Lib-Util | No | 21 | Style | Proper primitive — uses --ds-* tokens via Tailwind arbitrary values, not raw hex | None (all colors are var(--ds-*) tokens) | Keep — token-correct shared class strings; port as-is | ✓ read |
| 44 | src/lib/extractionSchemaHelpers.ts | Lib-Util | No | 203 | Logic | Proper primitive — standard useSyncExternalStore; Web Crypto hashing | None (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 |
| 45 | src/lib/extractionSchemasApi.ts | Lib-API | No | 93 | Logic | Proper primitive — routes all I/O through platformApi helpers; sound hand-rolled in-flight dedupe | None (PostgREST/Supabase deliberately avoided per header) | Keep — clean platform-api client; port as-is | ✓ read |
| 46 | src/lib/monacoPreviewConfig.ts | Lib-Util | No | 79 | Logic | Proper primitive — pure config/util | None (@monaco-editor/react only a label string, not imported) | Keep — pure, portable; copy as-is | ✓ read |
| 47 | src/lib/operationalReadiness.ts | Lib-API | No | 560 | Logic | Proper primitive — strong runtime validation, no ad-hoc fetch | supabase_admin_connectivity appears only as a string literal in OperationalReadinessProbeKind (label, not an import) — flag for readiness-rename sweep | Keep — blockdata SurfaceId + supabase_admin_connectivity probe-kind label are blockdata-specific; verify surface taxonomy on port | ✓ read |
| 48 | src/lib/parseApi.ts | Lib-API | No | 335 | Logic | Proper primitive — all via platformApiFetch | None directly; admin/blockdata-settings/base control-plane+profiles are near-duplicate triplets | Keep, consider merge — endpoints stable; triplication is a server-driven refactor candidate | ✓ read |
| 49 | src/lib/platformApi.ts | Lib-API | No | 228 | Logic | Proper primitive — THE canonical client primitive other api libs build on | Supabase seam — imports @/lib/supabase, calls supabase.auth.refreshSession() (fetch + upload retry); Bearer JWT is Supabase-issued | Refactor — central seam; replace refreshSession + JWT semantics with Better-Auth token refresh; keep relative /platform-api proxy + retry-once-on-401 | ✓ read |
| 50 | src/lib/platformWorkspace.ts | Lib-API | No | 257 | Logic | Proper primitive — all via platformApiFetch | None directly (auth via platformApi seam); localStorage only | Keep — orgs/membership/invites are platform-API concerns; user_id comes from Better-Auth post-port. Endpoints stable | ✓ read |
| 51 | src/lib/projectDetailHelpers.ts | Lib-Util | No | 353 | Logic | Proper primitive for the one API call; rest pure utils | None (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 |
| 52 | src/lib/projectFocus.ts | Lib-Util | No | 32 | Logic | n/a — pure util | None | Keep — client-only state, no backend/auth dependency; ports verbatim | ✓ read |
| 53 | src/lib/projectsApi.ts | Lib-API | No | 73 | Logic | Proper primitive — via platformApiFetch | None directly | Keep — endpoints stable; organization_id scoping ties to platform org identity; auth via platformApi/Supabase seam | ✓ read |
| 54 | src/lib/queryClient.ts | Lib-Util | No | 27 | Logic | Proper primitive — standard TanStack Query setup; testMode disables retries | None | Keep — backend-agnostic; carries over unchanged | ✓ read |
| 55 | src/lib/queryKeys/blockdataWorkbenchKeys.ts | Lib-Util | No | 126 | Logic | Proper primitive — centralized key factory; all as const | None | Keep — required hub; do not inline keys at call sites; port verbatim | ✓ read |
| 56 | src/lib/reactQuery/appQueryDefaults.ts | Lib-Util | No | 7 | Logic | Proper primitive — centralizes query defaults | None | Keep — base config constant; port as-is | ✓ read |
| 57 | src/lib/reactQuery/blockdataWorkbenchQueryPolicy.ts | Lib-Util | No | 17 | Logic | Proper primitive — derives gc from app default | None | Keep — central timing policy; port with appQueryDefaults | ✓ read |
| 58 | src/lib/storageUploadService.ts | Lib-API | No | 265 | Logic | Proper primitive — server-proxied upload (avoids browser→storage CORS); @noble/hashes for hashing | None — no @supabase; uploads route through platform-api, not Supabase storage SDK | Keep — core upload service; storage_surface:'assets' is blockdata-aware, confirm on port | ✓ read |
| 59 | src/lib/styleTokens.ts | Lib-Util | No | 109 | Style | Ad-hoc/hand-rolled (partial) — most semantic colors are CSS-var tokens, but grid.light/dark + gradient rgba are hardcoded | Hardcoded hex/rgba — grid hex (#ffffff,#faf9f7,#1c1917,#d6d3d1,#78716c,#09090b,#fafafa,#27272a,#a1a1aa) + gradient rgba; blockdata-named dims | Refactor — migrate grid hex + gradient rgba to design tokens; review blockdata-specific dims; keep layout dims + CSS-var sections | ✓ read |
| 60 | src/lib/supabase.ts | Lib-API | No | 10 | Logic | n/a — direct vendor SDK; exactly what migration removes | Supabase seam (PRIMARY removal target) — @supabase/supabase-js createClient; two VITE_SUPABASE_* env vars; central coupling point | Refactor/remove — eliminate client; migrate all consumers to platform-api; track every importer of @/lib/supabase. Highest-priority decoupling target | ✓ read |
| 61 | src/lib/types.ts | Types | No | 278 | Logic | n/a — type declarations only | None (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 |
| 62 | src/lib/uploadReservationRecovery.ts | Lib-API | No | 101 | Logic | Proper primitive — typed error class, single retry, idempotent cleanup | None | Keep — tightly coupled to storageUploadService; port together | ✓ read |
| 63 | src/lib/useIsDark.ts | Hook | No | 30 | Logic | Proper primitive — idiomatic useSyncExternalStore | None | Keep — clean, framework-portable theme hook | ✓ read |
| 64 | src/lib/utils.ts | Lib-Util | No | 7 | Atom | Proper primitive — canonical clsx + tailwind-merge cn | None | Keep — ubiquitous primitive; copy verbatim | ✓ read |
| 65 | src/lib/workbenchCloudImport.ts | Lib-API | No | 46 | Logic | Proper primitive — reuses upload response parser + platformApiFetch | None (Google/Dropbox are own-backend endpoints, not client SDKs) | Keep — thin provider clients; port with upload module | ✓ read |
| 66 | src/lib/workbenchFolderCatalog.ts | Lib-Util | No | 57 | Logic | n/a — pure data transforms (time formatting injected) | None | Keep — clean pure helpers with cycle guard; port verbatim | ✓ read |
| 67 | src/pages/BlockdataWorkbenchPage.css | Stylesheet | No | 211 | Style | n/a (pure CSS) | None — uses --ds-* tokens + color-mix(in oklab); no hex/rgba, no icons | Direct lift; ensure --ds-* tokens + blockdata-* classes (filter-chip, upload-progress, asset-filter-row) travel | ✓ read |
| 68 | src/pages/BlockdataWorkbenchPage.tsx | Route | Yes — /app/blockdata/workbench, /app/blockdata/workbench/schemas, /app/blockdata/workbench/jobs | 1436 | Page/Route | Compliant — Ark UI Splitter, Tabler icons | None — Supabase-free (all via abstracted API helpers); Tabler-only | Split candidate (1,436 LOC; page + 8 internal components). Re-point upload + workbench API helpers to Neon/Better-Auth; keep Ark Splitter | ✓ read |
| 69 | src/pages/blockdata-db-workbench/workbenchTypes.ts | Types | No | 65 | Logic | n/a | None (hardcoded base path is a route literal, legitimate) | Keep — canonical route-builder module; drop DB_WORKBENCH_BASE deprecated alias once callers migrate | ✓ read |
| 70 | src/pages/blockdata/BlockdataAssetTablePane.tsx | Component | No | 1825 | Organism (whole assets column/table pane) | Compliant — Ark UI checkbox/menu wrappers, Tabler icons | None in-file (no Supabase/auth); Tabler-only; heavy --ds-* + blockdata-* class reliance | Split 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 |
| 71 | src/pages/blockdata/BlockdataAssetsDockLayer.tsx | Component | No | 116 | Layout (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 CSS | Direct lift; tokenize the #111111 background; confirm dockview in target deps | ✓ read |
| 72 | src/pages/blockdata/BlockdataPreviewToolbar.tsx | Component | No | 97 | Molecule (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/DB | Direct lift; ensure --ds-* tokens + --bd-wb-preview-toolbar var travel | ✓ read |
| 73 | src/pages/blockdata/BlockdataSchemaEditor.tsx | Component | No | 951 | Organism (Visual/Split/Code schema editor) | Compliant — Ark UI Select/Splitter, Tabler icons | Hardcoded 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 extractionSchemaHelpers | Split 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 |
| 74 | src/pages/blockdata/BlockdataSchemasModal.tsx | Component | No | 233 | Organism (modal master/detail shell) | Compliant — Ark UI dialog + first-party dialog wrappers, Tabler icons | None — 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 |
| 75 | src/pages/blockdata/BlockdataSqlConnectionsRoute.tsx | Route | Yes — /app/blockdata/workbench/database | 11 | Page/Route (redirect shim) | n/a (no UI primitives — renders <Navigate>) | None — no Supabase/auth, no icons, no state/effects | Direct lift (11 LOC redirect shim); merge candidate if a routing index consolidates redirects | ✓ read |
| 76 | src/pages/blockdata/FolderNameEditor.tsx | Component | No | 94 | Molecule (inline rename/create field) | n/a (plain controlled <input>; no Ark/Tabler) | None — uses --ds-* tokens only; no icons; backend-agnostic | Direct lift; ensure --ds-* tokens (border-strong, canvas, text, brand, brand-tint-faint) exist in target | ✓ read |
| 77 | src/pages/blockdata/RunJobModal.tsx | Component | No | 285 | Organism | Proper 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 imports | Keep — self-contained, API-injected modal; port as-is, swap raw buttons for shared Button primitive if standardized | ✓ read |
| 78 | src/pages/blockdata/hooks/useBlockdataSchemas.ts | Hook | No | 106 | Logic | n/a (pure hook, no UI primitives) | None — explicitly platform-api only (no @supabase); all first-party imports | Keep — clean injected data hook; minor refactor: make deleteSchema optimistic for parity with create/update | ✓ read |
| 79 | src/pages/blockdata/lib/blockdataPreviewRegistry.tsx | Lib-Util | No | 825 | Logic + Organism | Proper Tabler (IconHash) + react-markdown/remark; mixed registry data + multiple React components in one file is structurally ad-hoc | Hardcoded 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 |
| 80 | src/pages/blockdata/lib/blockdataSchemaHelpers.ts | Lib-Util | No | 188 | Logic | n/a (no UI); Web Crypto API | None — zero imports, no Supabase/styling/cross-feature; self-contained fork | Keep — clean self-contained domain util; port as-is. Future: canonical-JSON hashing for order-independent computeSchemaUid | ✓ read |
| 81 | src/stores/uploadsStore.ts | Store | No | 143 | Logic | Proper primitive — idiomatic Zustand; integrates React Query via queryClient invalidation | None 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
| Level | Count | Files |
|---|---|---|
| Atom | 3 | utils.ts; pdf/PdfPageCanvas.tsx; pdf/PdfTextLayer.tsx |
| Molecule | 5 | RunJobConfigForm.tsx; CodePreview.tsx; pdf/PdfPreviewToolbar.tsx; splitter.tsx; FolderNameEditor.tsx |
| Organism | 11 | PipelineBar.tsx; DocxPreview.tsx; PdfPreview.tsx; PdfResultsHighlighter.tsx; PptxPreview.tsx; dialog.tsx; menu.tsx; RunJobModal.tsx; BlockdataSchemaEditor.tsx; BlockdataSchemasModal.tsx; BlockdataAssetTablePane.tsx |
| Layout | 1 | BlockdataAssetsDockLayer.tsx |
| Page/Route | 3 | BlockdataWorkbenchPage.tsx; BlockdataSqlConnectionsRoute.tsx; (BlockdataPreviewToolbar.tsx = Molecule+Logic, counted under Molecule) |
| Logic | 53 | all 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.) |
| Style | 5 | ShellHeaderTitle.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) andblockdataPreviewRegistry.tsx(Logic + Organism). Theeval-designer-surface.cssis 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(needsdata-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(notplatformApiFetch), hardcoded/platform-apibase, 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-jscreateClient; the client singleton (PRIMARY removal target). - src/auth/AuthContext.tsx —
@supabase/supabase-js(Session/User types) +@/lib/supabaseclient; 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.tsx —
rgba(238,238,238,…),rgba(0,0,0,0.4),rgba(120,170,255,0.14). - BlockdataAssetsDockLayer.tsx —
#111111panel bg. - BlockdataSchemaEditor.tsx —
#0e0e0e,#3B82F6,rgba(120,170,255,…),#111111; inline Monacoblockdata-darktheme. - blockdataPreviewRegistry.tsx —
MARKDOWN_PROSE_DARKblock,#3B82F6,#FFC470,#0e0e0e,rgba(255,255,255,…)(intentional dark prose, day/night viauseIsDark). - doclingOverlayColors.ts —
#0ea5e9,rgba(14,165,233,0.14),#f59e0b,#d97706,#38bdf8. - styleTokens.ts —
gridhex (#ffffff,#faf9f7,#1c1917,#d6d3d1,#78716c,#09090b,#fafafa,#27272a,#a1a1aa) + gradient rgba. - eval-designer-surface.css —
rgba(0,0,0,0.12)box-shadow (L473).
(c) Non-Tabler icons / cross-feature imports / dead refs:
- Non-Tabler icons:
dialog.tsx(HugeiconsCancel01Icon);menu.tsx(LucideChevronDownIcon);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.tsxuse shadcn--foreground/--muted-foreground/bg-primary/text-muted-foreground;eval-designer-surface.cssuses a third--app-workspace-*namespace. - Cross-feature / layering inversions:
blockdataWorkbenchJobs.ts(lib up-imports types fromcomponents/blockdata/*+pages/blockdata/RunJobModal);DocxPreview.tsx/PptxPreview.tsx/PdfPreview.tsx/pdf/PdfPreviewToolbar.tsx(components import frompages/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-schemaIconDotsVerticalactions placeholder);nav-config.ts(possibly-redundantSHARED_STATIC_SECTIONS/BLOCKDATA_NAV_SECTIONSbreadth, emptyBOTTOM_RAIL_NAV);types.ts(Run/BlockOverlay vs Extraction* families flagged possibly legacy/dead);PdfResultsHighlighter.tsxbrittle deepnode_modules/.../pdf.worker.min.mjspath.
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*Classconsts out ofpages/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.
Non-auth inventory (file by file)
Every code file in the non-auth surface, traced front-to-back, page by page, with backend owners and entanglement flags.
Stack comparison: blockdata vs. AI-agent template
Layer-by-layer — what blockdata adopts, keeps, swaps, or still has to decide if the vstorm full-stack-ai-agent-template's Python backend becomes the base.