# Cradle UI-port handover

## Rename

6 September 2026 — renamed from Launch Command to Cradle: a launch cradle is a common object that holds the vehicle steady while it is readied and never moves it itself, which is exactly how this product feels to operate, and a plain-noun name in the register of Asana. The repository is now `runeditrun/projects-cradle`.

## Manifest

8 September 2026 — `seed.json` migrated to `seeds/base/schema/SEED.schema.json` and given `category: records`, `spine` (`records`, "table with typed fields and views") and `replaces` (Airtable, null edition); env `purpose` became `why`, both externals' `dataShared` and `adapter` became `data` and `adapters`, `deploy.apiPrefix` became `apiPath`, `customFields` became the entity array, and `operatingCost` gained the `status` sentence the schema requires, carrying the 2026-08-31 estimate date that `estimateAsOf` held. Four things had no home in the schema and are recorded here rather than dropped: `displayName` only repeated `name`; `platform` recorded the stack as Cloudflare Workers, D1, R2, Queues, Cron Triggers and a Vite + React + TanStack Router operator app, which is the one stack every seed builds on; `customFields.types` listed the field types a campaign custom field may take — text, number, date, boolean, single-select, multi-select and url; and `extensionPoints.status` recorded the IDs as `candidate-unreleased`, planned to become stable v1 at first release once implementations and tests land. The manifest now names the records spine while `description`, `scope` and `nonGoals` still describe the launch-portfolio product — `nonGoals` still excludes arbitrary tables and user-defined formula and rollup fields — because the records contract has not been written; the catalogue's repoint says the launch-portfolio scope becomes a template, and that rewrite is the change that resolves this.

## Current product state

Cradle is now a real contract-led UI port, not a static prototype. One Cloudflare Worker serves the public owner landing, the authenticated Vite + React + TanStack Router operator SPA, and Hono APIs. The component layer uses Tailwind and a small shadcn-style composable control foundation. Product records live in D1 through a typed Drizzle client and feature-owned repositories and services. The first immutable migration and the canonical demo records are in `migrations/core/` and `sample-data/cradle.json`.

For local development only, `POST /auth/local-sign-in` is available when `LOCAL_DEV_SESSION=true`. It installs the canonical sample records through the same repositories used by the application, creates a persisted session, and is unavailable in production. This is a developer bootstrap, not the operator-controlled sample install/remove workflow required by SET-003.

`CONTRACT.md` remains the source of product guarantees. This milestone implements the complete UI-PORT surface and a deliberately thin real data spine. It does not claim the later backend work or complete clause coverage described below.

## Required rendering migration before implementation resumes (2026-09-08)

