toga-ai 1.0.391 → 1.0.392

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: Worker
6
6
  client: shared
7
7
  type: architecture
8
8
  status: active
9
- updated: 2026-07-09
9
+ updated: 2026-07-21
10
10
  owners: [jcardinal]
11
11
  files:
12
12
  - worker2/Controller/Index.php
@@ -53,7 +53,8 @@ All table creation, `ALTER` statements, index changes, and seed data — includi
53
53
  `jobType ENUM('ACTION','CRON')`, `cronJobId`, `dtQueued` (NULL = not yet queued),
54
54
  `dtStarted` (committed immediately at check-in), `dtCompleted`, `executionTime`,
55
55
  `instanceId`, `isSuccess` (NULL pending/running, 0 fail, 1 success), `action`,
56
- `parameters` JSON, `failureReason`.
56
+ `parameters` JSON, `output` (renamed from `failureReason`; **now holds both** failure text
57
+ **and** successful-run results — see the multi-producer rename note below).
57
58
 
58
59
  Derived status: `pending` (`dtQueued IS NULL AND isSuccess IS NULL`) → `queued` → `running`
59
60
  (`dtStarted` set, `dtCompleted` NULL) → `succeeded`/`failed`.
@@ -61,6 +62,21 @@ Derived status: `pending` (`dtQueued IS NULL AND isSuccess IS NULL`) → `queued
61
62
  **`Core.CronJobs`** — `isActive`, `name`, `schedule` (cron expr, **Central tz**),
62
63
  `maxExecutionTime` (watchdog seconds, default 300), `action`, `parameters` JSON.
63
64
 
65
+ ### `WorkerJobs.output` is written by MULTIPLE producers — rename it everywhere at once
66
+
67
+ The outcome column (renamed from `failureReason` → `output`, MEDIUMTEXT) is written by **four**
68
+ places that must change together: the PHP worker check-out (both paths in `Controller/Index.php`),
69
+ the `Retry()` reset (`Worker/Infrastructure/Worker.php`, which clears `output`), and the Python
70
+ **JobScheduler watchdog** Lambda (`LambdaFunctions/JobScheduler/lambda_function.py`, Part B timeout
71
+ UPDATE). Because this is a **rename, not add-and-keep**, old-code/new-column and new-code/old-column
72
+ both break — so the `dbchanges2` `ALTER TABLE Core.WorkerJobs CHANGE failureReason output MEDIUMTEXT
73
+ NULL` must land **simultaneously** with the code deploy, and the watchdog Lambda must be
74
+ **repackaged/redeployed separately** (a Python zip redeploy, not just a code push) or its UPDATE
75
+ errors on the missing column. The PHP `$failureReason` **local variables** were intentionally left
76
+ unchanged (only the SQL column moved). Do **not** touch the same-named-but-unrelated `failureReason`
77
+ fields on other tables: the `Email` table (`Worker/Infrastructure/Email/Send.php`) and
78
+ `Team.TranscriptExports` (`Worker/Team/Transcripts.php`).
79
+
64
80
  ## The four Lambdas (`worker2/LambdaFunctions/`, Python)
65
81
 
66
82
  `boto3` is in the runtime; `pymysql`, `croniter`, `pytz` are vendored into the zip.
@@ -91,7 +107,9 @@ New path (`{workerJobId}` present):
91
107
  3. Register DB_LOGS / DB_CLIENT_LOGS (try/catch → failure marks job failed, returns 200).
92
108
  4. Resolve class+method from action (`Clickup/Webhook` → `_Worker_Clickup::Webhook`).
93
109
  5. Call `initialize()` if present, then the action with spread parameters.
94
- 6. **Check-out:** `UPDATE dtCompleted, executionTime, isSuccess, failureReason`. Return 200.
110
+ 6. **Check-out:** `UPDATE dtCompleted, executionTime, isSuccess, output`. On success `output` =
111
+ the composed `"[<requestId>] Successfully Executed (<n>s): <return value>"` string (arrays/objects
112
+ `json_encode`d, escaped via `_Database::escape()`); on failure `output` = the failure text. Return 200.
95
113
 
96
114
  Direct-payload path (`action` present, no `workerJobId`): formerly the debug-only "legacy"
97
115
  path (untracked, could return HTTP 500). As of 2026-07-07 it is a **first-class tracked
@@ -211,6 +229,11 @@ the MySQL-first design was departed from **on purpose** here.
211
229
 
212
230
  ## Change history
213
231
 
232
+ - 2026-07-21 — `Core.WorkerJobs.failureReason` renamed to `output` and repurposed to capture
233
+ successful run results as well as failures (success writes the composed "Successfully Executed"
234
+ message, return value `json_encode`d). Multi-producer rename: PHP worker (both paths), `Retry()`
235
+ reset, and the JobScheduler watchdog Lambda change together with the `dbchanges2` `CHANGE`
236
+ migration; watchdog Lambda needs a separate redeploy. (jcardinal)
214
237
  - 2026-07-09 — Added the "long-running AI actions — sync vs. async writes" rule: reads-back
215
238
  writes go before the AI call, synchronous+committed; post-AI status writes go async.
216
239
  Distilled from the Talos Graph-direct pipeline (async pre-AI dedupe writes weren't durable
@@ -6,7 +6,7 @@ project: Worker
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-06-30
9
+ updated: 2026-07-21
10
10
  owners: [jcardinal, dfranks, mhammontree]
11
11
  files:
12
12
  - worker2/Worker/
@@ -133,11 +133,17 @@ Use realistic placeholder values, not empty strings/nulls.
133
133
 
134
134
  The EB worker dispatcher (`Controller/Index.php::worker()`) wraps your action call in
135
135
  `try { } catch (\Throwable $e)`:
136
- - **Returns normally** → `WorkerJobs.isSuccess = 1`, `dtCompleted` set.
137
- - **Throws** (any `Throwable`, incl. `Error`) → `isSuccess = 0`, `failureReason` = message +
136
+ - **Returns normally** → `WorkerJobs.isSuccess = 1`, `dtCompleted` set, and the composed success
137
+ message (`"[<requestId>] Successfully Executed (<n>s): <return value>"`, arrays/objects
138
+ `json_encode`d) written to the `output` column.
139
+ - **Throws** (any `Throwable`, incl. `Error`) → `isSuccess = 0`, `output` = message +
138
140
  `file:line` + full stack trace. (Two earlier phases — DB-logs registration and `initialize()` —
139
141
  fail the same way.)
140
142
 
143
+ > The outcome column on `Core.WorkerJobs` is named **`output`** (renamed from `failureReason`).
144
+ > It now captures **both** success results and failure text. See
145
+ > [architecture.md](../architecture.md) for the multi-producer rename gotcha.
146
+
141
147
  Crucially, the worker **always returns HTTP 200, even on a throw**, so SQS deletes the message
142
148
  immediately. **There is no DLQ and no automatic retry.** A throw makes the failure *visible* (a
143
149
  failed `WorkerJobs` row to alert on) — it does **not** re-run the job.
@@ -169,6 +175,9 @@ be reattempted.
169
175
  commit-before-SQS transaction pattern that the worker relies on.
170
176
 
171
177
  ## Change history
178
+ - 2026-07-21 — `WorkerJobs.failureReason` column renamed to **`output`** and repurposed to store
179
+ successful execution results as well as failure text; success now writes the composed
180
+ "Successfully Executed" message (return value `json_encode`d for arrays/objects). (jcardinal)
172
181
  - 2026-06-30 — Added the **`DB_CLIENT` auto-registration gotcha**: the dispatcher registers only
173
182
  `DB_CLIENT_LOGS`, so a worker loading a `Client_*` model must call
174
183
  `_Database::registerClientDatabases($clientId, $environment)` itself (proven by
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.391",
3
+ "version": "1.0.392",
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",