toga-ai 1.0.787 → 1.0.788

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-09-04
9
+ updated: 2026-09-09
10
10
  owners: [jcardinal, mhammontree, bala, ajean]
11
11
  files:
12
12
  - Core/
@@ -72,19 +72,21 @@ team-maintained `id`s** — ask the developer for the next value before insertin
72
72
  > trailing-space quirk like `2026-06-03- BLANK_CLIENT_DATABASE.sql`). The **only** hard rule
73
73
  > is the leading `YYYY-MM-DD<letter>` so ordering holds.
74
74
 
75
- ## One file per type per build (keep change files consolidated)
75
+ ## One file per realm per turn (keep change files consolidated)
76
76
 
77
- **Prefer a single `.sql` file per database type (folder) per build.** When a session produces
78
- several changes for the same target — e.g. three separate files under `Core/`, or four under
79
- `Client/` — **consolidate them into one dated file** for that folder instead. Multiple same-type
80
- files in one build are not forbidden, but they have become too common; keep it to one per type
81
- unless they genuinely must be separate (for example, an ordering gap where another folder's file
82
- must run between them).
77
+ **Prefer a single `.sql` file per realm (folder) per turn.** A *realm* is the target database a
78
+ folder maps to — `Core`, the shared `Client`, a single tenant like `Client_True`, `Logs`, a module,
79
+ and so on. When one response produces several changes for the **same** realm — e.g. three separate
80
+ files under `Core/`, or four under `Client/` — **consolidate them into one dated file** for that
81
+ folder instead of writing several. This is a **strong preference**, not an absolute rule: multiple
82
+ same-realm files in one turn are allowed when they genuinely must be separate (for example, an
83
+ ordering gap where another folder's file must run **between** them).
83
84
 
84
- - Combine same-folder statements into one `YYYY-MM-DD<letter> - <Description>.sql`.
85
- - Different folders (types) stay in their own files — that split is required (see isolation).
86
- - The `dbchanges2-file-sprawl` hook warns when a second file of the same type is created in a
87
- session, as a reminder to consolidate.
85
+ - Combine same-realm statements into one `YYYY-MM-DD<letter> - <Description>.sql`.
86
+ - Different realms (folders) stay in their own files — that split is **required** (see isolation);
87
+ never mix two realms in one file.
88
+ - The `dbchanges2-file-sprawl` hook warns when a second file for the same realm is created in a
89
+ turn, as a reminder to consolidate.
88
90
 
89
91
  ## Folder → database mapping
90
92
 
@@ -362,12 +364,23 @@ its own header.)
362
364
  the relevant clients list `<module>` in their `_modules.txt`.
363
365
  5. Never edit or re-date an already-applied file — add a new dated file instead. Never put new
364
366
  work in a `HISTORIC` folder.
365
- 6. **Never seed a `uuid` column with MySQL `UUID()`.** The 2.0 standard requires a fully-random
366
- **v4** UUID; `UUID()` is time/MAC-based (v1) and violates it. Since a migration can't call
367
- `_String::generateUuid()`, **pre-generate a v4 UUID literal** (e.g. a v4 generator) and
368
- hardcode the literal string in the `VALUES` clause. One earlier migration
369
- (`Core/2026-05-08 … CronJobs_WorkerCleanup_insert`) used `UUID()` — that is a known violation,
370
- not a precedent to copy. First applied correctly in
367
+ 6. **Never seed a `uuid` column with MySQL `UUID()` — not even in a bulk insert.** The 2.0 standard
368
+ requires a fully-random **v4** UUID; `UUID()` is time/MAC-based (v1) and violates it. Since a
369
+ migration can't call `_String::generateUuid()`:
370
+ - **Single-row insert:** **pre-generate a v4 UUID literal** (a real v4 generator) and hardcode
371
+ the literal string in the `VALUES` clause.
372
+ - **Multi-row / bulk `INSERT … SELECT`:** use the inline `RANDOM_BYTES()` v4 expression (see
373
+ `features/rerunnable-additive-inserts.md` → *Generating a real UUID4 inline*), never `UUID()`.
374
+
375
+ **Every UUID must be freshly, fully random — never derive one from another.** Do **not** take a
376
+ known uuid and bump a digit (`…-0001`, `…-0002`, …), copy-and-tweak, or otherwise pattern them.
377
+ When a file needs several literals, generate each one independently at random. (Patterned uuids
378
+ are guessable and defeat the uniqueness guarantee.) The one intended exception is a fan-out
379
+ `Client/` grant, which **reuses the same** literal per row across tenants on purpose for safe
380
+ rollback — that is deliberate reuse, not incrementing (see the feature doc).
381
+
382
+ One earlier migration (`Core/2026-05-08 … CronJobs_WorkerCleanup_insert`) used `UUID()` — that is
383
+ a known violation, not a precedent to copy. First applied correctly in
371
384
  `Core/2026-07-21b - Insert - SprintLockScheduled CronJob.sql`.
372
385
  7. **Guard every registration/seed insert with `NOT EXISTS` (or `INSERT IGNORE`).** Rows that
