@namzu/sdk 14.0.1 → 14.0.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## 14.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 9e03c89: `InMemoryTaskStore.block()` stops announcing an edge that already existed.
8
+
9
+ The two task stores disagreed about what `task.updated` means. `block()` is
10
+ idempotent on both — each guards its array against a duplicate entry — but only
11
+ the disk store guarded the _announcement_. Calling `block(a, b)` twice emitted
12
+ two `task.updated` events from the in-memory store and one from the disk store,
13
+ which is the one a host runs in production.
14
+
15
+ So a host rebuilding a dependency graph from the event stream did redundant
16
+ work against the reference implementation and not the durable one, and a host
17
+ counting events to detect change saw change where there was none. The
18
+ divergence is the kind that stays invisible until a store is swapped.
19
+
20
+ The disk store's behaviour was already correct and is now the behaviour of
21
+ both. No event is lost: a call that establishes a new edge — including one that
22
+ repairs a half-edge, where only one of the two arrays grows — still announces
23
+ both ends, because both ends are one fact.
24
+
25
+ The disk store's side of this had no test, which is why the disagreement
26
+ survived. Both are now driven from the same cases.
27
+
3
28
  ## 14.0.1
4
29
 
5
30
  ### Patch Changes
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=an-edge-that-already-exists-is-not-news.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"an-edge-that-already-exists-is-not-news.test.d.ts","sourceRoot":"","sources":["../../../../src/store/task/__tests__/an-edge-that-already-exists-is-not-news.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,95 @@
1
+ import { mkdtemp, rm } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { afterEach, describe, expect, it } from 'vitest';
5
+ import { DiskTaskStore } from '../disk.js';
6
+ import { InMemoryTaskStore } from '../memory.js';
7
+ /**
8
+ * The two stores disagreed about what `task.updated` means.
9
+ *
10
+ * `block()` is idempotent on both — it guards each array against a duplicate
11
+ * entry — but only the disk store guarded the *announcement*. Calling
12
+ * `block(a, b)` twice emitted two `task.updated` events from the in-memory
13
+ * store and one from the disk store, which is the one a host runs in
14
+ * production. So a host rebuilding a dependency graph from the stream did
15
+ * redundant work against the reference implementation and not the durable one,
16
+ * and a host counting events to detect change saw change where there was none.
17
+ *
18
+ * The disk store's behaviour is the correct one and the in-memory store now
19
+ * matches it: an edge that already existed is not news.
20
+ *
21
+ * Both are driven from the same cases here, because a reference implementation
22
+ * that disagrees with the durable one is worse than having only one — the
23
+ * disagreement is invisible until a host swaps stores in production.
24
+ */
25
+ const RUN = 'run_edge';
26
+ const dirs = [];
27
+ afterEach(async () => {
28
+ await Promise.all(dirs.map((d) => rm(d, { recursive: true, force: true })));
29
+ dirs.length = 0;
30
+ });
31
+ async function diskStore() {
32
+ const dir = await mkdtemp(join(tmpdir(), 'namzu-edge-'));
33
+ dirs.push(dir);
34
+ return new DiskTaskStore({ baseDir: dir, defaultRunId: RUN });
35
+ }
36
+ const IMPLEMENTATIONS = [
37
+ ['in memory', async () => new InMemoryTaskStore()],
38
+ ['on disk', diskStore],
39
+ ];
40
+ describe.each(IMPLEMENTATIONS)('an edge that already exists is not news (%s)', (_n, build) => {
41
+ async function twoTasks(store) {
42
+ const blocker = await store.create({ runId: RUN, subject: 'blocker' });
43
+ const blocked = await store.create({ runId: RUN, subject: 'blocked' });
44
+ return { blocker, blocked };
45
+ }
46
+ function recordUpdates(store) {
47
+ const seen = [];
48
+ store.on((event) => {
49
+ if (event.type === 'task.updated')
50
+ seen.push(event);
51
+ });
52
+ return seen;
53
+ }
54
+ it('announces both ends when the edge is written', async () => {
55
+ // The control: without it, "no second announcement" could be passing
56
+ // because nothing announces at all.
57
+ const store = await build();
58
+ const { blocker, blocked } = await twoTasks(store);
59
+ const seen = recordUpdates(store);
60
+ await store.block(blocker.id, blocked.id);
61
+ expect(seen.map((e) => e.taskId)).toEqual([blocker.id, blocked.id]);
62
+ });
63
+ it('says nothing the second time', async () => {
64
+ const store = await build();
65
+ const { blocker, blocked } = await twoTasks(store);
66
+ await store.block(blocker.id, blocked.id);
67
+ const seen = recordUpdates(store);
68
+ await store.block(blocker.id, blocked.id);
69
+ expect(seen).toEqual([]);
70
+ });
71
+ it('still records the edge exactly once after a repeated call', async () => {
72
+ // Suppressing the event must not become suppressing the write, and the
73
+ // arrays must not grow a duplicate.
74
+ const store = await build();
75
+ const { blocker, blocked } = await twoTasks(store);
76
+ await store.block(blocker.id, blocked.id);
77
+ await store.block(blocker.id, blocked.id);
78
+ expect((await store.get(blocker.id))?.blocks).toEqual([blocked.id]);
79
+ expect((await store.get(blocked.id))?.blockedBy).toEqual([blocker.id]);
80
+ });
81
+ it('announces a repair when only one side of the edge was missing', async () => {
82
+ // A half-edge is the case the early return must not swallow: one array
83
+ // already names the other and its counterpart does not. Both ends are
84
+ // one fact, so both are announced even though only one array grew.
85
+ const store = await build();
86
+ const { blocker, blocked } = await twoTasks(store);
87
+ await store.block(blocker.id, blocked.id);
88
+ // Reverse direction: `blocked` has not yet been recorded as blocking
89
+ // `blocker`, so this is a new edge, not the existing one.
90
+ const seen = recordUpdates(store);
91
+ await store.block(blocked.id, blocker.id);
92
+ expect(seen.map((e) => e.taskId)).toEqual([blocked.id, blocker.id]);
93
+ });
94
+ });
95
+ //# sourceMappingURL=an-edge-that-already-exists-is-not-news.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"an-edge-that-already-exists-is-not-news.test.js","sourceRoot":"","sources":["../../../../src/store/task/__tests__/an-edge-that-already-exists-is-not-news.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/store/task/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,EACX,gBAAgB,EAChB,IAAI,EAEJ,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,MAAM,2BAA2B,CAAA;AAmBlC,qBAAa,iBAAkB,YAAW,SAAS;IAClD,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,SAAS,CAA0B;IAE3C,EAAE,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,IAAI;IAO3C,OAAO,CAAC,IAAI;IAQN,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+B/C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAI1C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAwCxE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsBpC,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,UAAU,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAgBtF,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAc3D,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5B"}
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/store/task/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,EACX,gBAAgB,EAChB,IAAI,EAEJ,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,MAAM,2BAA2B,CAAA;AAmBlC,qBAAa,iBAAkB,YAAW,SAAS;IAClD,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,SAAS,CAA0B;IAE3C,EAAE,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,IAAI;IAO3C,OAAO,CAAC,IAAI;IAQN,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+B/C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAI1C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAwCxE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsBpC,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,UAAU,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAgBtF,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAc3D,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5B"}
@@ -150,17 +150,29 @@ export class InMemoryTaskStore {
150
150
  const blocked = this.tasks.get(blockedId);
151
151
  if (!blocker || !blocked)
152
152
  return;
153
+ let mutated = false;
153
154
  if (!blocker.blocks.includes(blockedId)) {
154
155
  blocker.blocks.push(blockedId);
156
+ mutated = true;
155
157
  }
156
158
  if (!blocked.blockedBy.includes(blockerId)) {
157
159
  blocked.blockedBy.push(blockerId);
160
+ mutated = true;
158
161
  }
162
+ // An edge that already existed is not news. This used to announce
163
+ // unconditionally while the disk store — the one a host runs in
164
+ // production — returned early, so the same call sequence produced two
165
+ // events from one implementation and none from the other. A host
166
+ // rebuilding a graph from the stream did redundant work against one
167
+ // store and not the other, and a host counting events to detect change
168
+ // saw change where there was none.
169
+ if (!mutated)
170
+ return;
159
171
  // Announce BOTH ends. The edge was written and nothing said so, which
160
172
  // left the graph observable only by polling: a listener saw a unit
161
173
  // created and never learned that something now waits on it. Both sides
162
- // changed, so both are announced a host tracking only one would draw
163
- // half the edge.
174
+ // are one fact, so both are announced even when only one array grew —
175
+ // a host tracking a single side would draw half the edge.
164
176
  const now = Date.now();
165
177
  this.emit({ type: 'task.updated', taskId: blockerId, task: blocker, timestamp: now });
166
178
  this.emit({ type: 'task.updated', taskId: blockedId, task: blocked, timestamp: now });
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/store/task/memory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/store/task/memory.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namzu/sdk",
3
- "version": "14.0.1",
3
+ "version": "14.0.2",
4
4
  "description": "Open-source AI agent SDK with a built-in runtime. Nothing between you and your agents.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "type": "module",
@@ -0,0 +1,115 @@
1
+ import { mkdtemp, rm } from 'node:fs/promises'
2
+ import { tmpdir } from 'node:os'
3
+ import { join } from 'node:path'
4
+ import { afterEach, describe, expect, it } from 'vitest'
5
+
6
+ import type { RunId } from '../../../types/ids/index.js'
7
+ import type { TaskEvent, TaskStore } from '../../../types/task/index.js'
8
+ import { DiskTaskStore } from '../disk.js'
9
+ import { InMemoryTaskStore } from '../memory.js'
10
+
11
+ /**
12
+ * The two stores disagreed about what `task.updated` means.
13
+ *
14
+ * `block()` is idempotent on both — it guards each array against a duplicate
15
+ * entry — but only the disk store guarded the *announcement*. Calling
16
+ * `block(a, b)` twice emitted two `task.updated` events from the in-memory
17
+ * store and one from the disk store, which is the one a host runs in
18
+ * production. So a host rebuilding a dependency graph from the stream did
19
+ * redundant work against the reference implementation and not the durable one,
20
+ * and a host counting events to detect change saw change where there was none.
21
+ *
22
+ * The disk store's behaviour is the correct one and the in-memory store now
23
+ * matches it: an edge that already existed is not news.
24
+ *
25
+ * Both are driven from the same cases here, because a reference implementation
26
+ * that disagrees with the durable one is worse than having only one — the
27
+ * disagreement is invisible until a host swaps stores in production.
28
+ */
29
+
30
+ const RUN = 'run_edge' as RunId
31
+
32
+ const dirs: string[] = []
33
+ afterEach(async () => {
34
+ await Promise.all(dirs.map((d) => rm(d, { recursive: true, force: true })))
35
+ dirs.length = 0
36
+ })
37
+
38
+ async function diskStore(): Promise<TaskStore> {
39
+ const dir = await mkdtemp(join(tmpdir(), 'namzu-edge-'))
40
+ dirs.push(dir)
41
+ return new DiskTaskStore({ baseDir: dir, defaultRunId: RUN })
42
+ }
43
+
44
+ const IMPLEMENTATIONS: ReadonlyArray<readonly [string, () => Promise<TaskStore>]> = [
45
+ ['in memory', async () => new InMemoryTaskStore()],
46
+ ['on disk', diskStore],
47
+ ]
48
+
49
+ describe.each(IMPLEMENTATIONS)('an edge that already exists is not news (%s)', (_n, build) => {
50
+ async function twoTasks(store: TaskStore) {
51
+ const blocker = await store.create({ runId: RUN, subject: 'blocker' })
52
+ const blocked = await store.create({ runId: RUN, subject: 'blocked' })
53
+ return { blocker, blocked }
54
+ }
55
+
56
+ function recordUpdates(store: TaskStore): TaskEvent[] {
57
+ const seen: TaskEvent[] = []
58
+ store.on((event) => {
59
+ if (event.type === 'task.updated') seen.push(event)
60
+ })
61
+ return seen
62
+ }
63
+
64
+ it('announces both ends when the edge is written', async () => {
65
+ // The control: without it, "no second announcement" could be passing
66
+ // because nothing announces at all.
67
+ const store = await build()
68
+ const { blocker, blocked } = await twoTasks(store)
69
+ const seen = recordUpdates(store)
70
+
71
+ await store.block(blocker.id, blocked.id)
72
+
73
+ expect(seen.map((e) => e.taskId)).toEqual([blocker.id, blocked.id])
74
+ })
75
+
76
+ it('says nothing the second time', async () => {
77
+ const store = await build()
78
+ const { blocker, blocked } = await twoTasks(store)
79
+ await store.block(blocker.id, blocked.id)
80
+ const seen = recordUpdates(store)
81
+
82
+ await store.block(blocker.id, blocked.id)
83
+
84
+ expect(seen).toEqual([])
85
+ })
86
+
87
+ it('still records the edge exactly once after a repeated call', async () => {
88
+ // Suppressing the event must not become suppressing the write, and the
89
+ // arrays must not grow a duplicate.
90
+ const store = await build()
91
+ const { blocker, blocked } = await twoTasks(store)
92
+
93
+ await store.block(blocker.id, blocked.id)
94
+ await store.block(blocker.id, blocked.id)
95
+
96
+ expect((await store.get(blocker.id))?.blocks).toEqual([blocked.id])
97
+ expect((await store.get(blocked.id))?.blockedBy).toEqual([blocker.id])
98
+ })
99
+
100
+ it('announces a repair when only one side of the edge was missing', async () => {
101
+ // A half-edge is the case the early return must not swallow: one array
102
+ // already names the other and its counterpart does not. Both ends are
103
+ // one fact, so both are announced even though only one array grew.
104
+ const store = await build()
105
+ const { blocker, blocked } = await twoTasks(store)
106
+ await store.block(blocker.id, blocked.id)
107
+ // Reverse direction: `blocked` has not yet been recorded as blocking
108
+ // `blocker`, so this is a new edge, not the existing one.
109
+ const seen = recordUpdates(store)
110
+
111
+ await store.block(blocked.id, blocker.id)
112
+
113
+ expect(seen.map((e) => e.taskId)).toEqual([blocked.id, blocker.id])
114
+ })
115
+ })
@@ -177,18 +177,29 @@ export class InMemoryTaskStore implements TaskStore {
177
177
  const blocked = this.tasks.get(blockedId)
178
178
  if (!blocker || !blocked) return
179
179
 
180
+ let mutated = false
180
181
  if (!blocker.blocks.includes(blockedId)) {
181
182
  blocker.blocks.push(blockedId)
183
+ mutated = true
182
184
  }
183
185
  if (!blocked.blockedBy.includes(blockerId)) {
184
186
  blocked.blockedBy.push(blockerId)
187
+ mutated = true
185
188
  }
189
+ // An edge that already existed is not news. This used to announce
190
+ // unconditionally while the disk store — the one a host runs in
191
+ // production — returned early, so the same call sequence produced two
192
+ // events from one implementation and none from the other. A host
193
+ // rebuilding a graph from the stream did redundant work against one
194
+ // store and not the other, and a host counting events to detect change
195
+ // saw change where there was none.
196
+ if (!mutated) return
186
197
 
187
198
  // Announce BOTH ends. The edge was written and nothing said so, which
188
199
  // left the graph observable only by polling: a listener saw a unit
189
200
  // created and never learned that something now waits on it. Both sides
190
- // changed, so both are announced a host tracking only one would draw
191
- // half the edge.
201
+ // are one fact, so both are announced even when only one array grew —
202
+ // a host tracking a single side would draw half the edge.
192
203
  const now = Date.now()
193
204
  this.emit({ type: 'task.updated', taskId: blockerId, task: blocker, timestamp: now })
194
205
  this.emit({ type: 'task.updated', taskId: blockedId, task: blocked, timestamp: now })