toga-ai 1.0.330 → 1.0.331

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.
@@ -6,7 +6,7 @@ project: "AI-BDR"
6
6
  client: shared
7
7
  type: feature
8
8
  status: draft
9
- updated: 2026-07-13
9
+ updated: 2026-07-14
10
10
  owners: [tcox]
11
11
  files:
12
12
  - bdr/PLAN.md
@@ -16,8 +16,15 @@ files:
16
16
  related:
17
17
  - architecture.md
18
18
  - web-funnel-content-model.md
19
+ - web-funnel-app.md
19
20
  ---
20
21
 
22
+ > **Execution status (2026-07-14):** PLAN **Phases 0–5 are BUILT and QA'd** — the web
23
+ > app engine, full mockup port, and real backend are done. Remaining work is
24
+ > decision-gated, not code (§9.10 HubSpot mechanism, leadership copy, Phase 7 polish,
25
+ > Phase 8 deploy). The built codebase is documented in `web-funnel-app.md`; this doc
26
+ > stays a plan mirror. This body still mirrors `BDR/PLAN.md`.
27
+
21
28
  # BDR: Multi-Campaign "AI BDR / Agent Studio" Web App — Implementation Plan
22
29
 
23
30
  > **Status:** Draft 2 (needs one more review). Open items tracked in §9; final campaign direction /
@@ -194,7 +201,7 @@ the bundle carries the UUID so a slug maps to the right campaign for logging.
194
201
  ## 4. Decisions locked at kickoff
195
202
  | Decision | Choice | Consequence |
196
203
  |---|---|---|
197
- | Repo name | **`bdr`** | New greenfield repo. Not yet in the TOGA registry. |
204
+ | Repo name | **`bdr`** | Greenfield repo, registered in the TOGA registry (`agilantsolutions/BDR`). |
198
205
  | Framework | **Next.js (App Router) + TypeScript** | Chosen because the site is highly public: SSR + SEO, and a built-in server for the secret-bearing HubSpot/Toga/content calls. Matches `info`, so its patterns port directly. |
199
206
  | UI source | **The mockup** | Rebuild its Agent Studio flow faithfully (pixel-perfect). The mockup is React, so components port cleanly into Next.js client components. |
200
207
  | Backend source | **`info`** | Reuse HubSpot/Toga/callback logic directly (same framework). |
@@ -551,5 +558,11 @@ so fidelity should be near-exact.
551
558
  - [ ] Pixel-perfect parity pass against the mockup screens + screenshots.
552
559
 
553
560
  ## Change history
561
+ - 2026-07-14 — Phases 0–5 executed and QA'd (engine + full mockup port + real backend);
562
+ built codebase now documented in `web-funnel-app.md`. `BDR/PLAN.md` itself corrected:
563
+ absolute local paths genericized, and the stale "not yet in TOGA registry" note fixed
564
+ (bdr IS registered). Repo now lives at `agilantsolutions/BDR` (branch `BDR-Development`);
565
+ the local `.claude/` harness is gitignored (devs pull it via `npx toga-ai`). Body still
566
+ mirrors PLAN.md. (tcox)
554
567
  - 2026-07-13 — Draft 2 resync: re-mirrored the body from the current `BDR/PLAN.md`. Framework locked to Next.js App Router (earlier React/Vite SPA idea dropped); content store decided HubSpot over Contentful (rationale in §4/§5.2); no-hardcoding (HubSpot-owned, fetched by slug from the start); same-product framing confirmed (front door of the existing AI-BDR backend, "backend relationship" open question resolved); meeting-specific dates/cadence removed. Still a draft. (tcox)
555
568
  - 2026-07-08 — Captured the full BDR web-funnel implementation plan verbatim into the knowledge repo as a companion to the distilled `web-funnel-content-model.md` feature doc (redundancy intentional). (tcox)
