# `supero-ui.js` Layered Split — Verification & Manifest

This folder contains a **layered modularization** of `../supero-ui.js`
into a 5-folder architecture (24 files in `api/`, `services/`,
`ui-core/`, `ui-service/`, `ui-app/` + `00-header.js` at root). The
split is **semantic** — symbols are grouped by layer, not by canonical
line order — so the joined output is **not** byte-identical to
canonical. But it **is** semantically equivalent:

- Every top-level symbol from canonical is preserved exactly
- Every `window.X = X` export is preserved
- Each individual symbol's bytes are unchanged (verified per-slot)
- The joined output parses cleanly as JS (`node -c` passes)
- **Backend layers (00–22) have zero hard references to UI symbols**

> **The canonical `../supero-ui.js` is still the shipped source.**
> This folder is an editing/reading aid. Nothing in PROJECT_MANIFEST,
> server.py, CDN, or test_bundle.py references these files.

The byte-identical 15-file verbatim split lives in `_verbatim_backup/`
as the rollback contract — if anything ever goes wrong here, the
backup still proves we lost no bytes vs canonical.

---

## TL;DR

- **Original:** `../supero-ui.js` — 18,717 lines, 1,086,229 bytes,
  md5 `caa675bf9750ad4fa186fa79876f9622`
- **Layered split:** 24 files in 5 folders, 18,837 lines (+120 from
  banners), 1,093,317 bytes, joined md5 `6243e0f050b51ca0cc3bbc86258f45e3`
- **Backup:** 15 files in `_verbatim_backup/`, joined md5 still matches
  canonical
- **Verification:** `python3 _verify_layered.py` — 7 passes, all green
  (including `node -c` parse of the 1.09 MB joined output)

```
web/
├── 00-header.js                   ← always loads first
├── api/                           layer 10 — data contract + transport
│   ├── 10-schemas.js
│   ├── 11-client.js
│   └── 12-helpers.js
├── services/                      layer 20 — service execution
│   ├── 20-map.js
│   ├── 21-transactional.js
│   └── 22-catalog.js
├── ui-core/                       layer 30 — UI primitives
│   ├── 30-primitives.js
│   ├── 31-theme.js
│   └── 32-charts-text.js
├── ui-service/                    layer 40 — service-aware UI
│   ├── 40-fields-forms.js
│   ├── 41-cards-actions.js
│   ├── 42-dispatchers.js
│   ├── 43-detail-data.js
│   ├── 44-transactional.js
│   ├── 45-modal-initiator.js
│   ├── 46-service-action.js
│   ├── 47-chat-invoice.js
│   └── 48-workflow-widgets.js
└── ui-app/                        layer 50 — composite app pages
    ├── 50-auth.js
    ├── 51-landing.js
    ├── 52-tenant.js
    ├── 53-shell.js
    └── 54-nav-widgets.js
```

**Load order: `00-header.js`, then `api/*`, `services/*`, `ui-core/*`,
`ui-service/*`, `ui-app/*` in that exact folder sequence.** Do NOT use
`find . -name '*.js' | sort` — alphabetical sort puts `ui-app` *before*
`ui-core`/`ui-service`, which would break load order. The folder
sequence must be enumerated explicitly.

---

## The 5-layer architecture

```
┌─────────────────────────────────────────────────────────────────┐
│ 00 header     │ config, load guards, React hook aliases         │
├───────────────┼─────────────────────────────────────────────────┤
│ 10 api_core   │ data contract: schema, client, formatters       │ ← shipped backend
│ 20 services   │ service execution: services map, txn, ACTION_OPS│   bundle would stop
├───────────────┼─────────────────────────────────────────────────┤   here
│ 30 ui_core    │ UI primitives: buttons, cards, theme, charts    │
│ 40 ui_service │ service-aware UI: forms, dispatchers, actions   │
├───────────────┼─────────────────────────────────────────────────┤
│ 50 ui_app     │ composite pages: auth, landing, AppShell, etc.  │
└───────────────┴─────────────────────────────────────────────────┘
```

**Critical property: backend layers (00, 10, 11, 12, 20, 21, 22) have
zero hard code references to UI symbols.** Grepped post-split for
every major UI symbol — the only hits in backend files are:

