toga-ai 1.0.849 → 1.0.850

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,8 +6,8 @@ project: _Underscore
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-09-16
10
- owners: ["jcardinal", "ajean", "rgirish"]
9
+ updated: 2026-09-21
10
+ owners: ["jcardinal", "ajean", "rgirish", "kyalamarthi"]
11
11
  files:
12
12
  - _underscore/ApiRequest.php
13
13
  - _underscore/Model/Client/Logs/Api.php
@@ -137,6 +137,18 @@ case-insensitive scan of already-set headers, so a caller-supplied `Content-Type
137
137
  - **A hand-rolled `curl` never appears in `Logs.Api`.** The logging belongs to `_ApiRequest`, so a
138
138
  manual/CLI `curl` reproduction of a vendor call is *correctly* absent from the log. Do not read
139
139
  that absence as "the platform did not call the vendor."
140
+ - **⚠ OPEN: valid JSON is rejected as "XML" when the body merely CONTAINS an XML declaration.**
141
+ `ApiRequest.php:360` decides a response is XML with
142
+ `stripos($this->responsePayload, '<?xml version=') === false` — a substring search over the
143
+ **whole body**, not a prefix check. So any JSON response carrying that literal anywhere inside it
144
+ throws `API response was received in XML encoding when it was expecting JSON encoding`. Live case
145
+ (2026-09-21): a ClickUp task description holding a pasted cXML document (an ODP cXML sample on
146
+ task TRUE-82107) broke a valid ClickUp task-page response. **The message blames the API, not the
147
+ ticket**, so it is very hard to diagnose — and the team handles cXML routinely, so expect it
148
+ again. **Workaround:** delete the `<?xml version="1.0"?>` line from the offending record (only
149
+ that exact literal is searched for). **Proposed fix, NOT shipped:** anchor the test —
150
+ `stripos(ltrim($this->responsePayload), '<?xml version=') !== 0`. It sits on every caller's path,
151
+ so get a `cto` opinion plus the normal reviewers before shipping it.
140
152
  - **`Logs.Api` is 1.4M+ rows and `source` is NOT indexed.** Any diagnostic query must be bounded by
141
153
  `dtStamp` (indexed) or it times out — `WHERE source = '…'` alone will not return.
142
154
 
@@ -18,6 +18,7 @@
18
18
  | [ClickUp Subtask Activity → Parent Opportunity/Epic Comments](features/clickup-subtask-activity.md) | Mirrors subtask status/comment activity up to its top-level Opportunity/Epic as one comment; open for the subtask fan-out, its dedup ledger, or structural ances |
19
19
  | [ClickUp Task Description Fluffer (Talos KB Investigation)](features/clickup-task-fluffer-talos.md) | Async worker that "fluffs" a new ClickUp task by running its name+description through the Talos `dev-core` KB agent and writing the report back; open for the fl |
20
20
  | [ClickUp Work Type Automation (Committed / Conditional / Stretch)](features/clickup-work-type-automation.md) | Auto-maintains each ClickUp task's Work Type (Committed/Conditional/Stretch) from its dependencies, status, and due date; open when work-type promotion/demotion |
21
+ | [worker2 — Committed Secrets & Config Exposure (debt register)](features/committed-secrets-and-config-debt.md) | Standing list of credentials committed to the worker2 repo (locations only); open before adding a credential to worker2 or assuming a config value is private. |
21
22
  | [Compass VIP Support Importer (worker2)](features/compass-vip-support-importer.md) | worker2 action that ingests Compass's quarterly VIP spreadsheet and sets each VIP's support tech (`Users.c_supportedByUserId` in `Client_Compass`); open when wo |
22
23
  | [Creating Worker Actions](features/creating-worker-actions.md) | How to add a new callable Worker action — a PHP class whose `public static` methods are invoked as background jobs (via webhook, cron, or `_Worker::runTask()`). |
23
24
  | [Cross-account AWS access for worker2 crons (_Component_Aws_Workloads)](features/cross-account-aws-access.md) | The standard, and only sanctioned, way any new worker2 cron obtains AWS access (any account/region/SDK client) via role-assume; open before writing worker2 code |
@@ -63,4 +64,5 @@
63
64
  | [Rotating the ClickUp API credential (and migrating to the devteam service account)](workflows/clickup-credential-rotation.md) | Procedure to rotate the ClickUp API token (or move traffic onto the `devteam@togatech.com` service account) without killing the live webhook subscription or sil |
64
65
  | [PHP Runtime Upgrade on Elastic Beanstalk (worker2 8.3 → 8.5 + PhpSpreadsheet 1.x → 3.x)](workflows/php-runtime-upgrade-dependency-audit.md) | Reusable checklist for moving a TOGA repo across an EB PHP runtime jump (worker2 8.3 → 8.5 + PhpSpreadsheet 1.x → 3.x); open before any runtime bump or when a c |
65
66
  | [Running worker2 locally against real NetSuite (and what EB does instead)](workflows/running-worker2-locally.md) | Boot worker2 on a dev machine to run a real worker action against live NetSuite + a local Forecast DB; open when local boot fails or before any local NetSuite r |
67
+ | [Repointing the Sprint Tooling at a New ClickUp Sprints Folder (+ table reset)](workflows/sprint-clickup-folder-repoint.md) | Move worker2's sprint tooling onto a new ClickUp "True Dev Sprints" folder and reset the Team sprint tables; open when the sprints folder id changes. |
66
68
  | [Ticket → ClickUp Pseudocode Planning (Talos-grounded)](workflows/ticket-to-pseudocode-planning.md) | Procedure to turn a ClickUp ticket into a reviewed, formatted plan posted to its `📝 Pseudocode` field (ClickUp + codebase + Talos); open when planning a ticket |
@@ -0,0 +1,72 @@
1
+ ---
2
+ title: "worker2 — Committed Secrets & Config Exposure (debt register)"
3
+ framework: "2.0"
4
+ repo: worker2
5
+ project: Worker
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-09-21
10
+ owners: ["kyalamarthi"]
11
+ files:
12
+ - worker2/.gitignore
13
+ - worker2/Worker/Team/Github.php
14
+ - worker2/.ebextensions/git.json
15
+ - worker2/Config/production.ini
16
+ - worker2/Config/netsuite_ec_key.pem
17
+ - worker2/Worker/Team/Sprint.php
18
+ related:
19
+ - ./automated-pr-merger-force-push-race.md
20
+ - ./team-sprint-management.md
21
+ - ../../_underscore/features/apirequest-json-content-type.md
22
+ - ../../../../clients/rate/features/paypal-subscription-purchase-webhook.md
23
+ ---
24
+
25
+ Standing list of credentials committed to the worker2 repo (locations only); open before adding a credential to worker2 or assuming a config value is private.
26
+
27
+ ## Summary
28
+
29
+ Every item below is **pre-existing** debt, found in a 2026-09-21 audit. Root cause:
30
+ `worker2/.gitignore` contains only `/vendor/`, so **every `Config/*.ini` and key file in the repo is
31
+ committed**. The repo is private (verified 2026-09-21 — the unauthenticated GitHub API returns 404),
32
+ which is the only thing containing the blast radius.
33
+
34
+ **Locations only. Never paste a credential value into this or any knowledge doc** — `validate` fails
35
+ the publish on a credential literal.
36
+
37
+ ## How it works
38
+
39
+ ### Inventory — where each credential lives
40
+
41
+ | Credential | Location | Why it is worse than it looks |
42
+ |---|---|---|
43
+ | GitHub personal access token, `agilantgit` account | `worker2/Worker/Team/Github.php:9` **and** `worker2/.ebextensions/git.json:4` (same token, two copies) | Committed since 2025-01-17 and present in **166 of 167 branches**, so scrubbing history is not a fix — **rotation is the only fix**. Org-wide reach. It is also interpolated into a `shell_exec` clone URL, so it shows up in the instance process list. |
44
+ | NetSuite EC private key | `worker2/Config/netsuite_ec_key.pem` | Tracked in git as a file. |
45
+ | TOGa IQ (`api.togaiq.com`) API key | `worker2/Worker/Team/Sprint.php:43`, used ~L422 | Still a class constant. There is **no `[togaiq]` config group yet**, so moving it means adding the config group first. |
46
+ | PayPal webhook signature verification **off** in production | `worker2/Config/production.ini:182` | Impact already written up — a caller who knows the URL can create a paid SalesOrder. See [Rate PayPal subscription webhook](../../../../clients/rate/features/paypal-subscription-purchase-webhook.md). |
47
+
48
+ ### Fixed / no longer true
49
+
50
+ - **ClickUp API token in `Sprint.php`** — the hardcoded `CLICKUP_API_ACCESS_TOKEN` constant is
51
+ **gone**. All 6 call sites now use `_Component_Api_Clickup::accessToken()`, which reads
52
+ `[clickup] token` from config. The component's own hardcoded fallback token, and the plaintext
53
+ `Authorization` header written into `Logs.Api`, are separate open items — see
54
+ [_ApiRequest gotchas](../../_underscore/features/apirequest-json-content-type.md#gotchas).
55
+
56
+ ## Gotchas
57
+
58
+ - **Config is not private here.** Moving a secret from a PHP constant into
59
+ `Config/production.ini` hides it from a grep of the source, not from git — it is still committed.
60
+ Treat that move as a refactor, not a remediation.
61
+ - **Any credential that has ever been committed must be rotated**, not just deleted. Deleting the
62
+ line leaves it in history and in every branch that still carries it (166 of 167, for the GitHub
63
+ token).
64
+ - **Keep this table current.** Add an entry whenever a committed credential is found, and move it to
65
+ *Fixed* when it is rotated and relocated, so this stays the one place the team looks.
66
+
67
+ ## Related
68
+
69
+ - [Automated PR Merger — force-push clobber race](./automated-pr-merger-force-push-race.md) (owns `Worker/Team/Github.php`)
70
+ - [Team Sprint Management & Reporting](./team-sprint-management.md)
71
+ - [_ApiRequest — encode/decode & api-logging behavior](../../_underscore/features/apirequest-json-content-type.md)
72
+ - [Rate PayPal Subscription Purchase & Webhook Pipeline](../../../../clients/rate/features/paypal-subscription-purchase-webhook.md)
@@ -6,17 +6,19 @@ project: Worker
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-09-16
9
+ updated: 2026-09-21
10
10
  owners: ["jcardinal", "kyalamarthi"]
11
11
  files:
12
12
  - worker2/Worker/Team/Sprint.php
13
+ - worker2/Config/production.ini
13
14
  - _underscore/Model/Team/Sprint.php
14
- - dbchanges2/Core/CronJobs (SprintLockScheduled seed)
15
15
  related:
16
16
  - ../architecture.md
17
17
  - ./creating-worker-actions.md
18
18
  - ./clickup-work-type-automation.md
19
19
  - ./clickup-project-routing.md
20
+ - ./committed-secrets-and-config-debt.md
21
+ - ../workflows/sprint-clickup-folder-repoint.md
20
22
  - ../workflows/php-runtime-upgrade-dependency-audit.md
21
23
  ---
22
24
 
@@ -48,8 +50,9 @@ everything.
48
50
  ### Key files / entry points
49
51
  - `Worker/Team/Sprint.php` — the entire feature (one abstract class, static methods).
50
52
  - `initialize()` — registers the `Logs_True` DB connection used for ClickUp API logging.
51
- - ClickUp config lives in class constants: `CLICKUP_TEAM_ID`, `CLICKUP_DEV_SPRINTS_FOLDER_ID` (the
52
- folder whose child lists are the sprints), and the API access token.
53
+ - ClickUp config lives in class constants: `CLICKUP_TEAM_ID` and `CLICKUP_DEV_SPRINTS_FOLDER_ID` (the
54
+ folder whose child lists are the sprints). The API token is **no longer** a constant here — all 6
55
+ call sites use `_Component_Api_Clickup::accessToken()`, reading `[clickup] token` from config.
53
56
  - AI config constants: `AI_API_ENDPOINT` (TOGa IQ `…/api/ai/generate`), `AI_MODEL_ID`
54
57
  (`bedrock/us.anthropic.claude-haiku-4-5-…`), temperature, max-tokens, timeout.
55
58
  - Report distribution: `SEND_LEADERSHIP_REPORTS_TO` (leadership email list); `SEND_EMAILS_FROM` /
@@ -106,8 +109,8 @@ Otherwise it returns a skip message (captured to `Core.WorkerJobs.output`) and d
106
109
  `SprintLock()` itself is unchanged — this only decides *whether* to run it today. Action path
107
110
  `Team/Sprint/SprintLockScheduled` → `_Worker_Team_Sprint::SprintLockScheduled`.
108
111
 
109
- **Deploy coupling.** The worker2 code deploy and the dbchanges2 migration that seeds the
110
- `Core.CronJobs` row must be **released together** — the cron row references the
112
+ **Deploy coupling.** The worker2 code deploy and the `Core.CronJobs` row insert must land
113
+ **together** (no committed migration seeds it — see Gotchas) — the cron row references the
111
114
  `Team/Sprint/SprintLockScheduled` action, which must exist in the deployed code or the scheduled job
112
115
  fails when it fires.
113
116
 
@@ -327,13 +330,50 @@ see [TOGa IQ Sprint Dashboard API](../../api2/features/sprint-dashboard-api.md)
327
330
  - **At-lock baseline is load-bearing.** Reliability/Integrity compare *now* vs *at lock*. If
328
331
  `SprintLock` did not run (or ran without capture), the `*AtLock` columns are empty and the
329
332
  end-of-sprint scores are meaningless. Lock must happen at launch.
330
- - **Sprint list naming is a contract.** Capture matches the ClickUp sprint list by its `Sprint NN
331
- (dates)` name / date range. A mis-named list is silently not found → leadership gets a "sprint not
332
- found" alert instead of a report.
333
- - **Hardcoded credentials.** ⚠ The ClickUp access token and the TOGa IQ AI API key are currently
334
- **hardcoded as class constants** in `Sprint.php` rather than read from config. This is a known
335
- security debt (secrets in source) — they should move to `Config/*.ini` and the committed values
336
- should be rotated. See team coding/security standards.
333
+ - **The sprint list NAME is a contract, and the YEAR is required.** All three capture paths
334
+ (`CaptureSprintDaily` ~L3477, `CaptureSprintEnd` ~L3231, `SprintLock` ~L3801) run the same
335
+ `preg_match('/Sprint (\d+) \((\d{1,2}\/\d{1,2}\/\d{2,4}) - (\d{1,2}\/\d{1,2}\/\d{2,4})\)/')` over
336
+ the list name. A list named `Sprint 1 (9/16 - 9/30)` — no year — does **not** match, `$matches[1]`
337
+ is undefined, and the run **fatals** two lines later (~L3479). A name that merely misses the date
338
+ window instead gives a silent "sprint not found" leadership alert. ClickUp's end date is the
339
+ **next** sprint's start (exclusive); the code stores `dateEnd` minus one day. **Proper fix for a
340
+ future ticket:** take the number from the name but the dates from the list object's `start_date` /
341
+ `due_date` (epoch ms), already fetched for the date-window match.
342
+ - **The tooling cannot bootstrap from an empty `Sprints` table — it deadlocks.** `SprintDaily`
343
+ (~L4806), `SprintEnd` (~L473-474) and `SendSprintEndWarnings` (~L218) all call `getSprint()`
344
+ **before** the `Capture*` method that would create the `Sprints` row, and `getSprint()`
345
+ (~L5702-5740) does `fetchRow()` with **no null check** — so on an empty table every entry point
346
+ fatals with `Attempt to read property "id" on null`. The thing that creates the row is never
347
+ reached. **Workaround (proven in production 2026-09-16):** `INSERT` one `Sprints` row by hand
348
+ (`sprint`, `dateStart`, `dateEnd`); `CaptureSprintDaily`'s "ensure the sprint record exists" block
349
+ (~L3478) self-heals from there. Anyone truncating these tables hits this — see
350
+ [Repointing the sprint tooling](../workflows/sprint-clickup-folder-repoint.md).
351
+ - **`getSprint()` uses `LIMIT 1` with no `ORDER BY`** (~L5717 and ~L5721, both branches). With
352
+ duplicate sprint numbers it returns an **arbitrary** row — a live violation of the
353
+ deterministic-`LIMIT 1` rule in
354
+ [backend-php standards](../../../standards/backend-php.md#a-limit-1-on-a-non-unique-key-must-have-a-deterministic-order-by).
355
+ - **`SprintLock` is NOT a safe way to repopulate empty tables.** It captures before it reads, so it
356
+ looks like a bootstrap (its `getSprint()` call is gated behind `$generateSprintLockReport`), but
357
+ its capture block (~L4016-4030) **writes back to ClickUp for every task** — sets Previous Sprint
358
+ Work Type, sets "Added at sprint launch" = true, sets Condition = "On Track". Run outside the real
359
+ launch ceremony it corrupts those fields across the whole sprint.
360
+ - **`SprintDaily` returns nothing on success** — a production run reads `Successfully Executed
361
+ (4.255 seconds): <no return message>`, so a run that worked is indistinguishable from one that
362
+ never fired. Breaks the return-on-both-paths rule in the
363
+ [worker2 architecture](../architecture.md); fix by returning a structured summary.
364
+ - **The Team/Sprint cron rows are not in git.** Nothing in `dbchanges2/Core/` registers
365
+ `Team/Sprint/%` (searched 2026-09-21), despite this doc previously listing a `CronJobs
366
+ (SprintLockScheduled seed)` file. A concrete case of "a committed migration records intent, not
367
+ deployed state" ([framework-rules](../../../standards/framework-rules.md)) — read the real
368
+ schedule from `Core.CronJobs` in the target environment.
369
+ - **The dev-sprints folder id lives in THREE places** — the `Sprint.php` constant, the
370
+ `Monitor/Oneuptime.php` fallback, and `[clickup] sprint_folder_id` in `Config/production.ini`.
371
+ They must move together, and `Worker/Clickup/Design.php`'s own Design-Sprints folder must not move
372
+ with them. Procedure:
373
+ [Repointing the sprint tooling](../workflows/sprint-clickup-folder-repoint.md).
374
+ - **Credentials.** The ClickUp token now comes from config (`_Component_Api_Clickup::accessToken()`);
375
+ the TOGa IQ AI key is **still a hardcoded constant** at `Sprint.php:43`. Locations and remediation
376
+ status: [committed secrets register](./committed-secrets-and-config-debt.md).
337
377
  - **Worker contract.** Like all 2.0 workers this must return cleanly and commit writes via the
338
378
  `_Db`/transaction layer to be durable — uncommitted captures can be silently dropped.
339
379
  - **ClickUp pagination returns duplicate tasks — the sync loop must be idempotent.** ClickUp's
@@ -0,0 +1,79 @@
1
+ ---
2
+ title: Repointing the Sprint Tooling at a New ClickUp Sprints Folder (+ table reset)
3
+ framework: "2.0"
4
+ repo: worker2
5
+ project: Worker
6
+ client: shared
7
+ type: workflow
8
+ status: active
9
+ updated: 2026-09-21
10
+ owners: ["kyalamarthi"]
11
+ files:
12
+ - worker2/Worker/Team/Sprint.php
13
+ - worker2/Worker/Monitor/Oneuptime.php
14
+ - worker2/Config/production.ini
15
+ - dbchanges2/Team/2026-09-16a - Reset sprint tables for new ClickUp folder.sql
16
+ related:
17
+ - ../features/team-sprint-management.md
18
+ - ../features/creating-worker-actions.md
19
+ - ../../dbchanges2/architecture.md
20
+ ---
21
+
22
+ Move worker2's sprint tooling onto a new ClickUp "True Dev Sprints" folder and reset the Team sprint tables; open when the sprints folder id changes.
23
+
24
+ ## Summary
25
+
26
+ Sprint numbering restarts at 1 in a new folder and collides with existing `Team.Sprints` rows, so a
27
+ repoint is a code + config change **plus** a data reset **plus** a manual seed row — not a one-line
28
+ constant edit. Done once on 2026-09-16 under TRUE-82052 (worker2 + dbchanges2).
29
+
30
+ ## Steps
31
+
32
+ 1. **Name the ClickUp lists `Sprint <n> (M/D/YY - M/D/YY)` — with the year.** Capture parses the list
33
+ name with a regex that requires the year; a list created as `Sprint 1 (9/16 - 9/30)` does not
34
+ match and the run fatals. See
35
+ [team-sprint-management → gotchas](../features/team-sprint-management.md#gotchas).
36
+ 2. **Update all three copies of the folder id — they must move together**, or the tooling
37
+ split-brains:
38
+ - `CLICKUP_DEV_SPRINTS_FOLDER_ID` — `worker2/Worker/Team/Sprint.php` (~L10)
39
+ - `CLICKUP_SPRINTS_FOLDER_ID_FALLBACK` — `worker2/Worker/Monitor/Oneuptime.php` (~L25)
40
+ - `[clickup] sprint_folder_id` — `worker2/Config/production.ini` (~L270); the escalation cron
41
+ reads this and it **wins** over the Oneuptime fallback.
42
+
43
+ Do **not** touch `DESIGN_SPRINTS_FOLDER_ID` in `worker2/Worker/Clickup/Design.php` — Design
44
+ Sprints is a different folder with its own id.
45
+ 3. **Run the reset migration alone, on a fresh connection**, against the `Team` database:
46
+ `dbchanges2/Team/2026-09-16a - Reset sprint tables for new ClickUp folder.sql`. It truncates
47
+ child → parent (`Tasks_Developers` → `Tasks` → `Sprints`) wrapped in
48
+ `SET FOREIGN_KEY_CHECKS = 0 / 1`, because MySQL refuses `TRUNCATE` on a table a foreign key
49
+ points at **even when the child is already empty**.
50
+ 4. **Insert one `Sprints` row by hand** (`sprint`, `dateStart`, `dateEnd`). Required: the tooling
51
+ **cannot bootstrap from an empty `Sprints` table** — every entry point calls `getSprint()` before
52
+ the capture that would create the row. See
53
+ [team-sprint-management → gotchas](../features/team-sprint-management.md#gotchas).
54
+ 5. **Deploy worker2, then run `Team/Sprint/SprintDaily` once** (manual POST — see
55
+ [creating-worker-actions](../features/creating-worker-actions.md)). From there
56
+ `CaptureSprintDaily`'s own "ensure the sprint record exists" block (~L3478) keeps `Sprints`
57
+ current on its own.
58
+ 6. **Verify in the DB, not from the reply.** `SprintDaily` returns nothing on success, so a good run
59
+ reads `Successfully Executed (…): <no return message>`. Confirm `Sprints` / `Tasks` repopulated.
60
+
61
+ ## Gotchas
62
+
63
+ - **`FOREIGN_KEY_CHECKS` is session-scoped.** Run nothing else on that connection, and if the file
64
+ stops part-way the flag stays **off** for the rest of that session — reconnect.
65
+ - **Do not use `SprintLock` to repopulate the tables.** It captures before it reads, so it looks
66
+ like a safe bootstrap, but its capture block **writes back to ClickUp** for every task. See
67
+ [team-sprint-management → gotchas](../features/team-sprint-management.md#gotchas).
68
+ - **Truncate throws away sprint history.** The alternative is renumbering the old rows. On
69
+ 2026-09-16 the developer chose truncate and declined a backup — if history matters next time,
70
+ renumber, or back up `Sprints` / `Tasks` / `Tasks_Developers` first.
71
+ - **The cron rows are not in git.** No committed migration seeds the `Team/Sprint/%` `CronJobs`
72
+ rows, so after a repoint the live schedule can only be read from `Core.CronJobs` in the target
73
+ environment.
74
+
75
+ ## Related
76
+
77
+ - [Team Sprint Management & Reporting](../features/team-sprint-management.md)
78
+ - [Creating Worker Actions](../features/creating-worker-actions.md)
79
+ - [dbchanges2 Architecture](../../dbchanges2/architecture.md)
@@ -20,7 +20,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
20
20
  ## 2.0 framework
21
21
 
22
22
  - **_underscore** (_Underscore) _(framework core)_ — 87 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
23
- - **worker2** (Worker) — 71 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
23
+ - **worker2** (Worker) — 73 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
24
24
  - **api2** (API) — 26 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
25
25
  - **dbchanges2** (Database Changes) _(framework core)_ — 19 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
26
26
  - **toga2-supply** (TOGa Supply) — 9 doc(s) → [2.0/apps/toga2-supply/INDEX.md](2.0/apps/toga2-supply/INDEX.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.849",
3
+ "version": "1.0.850",
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",