toga-ai 1.0.686 → 1.0.687

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.
@@ -5,13 +5,15 @@ project: _Underscore
5
5
  client: shared
6
6
  type: standard
7
7
  status: active
8
- updated: 2026-07-29
9
- owners: [jcardinal, ajean]
8
+ updated: 2026-08-28
9
+ owners: [jcardinal, ajean, apeterson]
10
10
  files: []
11
11
  related:
12
12
  - ../apps/_underscore/architecture.md
13
13
  - ../apps/worker2/architecture.md
14
14
  - ../apps/api2/architecture.md
15
+ - ../apps/dbchanges2/architecture.md
16
+ - ../apps/dbchanges2/features/surface-layer-schema.md
15
17
  ---
16
18
 
17
19
  # Framework 2.0 (_underscore) Rules
@@ -137,6 +139,14 @@ Enforced mechanically by the `PreToolUse` hook
137
139
  examples, and the approved rewrites: `2.0/apps/dbchanges2/architecture.md` → *Database
138
140
  isolation*. **Applies to `dbchanges2` only — the 1.0 `dbchanges` repo is exempt.**
139
141
 
142
+ **Verified empirically in production, 2026-08-28:** the Core reader exposes only `Core`,
143
+ `Forecast`, `Forecast_Archive` and `Team`; the client reader exposes only `Client_*`. This is a
144
+ **physical** boundary, not a permissions setting to be widened — a `Client_*` file naming `Core.*`
145
+ does not fail an authorization check, it cannot resolve at all. Corollary for **reviewers**: "it
146
+ ran locally" and "it ran on beta" are both worthless as evidence of production-runnability, because
147
+ every non-prod environment is all-in-one. The only meaningful checks are the hook, or a
148
+ connection-scoped run against a user granted just the one database.
149
+
140
150
  ### `Core.Records` / `Core.RecordFields` — the only hardcoded `id`s on the platform
141
151
 
142
152
  **These two tables, and only these two, have team-maintained primary keys.** Their `id` values are
