toga-ai 1.0.324 → 1.0.326
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.
- package/knowledge/2.0/apps/_underscore/INDEX.md +1 -0
- package/knowledge/2.0/apps/_underscore/features/cloud-s3-helpers.md +54 -0
- package/knowledge/2.0/apps/worker2/INDEX.md +1 -0
- package/knowledge/2.0/apps/worker2/features/oneuptime-worker2-monitoring.md +128 -0
- package/knowledge/INDEX.md +2 -2
- package/knowledge/clients/compass-usa/profile.md +1 -0
- package/knowledge/sessions/2026-07-13-bdr-plan-hubspot-tcox.md +63 -0
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
| [Assortment Name Translation (AssortmentTranslations sidecar)](features/assortment-name-translation.md) | Serves Assortment (product-grouping) **names** in multiple languages by adding a per-language **sidecar** table `AssortmentTranslations`, reusing the platform's | _underscore/Model/Client/AssortmentTranslation.php, dbchanges2/Client/2026-06-26a - AssortmentTranslations.sql, dbchanges2/Core/2026-06-26a - AssortmentTranslationsRecord.sql, dbchanges2/Client/2026-06-26b - AssortmentTranslationsAcl.sql |
|
|
10
10
|
| [Asynchronous Query Execution (writes-only, via Worker)](features/async-query-execution.md) | `_Query` can run a **write** query asynchronously so a long/slow write does not hold a request-scoped DB connection open long enough to hit **"MySQL server has | _underscore/Query.php, worker2/Worker/Infrastructure/Database.php, worker2/Worker/Team/Transcripts.php |
|
|
11
11
|
| [Carrier Shipping Labels (UPS/FedEx) & NetSuite Item Fulfillment](features/carrier-shipping-labels.md) | Backend mechanics behind TOGa Supply's Fulfill & Ship: buying a carrier label (UPS/FedEx), persisting it, and creating the NetSuite Item Fulfillment with tracki | _underscore/Model/Client/ItemFulfillment.php, _underscore/Model/Client/TrackingNumber.php, _underscore/Model/Client/ItemFulfillments/TrackingNumber.php, _underscore/Component/Library/LabelPdf/LabelPdf.php, _underscore/Component/Library/Carriers/ShipmentRequest/ShipmentRequest.php, _underscore/Component/Library/Carriers/Ups/Ups.php, _underscore/Component/Library/Carriers/Fedex/Fedex.php, _underscore/Trait/Netsuite/ItemFulfillment.php, _underscore/Trait/Netsuite/SalesOrder.php, _underscore/Component/Library/NetSuite/NetSuite.php, _underscore/Model/Client/TrackingNumber.php, _underscore/Model/Client/ShippingMethod.php, _underscore/Model.php, _underscore/Cloud.php |
|
|
12
|
+
| [_Cloud S3 helpers (copy / get / delete / list)](features/cloud-s3-helpers.md) | `_Cloud` centralizes AWS SDK S3 usage for the 2.0 stack so the `S3Client` never leaks into workers or app code. | _underscore/Cloud.php |
|
|
12
13
|
| [_Component_*/_Model_* project-namespace registration (autoloader) & backslash-qualify traps](features/component-model-namespace-registration.md) | Every **project-local** `_Component_*` and `_Model_*` class in a 2.0 app **must declare the project namespace** at the top of the file: ```php namespace <NAMESP | _underscore/Loader.php, worker2/_.php, api2/_.php, worker2/Component/Forecast/Db/Db.php, worker2/Component/Forecast/SaleImport/SaleImport.php, api2/Component/Api/Netsuite/Netsuite.php |
|
|
13
14
|
| [Client Email Template Sending](features/email-template-sending.md) | `_Model_Client_EmailTemplate` sends a stored, client-defined email template by UUID. | _underscore/Model/Client/EmailTemplate.php, _underscore/Model/Client/EmailTemplateOutgoingEmailAddress.php, _underscore/Email.php |
|
|
14
15
|
| [Error Reporting — Issue/Event Aggregation (agreed POST-to-receiver design)](features/error-reporting-issue-event.md) | Platform-wide error-reporting infrastructure for TOGA 2.0, built around a two-table **Issue / Event** aggregation model in the shared **Core Logs DB**. | _underscore/Error.php, _underscore/Model/Core/Logs/Issue.php, _underscore/Model/Core/Logs/Event.php, dbchanges2/Logs/2026-07-06 - Issue and Event tables.sql |
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: _Cloud S3 helpers (copy / get / delete / list)
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: _underscore
|
|
5
|
+
project: _Underscore
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-07-13
|
|
10
|
+
owners: ["jcardinal"]
|
|
11
|
+
files:
|
|
12
|
+
- _underscore/Cloud.php
|
|
13
|
+
related:
|
|
14
|
+
- ../../worker2/features/oneuptime-worker2-monitoring.md
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Summary
|
|
18
|
+
|
|
19
|
+
`_Cloud` centralizes AWS SDK S3 usage for the 2.0 stack so the `S3Client` never leaks into
|
|
20
|
+
workers or app code. Alongside the existing copy / get / delete methods it now has a
|
|
21
|
+
**LIST** method, `_Cloud::getS3Objects()`.
|
|
22
|
+
|
|
23
|
+
## Key files / entry points
|
|
24
|
+
|
|
25
|
+
- `_underscore/Cloud.php` — `_Cloud::getS3Objects($s3BucketName, $s3BucketPath = '')`.
|
|
26
|
+
|
|
27
|
+
## How it works
|
|
28
|
+
|
|
29
|
+
`getS3Objects()` uses the AWS SDK `S3Client->listObjectsV2` and **transparently paginates**
|
|
30
|
+
(`listObjectsV2` caps at 1000 keys per page), returning entries shaped:
|
|
31
|
+
|
|
32
|
+
- `Key` — object key
|
|
33
|
+
- `LastModified` — ISO-8601 string
|
|
34
|
+
- `Size`
|
|
35
|
+
|
|
36
|
+
The method is **purely additive** — no existing `_Cloud` method signature changed. Keeping
|
|
37
|
+
S3 listing here (rather than instantiating `S3Client` in a worker) is the reason to prefer
|
|
38
|
+
this helper over ad-hoc SDK calls.
|
|
39
|
+
|
|
40
|
+
First consumer: the worker2 Office Depot EDI backlog monitor — see
|
|
41
|
+
[OneUptime push-metric monitors](../../worker2/features/oneuptime-worker2-monitoring.md).
|
|
42
|
+
|
|
43
|
+
## Client variations
|
|
44
|
+
|
|
45
|
+
None — shared core helper.
|
|
46
|
+
|
|
47
|
+
## Gotchas / known issues
|
|
48
|
+
|
|
49
|
+
- Callers get every matching key regardless of count; pagination is handled internally, so
|
|
50
|
+
do not add your own `ContinuationToken` loop on top.
|
|
51
|
+
|
|
52
|
+
## Change history
|
|
53
|
+
- 2026-07-13 — Added `_Cloud::getS3Objects()` S3 LIST helper (paginated `listObjectsV2`,
|
|
54
|
+
returns `{Key, LastModified, Size}`); additive, no existing signatures changed. (jcardinal)
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
| [NetSuite Supporting-Record Webhook Importer (the reusable recipe)](features/netsuite-supporting-record-webhook-importer.md) | A single **repeatable recipe** for porting a legacy daily-pull NetSuite *supporting-record* importer (the lookup/dimension tables behind Forecast2 — Employees, | worker2/Worker/Netsuite/Employee.php, worker2/Worker/Netsuite/Account.php, worker2/Worker/Netsuite/Classification.php, worker2/Worker/Netsuite/Customer.php, worker2/Worker/Netsuite/Item.php, worker2/Worker/Netsuite.php, _underscore/Model/Forecast/Employee.php, _underscore/Model/Forecast/Account.php, _underscore/Model/Forecast/Classification.php, _underscore/Component/Forecast/Db/Db.php, test/@dave/test_employee_lifecycle.php, test/@dave/test_account_lifecycle.php, test/@dave/test_classification_lifecycle.php, test/@dave/NetSuite/api-message-queue/ue_api_msg_queue_enqueue.js, worker/crons/toga2/forecast2/import_supporting_records.php |
|
|
21
21
|
| [Background Email-Template Worker (_Worker_Notification_EmailTemplate)](features/notification-email-template.md) | `_Worker_Notification_EmailTemplate::Send(...)` dispatches a **stored, client-defined `EmailTemplates` row off-thread** as a background WorkerJob. | worker2/Worker/Notification/EmailTemplate.php, worker2/Worker/Client/True.php, _underscore/Model/Client/EmailTemplate.php |
|
|
22
22
|
| [DB-Driven Notification (Internal) Email](features/notification-email.md) | Internal/notification emails (merge-conflict alerts, ops notices — anything system-generated, not client-facing transactional mail) are sent through one worker | worker2/Worker/Notification/Email.php, _underscore/Model/Client/EmailTemplate.php, dbchanges2/Client/2026-06-23a - EmailTemplateWrapper.sql, dbchanges2/Client_True/2026-06-23a - EmailTemplateWrapper.sql |
|
|
23
|
+
| [OneUptime push-metric monitors for 2.0 workers](features/oneuptime-worker2-monitoring.md) | A second, **OneUptime-reporting** monitoring pattern for the 2.0 worker2 tier, ported from the 1.0 `App_SystemMonitor_Compass` monitors. | worker2/Worker/Monitor/Compass.php, _underscore/Cloud.php |
|
|
23
24
|
| [Startech Webhook Handler (worker2)](features/startech-webhook-handler.md) | Receives inbound webhook events from Startech (Easeedesk) and creates or updates the corresponding ticket in TOGA 2.0. | worker2/Worker/Startech.php |
|
|
24
25
|
| [Talos (TOGa IQ) Meeting-Notes Integration & Token Auto-Refresh (consumer)](features/talos-meeting-notes-integration.md) | How a **dev tool / agent consumes Talos (TOGa IQ)** to query the team meeting-notes corpus programmatically. | .claude/skills/plan-ticket/scripts/talos.js |
|
|
25
26
|
| [Talos Pricing Automation (worker2 Cron — AWS Actuals, Calibration, Monthly Report)](features/talos-pricing-automation.md) | The worker2 half of the **Talos Pricing Platform** (see the talos `pricing-cogs-model` and tools `talos-pricing-ui` docs for the other halves). | worker2/Worker/Talos/Pricing.php, worker2/Database/TalosPricingCrons.sql |
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: OneUptime push-metric monitors for 2.0 workers
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: worker2
|
|
5
|
+
project: Worker
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-07-13
|
|
10
|
+
owners: ["jcardinal"]
|
|
11
|
+
files:
|
|
12
|
+
- worker2/Worker/Monitor/Compass.php
|
|
13
|
+
- _underscore/Cloud.php
|
|
14
|
+
related:
|
|
15
|
+
- ./monitoring-framework.md
|
|
16
|
+
- ../../_underscore/features/cloud-s3-helpers.md
|
|
17
|
+
- ../../../1.0/apps/worker/features/oneuptime-worker-uptime-monitoring.md
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Summary
|
|
21
|
+
|
|
22
|
+
A second, **OneUptime-reporting** monitoring pattern for the 2.0 worker2 tier, ported from
|
|
23
|
+
the 1.0 `App_SystemMonitor_Compass` monitors. A worker2 cron action runs a self-contained
|
|
24
|
+
check, decides pass/fail itself, and POSTs a JSON metric body to a OneUptime "Incoming
|
|
25
|
+
Request" monitor — replacing the 1.0 tier's email alerts. First monitor:
|
|
26
|
+
`_Worker_Monitor_Compass::OfficeDepotEdiImportQueue()`, which watches the Office Depot
|
|
27
|
+
inbound EDI import backlog. Designed to be **client-agnostic** — a reusable template for
|
|
28
|
+
future monitors and clients.
|
|
29
|
+
|
|
30
|
+
This is distinct from the DB-driven email-orchestrator
|
|
31
|
+
[Monitoring Framework](./monitoring-framework.md) (`_Worker_Monitor` orchestrator +
|
|
32
|
+
`_Worker_Monitors_<Name>` children + `Core.Monitors` table, sends email). This pattern has
|
|
33
|
+
**no orchestrator and no `Core.Monitors` table** — each monitor is a plain worker2 action
|
|
34
|
+
that reports straight to OneUptime. Note the folder difference: these live under
|
|
35
|
+
`Worker/Monitor/` (singular) vs. the framework's `Worker/Monitors/` (plural).
|
|
36
|
+
|
|
37
|
+
## Key files / entry points
|
|
38
|
+
|
|
39
|
+
- `worker2/Worker/Monitor/Compass.php` — `abstract class _Worker_Monitor_Compass`; each
|
|
40
|
+
monitor is a `public static` action method returning a summary string recorded in
|
|
41
|
+
`WorkerJobs` (standard worker2 action conventions). First method:
|
|
42
|
+
`OfficeDepotEdiImportQueue()`.
|
|
43
|
+
- `_underscore/Cloud.php` — `_Cloud::getS3Objects()` list helper this monitor relies on
|
|
44
|
+
(see [Cloud S3 helpers](../../_underscore/features/cloud-s3-helpers.md)).
|
|
45
|
+
|
|
46
|
+
## How it works
|
|
47
|
+
|
|
48
|
+
Registered as a `Core.CronJobs` entry: schedule `*/5 6-20 * * *`, action
|
|
49
|
+
`Monitor/Compass/OfficeDepotEdiImportQueue`. Each tick, `OfficeDepotEdiImportQueue()`:
|
|
50
|
+
|
|
51
|
+
1. Lists `s3://agilant-as2/OfficeDepot/` via `_Cloud::getS3Objects()`, then counts files
|
|
52
|
+
older than `AGED_FILE_MINUTES` (10), **excluding** the `OUTBOX/` and `SENT/` sub-prefixes
|
|
53
|
+
and directory-placeholder keys.
|
|
54
|
+
2. Decides the alarm state itself and POSTs a JSON metric body to the OneUptime "Incoming
|
|
55
|
+
Request" monitor via `_ApiRequest` — with **logging disabled** and
|
|
56
|
+
**`throwExceptionsOnFailure` disabled**, so a failed ping never fails the worker job.
|
|
57
|
+
3. On S3 failure it still POSTs `{"status":"error"}` so a blind/dead checker is
|
|
58
|
+
distinguishable from a real backlog.
|
|
59
|
+
|
|
60
|
+
Body tokens (see the alarm contract below): `"alarm":"HIGH"` when the aged-file count is
|
|
61
|
+
over threshold, else `"alarm":"OK"`; `"status":"error"` on S3 failure.
|
|
62
|
+
|
|
63
|
+
### The token-based alarm contract (critical — OneUptime cannot compare numbers)
|
|
64
|
+
|
|
65
|
+
OneUptime **Incoming Request** monitors **cannot** do numeric threshold comparison on a
|
|
66
|
+
pushed body. Verified in OneUptime source (`Common/Server/.../IncomingRequestCriteria.ts`):
|
|
67
|
+
a `checkOn: "Request Body"` filter supports only `Contains` / `NotContains` **string**
|
|
68
|
+
matching — it does **not** JSON-parse the body, does **not** target a nested key, and does
|
|
69
|
+
**not** support Greater Than / Less Than (those filter types apply only to
|
|
70
|
+
outgoing/synthetic checks like Response Time / Status Code / Metric Value).
|
|
71
|
+
|
|
72
|
+
Consequence: the "dumb reporter, smart monitor" ideal (push a raw number, let OneUptime
|
|
73
|
+
compare `> threshold`) is **not achievable for push monitors**. Instead the **worker makes
|
|
74
|
+
the threshold decision** and emits a string token that OneUptime matches with `Contains`.
|
|
75
|
+
OneUptime criteria for this monitor:
|
|
76
|
+
|
|
77
|
+
- Request Body **Contains** `"alarm":"HIGH"` → Offline + incident.
|
|
78
|
+
- Request Body **Contains** `"status":"error"` → Offline + incident.
|
|
79
|
+
- **Online** requires BOTH "received in 1 min" AND Request Body **Contains** `"alarm":"OK"`
|
|
80
|
+
— so status does not flap back to Operational while the alarm is still HIGH.
|
|
81
|
+
|
|
82
|
+
### Heartbeat / cron cadence timing
|
|
83
|
+
|
|
84
|
+
Heartbeat missed-ping thresholds must match the cron cadence. With a **5-minute** push
|
|
85
|
+
cadence: **Degraded at 10 min / Offline at 15 min**. An initial 3/5-min setting
|
|
86
|
+
false-alarmed on a single missed ping. The Office Depot backlog alarm threshold is
|
|
87
|
+
**10 aged files**.
|
|
88
|
+
|
|
89
|
+
## Provisioning a monitor (runbook)
|
|
90
|
+
|
|
91
|
+
1. Write the monitor method on `_Worker_Monitor_Compass` (or a new `_Worker_Monitor_<X>`
|
|
92
|
+
class). Keep it **fully self-contained**: no private helpers, no class constants — all
|
|
93
|
+
per-monitor config lives as `ALL_CAPS` local variables inside the method (PHP disallows
|
|
94
|
+
`const` at function scope), so the class stays clean as monitors accumulate.
|
|
95
|
+
2. Provision the OneUptime monitor by cloning the reusable import/export template at
|
|
96
|
+
`monitor-import-OfficeDepot-EDI-1.0.json` (a local dev artifact, not a repo file) and
|
|
97
|
+
importing it into OneUptime; wire the Contains criteria above.
|
|
98
|
+
3. Register the OneUptime push URL as a local/constant in the monitor method — it is a
|
|
99
|
+
**push credential**; never log it and never record its value in a doc.
|
|
100
|
+
4. Add the `Core.CronJobs` row (`action = 'Monitor/<Class>/<Method>'`) with the schedule,
|
|
101
|
+
and set OneUptime's Degraded/Offline thresholds to match the cadence.
|
|
102
|
+
|
|
103
|
+
## Client variations
|
|
104
|
+
|
|
105
|
+
None — the pattern is shared infrastructure. The first monitor targets Compass USA's
|
|
106
|
+
Office Depot inbound EDI (vendor ODP), but the class and template are client-agnostic;
|
|
107
|
+
clone the template to provision the same check for another client.
|
|
108
|
+
|
|
109
|
+
## Gotchas / known issues
|
|
110
|
+
|
|
111
|
+
- OneUptime Incoming Request bodies are matched **as strings only** (Contains/NotContains) —
|
|
112
|
+
no numeric comparison, no JSON key targeting. Always emit a decided token, never a raw
|
|
113
|
+
number, for push monitors.
|
|
114
|
+
- The OneUptime push URL is a credential — keep it as a local/constant in the method; never
|
|
115
|
+
log it or write its value into knowledge docs.
|
|
116
|
+
- Keep the metric POST non-fatal (`throwExceptionsOnFailure` off) so a monitoring outage
|
|
117
|
+
never breaks the worker job it rides in.
|
|
118
|
+
|
|
119
|
+
## Change history
|
|
120
|
+
- 2026-07-13 — Ported Compass monitoring from the 1.0 worker tier into worker2 reporting to
|
|
121
|
+
OneUptime; built `_Worker_Monitor_Compass::OfficeDepotEdiImportQueue()` (Office Depot EDI
|
|
122
|
+
backlog), the token-based alarm contract (OneUptime Incoming Request can only string-match
|
|
123
|
+
Contains, not compare numbers), and the 5-min cadence → 10/15-min heartbeat timing. (jcardinal)
|
|
124
|
+
|
|
125
|
+
## Related docs
|
|
126
|
+
- [Monitoring Framework](./monitoring-framework.md) — the parallel DB-driven, email-alert monitoring pattern
|
|
127
|
+
- [Cloud S3 helpers](../../_underscore/features/cloud-s3-helpers.md) — `_Cloud::getS3Objects()` used to list the EDI bucket
|
|
128
|
+
- [OneUptime 1.0 worker uptime monitoring](../../../1.0/apps/worker/features/oneuptime-worker-uptime-monitoring.md) — the 1.0 push-heartbeat predecessor
|
package/knowledge/INDEX.md
CHANGED
|
@@ -17,8 +17,8 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
17
17
|
|
|
18
18
|
## 2.0 framework
|
|
19
19
|
|
|
20
|
-
- **_underscore** (_Underscore) _(framework core)_ —
|
|
21
|
-
- **worker2** (Worker) —
|
|
20
|
+
- **_underscore** (_Underscore) _(framework core)_ — 31 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
|
|
21
|
+
- **worker2** (Worker) — 28 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
|
|
22
22
|
- **api2** (API) — 10 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
|
|
23
23
|
- **dbchanges2** (Database Changes) _(framework core)_ — 3 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
|
|
24
24
|
- **toga2-supply** (TOGa Supply) — 3 doc(s) → [2.0/apps/toga2-supply/INDEX.md](2.0/apps/toga2-supply/INDEX.md)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: session
|
|
3
|
+
slug: bdr-plan-hubspot
|
|
4
|
+
title: BDR web-funnel implementation plan + HubSpot content decision
|
|
5
|
+
author: tcox
|
|
6
|
+
repos: [bdr, ai-bdr]
|
|
7
|
+
framework: "2.0"
|
|
8
|
+
client: shared
|
|
9
|
+
status: active
|
|
10
|
+
created: 2026-07-13
|
|
11
|
+
updated: 2026-07-13
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Session: bdr-plan-hubspot
|
|
15
|
+
**Date:** 2026-07-13
|
|
16
|
+
**Project/Repo:** bdr (new) — knowledge filed under `2.0/apps/ai-bdr/` (2.0)
|
|
17
|
+
**Task:** Produce the implementation plan for BDR — a multi-campaign "AI BDR / Agent Studio" public web funnel (Next.js) that is the new UI/front door of the existing AI-BDR product — and capture the plan + decisions into the team knowledge base.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What WORKED
|
|
22
|
+
- Authored the full plan at `C:\WWW\BDR\PLAN.md` (local, Draft 2), grounded in a full read of the mockup (`C:\WWW\BDR\mockup\` — `app.jsx`, `screens.jsx`, `components.jsx`, `styles.css`, `CLAUDE.md`) and the `info` repo backend (`C:\WWW\info\src`).
|
|
23
|
+
- Confirmed `info`'s HubSpot usage is a ~15-line server-side fetch proxied by a Next route handler (`info/src/lib/hubspot.ts` = `getContact` via `/crm/v3/objects/contacts/{id}`; `info/src/app/bdr/api/contact/route.ts` = the proxy). This validated the "HubSpot integration is trivial" claim. `info` uses "campaign" for attribution only (`hsCampaignId` → Toga `addContactToCampaign`); it never fetches marketing content from HubSpot.
|
|
24
|
+
- Captured knowledge under `2.0/apps/ai-bdr/`: `features/bdr-web-funnel-plan.md` (full plan mirror, paths genericized), `features/web-funnel-content-model.md` (distilled), and an additive HubSpot-over-Contentful note in `architecture.md`. Registered the `bdr` repo in `registry.json`. `validate: OK (238 docs)` each pass.
|
|
25
|
+
- Kept the two feature docs at `status: draft` (this is Draft 2, still needs one more review). Architecture.md left `status: active` (shared voice-system doc; edit was additive only).
|
|
26
|
+
|
|
27
|
+
## What did NOT work — DO NOT RETRY THESE
|
|
28
|
+
- **CLI git push fails:** `fatal: could not read Username for 'https://github.com'` — the `toga-tech` origin is HTTPS with no credential helper and the shell is non-interactive. `gh` CLI is NOT installed (checked both bash and PowerShell). DO NOT retry CLI push or `gh` — the developer pushes via **GitHub Desktop**.
|
|
29
|
+
- **Filing the doc under a separate `2.0/apps/bdr/` folder:** validate failed with `ERROR: frontmatter repo "bdr" != folder "ai-bdr"`. Resolved by setting the doc's frontmatter `repo: ai-bdr` (BDR knowledge lives under the ai-bdr app per developer directive). DO NOT create a `2.0/apps/bdr/` folder.
|
|
30
|
+
- **Reverted approaches (do not reintroduce):** (1) React/Vite SPA — reverted to **Next.js** because the site is highly public (SSR/SEO) and Next's server hosts the secret-bearing calls. (2) "Hybrid" static-config-in-repo-now/CMS-later — killed. (3) Hardcode-copy-now/HubSpot-later phasing — reverted; content is HubSpot-owned from the start, no in-repo/hardcoded content.
|
|
31
|
+
|
|
32
|
+
## Not tried yet (candidates for next session)
|
|
33
|
+
- Final review of `PLAN.md` (Draft 2); on approval, flip the two feature docs off `draft` and re-capture the final version.
|
|
34
|
+
- Decide §9.10: how campaign content is modeled in HubSpot (**HubDB** likely vs custom object) — gates the content-layer build; confirm with the HubSpot instance owner. Hard part = nested content (Q&A pool + rotation sets, call summaries, accent RichLines).
|
|
35
|
+
- Create the actual `agilantsolutions/BDR` GitHub repo (needs gh install or the GitHub web UI) and version `PLAN.md` there.
|
|
36
|
+
- Resolve remaining §9 open questions: agent choice (fixed preset vs manual Creator), service-picker in scope, tweaks panel in prod, `togatech` integration mechanism, campaign catalog + who authors, first campaign direction/verbiage (pending leadership).
|
|
37
|
+
|
|
38
|
+
## Current file state
|
|
39
|
+
| File | Status | Notes |
|
|
40
|
+
|------|--------|-------|
|
|
41
|
+
| `C:\WWW\BDR\PLAN.md` | Modified (local only, not in git) | Draft 2, complete. Next.js + HubSpot-owned runtime content + same-product framing. |
|
|
42
|
+
| `knowledge/2.0/apps/ai-bdr/features/bdr-web-funnel-plan.md` | Updated, committed `c016f4e` (UNPUSHED) | Full plan mirror; `status: draft`. |
|
|
43
|
+
| `knowledge/2.0/apps/ai-bdr/features/web-funnel-content-model.md` | Updated, committed `c016f4e` (UNPUSHED) | Distilled facts; `status: draft`. |
|
|
44
|
+
| `knowledge/2.0/apps/ai-bdr/architecture.md` | Updated, committed `0b38d14` (UNPUSHED) | Additive HubSpot-over-Contentful note; `status: active`. |
|
|
45
|
+
| `knowledge/registry.json` | `bdr` registered (already pushed) | `{repo:"bdr", project:"BDR", framework:"2.0", role:"app", dependsOn:["api2"]}`. |
|
|
46
|
+
|
|
47
|
+
## Decisions made
|
|
48
|
+
- **Framework = Next.js (App Router) + TypeScript** (over React/Vite SPA). Rationale: highly public site → SSR + SEO, and Next's server components + route handlers host the secret-bearing HubSpot/Toga calls with no separate backend. Matches `info`.
|
|
49
|
+
- **Content store = HubSpot** (over Contentful). Rationale: marketing already operates in HubSpot; the campaign/attribution model already exists there; the API read is trivial (proven in `info`); no new vendor. Trade-off accepted: HubSpot is not a purpose-built content CMS (weaker nested-content + editor UX), acceptable because the content shape is stable / not frequently restructured. Contentful rejected as overkill for stable content + a new SaaS dependency.
|
|
50
|
+
- **Content is HubSpot-owned, fetched by slug at runtime, no hardcoding, no in-repo content**, behind one `CampaignContentProvider` seam + `DEFAULT` fallback. Rejected: hybrid static bundles; hardcode-then-HubSpot phasing.
|
|
51
|
+
- **BDR is the UI/front door of the existing AI-BDR product** (same product, not standalone) — so knowledge is filed under `2.0/apps/ai-bdr/`, and BDR reuses `info`'s backend calls. Resolved the earlier "backend relationship" open question.
|
|
52
|
+
- **Config-driven components** — campaign = serializable data bundle keyed by slug; never `if(campaign===x)` in components; behavior/icons via enum→registry. Follows toga25-supply `useClientFields` + toga2-commerce Cart C1-C7 precedents.
|
|
53
|
+
- **New code repo named `BDR`** (greenfield). The external `info` repo (github.com/agilantsolutions/info) is reference-only, not a TOGA registry repo.
|
|
54
|
+
|
|
55
|
+
## Blockers
|
|
56
|
+
- Knowledge commits `c016f4e` + `0b38d14` are committed locally but **UNPUSHED** — CLI auth fails; awaiting the developer's manual push via GitHub Desktop.
|
|
57
|
+
- §9.10 (HubSpot content mechanism: HubDB vs custom object) undecided — gates building the content layer.
|
|
58
|
+
|
|
59
|
+
## Exact next step
|
|
60
|
+
> In GitHub Desktop, push the `toga-tech` `_main` commits (`c016f4e` + `0b38d14`) to `agilantsolutions/claude`. Then do the final review of `C:\WWW\BDR\PLAN.md` (Draft 2); on approval, ask Claude to flip the two ai-bdr feature docs off `status: draft` and re-capture.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
_Saved by /session-save on 2026-07-13_
|
package/package.json
CHANGED