chore(ui): add platform migration baseline audit

This commit is contained in:
Saravana Achu Mac 2026-05-06 13:46:10 -07:00
parent 5cc5c8af37
commit f0cdfe6776
5 changed files with 189 additions and 75 deletions

View File

@ -3,7 +3,14 @@ const path = require('node:path');
const PACKAGE_SCOPE = '@bytelyst/';
const PACKAGE_SOURCE = process.env.BYTELYST_PACKAGE_SOURCE || 'vendor';
const COMMON_PLAT_ROOT = process.env.BYTELYST_COMMON_PLAT_ROOT || '/opt/bytelyst/learning_ai_common_plat';
const DEFAULT_COMMON_PLAT_ROOTS = [
path.resolve(__dirname, '..', 'learning_ai_common_plat'),
'/opt/bytelyst/learning_ai_common_plat',
];
const COMMON_PLAT_ROOT =
process.env.BYTELYST_COMMON_PLAT_ROOT ||
DEFAULT_COMMON_PLAT_ROOTS.find((candidate) => fs.existsSync(path.join(candidate, 'packages'))) ||
DEFAULT_COMMON_PLAT_ROOTS[0];
const COMMON_PLAT_PACKAGES_ROOT = path.join(COMMON_PLAT_ROOT, 'packages');
const VENDOR_PACKAGES_ROOT = path.join(__dirname, 'vendor', 'bytelyst');
const VERSION_CACHE = new Map();

View File

