DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path change-requests/cr-create-conversation-opening-turn-v0_1.md

Change Request — Create conversation opening turn (door 1) — v0.1

Document: cr-create-conversation-opening-turn-v0_1 Version: v0.1 Date: 2026-06-28 Type: Phase change request — Operator Layer frontend only (loomworks). No engine change — the engine's speak-first machinery is already built. This is the door-1 piece of the engagement create-stage three-door design. Consumer: Claude Code (executor). Branch base: OL main @ 3f2fca8 (the merged Companion-surface arc; branch fresh off main). Governing scoping note: loomworks-create-stage-three-doors-scoping-note-v0_1 (door 1 — the conversation, the common finishing room). Grounding: the create-page opening-turn inspection this session (the create_engagement_entry template, the ChatView mount behavior, the dropped Workshop greeting, the unwired empty-state copy — engine 5ccc3d7, OL pre-merge 3f2fca8).


Plain-language summary

When you go to create an engagement, the page lands as a bare "Message Companion…" box on an empty screen — nothing greets you, nothing tells you what to do. The Companion is built to speak first (greet you and ask the first question), but the screen never gives it the chance to. This fixes that: when the create conversation opens, the Companion greets you and asks the first thing — what the work is, who it's for. One change, frontend only; the engine already knows how to greet. This is the first of three "doors" into creating an engagement (the others — a quick generator and a document converter — come later and feed into this same conversation).


What's true today (grounded)

The opening turn is a frontend wiring gap over a ready engine — confirmed by inspection:

Net: the create surface is worse than a normal empty conversation — engine ready to greet, frontend never asks it, both fallback greetings absent. The screenshot's bare box is the precise signature of all three.


Seed alignment

Aligned. Door 1 is the conversational authoring of the seed — the seed's own machinery (the create conversation already writes the reviewed conversation's facts into the engagement's Memory at commit, Operator-authority). A warm open is the entry to that authoring act. The greeting comes from the engine template (persona-aware, plain-terms) — consistent with the Companion's voice. No seed commitment is touched; this is the opening of the conversation that later produces the seed.


Decisions (settled, grounded)

  1. Lean on the built engine half — fire an opening converse call on create-mode mount (empty message + intent_hint="create_engagement_entry"); the engine's existing template greets and asks the first question. Do NOT revive the old static OpeningDoor string (that would be a second, competing greeting source).
  2. One greeting source — the engine template. Dynamic, persona-aware. The static-string path is not revived.
  3. The opening call bypasses the handleSend empty-guard — a dedicated mount effect, not handleSend (which early-returns on empty by design, correctly, for typed sends).
  4. Keep the create-mode history-fetch skip (ChatView.tsx:156-159) — the opening turn is generated, not fetched; the skip stays.
  5. A loading state covers the round-trip beat — between mount and the greeting arriving there's one network round-trip; show the existing thinking/loading indicator so the surface isn't briefly blank-then-populated with no signal.

Decision deferred (named)

Scope boundary — what this does NOT do


The build — steps

Per-step commits, suite green at each, halt-before-push. Frontend only; no engine, no migration.

Step 0 — inspect before building (no code)

Confirm against OL main @ 3f2fca8:

  1. Branch fresh off main at 3f2fca8.
  2. ChatView create-mode initialization — the mount/effect structure (:156-159 history-skip, :259 handleSend empty-guard, :302-305 intent_hint attach). Confirm where a mount effect that fires once on create-mode entry attaches, and that it can call the converse path without going through handleSend's empty-guard.
  3. The converse call path ChatView uses (the client converse function / hook) — confirm an opening call can send an empty message + intent_hint="create_engagement_entry" (the endpoint accepts it per grounding; confirm the client wrapper doesn't itself guard against empty).
  4. The thinking/loading indicator ChatView already shows during a normal turn — confirm it can cover the opening round-trip (so mount → loading → greeting, not mount → blank → greeting).
  5. The "fire once" guard — the effect must fire exactly once on create-mode entry, not re-fire on re-render or on every state change (a ref/initialized flag). Confirm the idiom the codebase uses for once-on-mount.

Report findings, then build.

Step 1 — Fire the opening converse call on create-mode mount

In ChatView (create mode only):

Suite expectation: a test that mounting ChatView in create mode fires one opening converse call with intent_hint="create_engagement_entry" and an empty message; that it fires exactly once; that the greeting turn renders. Existing ChatView tests unaffected (standard mode doesn't fire the opening call — confirm standard mode is untouched).

Step 2 — Confirm standard mode is untouched

Verify (test + manual) that opening an existing engagement's conversation (standard mode) does NOT fire the opening call — the opening greeting is create-mode-only. Standard mode keeps its existing behavior (history fetch, no auto-greeting).

Suite expectation: a test asserting standard mode fires no opening call on mount. (May fold into Step 1's test file.)


Acceptance

Note on lint: this CR adds a useEffect that fires a call on mount — adjacent to the setState-in-effect pattern that makes up the standing lint debt. Structure the effect to not add a new lint error (the call is a side-effect dispatch, not a setState-in-effect; if it trips the rule, that's worth getting right rather than adding to the debt this very session named).

What this sets up (named)


DUNIN7 — Done In Seven LLC — Miami, Florida Change Request — Create conversation opening turn (door 1) — v0.1 — 2026-06-28 Fires the engine's ready opening greeting on create-mode mount (empty message + intent_hint="create_engagement_entry"), bypassing the handleSend empty-guard, once, with a loading state over the round-trip. Frontend-only — the engine's speak-first machinery is built; ChatView just never gave it the opening. Closes the empty-create-conversation regression and stands up door 1 (the conversation finishing room) of the create-stage three-door design. One greeting source (the engine template); the static OpeningDoor is not revived; the empty-state fallback is deferred. Base OL main 3f2fca8.