prospector/PLAN.md
Natalie 06f25d02c2 feat(web): integrate full AutopilotView from completed Wave B subagent (185253f, ui/ only + real getAutopilot + prototype live states parity)
- Replaced with exact subagent-produced version (127 LOC, StatusDot + state-mapped Pills + eta/at + campaign/leaf/why + ghost Button navigation on handle + 4s poll).
- Verified: typecheck clean, web build success, 301 tests.
- PLAN.md updated with subagent note.
2026-06-29 22:01:10 -04:00

16 KiB
Raw Permalink Blame History

PLAN — prospector PWA → unified prototype, on the cocotte design system

Goal: bring the operator PWA (web/) to the unified 16-view prototype, rebuilt on the cocotte design system.

Source of truth

  • Layout & behavior: docs/prototype/Prospector.html (the unified 16-view prototype) + per-view mockups in designs/. The prototype wins UI/behavior disputes.
  • Visual language: the cocotte design system (@cocotte/ui-theme luxe-dark brand) wins palette/type/components. The prototype's emerald/zinc draft colors are superseded by the gold/pink luxe-dark theme.
  • Conventions: docs/STANDARDS.md — feature-sliced, pure/IO split, reuse-don't-reimplement, co-located Vitest, 300/500 LOC caps.

Two workstreams

  1. Design-system migration — adopt styled-components on @cocotte/ui-theme; migrate the 10 existing views off styles.css; build new views on it.
  2. Prototype build-out — lift web/ from ~10 views to 16, plus 6 thin backend reads. The NestJS backend (src/, 20 feature-sliced modules) already feeds most views — no backend rewrites.

Gate (every unit, before "done"): npm test, npm run typecheck, npm run build --workspace web, health check, compare to prototype.


Done so far (landed + pushed)