@ -0,0 +1,41 @@
# UI/UX Platform Core Migration Roadmap
Live source of truth for migrating `learning_ai_invt_trdg` UI/UX and platform clients onto the shared ByteLyst common platform at `/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat`.
## Current Baseline
- Product repo: `/Users/saravana/BytelystAI/learning_ai/learning_ai_invt_trdg`
- Common platform repo: `/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat`
- Local package toggle: `BYTELYST_PACKAGE_SOURCE=common-plat pnpm install -r`
- Current common-platform usage: `@bytelyst/api-client`, `@bytelyst/config`, `@bytelyst/errors`, `@bytelyst/kill-switch-client`, `@bytelyst/react-auth`, `@bytelyst/react-native-platform-sdk`, `@bytelyst/telemetry-client`
- UI duplicates to migrate: local `web/src/components/ui/*`, raw HTML controls, legacy global surface classes, hardcoded color literals, local status/surface/list/table patterns
- Common UI target: `@bytelyst/ui`
- Design token target: `@bytelyst/design-tokens` with product aliases to `--bl-*`
## Component Ownership
- Common platform core UI (`learning_ai_common_plat/packages/ui`): product-agnostic primitives such as Button, IconButton, Card, Panel, Surface, Badge, StatusBadge, StatusDot, Input, Textarea, Select, Label, Checkbox, RadioGroup, Switch, Tabs, SegmentedControl, DropdownMenu, Tooltip, Modal, ConfirmDialog, DataList, DataTable, Timeline, DiffCard, EmptyState, LoadingSpinner, Sidebar/AppShell base pieces.
- Product UI adapter (`web/src/components/ui/Primitives.tsx`, to be added): imports from `@bytelyst/ui`, maps product defaults, status tones, density, radius, focus behavior, and preserves trading-domain composition locally.
- Product-owned UI: trading workflows, strategy/risk/execution domain composition, charts, order lifecycle views, and product-specific copy/state.
## Roadmap
| Status | Phase | Scope / Repo | Implementation Summary | Verification Commands | Commit Hash | Notes / Deferrals |
|---|---|---|---|---|---|---|
| [ ] | 1. Baseline audit and package-source rules | product | Add UI drift audit script and package scripts; document ownership; keep local common-platform resolution available through sibling checkout without editing `.npmrc`. | `pnpm run audit:ui`; `pnpm run audit:ui:strict` expected to fail during debt baseline; `node -e "require('./.pnpmfile.cjs')"`; `git diff --check` | Pending | Strict audit remains disabled until cleanup phase. |
| [ ] | 2. Common-platform package inventory | product + common | Map product needs to existing common packages for UI, design tokens, platform/auth/session, telemetry, diagnostics, feature flags, kill switch, blob/extraction/offline/broadcast/billing/feedback/survey, datastore/config/errors. | `rg "@bytelyst/" --glob '!node_modules/**'`; common package export inspection | Pending | Record any missing common-platform gaps before product migration. |
| [ ] | 3. Common-platform UI gap closure | common | Add or adjust reusable primitives only if product migration discovers missing generic capability. | `pnpm --filter @bytelyst/ui run build`; `pnpm --filter @bytelyst/ui exec eslint src --ext .ts,.tsx`; `git diff --check` | Pending | Defer if current `@bytelyst/ui` coverage is enough. |
| [ ] | 4. Product UI adapter foundation | product | Add `web/src/components/ui/Primitives.tsx` wrapping/re-exporting `@bytelyst/ui`; add `@bytelyst/ui` and `@bytelyst/design-tokens` dependencies through local common-platform resolution. | `BYTELYST_PACKAGE_SOURCE=common-plat pnpm install -r`; `pnpm --filter @bytelyst/trading-web typecheck`; `pnpm run audit:ui`; `git diff --check` | Pending | Direct `@bytelyst/ui` imports should be isolated to adapter. |
| [ ] | 5. Design token alias foundation | product | Import shared design tokens and add global aliases from product tokens to `--bl-*` in web CSS. | `pnpm --filter @bytelyst/trading-web typecheck`; `pnpm --filter @bytelyst/trading-web test -- --runInBand` if supported; `pnpm run audit:ui`; `git diff --check` | Pending | Keep visual behavior stable while aliases are introduced. |
| [ ] | 6. Highest-value workflow migration | product | Migrate the top operator workflow first, preserving E2E-visible text and behavior while replacing raw controls/surfaces with adapter primitives. | Focused DOM tests for changed workflow; `pnpm --filter @bytelyst/trading-web typecheck`; `pnpm run audit:ui`; `git diff --check` | Pending | Candidate workflow: positions / trade plan navigation based on recent active changes. |
| [ ] | 7. Forms, modals, and settings migration | product | Migrate auth/settings/share/create/edit forms to adapter primitives and common modal/dialog patterns. | Focused DOM tests; `pnpm --filter @bytelyst/trading-web typecheck`; `pnpm run audit:ui`; `git diff --check` | Pending | Verify labels and keyboard interaction. |
| [ ] | 8. Dashboard, search, and workspace migration | product | Migrate cards/lists/tables/filter chips to Panel, DataList, DataTable, Badge, StatusBadge, and EmptyState. | Focused DOM tests; responsive smoke where available; `pnpm --filter @bytelyst/trading-web typecheck`; `pnpm run audit:ui`; `git diff --check` | Pending | Preserve dense operational layout. |
| [ ] | 9. Advanced product-specific surfaces | product | Keep trading-domain logic local while using common primitives for shells, toolbars, menus, panels, lists, status, and diffs. | Focused DOM/unit tests; `pnpm --filter @bytelyst/trading-web typecheck`; `pnpm run audit:ui`; `git diff --check` | Pending | Charts and strategy logic remain product-owned. |
| [ ] | 10. Legacy global cleanup and strict audit | product | Remove or greatly reduce old global classes and hardcoded literals; enable strict audit only after accepted debt is cleared. | `pnpm run audit:ui:strict`; `pnpm verify`; `pnpm lint`; `git diff --check` | Pending | Strict mode intentionally fails until this phase. |
## Running Notes
- Do not hand-edit `.npmrc`.
- Do not move trading-domain behavior into common platform.
- Keep Gitea and vendor support available; use local common platform for implementation and verification.
- Commit and push each implementation step, then update this roadmap with commit hash and verification notes in a separate commit.

View File