- Two doc comments in `10-api-schemas.js` mentioning `DataTab` as
  documentation pointing to consumer code
- Three data strings inside `SERVICE_MANIFESTS` / `ACTION_OPS` metadata
  (e.g., `reuses: 'AIChatPanel'` — a string, not a code reference)
- One `console.log('… AppShell ready …')` string at the end of
  `22-services-catalog.js`

Conclusion: **the backend layer is a clean, standalone subsystem.**
You could literally serve `00 + 10*.js + 11*.js + 12*.js + 20*.js +
21*.js + 22*.js` as a pure backend bundle and it would work as a
data-layer-only library (no React required for those files).

---

## File manifest

### Backend (00 + 10-22) — pure data / contract / transport

| Layer | File | Slots | Lines | Bytes | Contents |
|-------|------|-------|-------|-------|----------|
| 00 | `00-header.js` | 14 | 130 | 6,536 | Load guards, `SUPERO_CONFIG`, `_APP_*` vars, React hook aliases (`useState`/`useEffect`/`useRef`/`useCallback` — **moved from canonical line 3756**), version + APP_DOMAIN exports |
| 10 | `api/10-schemas.js` | 8 | 765 | 32,315 | `SuperoSchemaRegistry`, `SuperoUISchemaResolver`, `_qualifySchema`, `_SYSTEM_TYPES`. **`SuperoFieldEditor` and `ChildListPanel` were moved OUT of this file to `ui-service/40-fields-forms.js`** — they were misplaced React UI in a schema file. |
| 10 | `api/11-client.js` | 6 | 483 | 23,173 | `SuperoClient` (CRUD client), `_extractObjectUuid`, `client` singleton |
| 10 | `api/12-helpers.js` | 23 | 239 | 10,957 | `fileService`, formatters (`formatCurrency`/`Number`/`Date`/`FieldValue`/`RelativeTime`/`DateTime`), `resolveImageUrl`, state-machine helpers (`getEnabledOperations`, `parseStateTransitionError`, `getStateMetadata`) |
| 20 | `services/20-map.js` | 15 | 415 | 25,589 | `_svc` dispatcher, `services` map (email/sms/whatsapp/push/slack/stripe/billing/salesforce/s3/drive/calendar/servicenow/ai/otp/search/instagram/twitter), AI chat helpers (`aiChatStream`/`Confirm`/`Reject`, file/tool helpers, history persistence) |
| 20 | `services/21-transactional.js` | 20 | 598 | 33,254 | `SuperoTransactionalRegistry`, 6 `Txn*Error` classes, `_classifyHttpError`, `_txnOpCategory`, `_txnBackoff`, `_txnRunAction`, `_txnDefaultErrorMessage` |
| 20 | `services/22-catalog.js` | 15 | 965 | 82,640 | `SERVICE_MANIFESTS` (per-service capability declarations), `SuperoServiceRegistry`, `ACTION_OPS` (32 services × 86 ops), `ACTION_OPS_UX`, services-status fetcher + cache, `_superoBackendIdForKey` |

**Backend total: 7 files, ~3,595 lines, ~215 KB.**

### UI Core (30–32) — service-agnostic primitives

| Layer | File | Slots | Lines | Bytes | Contents |
|-------|------|-------|-------|-------|----------|
| 30 | `ui-core/30-primitives.js` | 39 | 972 | 45,185 | `_router`, icons (Pencil/Trash/Plus/X/Check/Search/Chevrons/ArrowLeft/MoreHoriz), `_buttonStyle` + button factory, `PrimaryButton`/`SecondaryButton`/`EditButton`/`DeleteButton`/`IconButton`, `Card`/`Section`/`EmptyState`/`Badge`/`SuperoSkeleton`/`Spinner`, `AuthedImg` + auth-blob URL cache, tenant context + noun resolution, `resolveFileUrl` |
| 30 | `ui-core/31-theme.js` | 21 | 719 | 59,995 | `_DEFAULT_THEME`, palette generators (`_hexToHSL`/`_hslToHex`/`_generatePalette`), `SUPERO_THEME_PRESETS`, `_resolveThemePreset`, `THEME`, `_THEME_PRESETS`, light/dark token sets, `_resolveTheme`/`_applyTheme`/`_applyAppTokens`/`_injectGlobalStyles`, `_validateConfig`, logger |
| 30 | `ui-core/32-charts-text.js` | 22 | 595 | 34,337 | `ErrorBoundary`, `SkeletonCard`/`SkeletonImageCard`, `getLayoutType`, `Sparkline`/`StatCard`/`DashboardChart` + `_CHART_PALETTE`, `renderMarkdown`, `getStatusColor`, `showToast` + container |

