Document: cr-restore-engagement-creation-affordance-v0_1
Version: v0.1
Date: 2026-06-28
Type: Phase change request — frontend only (Operator Layer loomworks repo). No engine, no classifier, no create-page change.
Consumer: Claude Code (executor).
Branch base: feat-companion-surface @ dac9fec (current OL HEAD; carries the mobile Companion surface + add-side work).
Governing scoping note: loomworks-restore-engagement-creation-affordance-scoping-note-v0_1.
Grounding: loomworks-create-flow-and-old-surface-omissions-inspection-v0_1 (capability is live, only the entry point is gone) + the CR-drafting grounding pass (real Home.tsx, HomeCards.tsx, create-engagement/page.tsx, TopBar.tsx at dac9fec).
You can create an engagement today — the engine, the Companion, and the create page all work — but there's no visible way in from the home where you manage your engagements. The old home had a create button; the new home (built to a mockup that omitted it) doesn't. This adds a create button back to the home that opens the create conversation. One control, both layouts (desktop and mobile), nothing new underneath — it points at the create page that already exists.
dac9fec)create_engagement_entry/_active/_commit) with real handlers; the create page /operator/create-engagement renders ChatView mode="create-engagement" and works. (Inspection-confirmed.)create-engagement/page.tsx auth-guards then renders <ChatView mode="create-engagement" />; ChatView in create mode sends intent_hint: "create_engagement_entry" on the first turn and operates with no projectId. So the affordance target is a bare router.push("/operator/create-engagement") — nothing to thread.Home.tsx desktop header (:289-297) is wordmark + operator name (left) · Avatar (right); the lens-tab row (:298-325) is the three tabs, a flex-1 spacer, then HOME.voiceHint as a static string at top-right (:324). No create button anywhere; grep "Create/New/Start engagement" → 0.HOME.voiceHint string, no click behavior. The real tryPromptHint mechanism lives in TopBar.tsx as a mic-button tooltip, and TopBar is the in-engagement surface, not the home. There is no interactive prompt seam on the home to add a create prompt to. The affordance is therefore a new button, not an added prompt. (This simplifies the CR.)<button onClick={() => onOpen(projectId, displayIdentifier)}> (HomeCards.tsx); onOpen (Home.tsx:113-117) does focusCtx.setFocus(...) then router.push("/operator/engagement/<address>"). A create control follows this idiom — a <button> doing router.push("/operator/create-engagement") — minus the focus-set (no engagement exists yet to focus).Aligned — restores a capability the seed's success conditions assume (creating an engagement is the operator's first action). "Only show what is available" cuts toward this: creation IS available (live), so it must appear; its absence is the surface failing to show an available capability — the same omission class as upload / navigation / the mobile transcript.
router.push("/operator/create-engagement"), reusing the working create page exactly as-is. The in-place option (rendering the create conversation on the home) is a deliberate later refinement, out of scope here.<button> with the home's existing button styling, router.push on click, no focus-set.sendConverse({surfaceContext:"home"}), the engine handles the create intent) but desktop has only the static hint. Surfacing desktop home voice is a real adjacent improvement — but it's a different gap (desktop home voice, already listed in build-queue v0.3 open gaps as "desktop home voice — TBD"), not the create-button gap. Out of scope — folding it in would make this two unrelated changes. Named for its own keep-or-drop.Per-step commits, suite green at each, halt-before-push. Frontend only; no engine, no migration, no create-page change.
Confirm against feat-companion-surface @ dac9fec:
dac9fec.Home.tsx lens-tab row structure (:298-325) — the flex-1 spacer + HOME.voiceHint right-cluster placement is as grounded, so the create button has a home in that cluster.:335-431) — where a create control sits there (the mobile home has Personal pinned above a swipe stack + an anchored bottom bar with a mic). Identify the mobile placement (lean: near the header or as a visible control above/within the zone list — NOT hidden in the bottom bar, which is the voice composer).CARD class in HomeCards.tsx) so the create button reads as native chrome, not a bolt-on.Report findings, then build.
In Home.tsx, add a create button to the lens-tab row's right cluster (:298-325), beside or in place-of-prominence with the static HOME.voiceHint. The button:
HOME.createEngagement string — see Step 3).onClick → router.push("/operator/create-engagement"). (The router is already in scope in Home.tsx — it drives onOpen's push.)HOME.voiceHint beside the button, or let the button replace it as the right-cluster element. Lean: keep the button as the primary right-cluster affordance; the static hint can sit beside it or be dropped (it described voice discoverability, which the button doesn't replace — so keep it on mobile where voice is wired; on desktop where there's no mic, the hint is arguably misleading and the button is the real affordance). Confirm at Step 0 against the real layout.
Suite expectation: new visible control; existing home tests unaffected (additive). Add a test: the create button renders on the desktop home and navigates to /operator/create-engagement on click.
In Home.tsx's mobile layout (:335-431), add the same create affordance, placed per the Step-0 finding (lean: a visible control near the header or above the zone list — not buried in the voice bottom bar). Same router.push("/operator/create-engagement") handler.
Suite expectation: add a test: the create button renders on the mobile home and navigates on click. Existing mobile-home tests unaffected.
Note: Steps 1 and 2 may collapse into one commit if the create button is a shared element both layouts render (cleaner — one button component, placed in each layout). Lean: a single shared CreateEngagementButton (or inline shared element) rendered in both layouts, one commit, rather than two divergent inline buttons. CC's call at build time based on the real layout structure — but prefer the shared element to avoid two buttons drifting.
Add to HOME in src/lib/strings.ts:
createEngagement: "Create engagement" — the button label. (Plain-terms; "engagement" is the seed's word, wall-safe.)
Confirm the vocabulary wall accepts it (it uses "engagement" already throughout HOME).
/operator/create-engagement, which renders the working create flow. End-to-end: button → create page → (Operator converses) → engagement created. (The create flow itself is untouched and already works; this CR's acceptance is that the button reaches it.)main — lands on feat-companion-surface; merge is a separate authorization.DUNIN7 — Done In Seven LLC — Miami, Florida Change Request — Restore engagement-creation affordance (lens-home) — v0.1 — 2026-06-28 Adds a create-engagement button to the lens-home (desktop + mobile) doing router.push("/operator/create-engagement"), following the card-button idiom minus focus-set. The capability is live end-to-end; only the entry point was dropped to a mockup. Frontend-only, additive, on dac9fec. Desktop home voice + other omissions named but out of scope.