cocottetech/@platform/codebase/@features/ai-copilot/docs/cross-surface-fanout.brief.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

17 KiB
Raw Blame History

cross-surface-fanout — "apply to all" as the canonical management interaction

Goal

The primary way Quinn manages her surfaces is through conversation in CocotteAI chat, not by opening per-surface screens. The keystone interaction is cross-surface fanout: Quinn states a direction once ("more tour-focused, less local, hike rates 15%"), Cocotte interprets, drafts per-surface adaptations, presents one approval card, and dispatches across N surfaces in parallel.

This brief defines:

  • the conversational grammar of cross-surface dispatch ("apply to all escort," "everywhere except Eros," etc.)
  • the per-surface adaptation engine (same logical change → surface-specific render via personas.facets)
  • the cross-surface approval card (one decision, N actions)
  • the progress + reconciliation UX (live streaming, retry-failed-only, partial-success)
  • the rollback model when a fanout goes wrong

Subsumes / extends brief H §H4 (multi-surface approval card sketch) and reframes surface-tryst.brief.md — every per-surface brief now declares whether actions on it are participants in fanouts.

Recommended read order: 00-system-voice.mdA-chat-surface.brief.mdH-recurring-chores.brief.md → this brief → surface-tryst.brief.md §14.

§1 Why conversation, not screens

The 8-screen Tryst set (tryst-profile-editor.screen.md, etc.) gives the impression that Quinn opens those screens to manage Tryst. She doesn't. Per Quinn's stated workflow (2026-05-18):

  • Quinn's #1 time-cost is per-platform repetition of the same logical change across 12+ directories + 11 content surfaces. Editing each in turn — even with great screens — recreates the time-cost CocotteAI is built to eliminate.
  • Conversation lets Quinn state the intent once, in natural language; Cocotte does the per-surface translation; Quinn approves once.
  • Screens still matter — as inspectors ("show me Tryst as a client sees it") and as emergency-edit fallbacks ("Cocotte got that wrong, let me fix it manually"). But they are not the canonical path.

The corpus should reflect this hierarchy. Every operate-on per-surface brief gets a §14 declaring its participation in fanout; every screen gets a header reframing its role.

§2 The conversational grammar

Quinn issues fanout commands in natural language; ai-copilot parses + routes. Recognized patterns:

§2a Audience selectors

Phrase Resolved set
"all escort platforms" / "all directories" / "all booking platforms" All active N2 surfaces (per O)
"all content platforms" / "all socials" All active N1 surfaces
"everywhere I'm active" Every connected surface across N1+N2 (excluding pending/blocked)
"the tier-1 directories" / "the anchor surfaces" Per-persona-config flag anchor=true (Quinn-marked)
"X, Y, Z" / "Tryst and TS4R" Explicit list
"everywhere except X" / "everywhere but Eros" All - X
"high-tier only" Per-persona-config flag tier='high'
"where I'm verified" Surfaces where verified=true on persona facet
"my bookings stack" / "directories where I bump" N2 surfaces with active H1 policies

Cocotte echoes the resolved set in the approval card: "Applying to 12 directories: Tryst, TS4R, Slixa, Eros, Seeking, PrivateDelights, TSEscorts, AdultSearch, AdultLook, EroticMonkey, SkipTheGames, MegaPersonals. Excluded: Eros (per your filter)."

§2b Action verbs

Verb family Examples Per-surface adaptation
Profile copy "rewrite my bio more playful" / "drop the corporate line" / "say I'm based in SF, touring Berlin Oct" About-me text drafted; per-surface adapted to char limits + tone (persona facet)
Rates "hike rates 15% everywhere" / "set incall 1h to $400 across directories" / "match my Tryst rates on TS4R" Tabular field updates; per-surface schema differences handled
Photos "set my hero to the red dress" / "remove the office photo from everywhere" Per-surface slot mapping; photo asset shared by reference
Tours "I'll be in Berlin Oct 37" H §H3 multi-surface tour fan-out; existing pattern
Visibility "pause all my bumps" / "vacation mode through Friday" H §H1 policy fan-out
Blocklist / safety "block @felix everywhere" / "no real-name mentions anywhere" K §K1K2 entries fanned with per-surface scope

§2c Constraint qualifiers

Quinn often pairs commands with constraints Cocotte must honor:

  • "but keep Eros wording corporate" — surface-specific override despite a global change
  • "draft only, don't push yet" — approval-card surfaced but stays in pending until separate approve
  • "if it pushes the price above my Tryst tier cap, skip Tryst" — per-surface conditional
  • "anonymize names" — applies the K2 phrase-blocklist as part of the draft

Cocotte's parsing surface (per voice.md) handles these as modifiers on the primary verb; the approval card shows the resolved per-surface plan including any skipped/conditional rows.

§3 The per-surface adaptation engine

Same logical change ≠ same per-surface render. Adaptation is driven by personas.facets[surface_id] config, which holds:

{
  voice_lean: 'hearth' | 'working' | 'plain',   // per voice.md §V4
  char_limit_about: number,                     // surface-specific
  char_limit_caption: number,
  banned_phrases_inherited: string[],           // K2 personal + surface-specific
  rate_schema: 'tryst' | 'ts4r' | 'slixa' | 'simple' | 'tier-table',
  posting_mode: 'real-api' | 'web-session' | 'manual-only',
  nsfw_allowed: boolean,
  cross_post_to: string[],                       // implicit fanout target hints
  anchor: boolean,                               // marks tier-1 surfaces
  tier: 'high' | 'mid' | 'long-tail',
  // ... surface-specific extensions
}

When Quinn says "rewrite my bio more playful":

  • Cocotte's strategist reads the active facets across resolved-audience surfaces.
  • For each surface, Cocotte composes a per-surface draft: same intent, surface-specific voice + char limit + banned-phrase filter.
  • Tryst (hearth-leaning, 500-char limit, "real name" banned) gets one draft.
  • Slixa (working-leaning, 250-char limit) gets a tighter draft.
  • TSEscorts (~2800 chars, ✦ spacers convention) gets a longer draft with formatting.

The approval card surfaces all N drafts in one view (collapsed by default; tap a surface row to expand its draft for inline edit).

§4 The cross-surface approval card

Anatomy (extends approval-card.screen.md kind=cross-surface-fanout):

┌─────────────────────────────────────────────────┐
│ ┃ ▢ More playful bio across 12 directories      │   stakes color + header
│ ┃ Audience: all escort directories              │   resolved audience echo
│ ┃ Excluded: Eros (per your filter)              │
│ ┃                                                │
│ ┃ Per-surface drafts:                           │
│ ┃ ▶ Tryst       · 432 chars · hearth · OK       │   one row per surface
│ ┃   (tap to expand draft + edit)                │
│ ┃ ▶ TS4R        · 380 chars · hearth · OK       │
│ ┃ ▶ Slixa       · 248 chars · working · OK      │
│ ┃ ▶ Seeking     · 410 chars · working · OK      │
│ ┃ ▶ PD          · 412 chars · hearth · ⚠ phrase │   K2 phrase hit
│ ┃ ▶ TSEscorts   · 2780/2800 chars · hearth · OK │
│ ┃ ▶ AdultSearch · 2790/2800 chars · hearth · OK │
│ ┃ … 5 more                                       │
│ ┃                                                │
│ ┃ One surface flagged a banned phrase           │   per-row issues summary
│ ┃ ⓘ "real name" in PD draft — strategist        │
│ ┃    suggested a replacement                    │
│ ┃                                                │
│ ┃ [ Edit per-surface ] [ Set aside ] [ Apply ]  │
└─────────────────────────────────────────────────┘