@ -6,6 +6,8 @@
"type": "module",
"scripts": {
"build": "pnpm --filter @bytelyst/trading-backend build && pnpm --filter @bytelyst/trading-web build && pnpm --filter @bytelyst/trading-mobile typecheck",
"audit:ui": "sh ./scripts/ui-drift-audit.sh",
"audit:ui:strict": "sh ./scripts/ui-drift-audit.sh strict",
"install:common-plat": "BYTELYST_PACKAGE_SOURCE=common-plat pnpm install -r",
"install:gitea": "BYTELYST_PACKAGE_SOURCE=gitea pnpm install -r",
"install:vendor": "BYTELYST_PACKAGE_SOURCE=vendor pnpm install -r",

148
pnpm-lock.yaml generated
View File

@ -4,24 +4,24 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
pnpmfileChecksum: sha256-ypESUoPlssLlRML8QDi8l46Bgd4uvEzkW98AojoOXw4=
pnpmfileChecksum: sha256-9nrEUcRW1dVQY29GEuBWlallHSWZBRpsHo3Y3rZLLdw=
importers:
.:
dependencies:
'@bytelyst/kill-switch-client':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/kill-switch-client
version: file:vendor/bytelyst/kill-switch-client
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/kill-switch-client
version: file:../learning_ai_common_plat/packages/kill-switch-client
'@bytelyst/react-auth':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/react-auth
version: file:vendor/bytelyst/react-auth(react@19.2.4)
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/react-auth
version: file:../learning_ai_common_plat/packages/react-auth(react@19.2.4)
'@bytelyst/react-native-platform-sdk':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/react-native-platform-sdk
version: file:vendor/bytelyst/react-native-platform-sdk(expo@54.0.33)(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4)
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/react-native-platform-sdk
version: file:../learning_ai_common_plat/packages/react-native-platform-sdk(expo@54.0.33)(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4)
'@bytelyst/telemetry-client':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/telemetry-client
version: file:vendor/bytelyst/telemetry-client
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/telemetry-client
version: file:../learning_ai_common_plat/packages/telemetry-client
devDependencies:
typescript:
specifier: ^5.9.3
@ -42,17 +42,17 @@ importers:
specifier: ^4.9.0
version: 4.10.0(@azure/core-client@1.10.1)
'@bytelyst/auth':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/auth
version: file:vendor/bytelyst/auth(bcryptjs@3.0.3)(jose@6.2.2)
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/auth
version: file:../learning_ai_common_plat/packages/auth(bcryptjs@3.0.3)(jose@6.2.2)
'@bytelyst/config':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/config
version: file:vendor/bytelyst/config(@azure/identity@4.13.1)(@azure/keyvault-secrets@4.10.0(@azure/core-client@1.10.1))(zod@4.3.6)
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/config
version: file:../learning_ai_common_plat/packages/config(@azure/identity@4.13.1)(@azure/keyvault-secrets@4.10.0(@azure/core-client@1.10.1))(zod@4.3.6)
'@bytelyst/cosmos':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/cosmos
version: file:vendor/bytelyst/cosmos(@azure/cosmos@4.9.2(@azure/core-client@1.10.1))
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/cosmos
version: file:../learning_ai_common_plat/packages/cosmos(@azure/cosmos@4.9.2(@azure/core-client@1.10.1))
'@bytelyst/llm':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/llm
version: file:vendor/bytelyst/llm
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/llm
version: file:../learning_ai_common_plat/packages/llm
'@supabase/supabase-js':
specifier: ^2.90.1
version: 2.101.1
@ -106,14 +106,14 @@ importers:
mobile:
dependencies:
'@bytelyst/kill-switch-client':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/kill-switch-client
version: file:vendor/bytelyst/kill-switch-client
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/kill-switch-client
version: file:../learning_ai_common_plat/packages/kill-switch-client
'@bytelyst/react-native-platform-sdk':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/react-native-platform-sdk
version: file:vendor/bytelyst/react-native-platform-sdk(expo@54.0.33)(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/react-native-platform-sdk
version: file:../learning_ai_common_plat/packages/react-native-platform-sdk(expo@54.0.33)(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)
'@bytelyst/telemetry-client':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/telemetry-client
version: file:vendor/bytelyst/telemetry-client
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/telemetry-client
version: file:../learning_ai_common_plat/packages/telemetry-client
'@expo-google-fonts/inter':
specifier: ^0.4.2
version: 0.4.2
@ -245,20 +245,20 @@ importers:
web:
dependencies:
'@bytelyst/api-client':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/api-client
version: file:vendor/bytelyst/api-client
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/api-client
version: file:../learning_ai_common_plat/packages/api-client
'@bytelyst/errors':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/errors
version: file:vendor/bytelyst/errors
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/errors
version: file:../learning_ai_common_plat/packages/errors
'@bytelyst/kill-switch-client':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/kill-switch-client
version: file:vendor/bytelyst/kill-switch-client
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/kill-switch-client
version: file:../learning_ai_common_plat/packages/kill-switch-client
'@bytelyst/react-auth':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/react-auth
version: file:vendor/bytelyst/react-auth(react@19.2.4)
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/react-auth
version: file:../learning_ai_common_plat/packages/react-auth(react@19.2.4)
'@bytelyst/telemetry-client':
specifier: file:/opt/bytelyst/trading/learning_ai_invt_trdg/vendor/bytelyst/telemetry-client
version: file:vendor/bytelyst/telemetry-client
specifier: file:/Users/saravana/BytelystAI/learning_ai/learning_ai_common_plat/packages/telemetry-client
version: file:../learning_ai_common_plat/packages/telemetry-client
'@dnd-kit/core':
specifier: ^6.3.1
version: 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@ -990,17 +990,17 @@ packages:
resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==}
hasBin: true
'@bytelyst/api-client@file:vendor/bytelyst/api-client':
resolution: {directory: vendor/bytelyst/api-client, type: directory}
'@bytelyst/api-client@file:../learning_ai_common_plat/packages/api-client':
resolution: {directory: ../learning_ai_common_plat/packages/api-client, type: directory}
'@bytelyst/auth@file:vendor/bytelyst/auth':
resolution: {directory: vendor/bytelyst/auth, type: directory}
'@bytelyst/auth@file:../learning_ai_common_plat/packages/auth':
resolution: {directory: ../learning_ai_common_plat/packages/auth, type: directory}
peerDependencies:
bcryptjs: '>=2.4.0'
jose: '>=5.0.0'
'@bytelyst/config@file:vendor/bytelyst/config':
resolution: {directory: vendor/bytelyst/config, type: directory}
'@bytelyst/config@file:../learning_ai_common_plat/packages/config':
resolution: {directory: ../learning_ai_common_plat/packages/config, type: directory}
peerDependencies:
'@azure/identity': '>=4.0.0'
'@azure/keyvault-secrets': '>=4.8.0'
@ -1011,34 +1011,34 @@ packages:
'@azure/keyvault-secrets':
optional: true
'@bytelyst/cosmos@file:vendor/bytelyst/cosmos':
resolution: {directory: vendor/bytelyst/cosmos, type: directory}
'@bytelyst/cosmos@file:../learning_ai_common_plat/packages/cosmos':
resolution: {directory: ../learning_ai_common_plat/packages/cosmos, type: directory}
peerDependencies:
'@azure/cosmos': '>=4.0.0'
'@bytelyst/errors@file:vendor/bytelyst/errors':
resolution: {directory: vendor/bytelyst/errors, type: directory}
'@bytelyst/errors@file:../learning_ai_common_plat/packages/errors':
resolution: {directory: ../learning_ai_common_plat/packages/errors, type: directory}
'@bytelyst/kill-switch-client@file:vendor/bytelyst/kill-switch-client':
resolution: {directory: vendor/bytelyst/kill-switch-client, type: directory}
'@bytelyst/kill-switch-client@file:../learning_ai_common_plat/packages/kill-switch-client':
resolution: {directory: ../learning_ai_common_plat/packages/kill-switch-client, type: directory}
'@bytelyst/llm@file:vendor/bytelyst/llm':
resolution: {directory: vendor/bytelyst/llm, type: directory}
'@bytelyst/llm@file:../learning_ai_common_plat/packages/llm':
resolution: {directory: ../learning_ai_common_plat/packages/llm, type: directory}
'@bytelyst/react-auth@file:vendor/bytelyst/react-auth':
resolution: {directory: vendor/bytelyst/react-auth, type: directory}
'@bytelyst/react-auth@file:../learning_ai_common_plat/packages/react-auth':
resolution: {directory: ../learning_ai_common_plat/packages/react-auth, type: directory}
peerDependencies:
react: '>=18.0.0'
'@bytelyst/react-native-platform-sdk@file:vendor/bytelyst/react-native-platform-sdk':
resolution: {directory: vendor/bytelyst/react-native-platform-sdk, type: directory}
'@bytelyst/react-native-platform-sdk@file:../learning_ai_common_plat/packages/react-native-platform-sdk':
resolution: {directory: ../learning_ai_common_plat/packages/react-native-platform-sdk, type: directory}
peerDependencies:
expo: '>=49.0.0'
react: '>=18.0.0'
react-native: '>=0.72.0'
'@bytelyst/telemetry-client@file:vendor/bytelyst/telemetry-client':
resolution: {directory: vendor/bytelyst/telemetry-client, type: directory}
'@bytelyst/telemetry-client@file:../learning_ai_common_plat/packages/telemetry-client':
resolution: {directory: ../learning_ai_common_plat/packages/telemetry-client, type: directory}
'@colors/colors@1.6.0':
resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==}
@ -7442,49 +7442,49 @@ snapshots:
dependencies:
css-tree: 3.2.1
'@bytelyst/api-client@file:vendor/bytelyst/api-client': {}
'@bytelyst/api-client@file:../learning_ai_common_plat/packages/api-client': {}
'@bytelyst/auth@file:vendor/bytelyst/auth(bcryptjs@3.0.3)(jose@6.2.2)':
'@bytelyst/auth@file:../learning_ai_common_plat/packages/auth(bcryptjs@3.0.3)(jose@6.2.2)':
dependencies:
'@bytelyst/errors': file:vendor/bytelyst/errors
'@bytelyst/errors': file:../learning_ai_common_plat/packages/errors
bcryptjs: 3.0.3
jose: 6.2.2
'@bytelyst/config@file:vendor/bytelyst/config(@azure/identity@4.13.1)(@azure/keyvault-secrets@4.10.0(@azure/core-client@1.10.1))(zod@4.3.6)':
'@bytelyst/config@file:../learning_ai_common_plat/packages/config(@azure/identity@4.13.1)(@azure/keyvault-secrets@4.10.0(@azure/core-client@1.10.1))(zod@4.3.6)':
dependencies:
zod: 4.3.6
optionalDependencies:
'@azure/identity': 4.13.1
'@azure/keyvault-secrets': 4.10.0(@azure/core-client@1.10.1)
'@bytelyst/cosmos@file:vendor/bytelyst/cosmos(@azure/cosmos@4.9.2(@azure/core-client@1.10.1))':
'@bytelyst/cosmos@file:../learning_ai_common_plat/packages/cosmos(@azure/cosmos@4.9.2(@azure/core-client@1.10.1))':
dependencies:
'@azure/cosmos': 4.9.2(@azure/core-client@1.10.1)
'@bytelyst/errors@file:vendor/bytelyst/errors': {}
'@bytelyst/errors@file:../learning_ai_common_plat/packages/errors': {}
'@bytelyst/kill-switch-client@file:vendor/bytelyst/kill-switch-client': {}
'@bytelyst/kill-switch-client@file:../learning_ai_common_plat/packages/kill-switch-client': {}
'@bytelyst/llm@file:vendor/bytelyst/llm': {}
'@bytelyst/llm@file:../learning_ai_common_plat/packages/llm': {}
'@bytelyst/react-auth@file:vendor/bytelyst/react-auth(react@19.2.4)':
'@bytelyst/react-auth@file:../learning_ai_common_plat/packages/react-auth(react@19.2.4)':
dependencies:
'@bytelyst/api-client': file:vendor/bytelyst/api-client
'@bytelyst/api-client': file:../learning_ai_common_plat/packages/api-client
react: 19.2.4
'@bytelyst/react-native-platform-sdk@file:vendor/bytelyst/react-native-platform-sdk(expo@54.0.33)(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)':
'@bytelyst/react-native-platform-sdk@file:../learning_ai_common_plat/packages/react-native-platform-sdk(expo@54.0.33)(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)':
dependencies:
expo: 54.0.33(@babel/core@7.29.0)(@expo/metro-runtime@6.1.2)(expo-router@6.0.23)(react-native-webview@13.15.0(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)
react: 19.1.0
react-native: 0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.1.0)
'@bytelyst/react-native-platform-sdk@file:vendor/bytelyst/react-native-platform-sdk(expo@54.0.33)(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4)':
'@bytelyst/react-native-platform-sdk@file:../learning_ai_common_plat/packages/react-native-platform-sdk(expo@54.0.33)(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4)':
dependencies:
expo: 54.0.33(@babel/core@7.29.0)(@expo/metro-runtime@6.1.2)(expo-router@6.0.23)(react-native-webview@13.15.0(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(react-native@0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4)
react: 19.2.4
react-native: 0.81.4(@babel/core@7.29.0)(@react-native/metro-config@0.84.1(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4)
'@bytelyst/telemetry-client@file:vendor/bytelyst/telemetry-client': {}
'@bytelyst/telemetry-client@file:../learning_ai_common_plat/packages/telemetry-client': {}
'@colors/colors@1.6.0': {}
@ -10804,9 +10804,9 @@ snapshots:
'@typescript-eslint/eslint-plugin': 8.58.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.4(jiti@2.6.1)
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1))
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1))
eslint-plugin-expo: 1.0.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1))
eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@2.6.1))
eslint-plugin-react-hooks: 5.2.0(eslint@9.39.4(jiti@2.6.1))
globals: 16.5.0
@ -10824,7 +10824,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)):
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.3
@ -10835,18 +10835,18 @@ snapshots:
tinyglobby: 0.2.15
unrs-resolver: 1.11.1
optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)):
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.4(jiti@2.6.1)
eslint-import-resolver-node: 0.3.10
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1))
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
@ -10859,7 +10859,7 @@ snapshots:
- supports-color
- typescript
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)):
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@ -10870,7 +10870,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.39.4(jiti@2.6.1)
eslint-import-resolver-node: 0.3.10
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1))
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3