**UI Core total: 3 files, ~2,286 lines, ~140 KB.**

### UI Service (40–48) — service-aware UI

| Layer | File | Slots | Lines | Bytes | Contents |
|-------|------|-------|-------|-------|----------|
| 40 | `ui-service/40-fields-forms.js` | 28 | 1,739 | 96,174 | `SuperoFieldEditor` (**moved from canonical file 02**), `ChildListPanel` (**moved from canonical file 02**), `ImageFieldInput`/`ImageListFieldInput`, `ParentChainSelector`, `TenantSwitcher`, `BrowseList`, `ReferenceDropdowns`, `TagListInput`, `CheckboxGrid`, `pickFormContainer`, `SlideOverForm`, `CrudModal`, `DeleteModal` |
| 40 | `ui-service/41-cards-actions.js` | 21 | 951 | 61,641 | `ImageCard`/`ProfileCard`/`GenericCard`/`TemplateCard`/`CinemaCard`/`MagazineListCard`/`CompactImageRow`/`CleanListRow`, `KanbanView`, `_suiActionButtonContext`, `_resolveActionParams`, `ActionButtons` |
| 40 | `ui-service/42-dispatchers.js` | 3 | 405 | 17,289 | `SuperoViewDispatcher`, `SuperoCardDispatcher`, `SuperoDetailDispatcher` — the late-binding registry layer (uses `typeof X === 'undefined'` guards) |
| 40 | `ui-service/43-detail-data.js` | 19 | 1,268 | 81,369 | `ImageLightbox`, `DetailFrame`, `PrimaryActionButton` + filter, `GenericDetail`/`ProfileDetail`/`TransactionalDetail` + their title/field renderers, `DetailView`, `FullPageCreate`, `DataTab` |
| 40 | `ui-service/44-transactional.js` | 17 | 477 | 23,723 | `TXN_PALETTES`, `TxnStateBadge`, `TxnActionButton`, txn toast infrastructure, `TransactionalListView` + row renderer, `TransactionalDetailView` + record/child-table/ref-panel renderers |
| 40 | `ui-service/45-modal-initiator.js` | 19 | 604 | 24,302 | `SuperoModalShell` + module-level state, `SuperoModal` API, initiator-flow primitives (`_resolveInitiatorRef`/`Prefill`/`Refs`/`Template`, validation, field renderer, `_runInitiatorFlow`, `_deriveUuidField`, `openInitiatorFormModal`, `_InitiatorFormBody`) |
| 40 | `ui-service/46-service-action.js` | 29 | 1,304 | 57,762 | `ServiceWidget`, `_ServiceStatusBadge`, `_sui*` form helpers (type-render, interpolate, init form data, validate required/json, coerce for submit, input style, acronym helpers, field label/help/render, output field render, secret-field sanitization), `_ServiceActionForm`, `_ServiceActionResult`, `_suiUxOverlay`, `_suiInterpolateResult`, `_suiRenderResultTemplate`, `_suiEmptyStateProps`, `_suiRenderCardActions`, `_suiInvokeCardAction` |
| 40 | `ui-service/47-chat-invoice.js` | 12 | 575 | 34,601 | `InvoicePayPanel`, `parse422Error`, `buildFieldsFromAttrs`, `ToolStepRow`, `getQuickCommands`, `AIChatPanel` |
| 40 | `ui-service/48-workflow-widgets.js` | 10 | 560 | 30,055 | `SvgBarChart`, `WorkflowBadge`, `WorkflowTriggerButton`, `WorkflowTestPanel`, `_WfResults`, `SuperoWidgetRegistry`, `RecentListWidget` |

