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>
9.1 KiB
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 P0–P4 schema decisions (org-aware
user_id+org_idfrom 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 ▾orDemimonde / 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
prospectsprovider re-binds to org-scoped prospects. - The
auditprovider re-binds to the org'sagent_actionsslice. - The
policiesprovider 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 backto 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 = quinnorg_id = NULL(personal target) ororg_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 backto 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.
Related
- 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-replay —
action_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.