@@ -161,6 +171,58 @@ This is also what makes the `dbchanges2` isolation rule above workable: a `Clien
161
171
  never has to read `Core` to resolve a `recordFieldId`. Full detail and examples:
162
172
  `2.0/apps/dbchanges2/architecture.md` → *`Core.Records` / `Core.RecordFields`*.
163
173
 
174
+ #### ⚠ Bounded exemption — the Surface tables
175
+
176
+ **`Core.Surfaces`, `Core.SurfaceElements` and `Core.Messages` also carry team-reserved literal `id`
177
+ blocks.** This is a **specific exemption for the Surface layer, not a general precedent** — do not
178
+ cite it to justify hardcoding ids for any other feature. Reserving them was forced by the cluster
179
+ split above: `SurfaceOverrides` lives in the **Client** DB while the elements it overrides live in
180
+ **Core**, so a `Client_*` override file must reference a Core id it is forbidden to look up at run
181
+ time. Without a stable literal there is nothing for that file to hardcode.
182
+
183
+ When seeding into these three tables:
184
+
185
+ - **Verify the block is actually free** — run both `SELECT MAX(id)` *and*
186
+ `SELECT id FROM … WHERE id BETWEEN <lo> AND <hi>`. Confirm whether a number you were handed means
187
+ **"next free"** or **"highest used"**; reading one as the other has already caused a live
188
+ collision.
189
+ - **Use a plain `INSERT`, never `INSERT IGNORE`.** `IGNORE` turns a primary-key collision — the one
190
+ error that must halt the migration — into a silent mis-wiring. Put idempotency in a `NOT EXISTS`
191
+ guard on a *semantic* key, or in a paired `UPDATE`.
192
+
193
+ Blocks in use, the authoring house style, and the collision incident:
194
+ [surface-layer-schema](../apps/dbchanges2/features/surface-layer-schema.md).
195
+
196
+ ### A committed migration records INTENT, not deployed state
197
+
198
+ **Never infer what an environment contains by reading `dbchanges2`. Query the environment.**
199
+
200
+ There is no automated executor. A human applies each `.sql` per environment, and where the
201
+ isolation rule bites — a client-side file that needs a Core id — the operator resolves the id
202
+ against the target's Core and **hand-writes the literal statement at run time**. Those
203
+ transpositions have historically **not been written back to the repo**. The consequence is
204
+ permanent and structural, not a backlog item:
205
+
206
+ - A file in the repo may never have run anywhere.
207
+ - A file that *did* run may have run in an edited form that exists nowhere in version control.
208
+ - Deployed rows can therefore have no committed file that would reproduce them.
209
+
210
+ So before authoring anything whose correctness depends on current state — an override, a
211
+ correction, an `INSERT … NOT EXISTS` guard, an id block — **establish that state with read-only
212
+ `SELECT`s against the target environment's read replicas.** Connect using the `readhost` keys of
213
+ the `[database]` and `[databaseClient]` groups in `api2/Config/production.ini`; never copy
214
+ credential values into a doc, a ticket, a commit or a chat message.
215
+
216
+ **The hook cannot save you here.** `dbchanges2-cluster-isolation.js` is a static check on the text
217
+ of a file, so it catches a cross-database *reference* at authoring time. It cannot know whether a
218
+ file ever ran, ran in edited form, or matches the target environment. Cluster isolation is
219
+ mechanically enforced; state verification is **on you**.
220
+
221
+ Worked examples of both failure modes — a file unrunnable in prod, and prod rows with no
222
+ corresponding committed file — are in
223
+ [surface-layer-schema](../apps/dbchanges2/features/surface-layer-schema.md) and
224
+ [surface-resolver](../apps/_underscore/features/surface-resolver.md).
225
+
164
226
  ## Checking dependencies before touching shared code
165
227
 
166
228
  `dependsOn` in `knowledge/registry.json` means a repo extends or depends on another repo's classes. Before modifying a class in a dependency repo (e.g. `_underscore` core):
@@ -230,6 +292,22 @@ and not how the convention works. Use a non-`c_` column when you *do* want the f
230
292
  ACL-governed field treatment.
231
293
 
232
294
  ## Change history
295
+ - 2026-08-28 — Extended § Schema migrations with the production-state rules. Recorded that cluster
296
+ isolation is **physical** (verified: the prod Core reader exposes only Core/Forecast/
297
+ Forecast_Archive/Team, the client reader only `Client_*`), so a cross-database reference cannot
298
+ resolve rather than merely being denied — and that neither a local nor a beta run is evidence of
299
+ prod-runnability, since every non-prod environment is all-in-one. Added a **bounded exemption**
300
+ to the hardcoded-id rule for the Surface tables only (`Core.Surfaces`/`SurfaceElements`/
301
+ `Messages` carry reserved literal blocks because `Client_*` override files must reference Core
302
+ ids across the cluster split and cannot resolve them at run time) — **explicitly not a general
303
+ precedent**; the platform rule that only `Core.Records`/`Core.RecordFields` have team-maintained
304
+ ids is unchanged. Attached the seeding safeguards to that exemption (verify the block is free
305
+ with `MAX(id)` *and* a `BETWEEN` check; "next free" vs "highest used"; plain `INSERT`, never
306
+ `INSERT IGNORE`). New subsection: **a committed migration records intent, not deployed state** —
307
+ there is no automated executor, operators hand-transpose Core ids at run time and historically
308
+ did not write them back, so current state must be established with read-only queries against the
309
+ target environment, and the cluster-isolation hook catches cross-database references but
310
+ **cannot** catch state drift. (apeterson)
233
311
  - 2026-07-29 — Documented the `c_`-prefixed framework-dynamic column convention (schema-only,
234
312
  no model-class/RecordFields/ACL declaration), generalized from the transcript AI-model routing
235
313
  work. (ajean)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.686",
3
+ "version": "1.0.687",
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",