cocottetech/@platform/codebase/@features/ai-copilot/docs/context-switch.flow.md
natalie 1b719e1fd7 chore(bootstrap): initial V4 commit
Clean successor to V3 (forge: lilith/atlilith). Seeded from local Mac
working tree at ~/Code/@projects/@cocottetech/. node_modules and build
artifacts excluded via .gitignore.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 08:11:41 -07:00

9.1 KiB
Raw Blame History

Flow — context switch (personal ⇄ Demimonde) — P5+ pre-design

P5+ pre-design. Org overlay ships P5+ per plan. This flow defines what the switch must look like when it lands so P0P4 schema decisions (org-aware user_id + org_id from day one) stay forward-compatible. Pair with W org overlay §W2.

Goal

Quinn moves between her personal scope and Demimonde org scope without losing her thread with ai-copilot. Drawers re-render against the new scope, the voice register shifts, and held cards block on mixed-scope conflicts before they commit.

Triggers

  • Top-bar context chip (W §W2). Tap the chip left of the settings gear (Quinn ▾ or Demimonde / Quinn ▾) → switcher sheet opens.
  • Voice (W-Q3, [nice-to-have] leaning supported). "Switch to Demimonde" / "switch back to personal" → ai-copilot answers with a vocal confirmation ("Switching to Demimonde — confirm?") before executing. Confirmation is required because mis-scoped actions are a high-stakes class of mistake.
  • Settings → S1 → org row → opens roster, with a "switch into this scope" affordance.

Step 1 — Switcher sheet open (W §W2 spec)

Sheet animates in from bottom. Three-row picker:

Switch context. Each scope is what Cocotte sees and acts on.

●  Quinn (personal)                             [current]
   Your own work. Persona, journals, your prospects.

○  Demimonde / Quinn (member)
   Org-shared work. Prospects routed to the org,
   shared content guidelines, org-wide audit.

○  Demimonde / org-wide (admin)                 [only if admin]
   Full org view. Aggregate of all members.

Recent: switched from Demimonde 2h ago

The org-admin row only renders if Quinn's role on Demimonde is Admin (per W §W3). Non-members see permission-denied (see Edge cases).

Step 2 — Scope choice

Quinn taps a row. Sheet does not auto-dismiss — a Switch confirm button at the bottom commits the choice. Tap outside cancels. This single confirm prevents fat-finger scope flips (especially under voice trigger).

Step 3 — Every drawer re-renders against the new scope

Switch is state-only, no data moves (W §W9). On commit:

  • The active chat surface stays mounted; thread scroll position preserved.
  • Every open drawer (B1 content, B2 assets, B3 prospects, I audit, T analytics, U search, R tours) re-queries platform.api with the new (user_id, org_id) filter and re-renders in place.
  • Personal-only surfaces (persona B5, journal Q, kill-switch K5, S2/S8 settings) ignore the switch — they stay personal regardless and hide the scope badge (W §W1).
  • Org-only surfaces (org roster, org-wide policies, org-wide audit) only mount under an org scope; they unmount on switch-to-personal.
  • The top-bar chip animates label + subtle background-material shift (W-Q4 lean: not a full color change).

Step 4 — ai-copilot context-provider re-scope (W-Q2)

ai-copilot's chat memory continues — the thread Quinn was in stays open, prior turns remain visible and addressable. What changes is its context providers:

  • The prospects provider re-binds to org-scoped prospects.
  • The audit provider re-binds to the org's agent_actions slice.
  • The policies provider switches from per-user defaults to Demimonde's org-wide policies (with member-overrides applied).
  • Persona provider stays personal (persona is identity, never org-asset).
  • Active retrieval is invalidated; the next turn re-grounds against the new scope.

If Quinn references prior-scope content in the next turn ("send that draft we just looked at"), ai-copilot resolves the reference against thread history but checks whether the referenced object is reachable in the new scope. If not, it surfaces a mixed-scope warning (Step 6).

Step 5 — Voice register shift (W §W5)

Under Demimonde, ai-copilot's system-prompt receives an org-context addendum: "You're acting on behalf of Demimonde. Decisions affect the org. Speak with that awareness." The audible effect:

  • Slightly more formal. Fewer hearth metaphors ("the pantry", "simmering" recede).
  • "The org" framing replaces "you" in some contexts ("the org has three open prospects").
  • Same TTS voice; prosodic delivery unchanged. Register shift is lexical, not vocal-character.
  • Quinn perceives the change by ear — the register itself is a redundant signal that the chip is correct.

