toga-ai 1.0.656 → 1.0.657

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,95 @@
1
+ ---
2
+ type: session
3
+ slug: bdr-landing-call-flow
4
+ title: BDR /landing "Call me now" flow built to the mock, real callback route wired but dormant
5
+ author: tcox
6
+ repos: [bdr]
7
+ framework: "2.0"
8
+ client: shared
9
+ status: active
10
+ created: 2026-08-26
11
+ updated: 2026-08-26
12
+ ---
13
+
14
+ # Session: bdr-landing-call-flow
15
+ **Date:** 2026-08-26
16
+ **Project/Repo:** bdr (2.0)
17
+ **Task:** On the BDR cybersecurity landing page (C:\WWW\BDR, route `/landing`): acted on the design lead's UI review by adding the chat drawer's "Call me now" button and its full flow (CallNow screen -> calling screen) ported from the restored `AI BDR - Security/` mockup, fixed the "Book a meeting" sizing, and wired a REAL anonymous-lead callback route (`POST /api/landing-call`) that stays dormant (503 -> simulation) until a cybersecurity Toga campaign exists and `TOGA_SECURITY_CAMPAIGN_UUID` is set. Also: diagnosed the chat fallback (origin gate), verified the Calendly link is dead, resolved the `_dev-sandbox` merge conflict. Nothing committed in the BDR working tree.
18
+
19
+ ---
20
+
21
+ ## What WORKED
22
+ - **Chat fallback root-caused with browser-shaped curl probes.** From origin `http://localhost:3000` the full talos-chat flow works end-to-end (token minted, real Sonnet reply with suggestions/cta/cited_slides). From `https://bdr.dev.sandbox.togatech.com` the session mint returns **403** (origin not allowlisted). CORS is fine (`access-control-allow-origin: *`, `authorization,content-type`); one 502 on a preflight was transient (3/3 retries -> 200). Recorded in `landing-chat-drawer.md`; short message for the Talos backend owner was drafted for the developer to send.
23
+ - **Calendly link verified dead**: `calendly.com/toga-technology/risk-assessment` AND `calendly.com/toga-technology` both 404; TOGA has no Calendly. Real booking system is **Cal.com team `toga-technology`** (worker2 `[calcom] team_slug`); the only public event type is `discovery-call` ("Healthcare AI Discovery Call"); prod `Client_True.Campaigns` both use `c_meetingType = discovery-call`. No security event type exists. Recorded in `security-landing-page.md`.
24
+ - **`_dev-sandbox` merge of TRUE-80965**: single conflicted file `src/content/security.ts`, 4 hunks, all resolved to the TRUE-80965 side with `perl -0pi -e 's/<<<<<<< HEAD\r?\n.*?=======\r?\n(.*?)>>>>>>> TRUE-80965\r?\n/$1/gs'`; resolved file byte-identical to `MERGE_HEAD`; tsc/lint/367 tests green; staged. Developer commits the merge.
25
+ - **"Book a meeting" sizing fixed**: root cause = the mock's chat actions are `<button>`s (browser default ~13.3px button font) while ours is an `<a>` inheriting the panel body size. `.security-shell .chatactions .btn{ font-size:13.5px; padding:0 16px; min-height:44px }`.
26
+ - **Call flow built to the mock**: `ChatPanel` `onCall` prop + "Call me now" button (above Book, mock order); `SecurityCallNow.tsx` (trust column, business email with live domain hint, masked phone, submit gated on valid email AND viable phone); `SecurityCalling.tsx` (dialing -> Connected + mm:ss -> End call -> Call ended with rotating recap + Copy, Call me again / Book a meeting / Back to overview); `securityCallFlow.ts` pure helpers; `SecurityLanding` became a `landing|call|calling` router via `SwapFade` (outMs 240 / inMs 460 / rise 12 / drop 18, mock app-shell timings); copy in `security.ts` `callNow` + `calling`. Evidence: tsc clean, lint clean, vitest 376/376 at that point, `next build` clean, `/landing` still prerendered static.
27
+ - **Real callback path built, gated**: `POST /api/landing-call` {email, phoneNumber} -> validate -> require env `TOGA_SECURITY_CAMPAIGN_UUID` (else **503 before any upstream call**) -> `togaLeadSink.upsertLead` (name from email via `nameFromEmail`) -> `togaCallbackService.requestCall(uuid,{type:"now"},phone)` (same path as /api/call-now: dialer + fast dial) -> status/share tokens. Client `submitLandingCall()` returns `{live, statusHandle}`; any non-success -> simulation. `SecurityCalling` drives the live path through `useCallStatusViewModel` (real phases, real Vapi recap, no "End call" on live, unavailable holds at dialing). `/api/landing-call` on the /api/call-now limiter bucket + matcher. `.env.example` documents the var. Evidence: tsc clean, lint clean, **vitest 385/385**, `next build` clean (`ƒ /api/landing-call`, `/landing` static).
28
+ - **Mockup restored + eslint ignore restored**: `"AI BDR - Security/**"` back in `globalIgnores`; lint clean.
29
+ - **KB captured** (`/capture`): CREATE `landing-call-flow.md`; UPDATE `security-landing-page.md`, `landing-chat-drawer.md`, `web-funnel-app.md`, `live-call-status.md`. Pushed to `_main`, 417 docs. Earlier manual pushes today/yesterday: 595620a (mockup deleted, now corrected), 0fa110e (origin gate), 0924ef5 (Calendly dead).
30
+
31
+ ## What did NOT work — DO NOT RETRY THESE
32
+ - **`perl -0pi -e 's/<<<<<<< HEAD\n.*?=======\n(.*?)>>>>>>> TRUE-80965\n/$1/gs'` (LF-only) matched NOTHING** on `src/content/security.ts` — the file is **CRLF**. Use the `\r?\n` variant above. 12 markers untouched meant nothing was mangled; check `grep -c '^<<<<<<<'` after any automated resolution.
33
+ - **Bash single-quoted heredoc for a long markdown file** (session save) failed: `unexpected EOF while looking for matching `''`. Use the Write tool for multi-line files.
34
+ - **Relative paths after a `cd` in one Bash call**: the shell cwd resets to `c:\WWW` between calls, so `cat src/...` in the next call fails with "No such file". Always use absolute paths (`/c/WWW/BDR/...`).
35
+ - **Using `43fdf2b6-7a5d-4e85-be6b-911f42aa787f` as the Toga dialer campaign** — it is the TALOS CHAT campaign (api.togaiq.com `campaign_registry`), NOT a `Client_True.Campaigns` uuid. The dialer would find nothing. Prod Toga campaigns are only `15d0c02f-501e-e081-2ead-61b78c854223` and `d8f7abe6-8f06-0218-03d1-50db575` (both healthcare).
36
+ - **Reusing the studio `CallNow.tsx` / `Success.tsx` on /landing** — rejected before trying: both read `useCampaign()` (CampaignBundle context) and `useLeadRef()`, neither provided on `/landing`; studio CallNow also has no email field. Purpose-built `SecurityCallNow` / `SecurityCalling` instead.
37
+ - **Pointing `TOGA_SECURITY_CAMPAIGN_UUID` at the healthcare test campaign to exercise the real path** — deliberately NOT done and the developer agreed not to: the healthcare Vapi assistant would pitch the wrong offer to a real phone.
38
+ - **Consuming blox Talos directly** (carried forward): unpublished to npm + React `^18` peers vs BDR React 19.2.4. Do not attempt until blox publishes with React 19 peers.
39
+ - **Glob on `c:\WWW` / BDR root** (carried forward): ripgrep timeout. Use `ls`/`find`/`rg` with explicit paths.
40
+ - **Grep content-mode showing `\*` for CSS `/*`** (carried forward): display artifact, not corruption.
41
+
42
+ ## Not tried yet (candidates for next session)
43
+ - **Commit**: the whole working tree (call flow, real route, eslint restore, sizing fix) is uncommitted on top of the `_dev-sandbox` merge (which is staged, uncommitted). Branch naming needs tcox's call.
44
+ - **Send the Alex (apeterson) note** — drafted (in the conversation and summarized in `landing-chat-drawer.md`), not sent: adapter matches his `TalosAdapter` seam, blockers (unpublished, React 18 peers), design divergence (Call me now / Book a meeting actions, cobalt theme).
45
+ - **Send the backend-owner note** — drafted: allowlist `https://bdr.dev.sandbox.togatech.com` (later the prod domain) for talos-chat; campaign `43fdf2b6…`.
46
+ - **Enable real calls** when a cybersecurity campaign + Vapi assistant exist in Toga (runbook `ai-bdr/docs/client-onboarding-sop.md`): set `TOGA_SECURITY_CAMPAIGN_UUID` in `.env.local` + Amplify console, redeploy that version. First live run must verify: Toga accepts an EMPTY `lastName` for email-only leads (e.g. `jdoe@` -> firstName "Jdoe", lastName ""); deployed env has `TOGA_VAPI_TOKEN` (else the screen holds at dialing with the unavailable note).
47
+ - **Booking link**: create a Cal.com team event type for the security offer (`https://cal.com/team/toga-technology/<slug>`), then set `security.ts` `primaryCtaHref` (one line; drives page CTA, drawer Book, calling-screen Book) and pass the same URL as `cta_url` on the talos campaign ingest so the chat's `book_call` cta resolves (currently `cta: null`). Interim option: `discovery-call` (title mismatch "Healthcare AI").
48
+ - Render the chat reply's `cta` button and `cited_slides` thumbnails (needs `GET /api/ai/campaign/{id}`; presigned URLs expire ~7 days).
49
+ - Visual QA of the call screens at phone widths; `SecurityCalling` at <=840px relies on studio.css `.ended-cta` stacking.
50
+ - Optional visible "assistant unavailable" notice in the drawer when a chat reply is `offline: true` (currently silent).
51
+ - KB hygiene (unrelated): 20+ docs end with stray `</content>`/`</invoke>` lines (`grep -rln "^</invoke>$" knowledge/`); `validate` does not catch it.
52
+
53
+ ## Current file state
54
+ | File | Status | Notes |
55
+ |------|--------|-------|
56
+ | src/components/ChatPanel.tsx | modified | `onCall` prop; "Call me now" `<button>` above "Book a meeting" `<a>` |
57
+ | src/flow/screens/SecurityCallNow.tsx | created | Mock CallNow port: email + phone, domain hint, trust list; submit -> `submitLandingCall` -> `onConnect(detail, result)`; never blocks on backend |
58
+ | src/flow/screens/SecurityCalling.tsx | created | Mock Success (calling) port with live/sim split via `useCallStatusViewModel`; `SecurityCallSummary` renders real Vapi recap or rotating static variant + Copy |
59
+ | src/flow/screens/SecurityLanding.tsx | modified | `screen` state `landing\|call\|calling`, `detail`, `callResult`; SwapFade router; `backToOverview` resets recap rotation + scrollTo(0,0); `agentName` derived from `talos.title` |
60
+ | src/lib/securityCallFlow.ts | created | `fillTokens`, `emailDomain`, `isCallFormComplete`, `formatCallTimer`, `nextSummaryVariantIndex`, `resetSummaryRotation` |
61
+ | src/lib/leadName.ts | created | `nameFromEmail` (local part split on `._-+`, digits stripped, empty lastName allowed) |
62
+ | src/flow/landingCallApi.ts | created | `submitLandingCall(email, phone, fetchImpl?)` -> `{live, statusHandle}`; 20s timeout; logs status only |
63
+ | src/app/api/landing-call/route.ts | created | Anonymous-lead callback route, 503 when `TOGA_SECURITY_CAMPAIGN_UUID` unset/non-uuid; mirrors /api/call-now token minting |
64
+ | src/proxy.ts | modified | `/api/landing-call` on the call limiter branch + matcher |
65
+ | .env.example | modified | `TOGA_SECURITY_CAMPAIGN_UUID` documented (must be the CYBERSECURITY Toga campaign, not the chat campaign id) |
66
+ | src/content/security.ts | modified (+ dev's tabs/"Ask Alex Anything") | `talos.callCta`; new `callNow` + `calling` groups (incl. `calling.live` strings); merge-resolved to TRUE-80965 side |
67
+ | src/app/security.css | modified | chat action sizing fix; `.connect-intro*` / `.connect-trust` / `.agent-caption` / `.field-hint` ported; `.ended-cta a.btn` underline reset |
68
+ | eslint.config.mjs | modified | `"AI BDR - Security/**"` ignore RESTORED (mockup back) |
69
+ | AI BDR - Security/ (folder) | restored by dev | design reference, in repo again |
70
+ | test/securityCallFlow.test.ts | created | 9 tests |
71
+ | test/landingCallRoute.test.ts | created | 9 tests (400s, 503 pre-upstream, 500 without echoing input, nameFromEmail) |
72
+ | next-env.d.ts | modified (generated) | churn from tsc/build; discard if unwanted |
73
+
74
+ All BDR changes uncommitted; the `_dev-sandbox` merge is staged and awaiting `git commit`.
75
+
76
+ ## Decisions made
77
+ - **"Match the mock" = match the UI; wire everything that CAN be wired** (developer clarification). Result: real callback route built but dormant; simulation only as fallback.
78
+ - **Keep the real route in the repo, dormant, until a cybersecurity Toga campaign exists** (developer: "as long as it's wired up and ready for the campaign it's good"). Rejected: removing it (rebuild later); testing against the healthcare campaign.
79
+ - **Gate = env var `TOGA_SECURITY_CAMPAIGN_UUID`, 503 before any upstream call when unset** — enabling is config-only; the client treats any non-success as "play the simulation".
80
+ - **Purpose-built `SecurityCallNow`/`SecurityCalling` instead of reusing studio screens** — studio screens need bundle/lead contexts `/landing` lacks; the mock's CallNow differs (email field, trust column).
81
+ - **Live path never fakes progress**: no "End call" on a real call; unavailable status holds at dialing with a note; real Vapi recap replaces the static one; static recap only in simulation.
82
+ - **Anonymous lead name derived from the email local part** (`nameFromEmail`), lastName may be empty — flagged unverified. Rejected: adding a name field (not in the mock); inventing a placeholder surname (pollutes CRM).
83
+ - **Mock deviations kept**: no AmbientQuestions (bundle-driven); recap Copy without Share sheet; "Schedule a call" -> "Book a meeting" (Calendly) since no schedule screen; footnote Privacy/Terms = real togatech.com links.
84
+ - **Book-a-meeting sizing**: pin font-size/padding on `.chatactions .btn` rather than converting the anchor to a button (it must remain a link to open Calendly).
85
+ - **TRUE-80692 alignment: keep the disposable bridge shell**; send Alex a facts-first note (drafted). Rejected: pausing drawer work until blox publishes.
86
+ - **KB filing stays under `2.0/apps/ai-bdr/`**; mockup deletion history kept honest (superseded, not erased).
87
+
88
+ ## Blockers
89
+ None hard. External dependencies: (1) a cybersecurity campaign + Vapi assistant in Toga (owner outside bdr) before real calls can be enabled; (2) Talos backend owner to allowlist the sandbox/prod origins for talos-chat; (3) a Cal.com event type for the security offer (Cal.com owner) before the booking CTA works; (4) apeterson/design alignment on the shared component; (5) tcox's branch/commit go-ahead.
90
+
91
+ ## Exact next step
92
+ > In `C:\WWW\BDR`, decide the branch, then commit the staged `_dev-sandbox` merge and the working-tree call-flow work (`git add -A` — includes the restored `AI BDR - Security/` mockup and eslint ignore). Then send the two drafted notes (Talos backend owner: allowlist `https://bdr.dev.sandbox.togatech.com`; apeterson: shared-component alignment). Real calls stay off until you have the cybersecurity campaign UUID for `TOGA_SECURITY_CAMPAIGN_UUID`.
93
+
94
+ ---
95
+ _Saved by /session-save on 2026-08-26_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.656",
3
+ "version": "1.0.657",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",