@nanobpm/nano-workforce 0.99.1 → 0.101.0

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/app/agentCompletion.test.ts +92 -6
  3. package/app/agentCompletion.ts +86 -58
  4. package/app/contracts.ts +18 -2
  5. package/app/feature.ts +15 -166
  6. package/app/featureGateway.test.ts +6 -57
  7. package/app/migration049.test.ts +112 -0
  8. package/app/pollUserTasks.test.ts +39 -13
  9. package/app/service.test.ts +16 -0
  10. package/app/service.ts +107 -136
  11. package/app/stage.test.ts +7 -53
  12. package/app/stage.ts +5 -37
  13. package/app/userTasks.test.ts +1 -1
  14. package/app/userTasks.ts +3 -3
  15. package/app/world/checkpoint.test.ts +193 -0
  16. package/app/world/checkpoint.ts +142 -0
  17. package/app/world/effect-ledger.test.ts +86 -0
  18. package/app/world/effect-ledger.ts +103 -0
  19. package/app/world/git.ts +53 -0
  20. package/app/world/index.ts +26 -0
  21. package/app/world/store.test.ts +443 -0
  22. package/app/world/store.ts +320 -0
  23. package/app/world-marker.test.ts +79 -0
  24. package/db/migrations/049_drop_feature_escalation_surface.sql +25 -0
  25. package/db/migrations/049_world_checkpoint.sql +84 -0
  26. package/e2e/feature-run.e2e.ts +52 -41
  27. package/e2e/retire-escalation-subsystem.e2e.ts +26 -0
  28. package/openapi.yaml +7 -108
  29. package/operations/agentCompleteEscalation.ts +2 -2
  30. package/operations/completeUserTask.test.ts +25 -6
  31. package/operations/completeUserTask.ts +12 -10
  32. package/package.json +2 -2
  33. package/pages/feature.page.json +1 -37
  34. package/pages/overview.page.json +1 -39
  35. package/pages/tasks.page.json +78 -93
  36. package/resources/forms/feature-escalation.form +3 -0
  37. package/test/worldDb.ts +103 -0
  38. package/workers/persist-round/worker.ts +68 -0
  39. package/workers/record-blocked-ack/worker.test.ts +1 -4
  40. package/workers/record-blocked-ack/worker.ts +0 -5
  41. package/workers/record-feature/worker.ts +0 -6
  42. package/workers/record-feature-escalation/worker.test.ts +14 -27
  43. package/workers/record-feature-escalation/worker.ts +16 -22
  44. package/app/featureBlocked.test.ts +0 -182
  45. package/app/featureEscalation.test.ts +0 -235
  46. package/operations/acknowledgeBlocked.test.ts +0 -111
  47. package/operations/acknowledgeBlocked.ts +0 -62
  48. package/operations/answerFeatureEscalation.ts +0 -68