Returning to personal restores the full hearth/working/plain gradient per voice.

Step 6 — Mixed-scope warning if held card is from prior scope (W §W2)

If Quinn has an approval card open (mid-decision) when she initiates a switch, the card greys and a banner anchors at the top:

This card is org-scoped. You're now in personal. Continue under org or cancel.

Plain register, per W §W5's high-stakes copy. Two affordances:

  • Continue under org — reverts the context chip to org, returns Quinn to the card's native scope, switch is abandoned.
  • Cancel card — discards the held action, commits the switch.

There is no "approve under wrong scope." That class of mistake is prevented structurally.

Step 7 — Confirmation receipt

Once the switch commits and drawers settle, ai-copilot drops a single-line ambient message into the chat:

Now acting on behalf of Demimonde. Drafts and decisions reflect the org. Say switch back to return to personal.

Working register. On switch-to-personal:

Back to personal. Org work is paused on the org side.

If the switch was voice-triggered, this same line is also spoken via TTS (per W-Q3's vocal confirmation lean).

Step 8 — Audit row writes

A single row is appended to agent_actions:

  • action_type = 'context_switched'
  • user_id = quinn
  • org_id = NULL (personal target) or org_id = demimonde (org target)
  • outcome_json = { from_scope, to_scope, trigger: chip|voice|settings, device_id }
  • created_at = now()

The row writes under the target scope so org-admins see when members enter and leave Demimonde. Personal→personal noise is suppressed.

Edge cases

  • Permission denied — Quinn taps a row for an org she isn't a member of (e.g. deep-linked from a stale notification). Sheet shows the W in-the-wild copy: "You're not a member of this org. Ask an admin to add you." Plain register. Row is non-tappable; no audit row written.
  • Cross-context prospect handoff (W §W6) — moving a personal prospect into Demimonde is its own sub-flow, not a side effect of context-switching. The switcher sheet does not migrate data. Handoffs run through the prospect drawer's "Share this prospect with Demimonde" affordance (B3), which has its own confirmation sheet and audit shape.
  • Cold-launch restores last-active scope (W-Q1) — on app open, the chip is initialized to whatever scope Quinn was in when the previous session ended. New installs default to personal. No mid-flight switch is replayed.
  • Org membership revoked mid-session — if Demimonde admin removes Quinn while she's in org scope: WebSocket push (per cross-device-handoff §State sync) forces a scope-reset to personal. ai-copilot drops a plain-register line: "Your access to Demimonde was removed. You're back in personal." Any held org-scoped card is discarded with a toast.
  • Voice-trigger ambiguity — "switch to demi" matches Demimonde fuzzily; ai-copilot confirms the full name before executing. No silent fuzzy-match scope changes.
  • Active org-scoped TTS readback in progress — TTS finishes the current sentence under prior-scope voice, then the register shifts on the next utterance. Mid-sentence register flips sound stilted.

Voice / TTS

Cocotte's acknowledgment line on entering org context (per W in-the-wild copy, working register):

Now acting on behalf of Demimonde. Drafts and decisions reflect the org. Say switch back to return to personal.

On voice-triggered switch, the pre-commit confirmation (plain register, because mis-scoped action is high-stakes):

Switching to Demimonde. Confirm?

TTS prosody is unchanged across scopes — single voice, lexical register shift only. Per voice V8 §6 read-aloud check: both lines pass as prose, not UI labels.

  • W org overlay — parent brief; §W2 context chip + switcher is the source spec.
  • S settings-ia §S1 — org switcher entry point (alternate trigger).
  • L specialists-fleet §L1 + W §W4 — specialist scope (personal / scoped / org-only) determines which forks re-bind on switch.
  • I audit-trust-replayaction_type='context_switched' row + scope filter on the audit drawer.
  • A chat-surface + W-Q2 — chat memory continuity across switches.
  • D onboarding — org-aware persona stays personal; switch never re-runs the seed interview.
  • cross-device-handoff — scope state syncs over the same WebSocket channel that powers device handoff.
  • 00-system-voice §V2 + W §W5 — register shift under org context.