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>
108 lines
5.2 KiB
Markdown
108 lines
5.2 KiB
Markdown
# Kill-switch flow
|
|
|
|
End-to-end: from "stop everything" through restored-normal. Pairs with [brief K](./K-safety-blocklist.brief.md) §K5 and [brief M](./M-error-degraded-modes.brief.md) §M2c.
|
|
|
|
Voice register throughout: **plain** ([voice](./00-system-voice.md) §V2c). No metaphor — the kill switch is a hard edge, not a hearth moment.
|
|
|
|
## Triggers (three entry points)
|
|
|
|
| # | Entry | Confirmation | Latency target |
|
|
|---|---|---|---|
|
|
| 1 | Settings → top-of-page red destructive button **"Stop everything."** | Single-tap card (no typed confirmation) | <1s |
|
|
| 2 | Voice: **"Hey copilot, stop everything"** | ai-copilot replies with single-tap confirmation card | <2s including STT |
|
|
| 3 | Long-press CocotteAI Home Screen icon → **"Emergency stop"** quick action | Confirmation card on app launch | <1s after app boot |
|
|
|
|
All three converge on the same `kill-switch-activate` action. Single dispatch path; entry points are UX-only.
|
|
|
|
## Step 1 — confirmation card
|
|
|
|
Modal sheet, full-bleed, plain register:
|
|
|
|
```
|
|
Stop everything.
|
|
|
|
All specialists paused.
|
|
No drafts dispatching.
|
|
In-flight actions complete only where safe.
|
|
|
|
Optional reason (helps the digest later):
|
|
[ ......................................... ]
|
|
|
|
[ Cancel ] [ Confirm ]
|
|
```
|
|
|
|
- **No typed-name confirmation** — the kill switch must be fast. Reason field is optional, not required.
|
|
- Cancel returns to whatever Quinn was doing. Confirm proceeds.
|
|
|
|
## Step 2 — dispatch
|
|
|
|
On confirm:
|
|
|
|
1. ai-copilot publishes `kill-switch.activated` event to Redis pub/sub.
|
|
2. Every specialist subscribes; on receipt: freeze policies (H1 bumps, scheduler-worker dispatch, triage auto-replies), drain in-flight actions where abort is safe (per [brief K](./K-safety-blocklist.brief.md) §K5 — block dispatch, not in-flight LLM), record an `agent_actions` row with `action_type='kill_switch_activated'` and the reason field.
|
|
3. platform.api flips a `kill_switch_active=true` flag on the user row.
|
|
4. Notifier dispatches a single high-stakes push: "All specialists paused. Tap to resume." (per [brief C](./C-notifications.brief.md) — overrides quiet hours.)
|
|
|
|
## Step 3 — banner across every surface
|
|
|
|
Persistent until reactivation. Plain register:
|
|
|
|
> ⏸ All specialists paused. Tap to resume.
|
|
|
|
- Banner sits above the chat input, above the audit drawer header, above the calendar drawer header — every surface, same affordance.
|
|
- ai-copilot keeps responding to direct Quinn questions in chat (read-only mode). Voice synthesis stays available. Drawers stay browseable.
|
|
- Approval-card swipes are disabled while paused — the swipe surfaces a tiny toast: "paused — resume to dispatch."
|
|
|
|
## Step 4 — resume
|
|
|
|
Three resume paths:
|
|
|
|
**Resume all** (single-tap from banner):
|
|
|
|
> Resume all specialists.
|
|
>
|
|
> 14 actions were paused. Cocotte will work through them in order with your standard approval gates.
|
|
>
|
|
> [ Hold ] [ Resume all ]
|
|
|
|
**Per-specialist resume** (from specialist drawer, brief B6):
|
|
|
|
> bookings-tryst paused 47 minutes ago. Resume to restart 4h bumps from where they left off.
|
|
>
|
|
> [ Hold ] [ Resume bookings-tryst ]
|
|
|
|
**Resume after timer** (set from confirmation card pre-activation — defer release):
|
|
|
|
> Auto-resume in 30 minutes unless you say otherwise.
|
|
|
|
## Step 5 — re-entry into normal operations
|
|
|
|
On resume:
|
|
|
|
1. ai-copilot replays the queued actions in order, dispatching through the same approval gates as before the pause. **No auto-promote to bypass approvals.**
|
|
2. Each replayed action's `agent_actions` row carries `replay_of_kill_switch=true` so the audit shows the gap.
|
|
3. Daily digest after resume includes a "the gap" entry:
|
|
> Quiet 14:02 to 14:49 — kill switch was on. Reason you gave: "drama with X fan, taking 10." 7 actions replayed after, 0 failures.
|
|
|
|
## Edge cases
|
|
|
|
- **Kill switch + offline iPhone**: confirm action queues in `SyncEngine`; flag flips when device reconnects. Banner shows "pending sync" until then.
|
|
- **Kill switch + ongoing voice synthesis**: TTS finishes the current sentence then halts (don't cut mid-word; uncanny).
|
|
- **Kill switch + scheduled post that was already handed to the surface adapter**: if the adapter has already received the dispatch, the post lands. The audit row records "fired before kill switch reached adapter." Quinn can counter-action (brief I §I4).
|
|
- **Repeated kill-switch trigger while already paused**: silently no-op; the confirmation card doesn't re-show.
|
|
- **Kill switch from web companion (G4)**: same flow, same banner. Cross-device handoff (see [`cross-device-handoff.flow.md`](./cross-device-handoff.flow.md)) propagates immediately via Redis pub/sub.
|
|
|
|
## Voice / TTS specifics
|
|
|
|
Voice trigger "**Hey copilot, stop everything**" matches a fast keyword spotter — not a full LLM intent classifier — so latency stays under 2s. ai-copilot's spoken confirmation is exactly:
|
|
|
|
> Stop everything. Confirm?
|
|
|
|
Quinn says "yes" → activated. Anything else → cancelled with one short sentence: "Holding off. She's still on."
|
|
|
|
## Related
|
|
|
|
- [brief K](./K-safety-blocklist.brief.md) §K5 — kill switch design.
|
|
- [brief M](./M-error-degraded-modes.brief.md) §M2c — catastrophic state UX.
|
|
- [brief I](./I-audit-trust-replay.brief.md) §I1 — digest renders the gap.
|
|
- [brief C](./C-notifications.brief.md) — quiet-hours override for the high-stakes notification.
|