**UI Service total: 9 files, ~7,883 lines, ~427 KB.**

### UI App (50–54) — composite app pages

| Layer | File | Slots | Lines | Bytes | Contents |
|-------|------|-------|-------|-------|----------|
| 50 | `ui-app/50-auth.js` | 8 | 595 | 42,001 | `LoginPage`, `SignupPage`, `ForgotPasswordPage`, `GoogleSignInButton`, `PasswordInput` |
| 50 | `ui-app/51-landing.js` | 25 | 2,526 | 152,078 | `SUPERO_HERO_VARIANTS` + warnings + palette resolvers, `SUPERO_STATS_VARIANTS` + `_renderStats` + `HeroSection`, `LandingNav`/`LandingFooter`/`LandingDescription`, `SUPERO_FEATURE_GRID_VARIANTS` + `_renderFeatureGrid`, `LandingPage` |
| 50 | `ui-app/52-tenant.js` | 2 | 297 | 18,580 | `CreateTenantPage`, `JoinTenantPage` |
| 50 | `ui-app/53-shell.js` | 18 | 1,469 | 92,272 | `Sidebar`, `Dashboard`, `TopNavShell`, `MagazineShell`, `MinimalShell`, `SearchOverlay`, `ChangePasswordModal`/`Mount`, `AppShell` |
| 50 | `ui-app/54-nav-widgets.js` | 4 | 186 | 7,489 | `_NavWidgetBar`, `_NavWidget` |

**UI App total: 5 files, ~5,073 lines, ~313 KB.**

---

## What changed vs the verbatim 15-file split

Five small moves were applied beyond pure relocation:

1. **`SuperoFieldEditor`** — moved from canonical file 02 (api_core
   schema-registry file) to `40-ui-fields-forms.js`. It's a React UI
   atom-dispatcher, not a schema-data thing.
2. **`ChildListPanel`** — same: moved from canonical file 02 to
   `40-ui-fields-forms.js`. React component that calls `getStatusColor`,
   never belonged in the api_core layer.
3. **React hook aliases** (`useState`/`useEffect`/`useRef`/`useCallback`)
   — moved from canonical line ~3756 (inside `12-api-helpers.js` region)
   to `00-header.js`. This eliminates the only place where api_core
   referenced symbols defined in a later layer.
4. **Slot-by-slot reordering** by layer. Inside each layer file, symbols
   stay in canonical source order; across layers, the order changes.
5. **24 banner comments** (one per file, 5 lines each) — 120 lines of
   pure overhead, explicitly labeled and accounted for in pass 1.

No symbol body was changed. No comment was deleted. No code was added
beyond the file banners.

---

## Verification (run any time)

```bash
cd ~/supero/platform/infra/libs/py/src/supero/ui/split

# 1. Re-run the layered split (deterministic — should reproduce same files)
python3 _layer.py

# 2. Run the 7-pass layered verifier
python3 _verify_layered.py
# expected: "RESULT: ALL PASSES GREEN ✓"

# 3. Verify the verbatim backup still matches canonical byte-for-byte
md5sum ../supero-ui.js
cat _verbatim_backup/01-*.js _verbatim_backup/02-*.js _verbatim_backup/03-*.js \
    _verbatim_backup/04-*.js _verbatim_backup/05-*.js _verbatim_backup/06-*.js \
    _verbatim_backup/07-*.js _verbatim_backup/08-*.js _verbatim_backup/09-*.js \
    _verbatim_backup/10-*.js _verbatim_backup/11-*.js _verbatim_backup/12-*.js \
    _verbatim_backup/13-*.js _verbatim_backup/14-*.js _verbatim_backup/15-*.js | md5sum
# both should print: caa675bf9750ad4fa186fa79876f9622
```

### What the 7 passes check