@@ -0,0 +1,143 @@
1
+ ---
2
+ title: Web Funnel — Built Next.js App (structure, stack, how to run)
3
+ framework: "2.0"
4
+ repo: ai-bdr
5
+ project: AI-BDR
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-07-14
10
+ owners: [tcox]
11
+ files:
12
+ - bdr/PLAN.md
13
+ - bdr/.gitignore
14
+ - bdr/eslint.config.mjs
15
+ - bdr/amplify.yml
16
+ - bdr/src/app
17
+ - bdr/src/lib/resolveCampaignId.ts
18
+ - bdr/src/content
19
+ - bdr/src/components
20
+ - bdr/src/flow
21
+ - bdr/src/server
22
+ - bdr/src/app/api
23
+ - bdr/test
24
+ - bdr/public
25
+ - bdr/mockup/styles.css
26
+ related:
27
+ - web-funnel-content-model.md
28
+ - bdr-web-funnel-plan.md
29
+ - ../architecture.md
30
+ ---
31
+
32
+ ## What this is
33
+
34
+ The **built** state of the BDR web funnel — the Next.js UI / lead-capture front
35
+ door of the existing AI-BDR product (see `../architecture.md`). The forward-looking
36
+ plan lives in `bdr-web-funnel-plan.md`; the config-driven content contract lives in
37
+ `web-funnel-content-model.md`. **This doc covers the actual shipped codebase: the
38
+ stack, the directory map, what was ported vs. parked, the test suite, and the
39
+ decisions that are load-bearing for anyone touching the repo.**
40
+
41
+ As of this writing **PLAN Phases 0–5 are BUILT and QA'd** — the web app engine and
42
+ full mockup port are complete, all screens/modals render config-driven from a
43
+ bundle, and the real backend is wired behind adapters. Developer QA verdict: the UI
44
+ is "very close, minimal adjustments to be near exact" vs. the mockup. Remaining work
45
+ is **decision-gated, not code** (see "What is parked / not built").
46
+
47
+ - **Repo:** `agilantsolutions/BDR` on GitHub, working branch `BDR-Development`. The
48
+ machine-local `.claude/` harness is **gitignored** — committing it would snapshot
49
+ the whole KB stale; devs get the harness via `npx toga-ai`, not from this repo.
50
+
51
+ ## Stack
52
+
53
+ - **Next.js 16.2.3, App Router + TypeScript**, mirroring the `info` repo's config.
54
+ - **No Tailwind (deliberate).** Tailwind 4's preflight reset would fight the mockup's
55
+ hand-authored CSS (ported verbatim as `src/app/studio.css`) and threaten pixel
56
+ parity. Do **not** add Tailwind to this repo — the styling is intentionally the
57
+ mockup's own CSS-variable system. See the styles.css escape-sequence gotcha below.
58
+ - **ESLint flat config** carries a **no-em-dash rule** on shipped strings
59
+ (`Literal` / `TemplateElement` / `JSXText` selectors) — enforces the mockup copy
60
+ rule on in-repo strings (`eslint.config.mjs`).
61
+ - **Vitest** test suite: **67 tests across 7 files, all green.** Every phase was
62
+ verified with `tsc` + lint + build + a live SSR `curl` before commit.
63
+ - **Deploy target:** AWS Amplify (SSR), `amplify.yml` present (Phase 8 not done).
64
+
65
+ ## Directory map (what got built)
66
+
67
+ - `src/app/*` — App Router shell + pages; `page.tsx` is a server component that
68
+ resolves the campaign and primes the lead server-side (from `?hsContactId`) and
69
+ **never fails rendering**. `src/app/studio.css` is the mockup CSS ported verbatim.
70
+ - `src/lib/resolveCampaignId.ts` — campaign entry resolution: `?campaign=<slug>` →
71
+ `?hsCampaignId=` mapped → `DEFAULT`. Slug regex `^[a-z0-9][a-z0-9-]{0,63}$`.
72
+ - `src/content/*` — the content layer (schema/provider/default/hook). See
73
+ `web-funnel-content-model.md` for the contract; the schema is now THE contract.
74
+ - `src/components/*` — full mockup component library port: `Ico` (27-icon registry
75
+ hydrating bundle icon keys), `SwapFade`, `TalkingPreview`, `VoiceDial`, etc., with
76
+ the mockup's motion hardening ported **verbatim** (do not "simplify" the settle
77
+ guards / effect-owned timers away).
78
+ - `src/flow/*` — `useAgentFlow` state machine (the `go()` / `back` map, modal gates)
79
+ plus the screens. Persists to `localStorage` (`aibdr.v2`) where **only voice
80
+ survives a refresh**; the flow restarts at Welcome.
81
+ - `src/server/*` — the real backend, ported from `info`'s `toga.ts` / `hubspot.ts`
82
+ behind `LeadSink` + `CallbackService` adapters (detail in
83
+ `web-funnel-content-model.md`).
84
+ - `src/app/api/*` — route handlers `call-now`, `call-later`, `contact`.
85
+ - `public/*` — assets pruned to the **default campaign only** (~6.2 MB).
86
+ - `test/*` — the 67-test Vitest suite.
87
+
88
+ ## How the built app behaves (key runtime facts)
89
+
90
+ - **Agent identity is campaign config.** AutoBuild lands on the campaign's
91
+ `bundle.agent`, **not** a hardcoded "Alex" — the presented agent (art, accent,
92
+ voice, name) comes from the resolved bundle. The manual Creator is parked, so the
93
+ user does not pick the agent in the default flow.
94
+ - **Template tokens** `<agent>` / `<date>` / `<tz>` / `<time>` / `<detail>` in bundle
95
+ strings are substituted at render by an `agentize()` helper.
96
+ - **Funnel always renders.** `resolveCampaign` never throws — an unknown slug or a
97
+ provider failure returns the `DEFAULT` bundle. The server page primes the lead but
98
+ never fails rendering on a bad/absent contact.
99
+ - **Boundary validation on every route handler.** 16 KB body cap; phone / UUID / ISO
100
+ checks; all handlers return the `{isSuccess, status, error, messages, data}`
101
+ envelope (same contract as `info`/Toga).
102
+
103
+ ## What is parked / not built
104
+
105
+ - **Creator screen + `TweaksPanel` — deliberately NOT ported** (parked per plan
106
+ §9.3 / §9.7).
107
+ - **`hubspotProvider` is a throwing stub**, gated on the §9.10 HubSpot content-
108
+ modeling decision. Until HubSpot is seeded, `DEFAULT_BUNDLE` carries the mockup's
109
+ copy verbatim as documented **interim dev content**; it slims to a bare
110
+ engineering fallback once HubSpot is seeded.
111
+ - **`info`'s dead 501 `visit` route was dropped** on purpose (attack surface, no
112
+ caller).
113
+ - **Remaining work is decision-gated, not code:** §9.10 HubSpot content mechanism
114
+ (HubDB likely — gates the provider + campaign seeding, Phase 6); leadership's
115
+ first-campaign copy; Phase 7 pixel/GA4/accessibility polish; Phase 8 Amplify SSR +
116
+ `togatech` integration.
117
+
118
+ ## Gotchas
119
+
120
+ - **The mockup's `mockup/styles.css` contains literal `\n` and `\"` escape sequences**
121
+ (JS-string generation artifacts, around lines ~759 / ~840) that break real CSS
122
+ parsers. This was **fixed in the ported `src/app/studio.css`**, but
123
+ `mockup/styles.css` was intentionally left pristine — so **anyone re-porting the
124
+ mockup CSS must re-apply this fix.**
125
+ - **No PII in logs.** All of `info`'s PII-logging was stripped on port (identifier-
126
+ only logs); the Toga error paths **strip query strings** because the contact
127
+ lookup carries the email in the query. Do not reintroduce value logging.
128
+ - **No Tailwind** — see Stack. The mockup CSS is the styling system; adding Tailwind
129
+ risks pixel parity.
130
+ - **`.claude/` is gitignored** in the BDR repo on purpose — do not commit the
131
+ harness; pull it with `npx toga-ai`.
132
+
133
+ ## Change history
134
+ - 2026-07-14 — Initial doc: recorded the BUILT state of the BDR web funnel (PLAN
135
+ Phases 0–5 executed + QA'd). Next.js 16.2.3 App Router/TS, deliberate no-Tailwind,
136
+ ESLint no-em-dash rule, `resolveCampaignId`, full mockup component/flow port
137
+ (`useAgentFlow`, Ico registry, motion hardening verbatim), agent identity as
138
+ campaign config, real backend behind LeadSink/CallbackService with PII logging
139
+ stripped and boundary-validated route handlers, 67 green Vitest tests. Recorded the
140
+ parked items (Creator/TweaksPanel, throwing hubspotProvider, dropped `visit` route)
141
+ and the `mockup/styles.css` escape-sequence re-port gotcha. (tcox)
142
+ </content>
143
+ </invoke>
@@ -6,22 +6,31 @@ project: AI-BDR
6
6
  client: shared
7
7
  type: feature
8
8
  status: draft
9
- updated: 2026-07-13
9
+ updated: 2026-07-14
10
10
  owners: [tcox]
11
11
  files:
12
12
  - bdr/src/content/schema.ts
13
13
  - bdr/src/content/hubspotProvider.ts
14
14
  - bdr/src/content/useCampaign.ts
15
15
  - bdr/src/content/default.ts
16
+ - bdr/src/lib/resolveCampaignId.ts
16
17
  - bdr/src/server/leadSink.ts
17
18
  - bdr/src/server/callbackService.ts
18
19
  - bdr/src/app/api/call-now/route.ts
19
20
  - bdr/src/app/api/call-later/route.ts
21
+ - bdr/src/app/api/contact/route.ts
20
22
  related:
21
23
  - ../architecture.md
22
24
  - call-orchestration.md
25
+ - web-funnel-app.md
23
26
  ---
24
27
 
28
+ > **Status note:** the content **contract** below (schema, provider seam, adapters)
29
+ > is now BUILT and QA'd (PLAN Phases 0–5). The built codebase — structure, stack,
30
+ > how to run — is documented in `web-funnel-app.md`. The one part still **not** built
31
+ > is the HubSpot content *sourcing* (`hubspotProvider` is a throwing stub gated on the
32
+ > §9.10 mechanism decision), which is why this doc stays `draft`.
33
+
25
34
  ## What this is
26
35
 
27
36
  The **public-facing web funnel** is the new UI / lead-capture front door of the **same
@@ -100,6 +109,24 @@ optional `build` (AutoBuild beats), `analytics`, and `features[]` capability fla
100
109
  `RichLine` supports the accent-inked span the mockup uses (e.g. `"<agent> is ready to
101
110
  work."`). The mapping layer is the seam between HubSpot storage and this contract.
102
111
 
112
+ **Schema calibrated by building (the §6 plan sketch was a sketch; `src/content/schema.ts`
113
+ is now THE contract).** Additions made while building the real screens: `chrome`
114
+ (wordmark / rail labels); capabilities `eyebrows` + qbank strings + `howLink`;
115
+ `connectNote` split to `{label, value}`; `earlyAccess` / `phone` / `recap` groups;
116
+ `build` made **required**. Bundle template tokens `<agent>` / `<date>` / `<tz>` /
117
+ `<time>` / `<detail>` are substituted **at render** by an `agentize()` helper (they are
118
+ plain strings in the bundle, so HubSpot only ever stores strings).
119
+
120
+ **`resolveCampaign` never throws** (built): an unknown slug or a provider failure
121
+ returns the `DEFAULT` bundle, so the funnel always renders. Entry resolution lives in
122
+ `src/lib/resolveCampaignId.ts` (`?campaign=<slug>` → mapped `?hsCampaignId=` →
123
+ `DEFAULT`; slug regex `^[a-z0-9][a-z0-9-]{0,63}$`).
124
+
125
+ **`hubspotProvider` is a throwing stub** explicitly gated on the §9.10 HubSpot-modeling
126
+ decision — it is not wired yet. Until HubSpot is seeded, **`DEFAULT_BUNDLE` carries the
127
+ mockup's copy verbatim as documented interim dev content**; once HubSpot is seeded it
128
+ slims to a bare engineering safety-net fallback (not authored marketing copy).
129
+
103
130
  ## Backend reuse (from the `info` repo; existing AI-BDR calls)
104
131
 
105
132
  The funnel's Call Now / Schedule screens submit to a real backend **ported from the
@@ -118,6 +145,16 @@ so only the impl changes later:
118
145
  - `CallbackService.requestCall(ref, whenOrNow, phone)` → Toga `requestCall`, immediate vs.
119
146
  scheduled mapped to `CONTACT_CALL_TYPE_UUID`.
120
147
 
148
+ **Built (PLAN Phase 5):** `info`'s `toga.ts` / `hubspot.ts` are ported into `src/server/`
149
+ behind those adapters with **all of `info`'s PII logging stripped** (identifier-only
150
+ logs; the Toga error paths **strip query strings** because the contact lookup carries
151
+ the email in the query). Route handlers `/api/call-now`, `/api/call-later`, `/api/contact`
152
+ **validate at the boundary** (16 KB body cap; phone / uuid / ISO checks) and always
153
+ return the `{isSuccess, status, error, messages, data}` envelope. The page primes the
154
+ lead server-side from `?hsContactId` and never fails rendering. `info`'s dead 501
155
+ `visit` route was deliberately dropped (attack surface, no caller). Verified by 67 green
156
+ Vitest tests. See `web-funnel-app.md` for the full built structure.
157
+
121
158
  Note on "campaign": `info` uses HubSpot **only to fetch the contact**; the URL's