64
scripts/ui-drift-audit.sh Executable file
View File

@ -0,0 +1,64 @@
#!/usr/bin/env sh
set -eu
MODE="${1:-report}"
ROOT_DIR="$(CDPATH= cd "$(dirname "$0")/.." && pwd -P)"
WEB_SRC="${ROOT_DIR}/web/src"
if [ ! -d "${WEB_SRC}" ]; then
echo "error: web source directory not found: ${WEB_SRC}" >&2
exit 2
fi
RG_BASE='--glob=*.ts --glob=*.tsx --glob=*.css --glob=!**/*.test.ts --glob=!**/*.test.tsx --glob=!**/*.dom.test.tsx --glob=!**/test/** --glob=!**/assets/**'
APPROVED_UI_GLOB='!components/ui/**'
section() {
printf '\n== %s ==\n' "$1"
}
count_matches() {
pattern="$1"
shift
# shellcheck disable=SC2086
rg -n $RG_BASE "$@" "${pattern}" "${WEB_SRC}" | wc -l | tr -d ' '
}
print_matches() {
pattern="$1"
shift
# shellcheck disable=SC2086
rg -n $RG_BASE "$@" "${pattern}" "${WEB_SRC}" || true
}
raw_controls_count="$(count_matches '<(button|input|textarea|select)(\s|>)' --glob="${APPROVED_UI_GLOB}")"
legacy_classes_count="$(count_matches '\b(surface-card|surface-muted|badge|input-shell)\b')"
hardcoded_colors_count="$(count_matches '(#[0-9a-f]{3,8}\b|rgba?\()')"
direct_common_ui_count="$(count_matches '@bytelyst/ui' --glob="${APPROVED_UI_GLOB}")"
echo "UI drift audit mode=${MODE}"
echo "raw interactive controls outside approved primitives: ${raw_controls_count}"
echo "legacy global surface classes: ${legacy_classes_count}"
echo "hardcoded color literals: ${hardcoded_colors_count}"
echo "direct @bytelyst/ui imports outside product adapter: ${direct_common_ui_count}"
section "Raw Interactive Controls"
print_matches '<(button|input|textarea|select)(\s|>)' --glob="${APPROVED_UI_GLOB}"
section "Legacy Global Surface Classes"
print_matches '\b(surface-card|surface-muted|badge|input-shell)\b'
section "Hardcoded Color Literals"
print_matches '(#[0-9a-f]{3,8}\b|rgba?\()'
section "Direct Common UI Imports Outside Adapter"
print_matches '@bytelyst/ui' --glob="${APPROVED_UI_GLOB}"
total_findings=$((raw_controls_count + legacy_classes_count + hardcoded_colors_count + direct_common_ui_count))
if [ "${MODE}" = "strict" ] && [ "${total_findings}" -gt 0 ]; then
echo "error: strict UI drift audit failed with ${total_findings} findings" >&2
exit 1
fi
exit 0