genesis-compiler 1.10.22 → 1.10.23

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genesis-compiler",
3
- "version": "1.10.22",
3
+ "version": "1.10.23",
4
4
  "type": "module",
5
5
  "description": "An agent-independent prompt, multi-language code-index, cleanup, and verification companion with project agent guidance.",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genesis",
3
- "version": "1.10.22",
3
+ "version": "1.10.23",
4
4
  "description": "Makes Codex aware of optional Genesis adoption for existing projects.",
5
5
  "author": {
6
6
  "name": "Mobily Enterprises"
@@ -86,10 +86,10 @@ Read the engineering approach's rules on query counts and realistic tests, and
86
86
  these sections of the sanity checks guide
87
87
  (`.agents/skills/genesis-project/references/sanity-checks.md`): "Never do
88
88
  these", "Data: one owner per table", "Data: one source for each fact", "Data:
89
- loading a dataset", "Data: each read asks for the rows it uses", "Data: saves,
90
- batches and background work" and "Inputs and access". They describe what good
91
- looks like; this pass applies them across the whole scope and fixes what they
92
- find.
89
+ loading a dataset", "Data: each read asks for the rows it uses", "Data: batches
90
+ and background work", "Data: two changes at once" and "Inputs and access". They
91
+ describe what good looks like; this pass applies them across the whole scope
92
+ and fixes what they find.
93
93
 
94
94
  Then list, for the scope: each table, collection or store with its one owner
95
95
  (`genesis/subsystems.md` records data ownership), who reads and writes it, its
@@ -173,35 +173,75 @@ one matching, and see it found.
173
173
 
174
174
  **Outer limit:** a capped read narrowed in code is broken at any size.
175
175
 
176
- ## Data: saves, batches and background work
176
+ ## Data: batches and background work
177
177
 
178
178
  **Good:** a batch writes each table in a few statements inside the owner's
179
179
  transaction, not one full create per row. Work nobody waits for runs as a
180
180
  scheduled or queued job in bounded chunks: it loops over units of work (a
181
181
  tenant, a user), one transaction each, never one around the whole run and
182
- never one per row. A read request takes no lock and writes nothing. Every path
183
- takes its locks in one order, parents before children, so two transactions
184
- never wait on each other. Two writers on the same records never produce a
185
- server error.
182
+ never one per row. A read request takes no lock and writes nothing.
186
183
 
187
184
  **Check:** count a batch's statements at 10 items and at 500. Look for due work
188
185
  run inside whichever request comes first, and one long transaction around it.
189
186
  Find any lock or write a read path takes for one-time setup: read first, lock
190
- only on the rare unset path. Compare the order in which each path locks rows.
191
- Run two writers on the same records; a retried transaction must be safe to
192
- repeat, so HTTP calls, email and uploads go before or after it, or into an
193
- outbox row written inside it.
187
+ only on the rare unset path.
194
188
 
195
189
  **Examples:**
196
190
  - An import created each row through the full single-record create path, with
197
191
  its lookups and read-back, one row at a time.
198
192
  - Overdue work ran inside the first user request after a quiet period, so that
199
193
  request's time depended on how long nobody had used the app.
200
- - Concurrent saves surfaced database deadlocks as 500s.
201
194
 
202
195
  **Outer limit:** thousands of queries or tens of seconds for one action, or a
203
196
  request whose time depends on how long since anyone used the app.
204
197
 
198
+ ## Data: two changes at once
199
+
200
+ **Good:** each write uses the lightest tool that keeps the stored data right.
201
+ Most need nothing beyond the transaction they already run in:
202
+ - An ordinary edit (a form saving a record, a name or a description, settings,
203
+ a saved game) is a plain write, and the last save wins: when two people edit
204
+ the same thing at the same moment, one change replaces the other. That is
205
+ usually acceptable, and it needs no lock and no concurrency test. Where
206
+ people would care, the save can carry the version it read and refuse when
207
+ the record has moved on, saying that someone else changed it and to reload.
208
+ - A change allowed only while a value still holds (open to booked, a reward
209
+ claimed once) is a conditional update, a compare-and-set: of two writers one
210
+ wins and the other gets a clear refusal, with no lock.
211
+ - A value that must be unique gets a unique index or constraint, and an
212
+ insert that loses that race is retried where the tools offer it, or refused
213
+ clearly.
214
+ - An explicit lock is for a race that would silently leave wrong data that
215
+ matters: stock or quantities, money or balances, sequential document
216
+ numbers, a capacity limit (two bookings of the last place), or a
217
+ check-then-act on a shared resource (is the drier empty? then load it).
218
+
219
+ A lock makes other writers wait, can deadlock and needs a test with two
220
+ writers, so it usually pays only where you can name the wrong data a race
221
+ would leave. Whatever the tool, a lost race never becomes a server error: the
222
+ loser gets a refusal it can act on, or its work runs again. Take locks in one
223
+ order on every path, parents before children, so two transactions never wait
224
+ on each other. Work that may run again must be safe to repeat, so HTTP calls,
225
+ email and uploads go before or after the transaction, or into an outbox row
226
+ written inside it.
227
+
228
+ **Check:** for each write path, name its tool and why: for a lock, the wrong
229
+ data a race would leave; for a plain write, why the last save winning is
230
+ acceptable. Run two writers at once on each path that locks, writes
231
+ conditionally or relies on a unique key, and see one win and the other refused
232
+ or run again, never a server error and never both applied. Compare the order in
233
+ which each path locks rows. An ordinary edit needs neither a lock nor a
234
+ two-writer test.
235
+
236
+ **Examples:**
237
+ - Concurrent saves surfaced database deadlocks as 500s.
238
+ - A business app locked the rows of every save, names and settings included,
239
+ and spent hours on lock order, deadlocks and two-writer tests for edits
240
+ where the last save winning was fine.
241
+
242
+ **Outer limit:** a lost race that ends in a server error, or that leaves stock,
243
+ money, numbering or a capacity limit silently wrong.
244
+
205
245
  ## Work that repeats or lingers
206
246
 
207
247
  **Good:** work whose answer does not change between calls runs once and is
@@ -440,8 +480,9 @@ hundreds of requests on a first screen.
440
480
 
441
481
  **Good:** the same state twice gives the same result. Each fact has one
442
482
  resolver. Each status names what clears it, and each gate has a case that must
443
- fail it. Writes are conditional on the version read. A delete removes what it
444
- created elsewhere. Readiness is checked directly.
483
+ fail it. A step that moves a status writes only while the status it read
484
+ still holds, so of two at once one wins and the other is refused. A delete
485
+ removes what it created elsewhere. Readiness is checked directly.
445
486
 
446
487
  **Check:** find every place that resolves the same fact. Check that what a
447
488
  delete created outside its table is gone. When a rule's result breaks another