toga-ai 1.0.483 → 1.0.485
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/INDEX.md
CHANGED
|
@@ -19,7 +19,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
19
19
|
## 2.0 framework
|
|
20
20
|
|
|
21
21
|
- **_underscore** (_Underscore) _(framework core)_ — 40 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
|
|
22
|
-
- **worker2** (Worker) —
|
|
22
|
+
- **worker2** (Worker) — 37 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
|
|
23
23
|
- **api2** (API) — 20 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
|
|
24
24
|
- **dbchanges2** (Database Changes) _(framework core)_ — 3 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
|
|
25
25
|
- **toga2-supply** (TOGa Supply) — 3 doc(s) → [2.0/apps/toga2-supply/INDEX.md](2.0/apps/toga2-supply/INDEX.md)
|
|
@@ -39,7 +39,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
39
39
|
- **togatech** (TOGA Technology Website) — 4 doc(s) → [standalone/apps/togatech/INDEX.md](standalone/apps/togatech/INDEX.md)
|
|
40
40
|
- **websocket** (WebSocket Server) — 2 doc(s) → [standalone/apps/websocket/INDEX.md](standalone/apps/websocket/INDEX.md)
|
|
41
41
|
- **forward** (Forwarder) — 3 doc(s) → [standalone/apps/forward/INDEX.md](standalone/apps/forward/INDEX.md)
|
|
42
|
-
- **claude** (Claude Harness) —
|
|
42
|
+
- **claude** (Claude Harness) — 3 doc(s) → [standalone/apps/claude/INDEX.md](standalone/apps/claude/INDEX.md)
|
|
43
43
|
|
|
44
44
|
## Clients
|
|
45
45
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: session
|
|
3
|
+
slug: TRUE-80487-Debug-Fix-Rate-WH-Warranty
|
|
4
|
+
title: Rate Whole Home Warranty per-address dedup — root-caused "works in beta, fails in prod"
|
|
5
|
+
author: mhammontree
|
|
6
|
+
repos: [_underscore, toga2-view, dbchanges2, test]
|
|
7
|
+
framework: "2.0"
|
|
8
|
+
client: rate
|
|
9
|
+
status: active
|
|
10
|
+
created: 2026-07-30
|
|
11
|
+
updated: 2026-07-30
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Session: TRUE-80487-Debug-Fix-Rate-WH-Warranty
|
|
15
|
+
**Date:** 2026-07-30
|
|
16
|
+
**Project/Repo:** _underscore / toga2-view / dbchanges2 / test (2.0)
|
|
17
|
+
**Task:** Production troubleshooting of the Rate Whole Home Warranty per-address duplicate-purchase guard (TRUE-79533, already deployed), reported as "works in beta, not in production" — root-caused to three independent code defects, none of them a deployment gap.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What WORKED
|
|
22
|
+
|
|
23
|
+
- **Eliminated every deployment-gap hypothesis with hard evidence.** `_underscore` `_production` HEAD is `ba7eff66` (TRUE-79533 PR #661 merged 2026-07-29); `dbchanges2` `_main` is `138df5e` (PR #418). `git diff origin/_beta -- Model/Rate/Entitlement.php` returns **zero diff** — prod and beta run identical code.
|
|
24
|
+
- **Confirmed all prod DB artifacts present.** `Core.RecordFields` id **2482** = `entitlements.serviceAddressId` registered; `Client_Rate.Entitlements.serviceAddressId` column + index exist; ACL grants present (`2482` → role 1 `isWritable=0`, mirroring `saleItemId` 1265; `addresses.id` field 41 → roles 1,2,3). `ApiPayloadInterceptors` in prod is **byte-identical to dev-sandbox** (id 4 = rec 191 PRE/POST `minDepth NULL`; id 2 = rec 191 POST/POST `minDepth 5`).
|
|
25
|
+
- **ROOT CAUSE #1 — the backend guard has never executed, in any environment.** `isWholeHomeWarranty()` at `_underscore/Model/Rate/Entitlement.php:116-118` reads `$payload->saleItem->title`, but the real checkout payload sends `"saleItem":{"uuid":"3e14effa-0f78-4708-b338-60872a39aff3"}` with **no `title`**. `stripos('', 'warranty')` → false → `prePost` returns at line 58 before the guard runs. Evidence: beta payload for entitlement 106, `Logs_Rate.Api` id 48823 (dev-sandbox, 2026-07-27 11:41:15), verbatim.
|
|
26
|
+
- **Proved it with beta's own data.** dev-sandbox has **three active WH entitlements at the same address** `1864 HIGH GROVE LN 60540`: `ET100057` (id 90, 2026-07-24), `ET100067` (id 100, **2026-07-27 10:10**), `ET100073` (id 106, **2026-07-27 11:41**) — two created on the very day the feature was marked "beta-verified". Plus two at `121 N LA SALLE ST 60602` (`ET100071`, `ET100072`). All same borrower `5686507f-a7b2-4fca-b007-dd3ae875e4bb`, all pinned, all active.
|
|
27
|
+
- **Confirmed the guard's rejection message appears in NO log, in either environment, ever.** All 8 beta `POST /v2/entitlements` 400s are `EV-12` (reference errors) and one `EV-8` (`contractFulfillmentPreference`, 2026-07-15, pre-dating the PRE interceptor registration).
|
|
28
|
+
- **ROOT CAUSE #2 — `state.code` vs `state.uuid`.** `prePost:66` reads `$address->state->code`, but the payload sends `"state":{"uuid":"94417b26-..."}`. Fixing #1 alone would make every WH purchase throw *"A valid service address is required"* — a false rejection on valid addresses. **Both must be fixed together.**
|
|
29
|
+
- **ROOT CAUSE #3 — frontend availability check fails open AND is borrower-scoped.** `toga2-view/src/pages/ZipValidation/viewModels/useZipValidationViewModel.ts:135-139` — `const address = entitlement.serviceAddress; if (!address?.line1) return false;` and `serviceAddress` is derived only from the pin (`useActiveServices.ts:108`). Worse, `useActiveServices.ts:69-71` scopes the query `where: { and: [{ "Customers.c_borrowerId": { "=": borrowerId } }] }` — so it can **never** see another borrower's warranty, while the backend guard is explicitly global. Its code comment claims "same source as the backend guard's dedup join" — that comment is wrong; the backend uses `COALESCE(serviceAddressId, ContactAddresses.addressId)`, the frontend has no fallback.
|
|
30
|
+
- **Verified the backend WOULD block, without paying.** Replicated `hasActiveWarrantyAtAddress()` SQL read-only against prod for `1864 HIGH GROVE LN / Naperville / 60540 / IL` → returns entitlement **43 (`ET100017`)**. So a real purchase reaches PayPal, the customer is charged, and *then* the entitlement POST is rejected.
|
|
31
|
+
- **Confirmed the apartment-building exposure is real.** Property type lives only in router state / `sessionStorage` (`useCheckoutPageViewModel.ts:178-205`) and is **never sent to the API** — the purchase payload contains no `propertyType` / `isEligible`. `prePost:68-70` requires line1/city/state/zip but **not** `line2`. The `requireUnitNumber` flow (`ZipValidation.tsx:62-75`, `198-199`) is client-side only and bypassable. Live proof: beta `ET100073` carries `line2: "STE 500"` on a single-family home, while ids 90/100 at the same `line1` have no unit.
|
|
32
|
+
- **Production data repaired by the developer and verified clean.** Three active WH warranties, all pinned + validated, both-or-neither invariant holds on all nine rows: 43 (`ET100017`) → addr 9 Naperville, 40 (`ET100014`) → addr 6 Nashua, 38 (`ET100012`) → addr 4 Wailuku. Subscription 22 (`ET100015`, Daniel Moran) closed out `isActive=0, dateCancelled='2026-06-03'`; address 7 `city` corrected `60657` → `Chicago`.
|
|
33
|
+
|
|
34
|
+
## What did NOT work — DO NOT RETRY THESE
|
|
35
|
+
|
|
36
|
+
- **"A migration is missing in production."** DISPROVEN. `Core.RecordFields` 2482 exists; `Client_Rate.Entitlements.serviceAddressId` column + index exist; both ACL grants landed. Do not re-audit `Core/2026-07-22a`, `Client/2026-07-22a`, `Client/2026-07-23a`, `Client_Rate/2026-07-23a`, `Client_Rate/2026-07-24a` — all applied.
|
|
37
|
+
- **"TRUE-79251 merge damage deleted the WH helper methods."** DISPROVEN. `git diff origin/_beta -- Model/Rate/Entitlement.php` → zero diff. `PASSTHROUGH_KEY_FULFILLMENT_PREFERENCE` (line 32) and all three private helpers (`normalizedField` 107, `isWholeHomeWarranty` 116, `hasActiveWarrantyAtAddress` 137) present.
|
|
38
|
+
- **"`_underscore` prod wasn't redeployed past the uuid-clobber fix `9c2e4b1c`."** DISPROVEN by the same zero diff + PR #661 merged.
|
|
39
|
+
- **"`toga2-view` prod still sends `{depth:-1}` and starves `postPost`."** DISPROVEN. `genericApi.ts:54,68` only append `?depth=-1` when `returnPayloadDepth` is explicitly set; no checkout override. Diff vs `_beta` touches only GetSupport files.
|
|
40
|
+
- **"Cross-cluster `Core.RecordFields` references from `Client*/` migration folders fail in prod."** DISPROVEN for this case. Despite prod splitting `prod-core` / `prod-client` / `prod-logs` / `prod-archive` onto separate clusters, the ACL grants landed correctly. ~20 long-standing ACL migrations use this same pattern. (Note: the `dbchanges2-cluster-isolation` hook was NOT found under `.claude/hooks/toga/` — separate follow-up, not this bug.)
|
|
41
|
+
- **"The interceptor row is missing, inactive, or duplicated in prod."** DISPROVEN — prod rows are identical to dev-sandbox, same ids and uuids.
|
|
42
|
+
- **"`POST /v2/entitlement-sales-orders` is the prod purchase path (record 257, no interceptor)."** DISPROVEN. It is only a bridge link: payload is `{"entitlement":{"uuid"},"salesOrder":{"uuid"}}`. It creates no entitlement and fires no interceptor.
|
|
43
|
+
- **"Production simply hasn't processed a purchase since deploy, so there's nothing to debug."** TRUE as a fact (last `POST /v2/entitlements` in prod = 2026-07-10, two × 400 `EV-8`; newest `Entitlements` row 2026-06-15) but WRONG as a conclusion — the developer then reproduced the failure live through the UI. Do not stop at this observation.
|
|
44
|
+
- **Query that hangs — do not run.** `SELECT ... FROM Logs_Rate.Api WHERE route LIKE '%address%'` timed out after **300s** (unindexed full scan on a ~12.7M-row table). Always constrain with the `dtStamp` index: `WHERE dtStamp >= '...' AND dtStamp < '...'`.
|
|
45
|
+
- **Columns that do not exist (queries will error).** `Client_Rate.ApiPayloadInterceptors.phpMethod` — absent in prod (yet `Client_Rate/2025-12-10 - PostInterceptor.sql` inserts it, so that file is not re-runnable). `Client_Rate.Contacts.emailAddress` — does not exist. `Logs_Rate.Api.uri` — the column is `route`.
|
|
46
|
+
- **Widening the frontend `useActiveServices` query to all borrowers.** REJECTED, do not do this — it would let any portal user read other customers' entitlements and addresses. A data-leak fix worse than the bug.
|
|
47
|
+
|
|
48
|
+
## Not tried yet (candidates for next session)
|
|
49
|
+
|
|
50
|
+
- Fix `isWholeHomeWarranty()` to resolve `saleItem.uuid` → item (fall back to payload `name` and/or `WH_SALE_ITEM_ID = 3`), matching the authority `hasActiveWarrantyAtAddress()` already uses in SQL.
|
|
51
|
+
- Fix state resolution to accept `state.uuid` with `state.code` as fallback.
|
|
52
|
+
- Normalize zip to first 5 digits in the dedup comparison (`Entitlement.php:161` is exact-match; frontend already truncates at `addressCompare.ts:22`). Untested risk: USPS returning `60540-9233` vs stored `60540`.
|
|
53
|
+
- Normalize the unit designator before comparison so `STE 500` / `Suite 500` / `#500` / `Unit 500` collapse to one dwelling.
|
|
54
|
+
- Build the server-side global pre-check: boolean-only scripted endpoint reusing `hasActiveWarrantyAtAddress()`, called from the availability step, deleting the frontend's local dedup. Needs a `dbchanges2` migration registering it in `Core.RecordScripts` **plus** the client ACL grant — note `validateAddress` (RecordScripts id 17) exists only in the live DB and NOT in `dbchanges2`, the exact parity trap to avoid.
|
|
55
|
+
- Log one raw USPS / FedEx / UPS validation response for a known apartment vs a known single-family address, to settle field names empirically. `Fedex.php:417-421` already receives the full `attributes` object and reads only `Matched` / `Resolved`; `Ups.php:801-807` reads only `NoCandidatesIndicator` / `Candidate`.
|
|
56
|
+
- Capture the USPS DPV "valid but secondary unit missing" signal into `validateAddress`'s normalized return with an explicit unknown state, and enforce in `prePost`.
|
|
57
|
+
- Send and persist `propertyType` with the purchase so eligibility is enforced server-side rather than trusted from the browser.
|
|
58
|
+
- Update `test/@Mark/Rate/verify_wholehome_per_address_guard.php` to use the REAL payload shape (uuid-only `saleItem`, uuid-only `state`). It currently passes 18/18 against a shape production never sends — this is why all three defects survived review.
|
|
59
|
+
- Clean up beta duplicates: dev-sandbox entitlements 100, 105, 106.
|
|
60
|
+
- Controlled prod WH purchase to exercise the untested `minDepth = 5` on the POST interceptor, and to test USPS "Suggested" (`60540-9233`) vs "You entered" (`60540`).
|
|
61
|
+
|
|
62
|
+
## Current file state
|
|
63
|
+
|
|
64
|
+
| File | Status | Notes |
|
|
65
|
+
|------|--------|-------|
|
|
66
|
+
| `_underscore/Model/Rate/Entitlement.php` | **investigated, NOT modified** | Holds root causes #1 (line 116-118) and #2 (line 66). Also: raw SQL string concatenation at lines 371/375 violates the parameterized-query standard; accepted TOCTOU noted at 133-135. |
|
|
67
|
+
| `toga2-view/src/pages/ZipValidation/viewModels/useZipValidationViewModel.ts` | **investigated, NOT modified** | Root cause #3 fail-open at 135-139. Misleading comment claims parity with backend join. |
|
|
68
|
+
| `toga2-view/src/hooks/useActiveServices.ts` | **investigated, NOT modified** | Borrower-scoped `where` at 69-71; pin-only `serviceAddress` resolution at 108; silent EZ-2 degrade at 90. |
|
|
69
|
+
| `toga2-view/src/pages/CheckOut/viewModel/useCheckoutPageViewModel.ts` | **investigated, NOT modified** | `propertyType` read from router state / sessionStorage (178-205), never sent to API. |
|
|
70
|
+
| `_underscore/Model/Client/Address.php` | **investigated, NOT modified** | `validateAddress` waterfall USPS→FedEx→UPS (31-46); returns success + normalized fields only, no unit-required signal. |
|
|
71
|
+
| `_underscore/Component/Library/Carriers/{Usps,Fedex,Ups}` | **investigated, NOT modified** | Signals available but discarded. NOTE: this is a namespace inside `_underscore`, NOT the 1.0 `library` repo. |
|
|
72
|
+
| `test/@Mark/Rate/verify_wholehome_per_address_guard.php` | **not opened** | Passes 18/18 against the wrong payload shape. Needs rewrite. |
|
|
73
|
+
| **Production `Client_Rate` data** | **CHANGED by developer, verified** | Ents 43→addr 9, 40→addr 6, 38→addr 4 pinned; those 3 addresses `isValidated=1`; subscription 22 closed `isActive=0, dateCancelled='2026-06-03'`; address 7 `city` → `Chicago`. No repo files changed this session. |
|
|
74
|
+
|
|
75
|
+
## Decisions made
|
|
76
|
+
|
|
77
|
+
- **Keep `dateEnd` OUT of the dedup predicate.** Rationale: the guard's contract is `isActive = 1 AND dateCancelled IS NULL`; adding `dateEnd` would let real duplicates through when a renewal hasn't rolled `dateEnd` forward yet. Rejected alternative: filter on `dateEnd`. Confirmed instance of the underlying problem: Kimberly Stearns (`ET100014`) has `dateEnd = 2026-06-01` yet was charged 2026-07-01 — renewals are not advancing `dateEnd`. **Separate ticket.**
|
|
78
|
+
- **Do NOT widen the frontend query to all borrowers; move the check server-side instead.** Rationale: the frontend fundamentally cannot answer "does anyone have a warranty here?" without exposing other customers' data. A boolean-only endpoint reusing the existing helper makes availability and purchase the same code path, so they cannot drift.
|
|
79
|
+
- **Skip the legacy-entitlement backfill migration.** Rationale: only two rows mattered and they were fixed by hand; once the server-side check ships, pinning is no longer required for dedup correctness. Migration would be pure data churn.
|
|
80
|
+
- **Do not chase "dwelling type" from shipping carriers.** Rationale: postal data models deliverability, not property characteristics — no carrier returns single-family vs multi-unit. UPS `AddressClassification` / FedEx `classification` only give Residential vs Commercial, and an apartment building is "Residential". The actionable signal is USPS DPV "secondary unit required but missing". True dwelling type needs property data (assessor/parcel, or Melissa/Smarty-class vendor) — a procurement decision for Paulina + underwriting.
|
|
81
|
+
- **Did NOT complete the PayPal test payment.** Rationale: the backend rejects *after* the charge; the read-only SQL replication already proved what the guard decides.
|
|
82
|
+
- **Branch naming = bare ticket ID `TRUE-80487`.** Rationale: matches live convention in all four repos (`TRUE-78188`, `TRUE-78314`, `TRUE-79191`, `TRUE-79868`). The documented `fix/short-description` rule in the git-workflow standard is stale — flag for correction.
|
|
83
|
+
- **Repo scope:** minimum `_underscore` + `test` (makes the global rejection actually work); add `dbchanges2` + `toga2-view` for the server-side pre-check. `api2` NOT needed (scripted endpoints are served by the V2 engine from `_underscore` models; registration is DB-side). Recommendation: branch all four — an unused branch is free, discovering a needed migration mid-sprint is not.
|
|
84
|
+
- **Reframed the ticket premise.** "Works in beta, fails in prod" is false. Same code, same migrations, same interceptor rows. Beta only *appeared* to work because its test data satisfied both frontend preconditions by accident — a single test borrower, and data created after the pin shipped. Production satisfied neither.
|
|
85
|
+
|
|
86
|
+
## Blockers
|
|
87
|
+
|
|
88
|
+
- **Need the current dev branch name** to base the four `TRUE-80487` branches on. `_underscore` shows `_beta`; `toga2-view` shows both `_beta` and `_stage`. Developer said they are on "a different dev branch now" — unresolved.
|
|
89
|
+
- **Need a product decision from Paulina: per-dwelling or per-building coverage?** Currently `123 Main St` and `123 Main St APT 2` are distinct addresses, so both can hold a warranty. This changes what the fix does. Sharpened by the finding that a *no-unit* purchase at a multi-unit address is indistinguishable from a single-family purchase and carries building-scale liability at single-home pricing.
|
|
90
|
+
- **Need a scope decision:** does property-type / unit-required enforcement land in TRUE-80487, or a separate ticket? Materially larger than "one warranty per address" — it is "what counts as an insurable address". The gate fixes are independent of both blockers and can proceed regardless.
|
|
91
|
+
|
|
92
|
+
## Exact next step
|
|
93
|
+
|
|
94
|
+
> Create the `TRUE-80487` branch on `_underscore` (base = the dev branch the developer names), then fix `isWholeHomeWarranty()` at `_underscore/Model/Rate/Entitlement.php:116-118` to identify a WH purchase by resolving `saleItem.uuid` → `Items` (with payload `name` / `WH_SALE_ITEM_ID = 3` as fallbacks) **together with** the `state.uuid` → `code` resolution at line 66 — never one without the other, or every WH purchase throws "A valid service address is required". Then run `test/@Mark/Rate/verify_wholehome_per_address_guard.php` rewritten to the real payload shape (uuid-only `saleItem` and `state`), and confirm it FAILS on the current code before the fix and passes after.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
_Saved by /session-save on 2026-07-30_
|
|
@@ -4,3 +4,4 @@
|
|
|
4
4
|
|-----|---------|-------|
|
|
5
5
|
| [Harness Distribution — How a knowledge.js Fix Reaches Teammates](workflows/harness-distribution.md) | There are **two copies** of `knowledge.js` on a developer's machine, and the skills use only one of them. | claude/scripts/install.js, claude/knowledge.js |
|
|
6
6
|
| [Knowledge Base Publish / Push Pipeline](workflows/knowledge-publish-pipeline.md) | How `/capture` and `/session-save` get knowledge docs from your working tree into `agilantsolutions/claude` on `_main`. | claude/knowledge.js |
|
|
7
|
+
| [MCP Tool Usage — "Talos" Means the Internal Knowledge Base, and Run Your Own SELECTs](workflows/mcp-tool-usage.md) | Two MCP connections are available in every session, and **Claude is expected to reach for them on its own judgement — nobody should have to say the word "MCP".* | claude/.claude/skills/kickoff/SKILL.md, claude/.claude/skills/capture/SKILL.md |
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: MCP Tool Usage — "Talos" Means the Internal Knowledge Base, and Run Your Own SELECTs
|
|
3
|
+
framework: "standalone"
|
|
4
|
+
repo: claude
|
|
5
|
+
project: Claude Harness
|
|
6
|
+
client: shared
|
|
7
|
+
type: workflow
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-07-30
|
|
10
|
+
owners: ["jcardinal"]
|
|
11
|
+
files:
|
|
12
|
+
- claude/.claude/skills/kickoff/SKILL.md
|
|
13
|
+
- claude/.claude/skills/capture/SKILL.md
|
|
14
|
+
related:
|
|
15
|
+
- standalone/apps/claude/workflows/harness-distribution.md
|
|
16
|
+
- standalone/apps/claude/workflows/knowledge-publish-pipeline.md
|
|
17
|
+
- 2.0/apps/talos/features/mcp-servers.md
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Summary
|
|
21
|
+
|
|
22
|
+
Two MCP connections are available in every session, and **Claude is expected to reach for them on
|
|
23
|
+
its own judgement — nobody should have to say the word "MCP".**
|
|
24
|
+
|
|
25
|
+
1. **`claude.ai Internal Knowledgebase`** — the AWS Bedrock knowledge base of cleaned meeting
|
|
26
|
+
transcripts. **This is what the team means when they say "Talos."**
|
|
27
|
+
2. **`toga-db`** — read-only MySQL access to every TOGA environment, production included.
|
|
28
|
+
|
|
29
|
+
**Critical rules:** When a teammate says **"ask Talos"**, **"use Talos"**, or **"check Talos"**,
|
|
30
|
+
that is an instruction to **search the Internal Knowledge Base MCP** — it is *not* a request to
|
|
31
|
+
open, read, or reverse-engineer the `talos` repo. Only treat "Talos" as the codebase when the
|
|
32
|
+
speaker explicitly frames it as the project ("the Talos repo", "Talos deployment", "the Talos
|
|
33
|
+
agent code"). **Never ask a developer to go run a SELECT** — Claude has read access and must run
|
|
34
|
+
its own. **Writes (INSERT/UPDATE/DELETE/DDL) are the developer's to execute** — the MCP is
|
|
35
|
+
read-only by design, so hand them the statement. Use both connections proactively as part of
|
|
36
|
+
normal research, unprompted.
|
|
37
|
+
|
|
38
|
+
## The word "Talos" is overloaded — resolve it by context
|
|
39
|
+
|
|
40
|
+
| A teammate says | They mean | What to do |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| "Ask Talos", "use Talos", "check Talos", "what does Talos say about…" | The **Internal Knowledge Base MCP** | `kb_search` — this is the default reading |
|
|
43
|
+
| "the Talos repo", "Talos deployment", "the Talos agent", "the LangGraph agent", "TOGa IQ" | The **`talos` codebase** (2.0, Python/FastAPI) | Open `2.0/apps/talos/` knowledge and the repo |
|
|
44
|
+
|
|
45
|
+
**Default to the MCP.** The overwhelming majority of spoken uses of "Talos" mean the knowledge
|
|
46
|
+
base. Reverse-engineering the `talos` project because someone said "ask Talos" is a real failure
|
|
47
|
+
mode — it burns a session answering the wrong question.
|
|
48
|
+
|
|
49
|
+
Note the collision in this knowledge base itself: `2.0/apps/talos/features/mcp-servers.md`
|
|
50
|
+
documents the MCP servers that the **talos project builds and hosts** (`clickup-mcp`,
|
|
51
|
+
`toga-db-mcp`). That doc is about *building* those servers. This doc is about *using* the
|
|
52
|
+
connections. They are different subjects.
|
|
53
|
+
|
|
54
|
+
> Aside: the team has not settled whether "Talos" is an engine, a chatbot, or the umbrella AI
|
|
55
|
+
> brand, nor whether it is written `Talos` or `TALOS` (see the 2026-07-16 *TOGA Tech Website
|
|
56
|
+
> Review* transcript). Ambiguity about what Talos *is* as a brand is expected; ambiguity about
|
|
57
|
+
> what "ask Talos" *means operationally* is not — it means the knowledge base.
|
|
58
|
+
|
|
59
|
+
## Internal Knowledge Base MCP ("Talos")
|
|
60
|
+
|
|
61
|
+
Cleaned, classified meeting transcripts loaded automatically within 5–10 minutes of a meeting
|
|
62
|
+
ending. This is the record of **what people actually said and decided** — the complement to this
|
|
63
|
+
knowledge base, which records **how the code works**.
|
|
64
|
+
|
|
65
|
+
- **Scope:** account-wide there are 40 knowledge bases across 7 categories; the harness API key
|
|
66
|
+
currently reaches **1 category, `development-team` (34 KBs)**. Other categories (sales, HR,
|
|
67
|
+
legal, contact-center, tech-support, operations) exist but are outside the key's grant.
|
|
68
|
+
- **Shape:** one KB per client bucket, documents at
|
|
69
|
+
`s3://togaiq/development-team/<client>/approved/YYYY-MM-DD - <Meeting Title>.txt`, each with an
|
|
70
|
+
`approved_at` date. Ranking blends semantic relevance with recency.
|
|
71
|
+
- **Client names differ from `registry.json`.** The KB uses `compass-group` (not
|
|
72
|
+
`compass-usa`/`compass-canada`), `health-and-hospitals` (not `nychh`), `nyc-doe` (not `nycdoe`),
|
|
73
|
+
and carries buckets with no registry entry at all — `northwell`, `endeavor-health`, `casl`,
|
|
74
|
+
`lenovo`, `adyen`, `speedcast`, `rumc`, `uma`, `craftex`, `dunn`, `interfaith-ministries`,
|
|
75
|
+
`ford-foundation`, `alpha-omega-plastics`, `american-campus-communities`, `ninja-rmm`, plus
|
|
76
|
+
non-client buckets `general`, `ai`, `power-bi`, `warehouse`, `toga-desk`, `toga-technology`.
|
|
77
|
+
Always pick the `client` value from the `available_clients` list the tool returns.
|
|
78
|
+
|
|
79
|
+
**When to reach for it without being asked:**
|
|
80
|
+
|
|
81
|
+
- A teammate relays something said in a meeting and the terminology is unfamiliar or ambiguous.
|
|
82
|
+
- A decision's *rationale* matters ("why did we do it this way?") — git history says what
|
|
83
|
+
changed, transcripts say why.
|
|
84
|
+
- Business-side vocabulary that has no code footprint (see the terminology gotcha below).
|
|
85
|
+
- Before concluding "there is no knowledge about X" — check here as well as the code KB.
|
|
86
|
+
|
|
87
|
+
**Treat transcripts as evidence, not specification.** They record what was said in a room,
|
|
88
|
+
including things later reversed. Cite the filename and `approved_at` date, prefer the most recent
|
|
89
|
+
when chunks conflict, and let the code knowledge base win on questions of how something is
|
|
90
|
+
actually built.
|
|
91
|
+
|
|
92
|
+
### Terminology that lives only in transcripts
|
|
93
|
+
|
|
94
|
+
These have no footprint in the code knowledge base, so a code-only search returns nothing:
|
|
95
|
+
|
|
96
|
+
- **TechHub** — what **TOGa Commerce** is called on the Compass side.
|
|
97
|
+
- **Mix** — the Compass-side equivalent platform. A request to update "TechHub and Mix" means
|
|
98
|
+
both teams make the same change.
|
|
99
|
+
- **TOGa Retail** — internal-only platform for store-associated transactions; not in `registry.json`.
|
|
100
|
+
- **Personas** — TOGa Supply's item-visibility mechanism (~39 of them; 1 = everyone, 4 = canteen,
|
|
101
|
+
12 = admin and sees everything, 33 = MacBook/Surface).
|
|
102
|
+
- **OptimumDesk / Star Tech** — the ticketing system Talos integrates with for Office Depot.
|
|
103
|
+
- **TOGA vs toga** — capital-A **TOGA** is the company; lowercase **toga** is the platform.
|
|
104
|
+
|
|
105
|
+
## Database MCP (`toga-db`)
|
|
106
|
+
|
|
107
|
+
Read-only MySQL across every environment. All 24 clusters were connected as of 2026-07-30.
|
|
108
|
+
|
|
109
|
+
**Run SELECTs yourself, unprompted.** Do not ask a developer to run a query and paste results
|
|
110
|
+
back — that wastes their time on something Claude can do directly. Query whenever it answers the
|
|
111
|
+
question faster or more reliably than reading code: confirming a schema, checking whether a row
|
|
112
|
+
exists, verifying a config value, sizing a table before proposing a migration, or grounding a
|
|
113
|
+
claim in real data instead of an assumption.
|
|
114
|
+
|
|
115
|
+
**Writes are the developer's job.** The MCP permits `SELECT`/`SHOW`/`DESCRIBE`/`EXPLAIN` only.
|
|
116
|
+
For any `INSERT`/`UPDATE`/`DELETE`/DDL, write the statement out, say which environment and schema
|
|
117
|
+
it targets, and hand it to the developer to execute.
|
|
118
|
+
|
|
119
|
+
**Environments** — pass any alias; the server resolves it:
|
|
120
|
+
|
|
121
|
+
| Group | Names | Naming scheme |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| V2 production | `prod` / `production` | `Core`, `Client_<id>`, `Archive_<id>`, `Logs_<id>` |
|
|
124
|
+
| V1 production | `legacy` / `v1` | `Core`, `TOGA_<id>`, `TOGaLogs_<id>` |
|
|
125
|
+
| Non-prod | `dev-sandbox`, `client-sandbox`, `client-{alpha,beta,gamma}`, `qa-{task,hotfix,alpha,beta,gamma}`, `qc-{task,hotfix,security,performance,alpha,beta,gamma}`, `stage`, `demo` | V2 naming |
|
|
126
|
+
|
|
127
|
+
**Production is four separate clusters** — `prod-core`, `prod-client`, `prod-archive`,
|
|
128
|
+
`prod-logs`. Every non-prod environment is a single all-in-one host holding all groups. This is
|
|
129
|
+
the same split that makes cross-database joins work locally and fail in production (see
|
|
130
|
+
`2.0/apps/dbchanges2/architecture.md`).
|
|
131
|
+
|
|
132
|
+
**`local` is not this MCP.** If someone means their own machine's database, use the `mysql` CLI
|
|
133
|
+
via shell, not `toga-db`.
|
|
134
|
+
|
|
135
|
+
**Resolving a client name to its databases:** `Core.Clients.clientIdentifier` is the exact suffix
|
|
136
|
+
used in `Client_<id>`, `Archive_<id>`, and `Logs_<id>`.
|
|
137
|
+
|
|
138
|
+
```sql
|
|
139
|
+
-- environment='prod', schema_name='Core'
|
|
140
|
+
SELECT name, clientIdentifier FROM Clients WHERE name LIKE '%<keyword>%';
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Gotcha — the client roster is wider than `registry.json`, and identifiers are not guessable
|
|
144
|
+
|
|
145
|
+
`Core.Clients` held **46 clients** on 2026-07-30 against 17 in `registry.json`. A client absent
|
|
146
|
+
from the registry is normal, not an error — the registry tracks clients whose *code knowledge* has
|
|
147
|
+
been captured, not the full book of business.
|
|
148
|
+
|
|
149
|
+
Identifiers do not follow from the display name, so **look them up, never construct them**:
|
|
150
|
+
|
|
151
|
+
| Display name | `clientIdentifier` | Trap |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| Compass Group | `Compass_Usa` | Carries an **underscore**, and "Compass Group" maps to the **USA** entity |
|
|
154
|
+
| CompassCanada | `Compass_Canada` | Underscore again |
|
|
155
|
+
| AIG | `Aig` | Title-case, not `AIG` |
|
|
156
|
+
| Staples | `Staples` | A **separate client** from AIG, despite the registry title "AIG (Staples Protection Plan)" |
|
|
157
|
+
| Growrks | `Growrk` | Display name is plural, identifier is not |
|
|
158
|
+
| NYC Health + Hospitals | `Nychh` | |
|
|
159
|
+
| Towfoundation | `Towfoundation` | |
|
|
160
|
+
| Wiss, Janney, Elstner Associates, Inc. | `Wje` | |
|
|
161
|
+
|
|
162
|
+
Schema names are **case-sensitive** — copy the exact value from `toga_list_schemas` or
|
|
163
|
+
`Core.Clients`. `Client_Aig` works; `Client_AIG` and `client_aig` do not.
|
|
164
|
+
|
|
165
|
+
## Applying this
|
|
166
|
+
|
|
167
|
+
- **Never make a teammate name the tool.** "Which environment is that in?" is a fair question;
|
|
168
|
+
"please run this SELECT and paste the output" is not.
|
|
169
|
+
- **Ask about environment only when it genuinely changes the answer** — and when the context makes
|
|
170
|
+
it obvious (a production incident, a client-specific bug), infer it and say which one was used.
|
|
171
|
+
- **State the source.** For a query: the environment and schema. For the knowledge base: the
|
|
172
|
+
filename and its date. That lets the developer judge the evidence.
|
|
173
|
+
- **Combine the three sources.** Code knowledge base → how it is built. Talos → what was decided
|
|
174
|
+
and why. Database → what is actually true right now.
|
|
175
|
+
|
|
176
|
+
## Change history
|
|
177
|
+
- 2026-07-30 — Created. Established that "ask/use Talos" means the Internal Knowledge Base MCP and not the `talos` repo; that Claude runs its own SELECTs unprompted while developers execute writes; and that both MCP connections are used proactively without being requested. Recorded the KB↔registry client-name divergence and the `Core.Clients` identifier traps (jcardinal)
|
package/package.json
CHANGED