373
386
  register platform behavior — `ApiPayloadInterceptors`, `Core.RecordFields`/`CustomRecordFields`,
@@ -562,8 +575,9 @@ Wrap the existing-set subquery in a **derived table** (with `DISTINCT` or `LIMIT
562
575
 
563
576
  ```sql
564
577
  -- CORRECT — the derived table snapshots the "already present" set before any insert
578
+ -- (uuid: inline RANDOM_BYTES() v4 expression, never UUID() — see rule #6 / the feature doc)
565
579
  INSERT INTO TranscriptPromptTerms (uuid, category, term, isActive, c_trueAiModelId)
566
- SELECT UUID(), t.category, t.term, t.isActive, m.mid
580
+ SELECT LOWER(CONCAT(HEX(RANDOM_BYTES(4)), '-', …)), t.category, t.term, t.isActive, m.mid
567
581
  FROM <base rows> t
568
582
  CROSS JOIN <active model ids> m
569
583
  WHERE m.mid NOT IN (
@@ -591,6 +605,15 @@ tables that `_Model_*` classes map to.
591
605
 
592
606
  ## Change history
593
607
 
608
+ - 2026-09-09 — **Two team-wide authoring changes (jcardinal).** (1) **UUIDs must be freshly, fully
609
+ random — never derived from another.** Sharpened rule #6: do not bump a digit / copy-and-tweak /
610
+ pattern uuid literals; generate each independently at random. Reaffirmed **never `UUID()` — not
611
+ even in bulk** (bulk uses the `RANDOM_BYTES()` v4 expression); fixed the doc's own
612
+ `TranscriptPromptTerms` example, which still used `UUID()`. The fan-out `Client/` same-literal
613
+ reuse is the one intended exception (deliberate reuse for safe rollback, not incrementing).
614
+ (2) **One file per realm per turn** — renamed/strengthened the consolidation section: prefer a
615
+ single `.sql` file per realm (`Core`, `Client`, `Client_<Name>`, …) per turn; a strong preference,
616
+ not absolute; different realms still split (never mix two realms in one file). (jcardinal)
594
617
  - 2026-08-18 - Added **rule 10**: a fan-out `Client/` file must never reference a
595
618
  `customRecordFieldId` or a client-specific label, because `CustomRecordFields` ids are per-client
596
619
  `AUTO_INCREMENT` - the same numeric id names a different field in every tenant and mis-wires
@@ -6,7 +6,7 @@ project: Database Changes
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-09-08
9
+ updated: 2026-09-09
10
10
  owners: [bala, kyalamarthi, apeterson, ajean, jcardinal]
11
11
  files:
12
12
  - dbchanges2/Client_Compass/2026-08-26a - CompassCreativeStudioPersona.sql
@@ -52,6 +52,14 @@ and `SUBSTRING('89ab', …)` picks the variant nibble. Verified working on prod
52
52
  that is *not* v4-shaped (older migrations concatenated `RANDOM_BYTES` without the version/variant
53
53
  nibbles). They are fine and must not be "fixed" — but do not use them as the template for new SQL.
54
54
 
55
+ **⚠ When a file needs several hardcoded literals, generate each one independently at random — never
56
+ derive one from another.** Do not paste one uuid and bump a digit (`…-0001`, `…-0002`, …) or
57
+ copy-and-tweak to make the next. Patterned uuids are guessable and undercut the uniqueness the column
58
+ exists to give. Generate each literal fresh from a real v4 generator. (The **one** intended exception
59
+ is the fan-out rule just below, which reuses the **same** literal per row across tenants on purpose —
60
+ deliberate reuse for a safe rollback, not incrementing.) `UUID()` is never allowed, in single-row or
61
+ bulk inserts — bulk uses the `RANDOM_BYTES()` expression above.
62
+
55
63
  ### ⚠ In a FAN-OUT grant migration, use HARDCODED uuid literals — generated uuids make rollback unsafe
56
64
 
57
65
  The generator above is right for a normal additive insert. It is **wrong for a `Client/` fan-out
@@ -310,6 +318,11 @@ concluding a migration is production-safe.
310
318
  [FIELD_SQL calculated fields](../../_underscore/features/calculated-sql-fields.md).
311
319
 
312
320
  ## Change history
321
+ - 2026-09-09 — Added the rule that **every hardcoded uuid literal must be generated independently at
322
+ random** — never bump a digit / copy-and-tweak / pattern them (guessable, defeats uniqueness); the
323
+ fan-out same-literal reuse is the one intended exception. Restated **never `UUID()`, single-row or
324
+ bulk** (bulk uses the `RANDOM_BYTES()` v4 expression). Team-wide authoring change alongside
325
+ architecture rule #6. (jcardinal)
313
326
  - 2026-09-08 — Extended the **`Core.CronJobs` registration** shape with three mechanics confirmed on
314
327
  `Core/2026-09-08e - Insert QcBatch CronJob.sql`: reference `CronJobs` **unqualified** in a `Core/`
315
328
  file (a `Core.` prefix is a cross-database reference that breaks in prod); **always set
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.787",
3
+ "version": "1.0.788",
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",