122
159
  `hsCampaignId` is passed to Toga as the attribution campaign UUID
123
160
  (`addContactToCampaign`) — attribution-only in `info`. **Fetching marketing content by
@@ -158,6 +195,16 @@ right campaign for logging.
158
195
  `var(--accent)` (+ derived `--accent-fill`); never hardcode an accent value.
159
196
 
160
197
  ## Change history
198
+ - 2026-07-14 — Content contract BUILT + QA'd (PLAN Phases 0–5): schema calibrated by
199
+ building the real screens (`src/content/schema.ts` is now THE contract — chrome,
200
+ capabilities eyebrows/qbank/howLink, `connectNote` {label,value}, earlyAccess/phone/
201
+ recap groups, `build` required, `agentize()` token substitution); `resolveCampaign`
202
+ never throws (unknown slug/provider failure → DEFAULT); `hubspotProvider` is a throwing
203
+ stub gated on §9.10; `DEFAULT_BUNDLE` carries the mockup copy as interim dev content.
204
+ Backend ported from `info` behind LeadSink/CallbackService with PII logging stripped,
205
+ boundary-validated route handlers, dead `visit` route dropped; 67 green Vitest tests.
206
+ Built structure split out to `web-funnel-app.md`. Kept `draft` because HubSpot content
207
+ sourcing (§9.10) is still open. (tcox)
161
208
  - 2026-07-13 — Draft 2 resync to the current plan: framework locked to Next.js App Router
162
209
  (earlier React/Vite SPA idea dropped); recorded the **HubSpot-over-Contentful** content-store
163
210
  decision + rationale (marketing already in HubSpot, campaign model already exists, trivial
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.330",
3
+ "version": "1.0.331",
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",