Adam ratification · amendment 9, plus the scale ruling · binding

The signed design contract

This pack gates Phases 2–5, so the parts a build has to honour are written down here rather than inferred from a mock. Six things are contract: the route map, the responsive states, the clearance boundary, the persona IDs, the member lifecycle, and the portrait recipe — the last two added by Khoa's scale ruling, which replaced the five-card room with an information architecture for 100+.

The one that costs most if it is got wrong: display names are a skin over stable internal IDs. The late Bindi gate can rename every member in a config change — but only if nothing downstream ever persisted a display name. If a run record, a lineage sibling or a proposal stores "Jimmy" instead of fan.verite-hand.v1, the rename becomes a migration.
Route ruling — the same principle, extended into URL space (Tom, 31 Jul, on my flag; his amendment note is the paper trail). The crew room’s route is /create/unit, not /create/crew-room and no longer /create/warroom. A route is an identifier, so it carries the most durable locked token. Unit is the load-bearing word of the design lock; crew room is display flavour that can still move at the Bindi gate, and amending the map to follow it would churn the contract twice. So the address bar says /unit while the heading says “crew room” — exactly the rule §4 already applies to persona IDs, which is why it needed no new argument. Renamed once. Scope-checked as product-local: no external deep-link contract references it (Keystack covers /film/* only) and we are pre-launch, so no redirects are owed.

1 · Route map — rebuilt from the product

This section was wrong and is rebuilt. The first version was written from a checklist, ratified in good faith, and described a product that does not exist: it mapped /create/unit, /create/:runId/plan, /my-work and /admin/bench, none of which are routes, and it invented six query parameters no code reads. It also missed /studio entirely — which is where Create actually lives. Everything below is now split into what EXISTS and what we are ADDING, so the next ratification is against reality rather than against prose. Evidence column says how each row was established: walked means I signed in to staging and clicked it; source means read at f5ce242, the commit staging serves.

1a · What exists today

The top-level IA is two modes, on an icon rail: Analyze — real films → measured grammar — and Create — grammar → generated films. Every route below sits in one of them.

RouteModeSurfaceReal paramsEvidence
/AnalyzeLibrary home — measured titles, two ways in ?filmId= legacy, redirects to the path formwalked
/film/:filmIdAnalyze The measured spine — 01 Identity · 02 Shot grammar · 03 Rhythm · 04 Dialogue · 05 Evidence · 06 Use as a style, with a persistent Instrument Readout ?tab=walked
/film/:filmId/cuts/:assetIdAnalyzeRe-cut editor ?draft=source
/studioCreate Create workspace — Projects · Cuts · Media ?contentType=director (the “Directors” nav item) · ?filmId= legacywalked
/studio/:filmIdCreateCreate for one film— source
/demo-access—Demo gate?next= walked
/sign-in · /sign-up · /forgot-password —Auth set?next=walked
/settings/account—Account— source
/api/auth/[...all] · /api/auth/enforcement— Auth handlers — enforcement is a capability with no surface— source
/api/demo-access · /api/video— Gate and video handlers?url= · ?t=source

The complete set of query parameters any code reads: tab · draft · filmId · t · next · draftTrailer · contentType · url. There are no others.

1b · What we are adding

Two additions only, and both sit inside the existing two-mode IA rather than beside it. The earlier map failed because it proposed a parallel hierarchy; this one extends what is there.

RouteModeWhat it addsWhy here
/studio/unitCreate The crew room — your fourth unit, search-primary at 100+ members Studio already carries Projects · Cuts · Media. The unit is a fourth tab in a rack that exists, not a new hierarchy. This replaces the invented /create/unit.
?fan=fan.*.v1Create Deep link opening one member’s dossier The only parameter we add. It follows the shape of the real ones and it never carries a search key.

1c · Retired from the map

Was mappedVerdictWhat is true instead
/create/* (unit, conditioning, plan, keyframes, render, cuts) retireCreate lives at /studio. The stages are states of one Studio run, not six routes.
/my-work · /my-work/:filmIdretire / is the library. There is no second one.
/admin/benchretire Admin is a clearance on existing surfaces, per §3 — not a route.
?scene= ?shot= ?school= ?pace= ?era=retireNo code reads any of them. Roster facets are UI state until someone asks for shareable filtered views.
The rule that would have prevented all of this. A route map is a claim about a running system, so it needs the same evidence discipline as any other claim: every row carries how it was established. Three of us signed the first version — Tom wrote the checklist, I built the map from it, Adam ratified it — and none of those steps involved looking at the product. Ratification records agreement between people; it is not evidence about software.

2 · Responsive states

Three, per my own OwnerMind pattern, and the same breakpoints the Instrument already uses.

WidthFunnelStageUnit drawer
Desktop ≥1200px246px, persistentfluid 400px, collapsible to 0 — the toggle says Show unit when hidden
Tablet <1200pxhiddenfull width hidden; reachable from the stage header
Phone <900pxhiddenfull width overlay, never a squeezed third column — fixed inset, own scroll, sticky header so the way out is always visible

The rule underneath: a pane is never narrowed below the width its content needs. When there is not room it becomes an overlay or it goes away and says how to get it back. A 400px drawer squeezed to 180px is worse than no drawer.

3 · Clearance boundary — one room, two faces

The same crew room, two audiences. The user face is the cinematic one; admin is the workshop that runs the unit. Nothing in the user face is a subset of a corpus view — the corpus is not rendered to users at all, which is what makes the provenance private.

User clearance

  • Dossier cards: avatar, first name + specialty tag, look-reel, coverage numbers, temperament
  • Measured / verified chips
  • The bio line, where and only where it is measured-true
  • Typeahead that resolves a private key to a persona
  • Hire as pilot · sit in as guest

Admin clearance — adds

  • The full fingerprint: distributions, shot-size mix, motion, the wave
  • Source titles and directors behind each grammar — the corpus
  • Graduation pipeline: what auto-review has passed, what is pending
  • Per-member call metering and session telemetry
  • Degenerate-profile warnings — which members are too thin to seat
The boundary is server-side, not a hidden div. The user payload must not contain the corpus fields at all. I built the typeahead the wrong way first and could read the whole director-to-fan map out of the bundle — a clearance enforced by what is rendered is not a clearance.

4 · Stable persona IDs

Naming is locked for design (Khoa, 31 Jul) — the fourth-unit vocabulary is final for every surface and no longer carries a provisional hedge. Scope, so nothing overreaches: this is a design lock, not a brand or marketing lock. Trademark and persona wording still clear at the Bindi pre-production gate, and the internal IDs below stay name-agnostic per the skin rule — which is exactly what lets a design lock be safe to take now and a naming ruling to arrive later without rework.

Display names are a skin. These IDs are what everything downstream stores.

Internal IDDisplay nameSpecialty tagCoverage Lifecycle stage — derived
fan.verite-hand.v1Jimmyhandheld verité 55 sc / 299 sh4 — verified · bio: Greengrass
fan.slow-bloom.v1Meisaturated interior 41 sc / 186 sh4 — verified · bio: Wong Kar-wai
fan.held-breath.v1Daralong-lens compression 38 sc / 241 sh3 — bio published · Bigelow
fan.long-room.v1Verastatic deep-focus master 29 sc / 97 sh 1 — in measurement · under the recipe floor
fan.cut-reflex.v1Otiskinetic montage 47 sc / 512 sh2 — measured · not attributed
The bio slot is a measured field, not a copy field. Director names are permitted as influences — but the listed directors are exactly those whose films we hold fingerprints for. Three hero-grade fingerprints are substantiated, so three of five members can carry a bio and two cannot. Those two say so on the card. The bio is generated from the fingerprint index, never authored: unchanged by the scale ruling and now mandatory, because at a hundred members nobody proofreads a bio for truth, so it must not be possible to write one that is not.

5 · The member lifecycle — contract, because it is derived

Every member passes through four stages: in measurement measured bio published verified. What makes this a contract item rather than a styling one is that the stage is computed, never stored.

No column anywhere holds a stage. stageOf(member) reads coverage against the recipe floor, whether a bio has been generated, and whether a human has verified it — in that order. A stored stage is a field that can drift out of agreement with the numbers printed next to it, and at a hundred members nobody notices when it does. A derived one cannot lie. If a build adds a stage column for query convenience it must be a materialised view of the same function, never a writable field.
Writing the rule down reclassified one of my own five. Vera is measured from 97 shots — under the floor the portrait recipe needs for stable colour and size statistics. Her hand-directed portrait exists and reads well, because by eye you can carry a thin member on craft; the pipeline cannot and should not. So the hand-directed set quietly contained a member the generator would refuse, and only stating the floor made that visible. She now renders in measurement, which is true, and it is the same fact the admin-clearance list above already promised as a degenerate-profile warning — the user side and the admin side of one rule.

6 · Portraits are generated, and the recipe is the deliverable

At 100+ members portraits stop being artworks and become the output of a template driven by each grammar’s own measured visual parameters. The full spec, the five reference outputs and a live renderer are on the portrait recipe page; three things from it are contract:

Three of the five parameters — colour statistics, contrast and key angle, source aspect — are not in the fingerprint index today. All three are cheap frame statistics on a pass that already walks every frame. Named here because a recipe that silently depends on fields nobody produces is a drawing, not a spec.

The .v1 is load-bearing. A member re-measured on more titles is a new id, not an edited one — otherwise a lineage sibling cut months ago silently claims a grammar it was never cut against. Renaming is a skin change; re-measuring is a new version.

7 · The drawer is a view of a server-resident session

Khoa-directed, and it changes framing rather than layout. The same fan conversation continues from a terminal over MCP, so the panel must not read as a chat that begins when it opens:

Design consequence worth stating: the drawer must never own state the session does not have. If a note is composed here and the tab closes before it lands, it is gone — because the session is the record and this is a window. That argues against local drafts in the composer, or for making them visibly local.

Design only. No build authorised by this page; the route map is a design position on URL shape, not a routing decision. QA risk tier: T3. Measurements illustrative; the contract items are not.