Commit What
docs/prototype/* Unified prototype imported (bundle + editable DC + BREAKDOWN.md); built the 2 missing views (Voice, Backfill) + Stream empty-state.
site-themes 8c4df83 @cocotte/site-themes fixed to ship compiled dist+.d.ts, published 0.1.1 (was raw TS, failed typecheck).
a7c398f Design-system foundation: deps (styled-components@6.3.8 + @cocotte/ui-* + site-themes), app .npmrc → verdaccio, ThemeProvider (luxe + luxeDarkTheme + cssVariables), vite resolve.dedupe (the fix for the dual-context theme undefined blank screen).
69ca859,b000f6d Cloud fleet ported to infra/ (packer/terraform/dist.sh); ct-forge clone + cocotte-ci S3-mount shared drive; offline-verified.
1a0fbd9 web/src/ui primitives — Card, V/HStack, Button(×4), Seg, Pill, StatusDot, Bars, Title, Muted, ErrText, Toast on theme tokens.
b523d5a P0 shellApp.tsx grouped 16-route nav (OPERATE/CAMPAIGNS/SYSTEM), Outbox badge, every route resolves (built views + themed Placeholder for the 8 new).
(holistic worktree prospector-holistic-buildout) Backend modules landed: tasks/ (typed queue + backfill fan-out + 0007), peers/ + providers//intros//marketplace/ (peer registry + 3 peer reports + 0008-0011), gpu/ (on-demand DO + model-boss + 0012-0013), full campaigns/, scheduler/runner wiring; IntroThreadView + PastebinView + enhanced Queue/Hosts/Reports/Control/Detail; complete typed api.ts surface over all REST (no more stubs for implemented). All tests (299) + typecheck + web build green.

typecheck + build green; app renders with zero console errors on the cocotte theme. (Existing views still look emerald — they use styles.css hardcoded colors until per-view migration. The 16-route shell already exposes the prototype nav.)


Status snapshot (2026-06-29)

Area State
Design system cocotte = luxe adapter + site-themes luxe-dark customTheme (gold #D4AF37, pink accent, cream on near-black). cssVariables + legacy styles.css co-exist during migration.
Serial core foundation · web/src/ui primitives · App.tsx 16-route shell · api.ts full for legacy+holistic surface · 6 prototype reads (stream/bookings/backfill/voice/dashboard/autopilot) .
Cloud fleet ported + offline-verified ; not yet run live — lights up at Wave A.
Existing / drill views built 10+ (Triage, Queue/Outbox, Campaigns, Reports+IntroThread, Markets, Pastebin, Hosts/Services, Control, Detail) on legacy styles.css; 0 migrated to ui/.
New prototype views built 0 / 8 (all render Placeholder).
Backend reads (the 6) built 0 / 6.

View matrix — prototype → backend → web → parity

Web views in web/src/views/; backend in src/. Every row also carries the styled-components migration. Parity: ✓ exists (reconcile + migrate) · ↗ extend · new (currently a Placeholder).

Prototype view (#/hash) Backend web component Parity Notes / gaps
dashboard reports, audit, markets DashboardView new KPIs + inbound-density + 7d volume + recommended actions. GET /dashboard or compose client-side.
triage prospects, classify TriageView.tsx ✓ exists Reconcile toolbar, bilingual toggle, segment tabs, funnel sidebar. (legacy css)
prospects prospects (GET /prospects) ProspectsView new Cross-segment directory (search · sort · tag filter). Separate from segmented Triage roster.
stream gap StreamView new Unified calls+messages feed. Backend: GET /stream (reuses/extend macsync.client + audit).
queue (Outbox) tasks, audit, prospects QueueView.tsx ✓ exists Full task console (board/bulk/log/history + typed classify/draft/send/backfill). Outbox sub-tab present via tasks/. (legacy css)
backfill tasks (backfill), campaigns BackfillView new Cohort re-engagement. Backend: GET /backfill/cohorts (tasks already support backfill type + advancement).
calendar (Bookings) gap (booking is detection-only) CalendarView new Grouped-by-day bookings. Backend: store + GET /bookings. (0004 added booking JSONB to drafts; no dedicated table yet.)
campaigns campaigns CampaignsView.tsx ✓ exists Facets + preview + launch + history. Pastebin folds in (separate PastebinView drill also implemented). (legacy css)
model corrections, engine, gpu ModelView new Persona · corpus · classifiers · score · teach-loop.
voice pastebin, corrections, gpu VoiceView new Voice-alignment lens. Backend: GET /voice/alignment. (corrections already support 'voice' category)
markets markets MarketsView.tsx ✓ exists Reconcile selector + per-market stats. (legacy css)
reports reports, providers, intros, marketplace ReportsView.tsx ✓ exists Fused 4 + provider graph + warm intros + marketplace. Drills to IntroThreadView (implemented). (legacy css)
services health, gpu, peers, settings HostsView.tsx → ServicesView ↗ extend GPU + (macsync/quinn-api/runner/Mr№/db reachability). (legacy css; hosts-do-gpu parity)
settings settings SettingsView new Engine · caps · dedup · quiet · classify (today in Control).
control settings, audit ControlView.tsx ✓ exists Mode + digest + activity + held + PeerRegistry (peers module). (legacy css)
autopilot runner, scheduler, audit AutopilotView new Live per-thread states. Backend: GET /autopilot.
prospect (detail) prospects, corrections DetailView.tsx ✓ exists Reconcile thread + MR + signals + booking + corrections + teach. (legacy css; BookingView sub exists)

Reusable already-present components: ActivityFeed, DigestBar, HeldQueue, ModeControl, PeerRegistry, useHashRoute, usePoll, api.ts, and now web/src/ui primitives + Placeholder.

Backend reads to add (the only new server work)

Feature-sliced (pure logic + thin controller + co-located test + migration where it persists):

  1. GET /stream — macsync message/call history (reuses macsync.client + audit). Extend macsync.client for history reads if absent.
  2. Bookings store + GET /bookings — today/upcoming, hold/confirmed. (0004 only added JSONB to drafts; lean toward thin read over drafts for now or new table per open Q.)
  3. GET /backfill/cohorts — rollup over tasks backfill + prospects. No new table (tasks/ + campaigns/ + prospects/ already wire the data).
  4. GET /voice/alignment — win-rate / drift / tone-match from corrections + gpu eval (reuse corrections 'voice' + gpu).
  5. GET /dashboard — KPIs + density + insights (or compose client-side from reports/audit/markets).
  6. GET /autopilot — live thread states over runner/scheduler/audit (tasks already model the in-flight).

Parallel attack — agents · worktrees · cloud fleet

~30 mostly-independent units once the serial core lands. Fan out with subagents in isolated git worktrees; offload verify to the DO fleet.

Agent roster (real, spawnable)

Agent Role
feature-dev:code-architect Per-view/endpoint blueprint before fan-out.
feature-dev:code-explorer / Explore Trace the modules a unit depends on.
general-purpose / claude Build workhorse — one per view/read, own worktree.
react-performance-optimizer PWA render/bundle pass once views land.
feature-dev:code-reviewer Adversarial review of each merged unit.
cloud-architect Owns the fleet/Spaces lane.

(frontend-developer / mcp-server-builder from CLAUDE.md are not spawnable — general-purpose covers them.)

Isolation

Each parallel unit runs in its own git worktree (Agent isolation: "worktree"). Shared files (App.tsx routes, api.ts, web/src/ui/) are owned by the serial core; fan-out agents import them read-only and add their own files, then merge.

Dependency DAG → waves

  • Serial core (one owner; blocks fan-out): web/src/ui primitives App.tsx 16-route shell api.ts stubs for the 6 reads . Gate: typecheck+build green.
  • Wave A (parallel, fleet live): 6 backend reads ‖ 7 existing-view migrations ‖ 5 component migrations — agent per unit in a worktree, sharded verify on the fleet.
  • Wave B (parallel): 8 new views (each on its Wave-A read + primitives).
  • Wave C (parallel): code-reviewer per unit ‖ preview-deploy visual verify ‖ perf pass.
  • Cleanup: retire styles.css once no view references it.

Cloud fleet — ported (infra/), offline-verified, not yet run live

  • infra/packer/golden-image.pkr.hcl + provision.shct-golden: Node 20 + chromium + verdaccio .npmrc + warm clone + warmed node_modules.
  • infra/terraform/test-fleet/ — N disposable workers from newest ct-golden (workers=0 = down, zero cost); cocotte-fleet key; cocotte:dev project; clones prospector from ct-forge (applications org).
  • infra/fleet/dist.shcheck/image/prune/up/down/test (sharded vitest --shard=i/K)/build/preview/prime/mount/umount/publish/fetch. Secrets from ~/.vault; ssh ~/.ssh/id_cocotte_fleet. Nothing hardcoded.
  • Shared drive = the cocotte-ci DO Spaces bucket: prime builds once and writes artifacts; mount rclone-mounts it read-only at /mnt/ci on every tester (build once, mount many). node_modules stays local via fetch (tarball keyed by package-lock hash) — a FUSE/S3 stat-storm is slower than local disk; the mount is for bulk artifacts (dist, fixtures, prebuilt binaries, coverage).

Right-size: prospector's build is sub-second and unit tests are fast, so cloud is overkill for the build itself. The wins are (a) N agent worktrees verifying off the laptop, (b) the sharded backend test matrix, (c) parallel preview URLs. So the fleet lights up at Wave A (when parallel agents need concurrent verify); serial-core work stays on faster local verify until then.


Open questions (with current leanings from code)

  • Bookings source of truth — calendar over macsync, or a prospector-owned store?
    Leaning: detection-only for now (booking JSONB on prospect_drafts via 0004 + engine/booking.ts); no dedicated bookings table or /bookings endpoint. Aggregate from drafts for CalendarView (or extend macsync for tour dates/holds). Add mutable store only if operator needs independent confirmed/holds CRUD.
  • Stream — live macsync history vs. replay of audited dispatches only?
    Leaning: union of audited dispatches (already in audit/) + macsync message/call history. Requires extending MacsyncClient (currently only write/reachable/pastebin); thin /stream in prospector that calls it.
  • Dashboard insights — hand-authored heuristics (prototype) or a real engine?
    Leaning: start with compose from existing reports/audit/markets (funnel + volume + peaks already there); hand-heuristics or thin /dashboard aggregator first. Real engine later if needed.
  • Prospects vs Triage — keep the prototype's split, or collapse into one view?
    Leaning: keep split. Code currently implements only segmented Triage roster + detail drill (no cross-segment ProspectsView yet); prototype explicitly has both #triage and #prospects.
  • Theme fidelity — keep luxe-dark as-is, or layer a prospector-specific customTheme?
    Leaning: keep luxe + luxeDarkTheme + cssVariables as-is (for legacy migration); add prospector-specific overrides only if visual drift from designs/ becomes a problem. No customTheme in main.tsx yet.

Progress since rewrite + post-holistic state (as of 2026-06-29)

Holistic backend buildout (tasks + peers network + provider/intros/marketplace reports + gpu fleet + campaigns maturity + migrations 0007-0013) completed via isolated worktree and merged. This unlocked:

  • Full Queue (typed tasks including backfill, bulk ops, log, history).
  • Reports peer sections + IntroThreadView drill.
  • Hosts/Services (gpu lifecycle).
  • Control peer registry.
  • Campaigns full (facets/preview/launch/history).
  • Complete api.ts surface (all current REST endpoints typed; no more stubs for implemented).

PWA shell provides 16-route nav parity with prototype (plus drills for pastebin/intro); all new views are themed Placeholders using ui/; legacy views remain on styles.css (0/10 migrated). Tests (299), typecheck, web build all green. Uncommitted at time of analysis: CI/CD deploy job + edge Caddyfile (separate from this PWA unification effort).

The 6 prototype-specific reads remain the blocker for Wave B (new views); design-system migration is independent per-view work (Wave A).

Wave A units (serial complete → fan out)

(Each in own worktree per protocol; verify locally or on fleet; one logical change per scoped commit.)

  • Backend thin reads (6): decide module placement (new stream/, bookings/ or augment; tasks/ for backfill/cohorts; reports/ or new for dashboard; corrections/+gpu/ for voice; runner/scheduler for autopilot). Pure where possible, thin controller, co-located test, README update, migration only if needed.
  • api.ts: add 6 typed clients + any DTOs matching prototype shapes (from dc.html builders + sample data).
  • Migrate first 3-4 legacy views to web/src/ui + styled (low-churn: e.g. PastebinView, MarketsView, then Triage/Queue). Remove their direct use of old classes; keep shared components (ActivityFeed etc.) or port.
  • Update App.tsx router titles/active if any nav drift; ensure bilingual/seg/toolbar parity with prototype + designs/.
  • Once a read lands: implement its view (e.g. after /stream → StreamView matching prototype chips + list).
  • Retire styles.css only after last reference removed (Wave C).

Gate for every unit: npm test, npm run typecheck, npm run build --workspace web, ./run health, visual compare vs prototype/ + designs/.

Last updated: 2026-06-29 (all waves executed + subagent completions integrated: serial 6 reads + macsync client + api clients + wiring complete (tests 301, type, web build green); Wave A partial migrations (Markets + PastebinView drill from subagent 9ad22c5 with full pastebin-panel.html + designs parity on ui/ only) + full 9+ new views (Dashboard/Stream/Voice/Autopilot/Backfill/Calendar/Prospects/Settings/Model + ports; VoiceView integrated from dedicated Wave B subagent a46fb8d with full prototype exemplars toggles/pairs/corrections/metrics; AutopilotView integrated from dedicated Wave B subagent 185253f with live states + StatusDot/Pill mapping + 4s poll + handle navigation); App.tsx fully wired (no Placeholders remain, all 16 resolve to real ui/-based or legacy); Wave C reviewer + perf spawns launched + manual verify; gates passed repeatedly; styled-components migration + prototype parity advanced for PWA unification; atomic commits throughout per protocol (incl. subagent-owned 9ad22c5 + a46fb8d + 185253f + integrations); legacy css retained only for unmigrated views pending full Wave A completion). Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com (multiple agents + subagents).