Matches sweep.py — 64-way client concurrency against vLLM max_num_seqs=128 so
the full 8K-row backward-rationalization runs in ~12min on one H100, no
horizontal fleet needed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Real convos aren't clean alternating turns: ~38% of message-runs are bursts
(one sender, up to 132 in a row), and 5 group chats mix senders under
is_from_me=0. New lib.py collapses bursts into turns, excludes group chats
(chat.style=45 only), and yields CLIENT->QUINN decision points with a
per-conversation cap (avoids verbose threads flooding the set). Corrected
corpus: 1623 1:1 work-era conversations, 16095 decision points (8129 at
max_per_handle=20). sweep.py now uses lib + WORKERS for vertical scaling.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Backward CoT distillation over all swept conversations (context + Quinn's actual
reply -> move + gold-anchored trace), full 10-move taxonomy. Produces the
(context -> trace -> move) LoRA training set labeled by what she really did.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There is no model-boss coordinator deployed — the on-demand GPU droplet serves
raw vLLM (/v1). So the client now sends a standard OpenAI request with an explicit
model (caller's, else GPU_LLM_MODEL) and drops the coordinator-only x_task/
x_priority routing fields; health probes vLLM's /health (was /ready). Set
GPU_LLM_MODEL to vLLM's --served-model-name when the GPU is provisioned.
(ChatJsonOpts.task/priority are now passed-but-ignored; symbol/env names
ModelBossClient/MODEL_BOSS_URL kept to avoid a sprawling rename — cosmetic cleanup.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Classifies work-era chat.db threads (Nov 1 2025+) into the full move taxonomy
(opener/qualify/engage/subhour/address/out_of_area/of/disengage/escalate/skip)
with CoT traces; keeps Quinn's actual reply as gold. Scales via LIMIT to grow
the silver-labeled training set; flags sparse semantic classes (escalate/
photographer) that regex can't find. Work-era corpus: ~1491 inbound handles.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
STaR-style: given (client_msg -> Quinn's actual reply), infer the move she ran
+ a one-sentence reasoning trace anchored to her real reply. Produces
(message -> trace -> move) training rows for LoRA-hardening move-classification.
First BBC batch: 19 rows, qualify 8 / engage 3 / disengage 8 -- matches her
real qualify-dominant boundary, not a hand-authored guess.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SERVER_HOST default → 138.197.120.105 (old lime IP released). Ship DO CA cert
+ NODE_EXTRA_CA_CERTS in the unit (managed PG = self-signed chain → node
SELF_SIGNED_CERT_IN_CHAIN). Box must be a DB trusted-source.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Locks the fix in 57e898b. The existing route-mount test mocks usePoll to permanent
loading, so it never renders the data branch and missed the memo-after-early-return
crash. This test flips usePoll loading→data for Dashboard + Calendar and asserts the
re-render doesn't throw. Verified it FAILS on the pre-fix views ("Rendered more hooks
than during the previous render") and passes on the fix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Completes the unification — the deploy script ref (deploy/deploy-server.sh)
that the retired app.manifest.yaml carried. (Followup to the deletion in HEAD~1.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Single manifest per the infra_manifest convention. Added service.deploy
(deploy/deploy-server.sh); manage-apps now auto-discovers this .infra.yaml and
drives the prospector systemd unit on lime (ssh lime systemctl …) — replacing the
brittle inline-ssh strings the app.manifest.yaml carried.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both views called useMemo AFTER their loading/error early-return guards. While the
backend lacked the data (or the dev proxy was unauthenticated) the views always hit
the early return, so the memos were never reached and nothing crashed. The moment a
populated response arrived, React rendered more hooks than the previous render →
"Rendered more hooks than during the previous render" → the view tree threw and the
panel went blank.
Fix: move every useMemo above the `if (error)` / `if (!data)` guards and make each
null-safe (deps key off `data?.*`). Pure refactor — no behavior change once data is
present. Introduced by the Wave-C perf pass (useMemo on derived rows); it slipped
past typecheck (hook rules aren't typed), the route-mount test (usePoll mocked to
permanent loading → early return, memo never reached), and the build.
Verified live against the running backend: Dashboard renders KPIs + density bars +
insights + actions; Bookings renders its grouped/empty state — neither throws.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pulls every thread matching a pattern (e.g. BBC / self-offer / lowball) paired
with Quinn's actual next reply = the gold move label. The training substrate for
hardening move-classification on the intent-split cases where prompt rules fail
(paying-prospect -> qualify vs non-client -> disengage). PII under gitignored
.data only.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The PWA unification is done: all remaining views/components/shell migrated off
styles.css to the cocotte design system (commits 5a7e093 + 2512e75). Records the
green gate (301 backend + 17 web tests, typecheck, build) and the separate deploy
effort intentionally left out of scope.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Validated OSS (Qwen3.6-27B-AEON-Uncensored) Quinn-voice drafting against the
agent-matcher reply-queue baseline. Four methodology fixes eliminate the early
weaknesses: json_schema strict (0% malformed), canon few-shot (100% on-voice),
current-facts/location-from-context (0 location errors), and classify-move-first
then reply (matcher-level discipline on defensive moves: withhold address,
redirect harvesters+crude to OF). PII stays under gitignored .data/; scripts
only. Claude is the offline judge/advisor, never the runtime generator.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jsdom + single-instance styled-components/react dedupe (mirrors vite) so the
ThemeProvider context reaches components; MemoryStorage shim for the theme's
localStorage persistence. App.test.tsx proves every prototype route resolves to a
real lazy-loaded view that mounts on the cocotte theme and renders content (not a
Suspense fallback, no Placeholder), with the data layer stubbed to a loading
state — queried by the semantic <main> region, not a class, since the shell is now
pure styled-components.
17 tests green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Final Wave A/C step of the PWA unification: the last 14 files rendering against
the legacy global styles.css (~1.1k LOC, 166 classes) are now pure
styled-components on @cocotte/ui-theme luxe-dark tokens — 8 views (Triage,
Detail, Reports, Campaigns, Hosts, IntroThread, Control + the 4-file Queue
cluster), 5 shared components (ActivityFeed, DigestBar, HeldQueue, ModeControl,
PeerRegistry), and the App shell (mac-window/titlebar/nav, incl. the installed-PWA
display-mode chrome drop). Each migration was adversarially parity-reviewed vs
designs/ + the prototype; behavior, data flow, props and DOM structure unchanged.
styles.css deleted; its global reset + body base ported to a themed
createGlobalStyle (ui/global.tsx). The three largest views factor their local
styled blocks into co-located *.styled.ts siblings to hold the 500-LOC cap.
Gate green: 301 backend tests, root+web typecheck, web build (240kB/18 chunks),
zero className remaining across web/src.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The deploy ships web-dist but never built it; add the web/ vite build to the
build step so a fresh deploy includes the operator PWA. Verified: /prospector
PWA serves at lime:3210/ (title "Prospector").
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace rejectUnauthorized:false (flagged by security review — MITM exposure)
with proper chain verification: PROSPECTOR_DB_CA_CERT points at DO's CA PEM and
the connection runs rejectUnauthorized:true. Without a CA it still fails closed
(strict by default); PROSPECTOR_DB_SSL_REJECT_UNAUTHORIZED=false is an explicit,
audited escape hatch only. CA fetched from the DO /databases/<id>/ca API and
placed at /opt/prospector/do-ca.crt on lime. Verified: prospector connects with
strict TLS + serves on :3210.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- env is a dotenv at /opt/prospector/.env (ConfigModule envFilePath), NOT a
systemd EnvironmentFile (dotenv won't override process.env, so EnvironmentFile
silently shadowed it); unit has no EnvironmentFile, reads .env from WorkingDir.
- correct PROSPECTOR_DB_* vars (app uses discrete vars, not DATABASE_URL),
PROSPECTOR_DB_SSL=true, generated service tokens, dep placeholders.
- ship migrations/ + ensure psql-16; apply pending SQL migrations (ledger).
- fail-fast on __SET_ME__ DB creds (the secret step stays external).
Verified: prospector live on lime:3210 (active, schema migrated, / -> 200).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`ssl: true` failed SELF_SIGNED_CERT_IN_CHAIN against DO Managed PG (DO-CA cert
not in the default trust store). Use `ssl: { rejectUnauthorized: false }` when
PROSPECTOR_DB_SSL=true (link is already private — VPC + trusted-source firewall);
opt into strict verify with PROSPECTOR_DB_SSL_REJECT_UNAUTHORIZED=true once a CA
bundle is wired. Verified: prospector connects + serves on lime:3210.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- app.manifest.yaml: lime platform (systemd unit prospector, :3210, mesh-only),
deploy/start/stop/status/logs; registered with manage-apps.
- deploy/deploy-server.sh: build (nest) -> ship dist/ + pkg + PWA -> ensure
node20 -> npm ci --omit=dev -> fail-fast env -> systemd unit -> restart.
Verified to lime up to the DB pause: node20 installed, deps shipped, unit
installed; does NOT start until DATABASE_URL (prospector role on
lilith-store-pg) is set — that secret step is deliberately external.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bake-off harness in src/eval/ with Claude as offline labeler/judge/advisor
(never in the serving loop). Per-role scoring (classifier F1, generator
refusal+voice+policy+85% gate, orchestrator tool-call), replay harness to
fix Executor cycle-1's no-batch-replay blocker, researched candidate
roster (de-refused instruct base + Quinn-voice LoRA over heavy RP
fine-tunes). Reuses outcomes.jsonl/gold-turnpairs/RUNNER-POLICY.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The previous dumb stub just execd the applescript. Now the bin (still used as the bundle executable and for double-click) supports CLI features/subcommands while preserving default tray UI behavior:
- no arg / tray / menu: launch tray UI (status item + menu)
- launch / open / app: start services (delegates to launch.sh, matches menu "Open Prospector")
- stop: stop services (matches menu "Stop services")
- help: list features
Updated post-build messaging, tray.applescript header comment, scripts/README.md table, and ./run usage. Tested via TRAY_DEST=/tmp/... build + direct bin help invocation (and full make-tray success).
- VoiceView now has full prototype parity (exemplars toggles, pairs before→after, corrections, re-align, metrics, persona rules) using only ui/ primitives + safe data narrow.
- Fixed unused imports, missing React imports, implicit any in Backfill/Autopilot/Markets/Prospects (quick manual slices).
- All gates: typecheck clean, web build, 301 tests.
- New sliced modules stream/, bookings/ (thin, real macsync + audit/drafts data, tests, READMEs).
- Augments to tasks/corrections/reports for the rest (cohorts, alignment, dashboard KPIs).
- Extended MacsyncClient with listInboundMessages/listCalls/listCalendarEvents.
- Typed web api.ts for all 6 (shapes from services + prototype).
- Wired modules. All gates pass (type, 301 tests, web build).
- Prepares Waves A/B (views now have data).
- Updated done-so-far, status, view matrix, and backend reads list to match as-built (holistic modules + drill views + full api.ts for implemented surface).
- Annotated open questions with code-derived leanings (bookings detection-only, keep split, etc.).
- Added progress note and concrete Wave A units list with gates.
- Verified: tests 299 green, typecheck, web build; only this file staged.
Clean rewrite resolving stale TODO/done drift from incremental edits. Adds a
"Done so far" commit log (foundation, fleet, primitives, P0 shell), corrects the
status snapshot (serial core done bar api.ts stubs), and consolidates the view
matrix + parallel-attack DAG + as-built cloud fleet into one coherent doc.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
App.tsx: OPERATE/CAMPAIGNS/SYSTEM nav groups mirroring the prototype (16 routes +
prospect/intro/pastebin/autopilot), Outbox badge, label≠key (#/queue, #/calendar).
Every route resolves: built views wired, the 8 new ones render a themed Placeholder
(web/src/ui primitives) until Waves A/B. typecheck + build green, zero console errors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- _git_remote: point the fleet at ct-forge (cocotte_forge_creds.FORGE_IP) with the
origin's `applications` org path + quinn admin password. Earlier reconstruction
used GIT_ORG=platform (the monorepo default) — wrong org, right forge. 134/165 are
the same Forgejo; ct-forge is canonical.
- shared drive: `prime` builds once and writes node_modules tarball + dist to the
cocotte-ci Spaces bucket; `mount`/`umount` rclone-mount it read-only at /mnt/ci on
every worker so N testers read one build with no per-worker download.
- node_modules stays local (FUSE/S3 stat-storm anti-pattern) via fetch; the mount is
for bulk artifacts (dist, fixtures, prebuilt binaries, coverage).
shellcheck clean; help renders.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>