| Pass | What it verifies | Why it matters |
|------|------------------|----------------|
| 1. File existence + UTF-8 | All 24 layer files present and decode cleanly | basic sanity |
| 2. Top-level symbol coverage | All 298 unique top-level symbols from canonical are defined in exactly one layer file (duplicates allowed where canonical has duplicates) | catches lost/extra/wrongly-duplicated symbols |
| 3. `window.*` export parity | All 132 `window.X =` exports preserved with same set + same count | runtime contract preserved |
| 4. Per-symbol content preservation | Each symbol's canonical byte range appears in its assigned layer file (substring match) | proves no symbol body was accidentally modified |
| 5. Layer ordering | No top-level immediate references to later-loaded symbols (excluding `typeof X === 'undefined'` guards and string literals) | the layered architecture is real — earlier files don't depend on later files at module-init time |
| 6. Newline termination | Each layer file ends with `\n` | shell `cat` join preserves line grammar |
| 7. **`node -c` parse** | The joined output (24 files concatenated in order) is syntactically valid JavaScript | the ultimate proof — if node parses it, layout-induced syntax issues are impossible |

Current state: all 7 passes green. One warn in pass 5 was a false
positive (a `console.log` string mentioning "AppShell ready" tripped
the heuristic) — verified by grep, no actual code-level violation.

---

## Backend-only deployment (future option)

The clean carve-out makes a **backend-only bundle** trivially possible:

```bash
cd ~/supero/platform/infra/libs/py/src/supero/ui/split
cat 00-header.js api/*.js services/*.js > /tmp/supero-backend.js
# ~215 KB — a pure data/services/transport library, no React required
# (the React-hook aliases in 00-header.js fail gracefully if React undef
#  unless you also load React first, but the api/ + services/ files
#  themselves never call useState/etc.)
```

This is **not** currently shipped or referenced — just demonstrating
what the layering enables. A real backend-only bundle would also need
to remove the React presence check in `00-header.js` lines 78–84.

---

## Re-joining (to ship a change)

If you ever decide to ship the layered files as a single
`supero-ui.js`:

```bash
cd ~/supero/platform/infra/libs/py/src/supero/ui/split

# Build joined file. Folder order matters — do NOT use `find | sort`,
# alphabetical would put ui-app before ui-core/ui-service.
cat 00-header.js \
    api/*.js \
    services/*.js \
    ui-core/*.js \
    ui-service/*.js \
    ui-app/*.js \
    > /tmp/supero-ui.layered.js

node -c /tmp/supero-ui.layered.js   # sanity-parse
diff -u ../supero-ui.js /tmp/supero-ui.layered.js | head -200  # see the moves

# To overwrite canonical (only after browser smoke-test):
cp ../supero-ui.js ../supero-ui.js.bak.$(date +%Y%m%d-%H%M%S)
cp /tmp/supero-ui.layered.js ../supero-ui.js
md5sum ../supero-ui.js   # new md5: 6243e0f050b51ca0cc3bbc86258f45e3
```

**Recommendation: do not propagate until you've smoke-tested in a
generated app.** The 7 passes prove syntactic validity, not behavioral
equivalence — the `_THEME_PRESETS` object initialization or a similar
top-level eval-time expression could still surprise you. The verbatim
backup is your rollback.

---

## Files in this directory

| Path | Role |
|------|------|
| `_layer.py` | The layered splitter. Reads `../supero-ui.js` + `LAYER_MAP` dict, writes 24 layered files into `api/`, `services/`, `ui-core/`, `ui-service/`, `ui-app/`. Auto-creates folders. Rerun any time canonical or the layer map changes. |
| `_verify_layered.py` | The 7-pass layered verifier. Imports `LAYER_MAP`/`FILE_ORDER`/`DECL_PAT`/`find_anchors`/`snap_backward` from `_layer.py`. Exits non-zero on failure. |
| `VERIFICATION.md` | This document. |
| `MODULARIZATION_PLAN.md` | The pre-execution analysis: feasibility study, layer architecture, work estimate, open decisions. (Decisions are now locked in — preserved for context.) |
| `00-header.js` | Single root-level file (loads first). |
| `api/*.js` | Layer 10 — 3 files. |
| `services/*.js` | Layer 20 — 3 files. |
| `ui-core/*.js` | Layer 30 — 3 files. |
| `ui-service/*.js` | Layer 40 — 9 files. |
| `ui-app/*.js` | Layer 50 — 5 files. |
| `_verbatim_backup/` | The earlier byte-identical 15-file split + its `_split.py` + `_verify.py`. Rollback safety net. |