@@ -0,0 +1,443 @@
1
+ // Tests for the durable world store (issue #324, ADR 0062 Slice 4/5) against a REAL in-memory SQLite
2
+ // engine with migration 049 applied — so the monotonic checkpoint offset, the effect-tail ordering,
3
+ // and the durable fence (`UNIQUE(pr_key, idempotency_key)` → `isApplied`/`markApplied`) are proven,
4
+ // not mocked.
5
+ import { test } from "node:test";
6
+ import { assert, assertEquals, assertRejects, assertThrows } from "#test-assert";
7
+ import { memWorldData } from "../../test/worldDb.ts";
8
+ import type { Effect } from "./effect-ledger.ts";
9
+ import { WorldStore } from "./store.ts";
10
+
11
+ const PR = "o/r#1";
12
+ const push = (sha: string): Effect => ({ kind: "push", idempotencyKey: sha });
13
+
14
+ test("nextOffset is a per-PR monotonic counter derived from the durable rows", async () => {
15
+ const { data } = memWorldData();
16
+ const store = new WorldStore(data);
17
+ assertEquals(await store.nextOffset(PR), 0, "first checkpoint is offset 0");
18
+ await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a" });
19
+ assertEquals(await store.nextOffset(PR), 1, "second is offset 1");
20
+ await store.recordCheckpoint({ prKey: PR, roundNo: 2, commitSha: "sha-b" });
21
+ assertEquals(await store.nextOffset(PR), 2);
22
+ // A different PR has its own independent counter.
23
+ assertEquals(await store.nextOffset("o/r#2"), 0, "offsets are scoped per PR");
24
+ });
25
+
26
+ test("lastCheckpoint returns the newest push-checkpoint (max offset), or null when none", async () => {
27
+ const { data } = memWorldData();
28
+ const store = new WorldStore(data);
29
+ assertEquals(await store.lastCheckpoint(PR), null, "no checkpoint yet — nothing to reconstruct");
30
+ await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a" });
31
+ await store.recordCheckpoint({ prKey: PR, roundNo: 2, commitSha: "sha-b" });
32
+ const last = await store.lastCheckpoint(PR);
33
+ assertEquals(last, { offset: 1, commitSha: "sha-b", roundNo: 2 }, "the newest checkpoint wins");
34
+ });
35
+
36
+ test("recordCheckpoint defaults to a single push effect keyed by the commit SHA", async () => {
37
+ const { data } = memWorldData();
38
+ const store = new WorldStore(data);
39
+ const offset = await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a" });
40
+ const tail = await store.effectTail(PR, offset);
41
+ assertEquals(tail, [{ kind: "push", idempotencyKey: "sha-a" }], "the push itself is the default effect");
42
+ });
43
+
44
+ test("effectTail returns the recorded effects in seq order", async () => {
45
+ const { data } = memWorldData();
46
+ const store = new WorldStore(data);
47
+ const effects: Effect[] = [
48
+ push("sha-a"),
49
+ { kind: "pr-comment", idempotencyKey: "c-1", description: "first" },
50
+ { kind: "merge", idempotencyKey: "m-1" },
51
+ ];
52
+ const offset = await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a", effects });
53
+ const tail = await store.effectTail(PR, offset);
54
+ assertEquals(tail.map((e) => e.idempotencyKey), ["sha-a", "c-1", "m-1"], "order is preserved");
55
+ assertEquals(tail[1].description, "first", "the audit description round-trips");
56
+ });
57
+
58
+ test("the durable fence: a re-recorded idempotency key is not a second effect row", async () => {
59
+ const { data } = memWorldData();
60
+ const store = new WorldStore(data);
61
+ await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a", effects: [push("sha-a")] });
62
+ // Re-record the SAME push (a duplicate persist-round) — the UNIQUE fence collapses it.
63
+ await store.recordCheckpoint({ prKey: PR, roundNo: 2, commitSha: "sha-a", effects: [push("sha-a")] });
64
+ const rows = await data.table("world_effects", "id").find({ pr_key: PR, idempotency_key: "sha-a" });
65
+ assertEquals(rows.length, 1, "one real effect → exactly one ledger row, despite two records");
66
+ });
67
+
68
+ test("recordCheckpoint is idempotent on the commit SHA: a re-record reuses the offset, never orphaning a pending tail", async () => {
69
+ const { data } = memWorldData();
70
+ const store = new WorldStore(data);
71
+ // Round records a checkpoint at a push with a PENDING tail effect (recorded before it is performed).
72
+ const first = await store.recordCheckpoint({
73
+ prKey: PR,
74
+ roundNo: 1,
75
+ commitSha: "sha-a",
76
+ effects: [push("sha-a"), { kind: "pr-comment", idempotencyKey: "c-1" }],
77
+ applied: false,
78
+ });
79
+ assertEquals(first, 0, "first checkpoint is offset 0");
80
+ // A retried/duplicate persist-round records the SAME {prKey, commitSha}. A naive impl allocates a
81
+ // fresh offset whose tail is empty (the global fence skips the already-recorded effects), making it
82
+ // the newest checkpoint and orphaning the genuinely-pending "c-1" effect on offset 0 — silent loss.
83
+ const second = await store.recordCheckpoint({
84
+ prKey: PR,
85
+ roundNo: 2,
86
+ commitSha: "sha-a",
87
+ effects: [push("sha-a"), { kind: "pr-comment", idempotencyKey: "c-1" }],
88
+ applied: false,
89
+ });
90
+ assertEquals(second, 0, "the re-record REUSES the existing offset, not a new one");
91
+ const last = await store.lastCheckpoint(PR);
92
+ assertEquals(last?.offset, 0, "the newest checkpoint is still the one carrying the pending tail");
93
+ const tail = await store.effectTail(PR, last?.offset ?? -1);
94
+ assertEquals(
95
+ tail.map((e) => e.idempotencyKey),
96
+ ["sha-a", "c-1"],
97
+ "the pending tail survives on the surviving checkpoint — no orphaned/ignored pending effect",
98
+ );
99
+ const cps = await data.table("world_checkpoints", "id").find({ pr_key: PR });
100
+ assertEquals(cps.length, 1, "exactly one checkpoint row for the SHA, despite two records");
101
+ });
102
+
103
+ test("recordCheckpoint reusing an offset appends a newly-supplied effect after the existing tail", async () => {
104
+ const { data } = memWorldData();
105
+ const store = new WorldStore(data);
106
+ await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a", effects: [push("sha-a")] });
107
+ // Same SHA re-recorded, now carrying an ADDITIONAL effect (e.g. a PR comment made after the push).
108
+ const offset = await store.recordCheckpoint({
109
+ prKey: PR,
110
+ roundNo: 1,
111
+ commitSha: "sha-a",
112
+ effects: [push("sha-a"), { kind: "pr-comment", idempotencyKey: "c-2" }],
113
+ });
114
+ const tail = await store.effectTail(PR, offset);
115
+ assertEquals(
116
+ tail.map((e) => e.idempotencyKey),
117
+ ["sha-a", "c-2"],
118
+ "the new effect is appended after the existing tail on the reused offset, in seq order",
119
+ );
120
+ });
121
+
122
+ test("fenceFor.isApplied is true only once an effect is recorded AND applied; markApplied flips it", async () => {
123
+ const { data } = memWorldData();
124
+ const store = new WorldStore(data);
125
+ // Record a PENDING tail effect (applied=false) — recorded before it is performed.
126
+ await store.recordCheckpoint({
127
+ prKey: PR,
128
+ roundNo: 1,
129
+ commitSha: "sha-a",
130
+ effects: [{ kind: "pr-comment", idempotencyKey: "c-1" }],
131
+ applied: false,
132
+ });
133
+ const fence = store.fenceFor(PR, 0);
134
+ assertEquals(await fence.isApplied("c-1"), false, "a pending effect is NOT yet applied");
135
+ assertEquals(await fence.isApplied("absent"), false, "an unknown key is not applied");
136
+ await fence.markApplied({ kind: "pr-comment", idempotencyKey: "c-1" });
137
+ assertEquals(await fence.isApplied("c-1"), true, "markApplied realises it so a later resume skips");
138
+ });
139
+
140
+ test("fenceFor.markApplied records a brand-new applied effect when the key is absent", async () => {
141
+ const { data } = memWorldData();
142
+ const store = new WorldStore(data);
143
+ await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a" });
144
+ const fence = store.fenceFor(PR, 0);
145
+ await fence.markApplied({ kind: "merge", idempotencyKey: "m-1" });
146
+ assert(await fence.isApplied("m-1"), "a newly-applied effect is now fenced");
147
+ });
148
+
149
+ test("recordCheckpoint is atomic: a mid-write effect failure rolls back the checkpoint row too", async () => {
150
+ const { data, db } = memWorldData();
151
+ // Decorate the transaction-scoped data source so the SECOND `world_effects` insert throws — a crash
152
+ // AFTER the checkpoint row + first effect but BEFORE the second. Without an enclosing transaction
153
+ // this leaves a checkpoint whose fence is missing ledger rows; the atomic write must roll it ALL back.
154
+ const realOpen = (data as unknown as { open: () => Record<string, unknown> }).open.bind(data);
155
+ (data as unknown as { open: () => Record<string, unknown> }).open = () => {
156
+ const ds = realOpen();
157
+ const realTable = (ds.table as (name: string, pk?: string) => Record<string, unknown>).bind(ds);
158
+ let effectInserts = 0;
159
+ ds.table = (name: string, pk?: string) => {
160
+ const t = realTable(name, pk);
161
+ if (name === "world_effects") {
162
+ const realInsert = (t.insert as (row: unknown) => Promise<number>).bind(t);
163
+ t.insert = async (row: unknown) => {
164
+ if (++effectInserts === 2) throw new Error("simulated crash mid-append");
165
+ return realInsert(row);
166
+ };
167
+ }
168
+ return t;
169
+ };
170
+ return ds;
171
+ };
172
+ const store = new WorldStore(data);
173
+ await assertRejects(
174
+ () =>
175
+ store.recordCheckpoint({
176
+ prKey: PR,
177
+ roundNo: 1,
178
+ commitSha: "sha-a",
179
+ effects: [
180
+ { kind: "push", idempotencyKey: "k1" },
181
+ { kind: "pr-comment", idempotencyKey: "k2" },
182
+ ],
183
+ }),
184
+ Error,
185
+ "simulated crash mid-append",
186
+ );
187
+ const cps = Number((db.prepare("SELECT COUNT(*) AS c FROM world_checkpoints").get() as { c: number }).c);
188
+ const effs = Number((db.prepare("SELECT COUNT(*) AS c FROM world_effects").get() as { c: number }).c);
189
+ assertEquals(cps, 0, "the checkpoint row was rolled back — no half-written checkpoint");
190
+ assertEquals(effs, 0, "the first effect row was rolled back too — the whole write is atomic");
191
+ });
192
+
193
+ test("the schema enforces one checkpoint row per (pr, commit SHA) — a raw duplicate insert is rejected", async () => {
194
+ const { data, db } = memWorldData();
195
+ const store = new WorldStore(data);
196
+ // The application path is idempotent (reuses the offset), so exercise the DURABLE guard directly:
197
+ // a second raw row for the same {pr_key, commit_sha} — as a racing/duplicate writer or legacy data
198
+ // could produce — must be rejected by `UNIQUE(pr_key, commit_sha)`, not silently accepted (which
199
+ // would let `findOne` pick an arbitrary offset and shadow the real effect tail).
200
+ await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a" });
201
+ assertThrows(
202
+ () =>
203
+ db
204
+ .prepare("INSERT INTO world_checkpoints (pr_key, round_no, checkpoint_offset, commit_sha, created_at) VALUES (?, ?, ?, ?, ?)")
205
+ .run(PR, 2, 1, "sha-a", new Date().toISOString()),
206
+ Error,
207
+ "UNIQUE",
208
+ );
209
+ const cps = await data.table("world_checkpoints", "id").find({ pr_key: PR, commit_sha: "sha-a" });
210
+ assertEquals(cps.length, 1, "still exactly one checkpoint row for the SHA");
211
+ });
212
+
213
+ test("fenceFor.markApplied appends new effects at the next seq — no seq collision at a shared offset", async () => {
214
+ const { data, db } = memWorldData();
215
+ const store = new WorldStore(data);
216
+ // recordCheckpoint seeds offset 0 with the default push effect at seq 0.
217
+ await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a" });
218
+ const fence = store.fenceFor(PR, 0);
219
+ // Two brand-new applied effects at the SAME offset must NOT both land at seq 0 (which would make
220
+ // effectTail's `a.seq - b.seq` tie-sort non-deterministic) — each takes the next available seq.
221
+ await fence.markApplied({ kind: "pr-comment", idempotencyKey: "c-1" });
222
+ await fence.markApplied({ kind: "merge", idempotencyKey: "m-1" });
223
+ const seqs = (
224
+ db.prepare("SELECT seq FROM world_effects WHERE pr_key = ? AND checkpoint_offset = 0 ORDER BY seq").all(PR) as {
225
+ seq: number;
226
+ }[]
227
+ ).map((r) => r.seq);
228
+ assertEquals(seqs, [0, 1, 2], "each new effect appends at a distinct, monotonically increasing seq");
229
+ const tail = await store.effectTail(PR, 0);
230
+ assertEquals(
231
+ tail.map((e) => e.idempotencyKey),
232
+ ["sha-a", "c-1", "m-1"],
233
+ "effectTail is deterministically ordered — insertion order, no ties",
234
+ );
235
+ });
236
+
237
+ test("recordCheckpoint tolerates a concurrent duplicate checkpoint insert — reuses the raced offset, no spurious failure", async () => {
238
+ const { data, db } = memWorldData();
239
+ // The check-then-insert race the `UNIQUE(pr_key, commit_sha)` fence guards: a concurrent/duplicate
240
+ // persist-round lands the checkpoint row for the SAME {pr, commit SHA} AFTER our `findOne` missed but
241
+ // BEFORE our `insert`. Decorate the transaction-scoped checkpoints table so the first insert first
242
+ // writes a concurrent row for the SHA, then delegates — the real insert now hits the fence.
243
+ const realOpen = (data as unknown as { open: () => Record<string, unknown> }).open.bind(data);
244
+ (data as unknown as { open: () => Record<string, unknown> }).open = () => {
245
+ const ds = realOpen();
246
+ const realTable = (ds.table as (name: string, pk?: string) => Record<string, unknown>).bind(ds);
247
+ let injected = false;
248
+ ds.table = (name: string, pk?: string) => {
249
+ const t = realTable(name, pk);
250
+ if (name === "world_checkpoints") {
251
+ const realInsert = (t.insert as (row: unknown) => Promise<number>).bind(t);
252
+ t.insert = async (row: unknown) => {
253
+ if (!injected) {
254
+ injected = true;
255
+ db.prepare(
256
+ "INSERT INTO world_checkpoints (pr_key, round_no, checkpoint_offset, commit_sha, created_at) VALUES (?, ?, ?, ?, ?)",
257
+ ).run(PR, 9, 0, "sha-a", new Date().toISOString());
258
+ }
259
+ return realInsert(row);
260
+ };
261
+ }
262
+ return t;
263
+ };
264
+ return ds;
265
+ };
266
+ const store = new WorldStore(data);
267
+ const offset = await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a" });
268
+ assertEquals(offset, 0, "the race is reconciled to the winner's offset, not surfaced as a spurious error");
269
+ const cps = await data.table("world_checkpoints", "id").find({ pr_key: PR, commit_sha: "sha-a" });
270
+ assertEquals(cps.length, 1, "exactly one checkpoint row for the SHA — the fence held");
271
+ assertEquals(
272
+ (await store.effectTail(PR, offset)).map((e) => e.idempotencyKey),
273
+ ["sha-a"],
274
+ "the push effect still lands at the reused offset",
275
+ );
276
+ });
277
+
278
+ test("recordCheckpoint tolerates a concurrent duplicate effect insert — the fence collapses it, no spurious failure", async () => {
279
+ const { data, db } = memWorldData();
280
+ // The effect ledger's `UNIQUE(pr_key, idempotency_key)` fence, raced: a concurrent writer records the
281
+ // SAME idempotency key between our `findOne` miss and our `insert`. Decorate so the FIRST effect insert
282
+ // first writes a concurrent row for that key, then delegates — the real insert hits the fence.
283
+ const realOpen = (data as unknown as { open: () => Record<string, unknown> }).open.bind(data);
284
+ (data as unknown as { open: () => Record<string, unknown> }).open = () => {
285
+ const ds = realOpen();
286
+ const realTable = (ds.table as (name: string, pk?: string) => Record<string, unknown>).bind(ds);
287
+ let injected = false;
288
+ ds.table = (name: string, pk?: string) => {
289
+ const t = realTable(name, pk);
290
+ if (name === "world_effects") {
291
+ const realInsert = (t.insert as (row: unknown) => Promise<number>).bind(t);
292
+ t.insert = async (row: unknown) => {
293
+ if (!injected) {
294
+ injected = true;
295
+ db.prepare(
296
+ "INSERT INTO world_effects (pr_key, checkpoint_offset, seq, kind, idempotency_key, description, applied, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
297
+ ).run(PR, 0, 0, "push", "sha-a", null, 1, new Date().toISOString());
298
+ }
299
+ return realInsert(row);
300
+ };
301
+ }
302
+ return t;
303
+ };
304
+ return ds;
305
+ };
306
+ const store = new WorldStore(data);
307
+ const offset = await store.recordCheckpoint({
308
+ prKey: PR,
309
+ roundNo: 1,
310
+ commitSha: "sha-a",
311
+ effects: [push("sha-a"), { kind: "pr-comment", idempotencyKey: "c-1" }],
312
+ });
313
+ const dup = await data.table("world_effects", "id").find({ pr_key: PR, idempotency_key: "sha-a" });
314
+ assertEquals(dup.length, 1, "the raced idempotency key yields exactly one row — the fence collapsed the duplicate");
315
+ assertEquals(
316
+ (await store.effectTail(PR, offset)).map((e) => e.idempotencyKey),
317
+ ["sha-a", "c-1"],
318
+ "the remaining effect still records after the collapsed duplicate — no spurious failure",
319
+ );
320
+ });
321
+
322
+ test("fenceFor.markApplied tolerates a concurrent effect insert — reconciles the raced row to applied, no spurious failure", async () => {
323
+ const { data, db } = memWorldData();
324
+ const store = new WorldStore(data);
325
+ await store.recordCheckpoint({ prKey: PR, roundNo: 1, commitSha: "sha-a" });
326
+ // Race markApplied's check-then-insert: a concurrent restore records the SAME key (as a PENDING tail
327
+ // entry) between our `findOne` miss and our `insert`. Decorate `table` so the effect insert first
328
+ // writes that concurrent pending row, then delegates — the real insert hits the fence.
329
+ const realTable = (data as unknown as { table: (name: string, pk?: string) => Record<string, unknown> }).table.bind(data);
330
+ let injected = false;
331
+ (data as unknown as { table: (name: string, pk?: string) => Record<string, unknown> }).table = (name: string, pk?: string) => {
332
+ const t = realTable(name, pk);
333
+ if (name === "world_effects") {
334
+ const realInsert = (t.insert as (row: unknown) => Promise<number>).bind(t);
335
+ t.insert = async (row: unknown) => {
336
+ if (!injected) {
337
+ injected = true;
338
+ db.prepare(
339
+ "INSERT INTO world_effects (pr_key, checkpoint_offset, seq, kind, idempotency_key, description, applied, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
340
+ ).run(PR, 0, 5, "merge", "m-1", null, 0, new Date().toISOString());
341
+ }
342
+ return realInsert(row);
343
+ };
344
+ }
345
+ return t;
346
+ };
347
+ const fence = store.fenceFor(PR, 0);
348
+ await fence.markApplied({ kind: "merge", idempotencyKey: "m-1" });
349
+ assert(await fence.isApplied("m-1"), "the raced pending row is reconciled to applied, not left pending or surfaced as an error");
350
+ const rows = await data.table("world_effects", "id").find({ pr_key: PR, idempotency_key: "m-1" });
351
+ assertEquals(rows.length, 1, "exactly one row for the key — the fence collapsed the duplicate");
352
+ });
353
+
354
+ test("recordCheckpoint re-recording a pending effect as applied reconciles the fence — no re-apply on restore", async () => {
355
+ const { data } = memWorldData();
356
+ const store = new WorldStore(data);
357
+ // Round records a tail effect PENDING (applied=false) — recorded before it is performed.
358
+ await store.recordCheckpoint({
359
+ prKey: PR,
360
+ roundNo: 1,
361
+ commitSha: "sha-a",
362
+ effects: [{ kind: "pr-comment", idempotencyKey: "c-1" }],
363
+ applied: false,
364
+ });
365
+ const fence = store.fenceFor(PR, 0);
366
+ assertEquals(await fence.isApplied("c-1"), false, "pending before it lands");
367
+ // The effect lands; a later record of the SAME key now knows it is applied. The duplicate-key
368
+ // short-circuit must NOT drop that knowledge — it must reconcile the surviving row to applied, or a
369
+ // later restore re-applies an already-executed side effect.
370
+ await store.recordCheckpoint({
371
+ prKey: PR,
372
+ roundNo: 2,
373
+ commitSha: "sha-a",
374
+ effects: [{ kind: "pr-comment", idempotencyKey: "c-1" }],
375
+ applied: true,
376
+ });
377
+ assertEquals(
378
+ await fence.isApplied("c-1"),
379
+ true,
380
+ "a re-record that knows the effect landed flips the pending row to applied (fence reconciled)",
381
+ );
382
+ const rows = await data.table("world_effects", "id").find({ pr_key: PR, idempotency_key: "c-1" });
383
+ assertEquals(rows.length, 1, "still exactly one row — the fence collapsed the re-record, it did not duplicate");
384
+ });
385
+
386
+ test("recordCheckpoint re-recording an applied effect as pending never un-applies it (monotone fence)", async () => {
387
+ const { data } = memWorldData();
388
+ const store = new WorldStore(data);
389
+ await store.recordCheckpoint({
390
+ prKey: PR,
391
+ roundNo: 1,
392
+ commitSha: "sha-a",
393
+ effects: [{ kind: "pr-comment", idempotencyKey: "c-1" }],
394
+ applied: true,
395
+ });
396
+ const fence = store.fenceFor(PR, 0);
397
+ assertEquals(await fence.isApplied("c-1"), true, "applied after it lands");
398
+ // A stray re-record carrying applied=false must NOT retreat the fence — an already-executed effect
399
+ // cannot become pending again, or a restore would re-apply it.
400
+ await store.recordCheckpoint({
401
+ prKey: PR,
402
+ roundNo: 2,
403
+ commitSha: "sha-a",
404
+ effects: [{ kind: "pr-comment", idempotencyKey: "c-1" }],
405
+ applied: false,
406
+ });
407
+ assertEquals(await fence.isApplied("c-1"), true, "a later pending re-record never un-applies (fence is monotone)");
408
+ });
409
+
410
+ test("effectTail breaks a duplicate seq tie by autoincrement id — deterministic even if the DB returns rows unordered", async () => {
411
+ const { data, db } = memWorldData();
412
+ // The seq allocator (`#nextSeqOn`) is a racy read-max-plus-one and the schema has no
413
+ // UNIQUE(pr_key, checkpoint_offset, seq), so two concurrent writers CAN land the same seq at one
414
+ // offset. `find` gives NO order guarantee either, so a sort on seq alone leaves a seq-tie in whatever
415
+ // (arbitrary) order the engine returned. Simulate the durable collision (two seq-1 rows, distinct
416
+ // ids) AND an adversarial engine that returns them in reverse-id order; the tail must still fall back
417
+ // to the monotonic `id` so replay/audit order is stable — the earlier-inserted (lower-id) row first.
418
+ const now = new Date().toISOString();
419
+ const insert = db.prepare(
420
+ "INSERT INTO world_effects (pr_key, checkpoint_offset, seq, kind, idempotency_key, description, applied, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
421
+ );
422
+ insert.run(PR, 0, 0, "push", "sha-a", null, 1, now);
423
+ insert.run(PR, 0, 1, "pr-comment", "c-first", null, 1, now);
424
+ insert.run(PR, 0, 1, "merge", "m-second", null, 1, now);
425
+ // Decorate the effects Table's `find` to return rows in reverse order, modelling an engine that does
426
+ // not return in insertion order — so a stable seq-only sort would surface the WRONG tie order.
427
+ const realTable = (data as unknown as { table: (n: string, pk?: string) => Record<string, unknown> }).table.bind(data);
428
+ (data as unknown as { table: (n: string, pk?: string) => Record<string, unknown> }).table = (n: string, pk?: string) => {
429
+ const t = realTable(n, pk);
430
+ if (n === "world_effects") {
431
+ const realFind = (t.find as (q: unknown) => Promise<unknown[]>).bind(t);
432
+ t.find = async (q: unknown) => (await realFind(q)).slice().reverse();
433
+ }
434
+ return t;
435
+ };
436
+ const store = new WorldStore(data);
437
+ const tail = await store.effectTail(PR, 0);
438
+ assertEquals(
439
+ tail.map((e) => e.idempotencyKey),
440
+ ["sha-a", "c-first", "m-second"],
441
+ "the seq-1 tie is broken by ascending id — the earlier-inserted row replays first, regardless of return order",
442
+ );
443
+ });