toga-ai 1.0.393 → 1.0.394
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: Database Changes
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: architecture
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-07-
|
|
9
|
+
updated: 2026-07-21
|
|
10
10
|
owners: [jcardinal, mhammontree, bala]
|
|
11
11
|
files:
|
|
12
12
|
- Core/
|
|
@@ -173,6 +173,13 @@ its own header.)
|
|
|
173
173
|
the relevant clients list `<module>` in their `_modules.txt`.
|
|
174
174
|
5. Never edit or re-date an already-applied file — add a new dated file instead. Never put new
|
|
175
175
|
work in a `HISTORIC` folder.
|
|
176
|
+
6. **Never seed a `uuid` column with MySQL `UUID()`.** The 2.0 standard requires a fully-random
|
|
177
|
+
**v4** UUID; `UUID()` is time/MAC-based (v1) and violates it. Since a migration can't call
|
|
178
|
+
`_String::generateUuid()`, **pre-generate a v4 UUID literal** (e.g. a v4 generator) and
|
|
179
|
+
hardcode the literal string in the `VALUES` clause. One earlier migration
|
|
180
|
+
(`Core/2026-05-08 … CronJobs_WorkerCleanup_insert`) used `UUID()` — that is a known violation,
|
|
181
|
+
not a precedent to copy. First applied correctly in
|
|
182
|
+
`Core/2026-07-21b - Insert - SprintLockScheduled CronJob.sql`.
|
|
176
183
|
|
|
177
184
|
## Bulk data loads — batch, and stage large sets in a temp table
|
|
178
185
|
|
|
@@ -285,3 +292,10 @@ platform-wide infrastructure, not a single application. It has no code dependenc
|
|
|
285
292
|
folder names mirror the DB families (`Core`, `Logs`, `Client_<Tenant>`, `Logs_<Tenant>`)
|
|
286
293
|
defined in `2.0/apps/_underscore/architecture.md`, and its change files create/alter the
|
|
287
294
|
tables that `_Model_*` classes map to.
|
|
295
|
+
|
|
296
|
+
## Change history
|
|
297
|
+
- 2026-07-21 — Added rule #6 to *Adding a new change*: never seed a `uuid` column with MySQL
|
|
298
|
+
`UUID()` (time/MAC-based v1, violates the 2.0 v4-UUID standard); pre-generate a v4 UUID
|
|
299
|
+
literal and hardcode it in `VALUES`. `Core/2026-05-08 … CronJobs_WorkerCleanup_insert` is a
|
|
300
|
+
known violation, not a precedent; first applied correctly in
|
|
301
|
+
`Core/2026-07-21b - Insert - SprintLockScheduled CronJob.sql`. (jcardinal)
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
| [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 |
|
|
29
29
|
| [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 |
|
|
30
30
|
| [Talos Transcript Ingestion Pipeline (worker2 → AWS Bedrock KBs)](features/talos-transcript-ingestion.md) | `_Worker_Team_Transcripts` runs a fully automated, cron-driven pipeline that ingests raw Teams transcripts into the **Talos / TOGa IQ** AWS Bedrock knowledge ba | worker2/Worker/Team/Transcripts.php, worker2/bin/sync-knowledge-bases.php, worker2/Config/production.ini, worker2/Database/TeamsTranscriptExports.sql, dbchanges2/Team/2026-06-30a, dbchanges2/Team/2026-06-30b, dbchanges2/Team/2026-06-30c, dbchanges2/Team/2026-06-30d, dbchanges2/Team/2026-06-30e, dbchanges2/Core/2026-06-30a, dbchanges2/Core/2026-07-02a, dbchanges2/Team/2026-07-02a, dbchanges2/Team/2026-07-08a, dbchanges2/Team/2026-07-09a, dbchanges2/Team/2026-07-10a |
|
|
31
|
-
| [Team Sprint Management & Reporting](features/team-sprint-management.md) | `_Worker_Team_Sprint` (file `Worker/Team/Sprint.php`) is the engine behind TOGA's internal **development-sprint process and reporting**. | worker2/Worker/Team/Sprint.php |
|
|
31
|
+
| [Team Sprint Management & Reporting](features/team-sprint-management.md) | `_Worker_Team_Sprint` (file `Worker/Team/Sprint.php`) is the engine behind TOGA's internal **development-sprint process and reporting**. | worker2/Worker/Team/Sprint.php, dbchanges2/Core/CronJobs (SprintLockScheduled seed) |
|
|
32
32
|
| [Teams Meeting Transcript Export](features/teams-transcript-export.md) | > **SUPERSEDED (2026-07-09) — the S3-staging model below is history.** `Export` is now a thin > **GRAPH-DIRECT** cron poller: it no longer archives raw VTT to ` | worker2/Worker/Team/Transcripts.php, worker2/Config/production.ini, worker2/Database/TeamsTranscriptExports.sql, dbchanges2/Core/2026-06-18a - Teams Transcript Export schedule.sql |
|
|
33
33
|
| [VAPI Webhook Handler (worker2 — AI-BDR end-of-call processing)](features/vapi-webhook-handler.md) | `_Worker_Vapi` ([worker2/Worker/Vapi.php](worker2/Worker/Vapi.php)) is the **PHP side of the AI-BDR call loop** — the webhook that receives VAPI's end-of-call r | worker2/Worker/Vapi.php, worker2/Worker/Ai/Bdr/Vapi.php |
|
|
34
34
|
| [WJE Freshservice Sync (worker2)](features/wje-freshservice-sync.md) | WJE ("WJE IT", helpdesk `wje.freshservice.com`) is a **Freshservice**-based help-desk client whose tickets, contacts, assets, groups, categories, and canned res | worker2/Worker/Wje.php, _underscore/Component/Api/Wje/Wje.php, _underscore/Model/Wje/Ticket.php, _underscore/Model/Wje/TicketNote.php, _underscore/Model/Wje/Contact.php, _underscore/Model/Wje/Unit.php, _underscore/Model/Wje/TicketTeam.php, _underscore/Model/Wje/TicketCategory.php, _underscore/Model/Wje/AssetType.php, _underscore/Model/Wje/PredefinedReply.php, library/app/api/wje.php, worker/crons/toga2/wje/import_supporting_records.php, worker/crons/toga2/wje/sync_togasupply_wje.php, worker/crons/notifications/reports/wje/wje_common.php, library/app/systemmonitor/wje.php, dbchanges2/Client_Wje/2024-10-04 - WjeOnboarding.sql |
|
|
@@ -111,11 +111,29 @@ No Lambda/routing changes — just create the file:
|
|
|
111
111
|
2. Insert a `Core.CronJobs` row:
|
|
112
112
|
```sql
|
|
113
113
|
INSERT INTO Core.CronJobs (uuid, isActive, name, schedule, maxExecutionTime, action, parameters)
|
|
114
|
-
VALUES (
|
|
114
|
+
VALUES ('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', 1, 'Daily Report Generation', '0 6 * * *', 300, 'Reports/Daily/Generate', NULL);
|
|
115
|
+
-- uuid MUST be a pre-generated v4 UUID literal, NOT MySQL UUID() (v1) — see dbchanges2 architecture.md rule #6
|
|
115
116
|
```
|
|
116
117
|
`schedule` is evaluated in **Central time**; `maxExecutionTime` is the watchdog timeout.
|
|
117
118
|
3. CronScheduler fires it at the next matching minute — no code wiring needed.
|
|
118
119
|
|
|
120
|
+
Adding a recurring job is **pure data**: inserting the `Core.CronJobs` row (uuid, isActive,
|
|
121
|
+
name, schedule, maxExecutionTime, action, parameters) is all that's needed. The CronScheduler
|
|
122
|
+
Lambda runs every minute, matches active schedules via `croniter`, and enqueues a `WorkerJobs`
|
|
123
|
+
job. There is **no Lambda/code change** beyond the row — but the referenced `action` must exist
|
|
124
|
+
in the deployed worker code, so ship the code deploy and the dbchanges2 cron-row migration
|
|
125
|
+
**together**.
|
|
126
|
+
|
|
127
|
+
> **Biweekly / non-cron schedules — run often, self-gate in PHP.** Cron (5-field) can express
|
|
128
|
+
> "every Wednesday" but **not** "every *other* Wednesday" (or any period cron can't name).
|
|
129
|
+
> Don't try to encode it in the schedule. Instead schedule the job at the coarser recurring
|
|
130
|
+
> interval it fits (e.g. `0 10 * * 3`) and have the action **self-gate against a date/state
|
|
131
|
+
> table** at the top of the method — run the real work only when the gate says today qualifies,
|
|
132
|
+
> otherwise return a skip message (captured to `Core.WorkerJobs.output`). Proven by
|
|
133
|
+
> `Team/Sprint/SprintLockScheduled`, which fires every Wednesday but only runs `SprintLock()`
|
|
134
|
+
> when a `Sprints` row ends yesterday — see
|
|
135
|
+
> [team-sprint-management](./team-sprint-management.md).
|
|
136
|
+
|
|
119
137
|
## Test any action directly
|
|
120
138
|
|
|
121
139
|
```bash
|
|
@@ -175,6 +193,12 @@ be reattempted.
|
|
|
175
193
|
commit-before-SQS transaction pattern that the worker relies on.
|
|
176
194
|
|
|
177
195
|
## Change history
|
|
196
|
+
- 2026-07-21 — Documented that adding a recurring job is **pure data** (a `Core.CronJobs` row;
|
|
197
|
+
CronScheduler Lambda matches via croniter every minute, no code wiring beyond the row — but
|
|
198
|
+
the action must be deployed), and the **biweekly self-gating pattern**: for schedules cron
|
|
199
|
+
can't express (e.g. every-other-Wednesday), run at a coarser cron interval and gate in PHP
|
|
200
|
+
against a date/state table, returning a skip otherwise. Proven by
|
|
201
|
+
`Team/Sprint/SprintLockScheduled`. (jcardinal)
|
|
178
202
|
- 2026-07-21 — `WorkerJobs.failureReason` column renamed to **`output`** and repurposed to store
|
|
179
203
|
successful execution results as well as failure text; success now writes the composed
|
|
180
204
|
"Successfully Executed" message (return value `json_encode`d for arrays/objects). (jcardinal)
|
|
@@ -6,10 +6,11 @@ project: Worker
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
9
|
+
updated: 2026-07-21
|
|
10
10
|
owners: ["jcardinal"]
|
|
11
11
|
files:
|
|
12
12
|
- worker2/Worker/Team/Sprint.php
|
|
13
|
+
- dbchanges2/Core/CronJobs (SprintLockScheduled seed)
|
|
13
14
|
related:
|
|
14
15
|
- ../architecture.md
|
|
15
16
|
- ./creating-worker-actions.md
|
|
@@ -64,6 +65,10 @@ A sprint runs ~14 days. Across the cycle these actions fire (scheduled as crons)
|
|
|
64
65
|
2. **~9:00 AM** — `SprintEnd` captures and scores the just-finished sprint, emails reports,
|
|
65
66
|
and (optionally) sends release notes.
|
|
66
67
|
3. **~9:45 AM (after launch ceremony)** — `SprintLock` freezes the new sprint's plan.
|
|
68
|
+
In production this is now invoked via the scheduled self-gating wrapper
|
|
69
|
+
`SprintLockScheduled` (see below), not by a cron that targets `SprintLock` directly —
|
|
70
|
+
because the launch day is **every other Wednesday** and cron cannot express a biweekly
|
|
71
|
+
schedule.
|
|
67
72
|
4. **Daily during the sprint** — `SprintDaily` emails leadership a progress dashboard.
|
|
68
73
|
|
|
69
74
|
Most methods accept an optional `$sprint` number; when omitted they resolve the relevant
|
|
@@ -89,6 +94,21 @@ alert. With `$generateSprintLockReport`, emits an Excel lock report of committed
|
|
|
89
94
|
unplanned/stretch points and tasks. When `$allowUnplannedTasks` is false, tasks appearing
|
|
90
95
|
after lock with an UNPLANNED work type are flagged.
|
|
91
96
|
|
|
97
|
+
### `SprintLockScheduled(): string`
|
|
98
|
+
A thin **scheduled wrapper around `SprintLock()`** that solves the biweekly-schedule problem.
|
|
99
|
+
The launch/lock ceremony runs every *other* Wednesday, but cron has no biweekly expression, so
|
|
100
|
+
its `CronJobs` row fires **every** Wednesday (`0 10 * * 3`, 10:00 AM Central) and this method
|
|
101
|
+
**self-gates in PHP** against the `Sprints` table: it queries for a sprint whose `dateEnd` =
|
|
102
|
+
**yesterday**. If one exists, today is a new-sprint start day → it calls `self::SprintLock()`.
|
|
103
|
+
Otherwise it returns a skip message (captured to `Core.WorkerJobs.output`) and does nothing.
|
|
104
|
+
`SprintLock()` itself is unchanged — this only decides *whether* to run it today. Action path
|
|
105
|
+
`Team/Sprint/SprintLockScheduled` → `_Worker_Team_Sprint::SprintLockScheduled`.
|
|
106
|
+
|
|
107
|
+
> **Deploy coupling.** The worker2 code deploy and the dbchanges2 migration that seeds the
|
|
108
|
+
> `Core.CronJobs` row must be **released together** — the cron row references the
|
|
109
|
+
> `Team/Sprint/SprintLockScheduled` action, which must exist in the deployed code or the
|
|
110
|
+
> scheduled job fails when it fires.
|
|
111
|
+
|
|
92
112
|
### `SprintDaily($sprint = null, …)`
|
|
93
113
|
In-sprint **leadership dashboard**, read-only with respect to metrics. Optionally re-captures
|
|
94
114
|
ClickUp data, then builds a multi-sheet workbook:
|
|
@@ -210,6 +230,13 @@ backfills `workTypeAtLock` the first time a task is seen).
|
|
|
210
230
|
|
|
211
231
|
## Change history
|
|
212
232
|
|
|
233
|
+
- 2026-07-21 — Added `SprintLockScheduled()` action + a `Core.CronJobs` seed
|
|
234
|
+
(`0 10 * * 3`, every Wednesday 10 AM Central, action `Team/Sprint/SprintLockScheduled`,
|
|
235
|
+
maxExecutionTime 600) to run **Sprint Lock automatically at the start of each biweekly
|
|
236
|
+
sprint**. Cron can't express "every other Wednesday", so the job runs every Wednesday and
|
|
237
|
+
self-gates in PHP: it calls the unchanged `SprintLock()` only when a `Sprints` row has
|
|
238
|
+
`dateEnd = yesterday` (i.e. today starts a new sprint), else returns a skip. Worker code and
|
|
239
|
+
the dbchanges2 cron-row migration must deploy together. (jcardinal)
|
|
213
240
|
- 2026-06-24 — Fixed a duplicate-key crash (`Tasks.sprintId_clickupIdentifier`) in the
|
|
214
241
|
ClickUp→DB sync: ClickUp pagination can return the same task on multiple pages, and the
|
|
215
242
|
loop was overloading one map (`$lookupTaskByClickUpId`) for both update-vs-insert and
|
package/package.json
CHANGED