States (operate-on cross-surface approval card):

  1. Default — drafts ready, no issues.
  2. Issues flagged — ≥1 surface row shows ⚠ chip; banner summarizes.
  3. Editing per-surface (tap "Edit per-surface") — opens a sheet listing all surfaces; per-row inline-editor; "Done" returns to card.
  4. Editing a single surface inline (tap a row's chevron) — that row expands to show full draft + edit; collapse to compact.
  5. Mid-apply — Apply tapped; card animates to a progress strip: per-surface rows with spinners.
  6. Apply complete — collapses to receipt: "Updated 11 of 12. PD failed (rate-limited)."
  7. Partial failure — failed-rows surface with retry chip + "Retry failed only" affordance.
  8. Apply cancelled mid-flight — per brief M: in-flight per-surface actions complete (or abort where safe); successful surfaces stay; failed/in-flight surfaces revert if rollback supported.
  9. Conflict (someone changed Tryst from another device mid-fanout) — per brief M §M7: 3-way diff per affected surface; surface-by-surface resolution.

§5 Progress + reconciliation

Apply triggers parallel dispatch to N specialists. Quinn sees:

  • Live progress strip: per-surface rows with status glyphs ( in-flight / ✓ done / ✗ failed / ⏸ skipped). Updates every ~500ms via SSE from platform.api.
  • Per-surface duration: visible after completion (helps Quinn understand which surfaces are slow / problematic).
  • Receipt collapse: when all rows complete, card collapses to a single chat receipt bubble; long-press to re-expand the full per-surface result.

Per-surface failures don't roll back successes by default. Quinn explicitly chooses:

  • Retry failed only — re-attempt just the failed rows.
  • Rollback successful — undo the changes on the rows that succeeded (only available where the action has a rollback implementation per _engineering-surface-adapter-container.md Layer 6).
  • Accept partial — mark partial-state as final; failed rows stay un-updated (most common; Quinn fixes failed surfaces individually later).

§6 Stakes inheritance

Cross-surface fanout inherits stakes per the highest-stakes participating surface, per voice.md + F §F1:

  • Bumping availability across 12 directories: low stakes (each surface is low; multiplied is still low).
  • Rewriting profile copy across 12 directories: medium stakes (reputation-shaping; mistakes are reversible but visible).
  • Changing rates 15% across 12 directories: high stakes (financially material; harder to walk back; clients may have seen the change before rollback).
  • Tour announcement (H §H3): medium to high depending on tour duration + visibility.

The approval card uses the resolved stakes for its color band + confirmation friction (high-stakes gets the M §M3 high-stakes-interrupt pattern).

§7 Conversational entry points

These all route into the same fanout machinery:

  • Direct ask: "rewrite my bio across all escort platforms" → strategist drafts → approval card.
  • Indirect repositioning: "I'm going tour-only" → ai-copilot proposes a plan (multiple fanout actions chained: change rates + rewrite bios + adjust home-cities + pause local-only surfaces) → each step is its own approval card.
  • Quick correction: "you said 'no rush' — change that to 'unhurried' everywhere" → micro-fanout; minimal card.
  • Voice command: same grammar over voice (per voice-input-settings.screen.md).
  • From a single surface's chat: Quinn in direct-conversation with bookings-tryst says "do this on TS4R too" → ai-copilot promotes the conversation context, surfaces a 2-surface fanout card.

§8 What's NOT fanned out

Some actions are inherently per-surface:

  • Tryst home-cities (per surface-tryst §7): unique tier-gated cadence model; doesn't generalize.
  • OF subscription pricing tiers: structure unique to OF; no cross-surface analog.
  • Sumsub KYC re-up: per-surface verification; can't be "applied to all."
  • Connect / re-auth: per-surface auth-grant; never a fanout.

Per-surface brief §14 (introduced for surface-tryst) declares which actions are fanout-participants and which are per-surface-only.

§9 Failure dictionary (cross-surface)

Failure Behavior
Some surfaces fail, others succeed Receipt shows partial; Quinn picks retry/rollback/accept
Audience resolves to 0 surfaces (e.g. "apply to escort platforms" but Quinn isn't connected to any) Pre-card warning: "I don't see any escort platforms connected yet. Connect one first?" Routes to surfaces-settings.screen.md
All surfaces fail (e.g. backend down) Per M §M2b: degraded banner; nothing applied; queued for replay
Quinn cancels mid-apply In-flight completes or aborts (per surface); successful rows stay; receipt shows interrupted state
Specialist-degraded mid-apply (one specialist offline) That specialist's row stays in ⏸ skipped state; other rows continue; degraded specialist surfaces M §M2a banner
Captcha required on N specialists during fanout HITL: Quinn pings to solve one challenge per affected surface, sequentially. Cocotte attempts to batch / dedup if same captcha; defer to L3 captcha-solver capability
Rate-limited across multiple surfaces simultaneously Cocotte spreads dispatch over time (jitter); banner notes "spreading over N minutes"

§10 Generalization across surface categories

Fanout works across N1 (content) + N2 (directories) + N7 (reviews-aggregators — flag-fanout) + N6 (screening — submit-fanout). NOT across N5 (commerce — money-touching) or N8 (bio-links — synced separately).

Per-surface brief §14 declares participation:

  • Operate-on surfaces (N1, N2): typically full fanout participants — bumps / posts / profile / rates.
  • Consume-from surfaces (N6 screening, N7 reviews): partial — only submission actions fan out (submit-to-blocklist, flag-as-defamatory).
  • Connect-only surfaces (N5): no fanout.

States to design (for an iOS-level designer / engineer)

  • Cross-surface approval card — all 9 states from §4 above.
  • Per-surface expanded inline editor (nested within the card).
  • Live progress strip animation.
  • Partial-success receipt + retry-failed UI.
  • Rollback confirmation (high-stakes pattern).
  • 3-way conflict resolution per surface (M §M7 inheritance).
  • Conversational entry points: the chat-side text Cocotte uses to confirm a parsed fanout intent before rendering the card ("Got it — bio change across 12 directories. Drafting...").
  • Voice-mode fanout: how does Cocotte read the per-surface plan over TTS? (Lean: summary only, "12 drafts ready, want to see them?" — don't read all 12 aloud.)

Open questions

  • Per-surface adaptation quality bar: how aggressively should Cocotte rewrite per-surface vs minimally transform? Lean conservative — preserve Quinn's intent; surface adaptations as suggestions she can override per-row.
  • Cross-surface undo TTL: how long after fanout completion can Quinn say "actually undo that"? Lean 24h for low-stakes, 1h for high-stakes; configurable per brief I trust-panel.
  • Streaming approval review: should the per-surface drafts appear progressively (faster surfaces first) or all-at-once? Lean all-at-once for cognitive cohesion; streaming makes the card unstable.
  • Conflict with H3 tours: a fanout that touches profile-text mid-tour might overlap with the tour-specific copy. Resolution rules need to be explicit.
  • Org-level fanout (W brief): when Quinn admins Demimonde + another member, can a fanout target the member's surfaces too? Org-overlay decision; defer.

Out of scope

  • Org-level fanouts spanning multiple members' surfaces — W brief territory.
  • Predictive "you probably want to fan this out" prompts — defer to a future strategist enhancement.
  • Cross-tenant fanout (a coop-shared template applied across multiple providers) — Y brief marketplace; out of P0/P1.