TanStack Start is the adopted shared React document layer. The **FIRST** resumed
implementation step is conversion through the accepted recipe, before further
product work. It is recorded locally at
`/Users/zemaj/.orchestrator/evidence/runeditrun/default-seed-on-tanstack-start-with-the-migration-recipe/MIGRATION.md`
and portably at [TANSTACK-START-MIGRATION.md](https://github.com/runeditrun/seed-spec/blob/main/TANSTACK-START-MIGRATION.md).

This is a forward target, not a claim that the current Vite + React + TanStack
Router runtime above has already migrated. Preserve the Cradle contract, native
auth, declared Hono HTTP surfaces, D1 data guarantees, and the custom Worker
entry's event and named exports. After conversion, Start owns selected React
document routes and `/_serverFn/`; Hono keeps only explicit HTTP families. A
returning orchestrator must bring these committed main-branch notes into any
existing parked implementation worktree before resuming it. Meet the recipe's
full local-workerd acceptance instead of treating a successful build as proof.

## Mounted surfaces and contract map

All `/app` routes require a persisted session. Each ported or freshly designed surface has a contract home; the clauses below are relevant to the rendered surface, not a claim that every mutation in each clause is complete.

| Route | Surface | Relevant clauses | Current real behavior |
| --- | --- | --- | --- |
| `/` | Owner identity plate | HOME-001 | Buyer-configured owner name, description, theme, sign-in link, and default-on static credit |
| `/signin` | Sign-in entry | BASE-ACCESS-003 | Reports the actual auth capabilities; local persisted sign-in is visible only in local development |
| `/app` | Workspace Home | VIEW-001, VIEW-004, CAMP-006, ACT-001 | Session identity, persisted portfolio metrics, upcoming milestones, and activity |
| `/app/overview` | Portfolio Overview | VIEW-001, VIEW-004, CAMP-005, CAMP-006 | Current campaign health, attention, decisions, milestones, and activity |
| `/app/campaigns` | Campaign Grid | VIEW-001, VIEW-004, VIEW-007, CAMP-007 | Persisted campaign collection and current record selection |
| `/app/campaigns/:campaignId` | Campaign Detail | VIEW-001, VIEW-002, VIEW-004, CAMP-004, CAMP-005, DELIV-002, ACT-001 | Detail bound to the URL ID; deliverable completion uses a real versioned mutation |
| `/app/lenses/risks` | Risks Lens | VIEW-001, VIEW-003, VIEW-004, RISK-005, LENS-005 | Exact current High/Critical result set from D1; honest unconfigured AI readout |
| `/app/risks/:riskId` | Risk Detail | VIEW-002, VIEW-004, RISK-001, RISK-003 | URL-bound current record and versioned escalation mutation |
| `/app/lenses/timeline` | Timeline Lens | VIEW-001, VIEW-004, MILE-002, MILE-006 | Real milestone dates and ranges; responsive desktop timeline and phone agenda |
| `/app/milestones/:milestoneId` | Milestone Detail | VIEW-002, VIEW-004, MILE-001, MILE-003 | URL-bound milestone, campaign, owner, dates, and dependencies |
| `/app/lenses/new` | Lens Builder | VIEW-001, VIEW-004, LENS-001, LENS-002, LENS-003, LENS-007 | Server-validated live preview and real persisted save |
| `/app/lenses/:lensId/edit` | Lens Editor | VIEW-001, VIEW-004, LENS-004, LENS-005 | Loads and version-updates the named persisted lens |
| `/app/decisions` | Decision Queue | VIEW-001, VIEW-004, DEC-002, DEC-003, DEC-004 | Current unresolved queue, record-bound detail, and terminal versioned outcomes |
| `/app/decisions/:decisionId` | Decision Detail | VIEW-002, VIEW-004, DEC-001, DEC-003 | Selected detail comes from the URL, never a frozen first record |
| `/app/automations` | Automation Monitor | VIEW-001, VIEW-004, AUTO-001, AUTO-006, AUTO-011 | Four persisted definitions and real stored run history; unsupported jobs remain read-only |
| `/app/notifications` | Notification Inbox | VIEW-004, NOTIFY-005 | Persisted per-operator unread state, subject links, mark-one and mark-all-read |
| `/app/settings` and `/app/settings/:section` | Settings | VIEW-004, SET-001, SET-002 | Persisted workspace and operator preferences; AI and mail capability states are explicit |

## Real data spine in this milestone

- D1 tables cover workspaces, operators, sessions, campaigns, deliverables, milestones and dependencies, risks, decisions, lenses, activity, automation definitions/runs/actions, notifications/read state, and settings.
- Only feature repositories issue database queries. Routes validate trust boundaries and call feature services.
- Collection and detail APIs are session guarded. Missing and unknown API routes return structured errors rather than SPA HTML.
- Campaign updates, deliverable completion, risk escalation, decision outcomes, lens save/edit, notification read state, and settings changes persist to D1 with version checks where the surface needs them.
- Sample content lives only in `sample-data/`; components contain no fixture arrays, fake fetch handlers, or semantic fallbacks.
- Loading, empty, failed, signed-out, and not-found states clear retained data rather than presenting a stale record as current.

## Visual origin and scope

Ported from the `.12ui` prototype into feature-owned React components:

- The responsive operator shell, Workspace Home, Portfolio Overview, Campaign Grid, Campaign Detail, Risks Lens, Timeline Lens, Lens Builder, Decision Queue, and Automation Monitor.
- The warm off-white, charcoal, and lime visual language, compact operational density, desktop rail, mobile drawer, table-to-card reflow, and timeline-to-agenda reflow.

Designed fresh during this port because the prototype had no trustworthy screen provenance:

- The public owner identity plate at `/`, using the product's visual language without inventing marketing content.
- Notification Inbox, including unread state and unavailable-subject handling.
- Settings, including workspace, profile, preferences, security, AI, email, and data/storage capability sections.

The original composition sources remain in `.12ui/`. Historical prototype captures remain in `evidence/qa/`; the current catalog and operator captures are in `visual/`, ordered from `01-landing.png` through desktop operator surfaces and a responsive phone state.

## Prototype fabrications deliberately rejected

The production path contains none of the following:

- Frozen `src/data.mjs` records, hard-coded result sets, mock services, or fake fetch handlers.
- Content Calendar and Customer Signals concept cards, which are not Cradle products.
- Stale campaign or decision inspectors after selecting a different URL-bound record.
- Toast-only import, share, save, approval, retry, checkbox, profile, or settings controls presented as completed work.
- Fabricated AI briefs, risk prose, recommendations, usage, mail delivery, provider success, or automation execution.
- Decorative timeline positions unrelated to stored milestone dates.
- Public record views, feature-tour marketing, pricing, testimonials, or invented metrics on the landing.
- Runtime Google Fonts requests; the app uses its bundled font assets.

The retired MJS prototype runtime and its frozen data source were deleted after the React/D1 composition replaced them. Its design source remains recoverable from git and `.12ui/`.

## AI and mail are honestly unconfigured

No AI provider or outbound mail adapter is implemented in this milestone. Settings reports AI as disabled and email as unavailable; Risks Lens names the missing AI capability instead of synthesizing a readout. Production magic-link sign-in is likewise not advertised as available. Every non-AI, non-mail read and implemented mutation continues to work.

## Later backend pass still owes

- Production native sessions and magic links, `mail.sender.v1`, delivery records, quiet hours, digesting, retries, and visible final failures.
- `ai.provider.v1` with strict schemas, allowed-context policy, provenance, usage and ceiling records, and explicit provider errors.
- Post-commit facts, Queue and Cron dispatch, immutable automation versions and executions, idempotency, retry/cancellation, and full run history behavior.
- Remaining contract mutations: create/edit/delete and lifecycle flows, campaign archive/restore/bulk/undo/duplicate, comments and mentions, milestone dependency validation, operator management, and policy-driven cross-record transactions.
- CSV import preview/commit, CSV export, R2-backed portable export/import, production setup/deploy commands, and operator-controlled sample install/remove.
- Stable extension mounts and adapters after their behavior and tests are real.
- Complete clause-tagged contract and baseline coverage, automated accessibility and Playwright journeys, and load tests that replace the manifest's stated estimates.

## Run and verify

- Install: `pnpm install --ignore-workspace`
- Run the local Worker, D1 migration, and asset watcher: `pnpm dev`
- Verify types, production assets, and an isolated live Worker/D1 journey: `pnpm verify`
- Open the landing: `http://127.0.0.1:4185/`
- Open the local operator entry: `http://127.0.0.1:4185/signin`

The smoke journey starts an isolated Miniflare Worker, installs the migration, signs in through the real local session route, exercises independent campaign details and mutations across every UI resource family, and verifies structured unauthenticated and not-found behavior. Production deployment credentials and external-provider configuration are intentionally outside this UI milestone.
