@mclean-capital/neura 3.4.0 → 3.5.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 (44) hide show
  1. package/README.md +8 -0
  2. package/core/server.bundled.mjs +2582 -1145
  3. package/core/server.bundled.mjs.map +4 -4
  4. package/core/version.txt +1 -1
  5. package/dist/commands/install.js +2 -2
  6. package/dist/commands/install.js.map +1 -1
  7. package/dist/commands/skill.d.ts +26 -0
  8. package/dist/commands/skill.d.ts.map +1 -0
  9. package/dist/commands/skill.js +111 -0
  10. package/dist/commands/skill.js.map +1 -0
  11. package/dist/index.js +7 -0
  12. package/dist/index.js.map +1 -1
  13. package/package.json +1 -1
  14. package/stores/index.js +171 -11
  15. package/stores/index.js.map +2 -2
  16. package/stores/mappers.d.ts +27 -3
  17. package/stores/mappers.d.ts.map +1 -1
  18. package/stores/mappers.js +23 -0
  19. package/stores/mappers.js.map +1 -1
  20. package/stores/migrations.d.ts.map +1 -1
  21. package/stores/migrations.js +106 -1
  22. package/stores/migrations.js.map +1 -1
  23. package/stores/migrations.test.d.ts +14 -0
  24. package/stores/migrations.test.d.ts.map +1 -0
  25. package/stores/migrations.test.js +164 -0
  26. package/stores/migrations.test.js.map +1 -0
  27. package/stores/pglite-store.d.ts +5 -7
  28. package/stores/pglite-store.d.ts.map +1 -1
  29. package/stores/pglite-store.js +2 -2
  30. package/stores/pglite-store.js.map +1 -1
  31. package/stores/pglite-store.test.js +110 -0
  32. package/stores/pglite-store.test.js.map +1 -1
  33. package/stores/task-comment-queries.d.ts +55 -0
  34. package/stores/task-comment-queries.d.ts.map +1 -0
  35. package/stores/task-comment-queries.js +98 -0
  36. package/stores/task-comment-queries.js.map +1 -0
  37. package/stores/task-comment-queries.test.d.ts +8 -0
  38. package/stores/task-comment-queries.test.d.ts.map +1 -0
  39. package/stores/task-comment-queries.test.js +321 -0
  40. package/stores/task-comment-queries.test.js.map +1 -0
  41. package/stores/work-item-queries.d.ts +47 -2
  42. package/stores/work-item-queries.d.ts.map +1 -1
  43. package/stores/work-item-queries.js +79 -6
  44. package/stores/work-item-queries.js.map +1 -1
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Tests for task-comment-queries.ts — the Phase 6b comments CRUD.
3
+ *
4
+ * Uses an in-memory PGlite via the PgliteStore facade. Comments are tied to
5
+ * a work_item (FK CASCADE), so every test creates a parent task first.
6
+ */
7
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
8
+ import { PGlite } from '@electric-sql/pglite';
9
+ import { vector } from '@electric-sql/pglite/vector';
10
+ import crypto from 'crypto';
11
+ import { runMigrations } from './migrations.js';
12
+ import { insertComment, listComments, pruneHeartbeats, countOpenRequests, TASK_COMMENT_CONTENT_MAX_BYTES, } from './task-comment-queries.js';
13
+ describe('task-comment-queries', () => {
14
+ let db;
15
+ let taskId;
16
+ beforeEach(async () => {
17
+ db = await PGlite.create({ extensions: { vector } });
18
+ await runMigrations(db);
19
+ // Seed a work_item to anchor comments to.
20
+ taskId = crypto.randomUUID();
21
+ await db.query(`INSERT INTO work_items (id, title, priority) VALUES ($1, $2, $3)`, [
22
+ taskId,
23
+ 'Test task',
24
+ 'medium',
25
+ ]);
26
+ });
27
+ afterEach(async () => {
28
+ await db.close();
29
+ });
30
+ describe('insertComment', () => {
31
+ it('inserts a progress comment and returns the entry', async () => {
32
+ const comment = await insertComment(db, {
33
+ taskId,
34
+ type: 'progress',
35
+ author: 'worker:abc-123',
36
+ content: 'Halfway done',
37
+ });
38
+ expect(comment.taskId).toBe(taskId);
39
+ expect(comment.type).toBe('progress');
40
+ expect(comment.author).toBe('worker:abc-123');
41
+ expect(comment.content).toBe('Halfway done');
42
+ expect(comment.urgency).toBeNull();
43
+ expect(comment.metadata).toBeNull();
44
+ expect(comment.attachmentPath).toBeNull();
45
+ expect(comment.createdAt).toBeTruthy();
46
+ });
47
+ it('inserts a clarification_request with urgency + metadata', async () => {
48
+ const comment = await insertComment(db, {
49
+ taskId,
50
+ type: 'clarification_request',
51
+ author: 'worker:abc-123',
52
+ content: 'Which branch should I push to?',
53
+ urgency: 'high',
54
+ metadata: { topic: 'git-branch-selection' },
55
+ });
56
+ expect(comment.type).toBe('clarification_request');
57
+ expect(comment.urgency).toBe('high');
58
+ expect(comment.metadata).toEqual({ topic: 'git-branch-selection' });
59
+ });
60
+ it('supports attachment_path for overflow content', async () => {
61
+ const comment = await insertComment(db, {
62
+ taskId,
63
+ type: 'error',
64
+ author: 'worker:abc-123',
65
+ content: 'Traceback summary (first 10 lines)…',
66
+ attachmentPath: '/tmp/worker/abc-123/_attachments/traceback-1.txt',
67
+ });
68
+ expect(comment.attachmentPath).toBe('/tmp/worker/abc-123/_attachments/traceback-1.txt');
69
+ });
70
+ it('rejects content exceeding the 32 KB cap', async () => {
71
+ const big = 'a'.repeat(TASK_COMMENT_CONTENT_MAX_BYTES + 1);
72
+ await expect(insertComment(db, { taskId, type: 'progress', author: 'worker:1', content: big })).rejects.toThrow(/exceeds/);
73
+ });
74
+ it('accepts content exactly at the 32 KB cap', async () => {
75
+ const exact = 'a'.repeat(TASK_COMMENT_CONTENT_MAX_BYTES);
76
+ const comment = await insertComment(db, {
77
+ taskId,
78
+ type: 'progress',
79
+ author: 'worker:1',
80
+ content: exact,
81
+ });
82
+ expect(Buffer.byteLength(comment.content)).toBe(TASK_COMMENT_CONTENT_MAX_BYTES);
83
+ });
84
+ it('rejects insertion for an unknown task_id (FK enforced)', async () => {
85
+ await expect(insertComment(db, {
86
+ taskId: 'does-not-exist',
87
+ type: 'progress',
88
+ author: 'worker:1',
89
+ content: 'orphan',
90
+ })).rejects.toThrow();
91
+ });
92
+ });
93
+ describe('listComments', () => {
94
+ it('returns comments in chronological order', async () => {
95
+ await insertComment(db, {
96
+ taskId,
97
+ type: 'progress',
98
+ author: 'worker:1',
99
+ content: 'first',
100
+ });
101
+ // Small delay so timestamps differ enough for ordering
102
+ await new Promise((r) => setTimeout(r, 5));
103
+ await insertComment(db, {
104
+ taskId,
105
+ type: 'progress',
106
+ author: 'worker:1',
107
+ content: 'second',
108
+ });
109
+ await new Promise((r) => setTimeout(r, 5));
110
+ await insertComment(db, {
111
+ taskId,
112
+ type: 'progress',
113
+ author: 'worker:1',
114
+ content: 'third',
115
+ });
116
+ const comments = await listComments(db, { taskId });
117
+ expect(comments).toHaveLength(3);
118
+ expect(comments[0].content).toBe('first');
119
+ expect(comments[1].content).toBe('second');
120
+ expect(comments[2].content).toBe('third');
121
+ });
122
+ it('filters by single comment type', async () => {
123
+ await insertComment(db, {
124
+ taskId,
125
+ type: 'progress',
126
+ author: 'worker:1',
127
+ content: 'p',
128
+ });
129
+ await insertComment(db, {
130
+ taskId,
131
+ type: 'clarification_request',
132
+ author: 'worker:1',
133
+ content: 'q',
134
+ });
135
+ await insertComment(db, {
136
+ taskId,
137
+ type: 'result',
138
+ author: 'worker:1',
139
+ content: 'done',
140
+ });
141
+ const requests = await listComments(db, { taskId, type: 'clarification_request' });
142
+ expect(requests).toHaveLength(1);
143
+ expect(requests[0].content).toBe('q');
144
+ });
145
+ it('filters by multiple comment types', async () => {
146
+ await insertComment(db, {
147
+ taskId,
148
+ type: 'progress',
149
+ author: 'worker:1',
150
+ content: 'p',
151
+ });
152
+ await insertComment(db, {
153
+ taskId,
154
+ type: 'clarification_request',
155
+ author: 'worker:1',
156
+ content: 'q',
157
+ });
158
+ await insertComment(db, {
159
+ taskId,
160
+ type: 'approval_request',
161
+ author: 'worker:1',
162
+ content: 'a',
163
+ });
164
+ const requests = await listComments(db, {
165
+ taskId,
166
+ type: ['clarification_request', 'approval_request'],
167
+ });
168
+ expect(requests).toHaveLength(2);
169
+ });
170
+ it('respects limit', async () => {
171
+ for (let i = 0; i < 5; i++) {
172
+ await insertComment(db, {
173
+ taskId,
174
+ type: 'progress',
175
+ author: 'worker:1',
176
+ content: `msg ${i}`,
177
+ });
178
+ }
179
+ const limited = await listComments(db, { taskId, limit: 3 });
180
+ expect(limited).toHaveLength(3);
181
+ });
182
+ it('cascades delete when parent task is deleted', async () => {
183
+ await insertComment(db, {
184
+ taskId,
185
+ type: 'progress',
186
+ author: 'worker:1',
187
+ content: 'orphan-to-be',
188
+ });
189
+ await db.query('DELETE FROM work_items WHERE id = $1', [taskId]);
190
+ const comments = await listComments(db, { taskId });
191
+ expect(comments).toHaveLength(0);
192
+ });
193
+ });
194
+ describe('pruneHeartbeats', () => {
195
+ it('deletes only heartbeat comments from the named author', async () => {
196
+ await insertComment(db, {
197
+ taskId,
198
+ type: 'heartbeat',
199
+ author: 'worker:alpha',
200
+ content: 'alive',
201
+ });
202
+ await insertComment(db, {
203
+ taskId,
204
+ type: 'heartbeat',
205
+ author: 'worker:alpha',
206
+ content: 'still alive',
207
+ });
208
+ await insertComment(db, {
209
+ taskId,
210
+ type: 'heartbeat',
211
+ author: 'worker:beta',
212
+ content: 'unrelated',
213
+ });
214
+ await insertComment(db, {
215
+ taskId,
216
+ type: 'progress',
217
+ author: 'worker:alpha',
218
+ content: 'keep-me',
219
+ });
220
+ const pruned = await pruneHeartbeats(db, taskId, 'worker:alpha');
221
+ expect(pruned).toBe(2);
222
+ const remaining = await listComments(db, { taskId });
223
+ expect(remaining).toHaveLength(2);
224
+ expect(remaining.some((c) => c.author === 'worker:beta' && c.type === 'heartbeat')).toBe(true);
225
+ expect(remaining.some((c) => c.author === 'worker:alpha' && c.type === 'progress')).toBe(true);
226
+ });
227
+ });
228
+ describe('countOpenRequests', () => {
229
+ it('counts unresolved clarification_request + approval_request comments', async () => {
230
+ await insertComment(db, {
231
+ taskId,
232
+ type: 'clarification_request',
233
+ author: 'worker:1',
234
+ content: 'q1',
235
+ });
236
+ await insertComment(db, {
237
+ taskId,
238
+ type: 'approval_request',
239
+ author: 'worker:1',
240
+ content: 'approve?',
241
+ });
242
+ expect(await countOpenRequests(db, taskId)).toBe(2);
243
+ });
244
+ it('excludes requests with a matching response comment', async () => {
245
+ const clarifyReq = await insertComment(db, {
246
+ taskId,
247
+ type: 'clarification_request',
248
+ author: 'worker:1',
249
+ content: 'q1',
250
+ });
251
+ await insertComment(db, {
252
+ taskId,
253
+ type: 'clarification_response',
254
+ author: 'orchestrator',
255
+ content: 'use main',
256
+ metadata: { resolves_comment_id: clarifyReq.id },
257
+ });
258
+ expect(await countOpenRequests(db, taskId)).toBe(0);
259
+ });
260
+ it('returns 0 on a task with no comments at all', async () => {
261
+ expect(await countOpenRequests(db, taskId)).toBe(0);
262
+ });
263
+ it('ignores orchestrator responses that point at a nonexistent request id', async () => {
264
+ await insertComment(db, {
265
+ taskId,
266
+ type: 'clarification_request',
267
+ author: 'worker:1',
268
+ content: 'real question',
269
+ });
270
+ // A malformed response that points at an id that doesn't exist on
271
+ // this task (e.g. from a prior session or a bug). Must not
272
+ // accidentally "resolve" the unrelated real request.
273
+ await insertComment(db, {
274
+ taskId,
275
+ type: 'clarification_response',
276
+ author: 'orchestrator',
277
+ content: 'dangling answer',
278
+ metadata: { resolves_comment_id: crypto.randomUUID() },
279
+ });
280
+ expect(await countOpenRequests(db, taskId)).toBe(1);
281
+ });
282
+ it('scopes resolution lookup to the current task — cross-task response ids do not resolve', async () => {
283
+ // Create a second task with its own request + response.
284
+ const otherTaskId = crypto.randomUUID();
285
+ await db.query(`INSERT INTO work_items (id, title, priority) VALUES ($1, $2, $3)`, [
286
+ otherTaskId,
287
+ 'Other task',
288
+ 'medium',
289
+ ]);
290
+ const otherReq = await insertComment(db, {
291
+ taskId: otherTaskId,
292
+ type: 'clarification_request',
293
+ author: 'worker:other',
294
+ content: 'other question',
295
+ });
296
+ // On our original task, have a request and then a malformed response
297
+ // that references the OTHER task's request id.
298
+ await insertComment(db, {
299
+ taskId,
300
+ type: 'clarification_request',
301
+ author: 'worker:1',
302
+ content: 'q1',
303
+ });
304
+ await insertComment(db, {
305
+ taskId,
306
+ type: 'clarification_response',
307
+ author: 'orchestrator',
308
+ content: 'cross-task leak attempt',
309
+ metadata: { resolves_comment_id: otherReq.id },
310
+ });
311
+ // The original task's request should still count as open.
312
+ // (countOpenRequests's subquery scopes to task_id = $1, so the
313
+ // cross-task response is invisible.)
314
+ expect(await countOpenRequests(db, taskId)).toBe(1);
315
+ // The other task's request should also still be open — the only
316
+ // response in the system references it from the wrong task.
317
+ expect(await countOpenRequests(db, otherTaskId)).toBe(1);
318
+ });
319
+ });
320
+ });
321
+ //# sourceMappingURL=task-comment-queries.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-comment-queries.test.js","sourceRoot":"","sources":["../../src/stores/task-comment-queries.test.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { PGlite } from '@electric-sql/pglite';
2
- import type { WorkItemEntry, WorkItemPriority } from '@neura/types';
2
+ import type { TaskContext, TaskSource, WorkItemEntry, WorkItemPriority, WorkItemStatus } from '@neura/types';
3
3
  export declare function getOpenWorkItems(db: PGlite, limit?: number): Promise<WorkItemEntry[]>;
4
4
  export declare function getWorkItems(db: PGlite, options?: {
5
5
  status?: string;
@@ -11,7 +11,52 @@ export declare function createWorkItem(db: PGlite, title: string, priority: Work
11
11
  dueAt?: string;
12
12
  parentId?: string;
13
13
  sourceSessionId?: string;
14
+ goal?: string;
15
+ context?: TaskContext;
16
+ relatedSkills?: string[];
17
+ repoPath?: string;
18
+ baseBranch?: string;
19
+ source?: TaskSource;
14
20
  }): Promise<string>;
15
- export declare function updateWorkItem(db: PGlite, id: string, updates: Partial<Pick<WorkItemEntry, 'status' | 'priority' | 'title' | 'description' | 'dueAt'>>): Promise<void>;
21
+ /**
22
+ * Fields the caller may update via {@link updateWorkItem}. Excludes
23
+ * system-managed columns (version, lease_expires_at, completed_at,
24
+ * updated_at — those are maintained by the DB layer).
25
+ */
26
+ export interface UpdateWorkItemFields {
27
+ status?: WorkItemStatus;
28
+ priority?: WorkItemPriority;
29
+ title?: string;
30
+ description?: string | null;
31
+ dueAt?: string | null;
32
+ goal?: string | null;
33
+ context?: TaskContext | null;
34
+ relatedSkills?: string[];
35
+ repoPath?: string | null;
36
+ baseBranch?: string | null;
37
+ workerId?: string | null;
38
+ leaseExpiresAt?: string | null;
39
+ }
40
+ /**
41
+ * Error thrown when an optimistic-lock version check fails. Caller should
42
+ * re-read the task and decide whether to retry or abort.
43
+ */
44
+ export declare class VersionConflictError extends Error {
45
+ readonly id: string;
46
+ readonly expectedVersion: number;
47
+ constructor(id: string, expectedVersion: number);
48
+ }
49
+ /**
50
+ * Update a work item. Increments `version` on every call. Pass
51
+ * `expectVersion` to enforce optimistic locking — the caller should have
52
+ * read the current version first and pass it here to prevent races
53
+ * between concurrent `update_task` calls (worker + orchestrator).
54
+ *
55
+ * Returns the new version on success. Throws {@link VersionConflictError}
56
+ * if `expectVersion` was supplied and the row's version has moved.
57
+ */
58
+ export declare function updateWorkItem(db: PGlite, id: string, updates: UpdateWorkItemFields, opts?: {
59
+ expectVersion?: number;
60
+ }): Promise<number>;
16
61
  export declare function deleteWorkItem(db: PGlite, id: string): Promise<void>;
17
62
  //# sourceMappingURL=work-item-queries.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"work-item-queries.d.ts","sourceRoot":"","sources":["../../src/stores/work-item-queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKpE,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAwBvF;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,OAAO,CAAC,aAAa,EAAE,CAAC,CA+B1B;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAevF;AAED,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,CAAC,EAAE;IACR,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GACA,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,aAAa,GAAG,OAAO,CAAC,CAAC,GAC/F,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E"}
1
+ {"version":3,"file":"work-item-queries.d.ts","sourceRoot":"","sources":["../../src/stores/work-item-queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,cAAc,EACf,MAAM,cAAc,CAAC;AAKtB,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAYvF;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,OAAO,CAAC,aAAa,EAAE,CAAC,CAmB1B;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAGvF;AAED,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,CAAC,EAAE;IACR,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB,GACA,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;aAE3B,EAAE,EAAE,MAAM;aACV,eAAe,EAAE,MAAM;gBADvB,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,MAAM;CAK1C;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,oBAAoB,EAC7B,IAAI,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAChC,OAAO,CAAC,MAAM,CAAC,CAkFjB;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E"}
@@ -3,7 +3,7 @@ import { mapWorkItem } from './mappers.js';
3
3
  // --- Work items ---
4
4
  export async function getOpenWorkItems(db, limit = 50) {
5
5
  const result = await db.query(`SELECT * FROM work_items
6
- WHERE status IN ('pending', 'in_progress')
6
+ WHERE status IN ('pending', 'awaiting_dispatch', 'in_progress', 'awaiting_clarification', 'awaiting_approval', 'paused')
7
7
  ORDER BY
8
8
  CASE priority WHEN 'high' THEN 0 WHEN 'medium' THEN 1 WHEN 'low' THEN 2 END,
9
9
  due_at ASC NULLS LAST,
@@ -35,8 +35,11 @@ export async function getWorkItem(db, id) {
35
35
  }
36
36
  export async function createWorkItem(db, title, priority, options) {
37
37
  const id = crypto.randomUUID();
38
- await db.query(`INSERT INTO work_items (id, title, priority, description, due_at, parent_id, source_session_id)
39
- VALUES ($1, $2, $3, $4, $5, $6, $7)`, [
38
+ await db.query(`INSERT INTO work_items (
39
+ id, title, priority, description, due_at, parent_id, source_session_id,
40
+ goal, context, related_skills, repo_path, base_branch, source
41
+ )
42
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`, [
40
43
  id,
41
44
  title,
42
45
  priority,
@@ -44,11 +47,40 @@ export async function createWorkItem(db, title, priority, options) {
44
47
  options?.dueAt ?? null,
45
48
  options?.parentId ?? null,
46
49
  options?.sourceSessionId ?? null,
50
+ options?.goal ?? null,
51
+ options?.context ? JSON.stringify(options.context) : null,
52
+ JSON.stringify(options?.relatedSkills ?? []),
53
+ options?.repoPath ?? null,
54
+ options?.baseBranch ?? null,
55
+ options?.source ?? 'user',
47
56
  ]);
48
57
  return id;
49
58
  }
50
- export async function updateWorkItem(db, id, updates) {
51
- const sets = ['updated_at = NOW()'];
59
+ /**
60
+ * Error thrown when an optimistic-lock version check fails. Caller should
61
+ * re-read the task and decide whether to retry or abort.
62
+ */
63
+ export class VersionConflictError extends Error {
64
+ id;
65
+ expectedVersion;
66
+ constructor(id, expectedVersion) {
67
+ super(`version conflict on work_item ${id} (expected ${expectedVersion})`);
68
+ this.id = id;
69
+ this.expectedVersion = expectedVersion;
70
+ this.name = 'VersionConflictError';
71
+ }
72
+ }
73
+ /**
74
+ * Update a work item. Increments `version` on every call. Pass
75
+ * `expectVersion` to enforce optimistic locking — the caller should have
76
+ * read the current version first and pass it here to prevent races
77
+ * between concurrent `update_task` calls (worker + orchestrator).
78
+ *
79
+ * Returns the new version on success. Throws {@link VersionConflictError}
80
+ * if `expectVersion` was supplied and the row's version has moved.
81
+ */
82
+ export async function updateWorkItem(db, id, updates, opts) {
83
+ const sets = ['updated_at = NOW()', 'version = version + 1'];
52
84
  const values = [];
53
85
  let paramIdx = 1;
54
86
  if (updates.title !== undefined) {
@@ -76,8 +108,49 @@ export async function updateWorkItem(db, id, updates) {
76
108
  sets.push(`due_at = $${paramIdx++}`);
77
109
  values.push(updates.dueAt);
78
110
  }
111
+ if (updates.goal !== undefined) {
112
+ sets.push(`goal = $${paramIdx++}`);
113
+ values.push(updates.goal);
114
+ }
115
+ if (updates.context !== undefined) {
116
+ sets.push(`context = $${paramIdx++}`);
117
+ values.push(updates.context === null ? null : JSON.stringify(updates.context));
118
+ }
119
+ if (updates.relatedSkills !== undefined) {
120
+ sets.push(`related_skills = $${paramIdx++}`);
121
+ values.push(JSON.stringify(updates.relatedSkills));
122
+ }
123
+ if (updates.repoPath !== undefined) {
124
+ sets.push(`repo_path = $${paramIdx++}`);
125
+ values.push(updates.repoPath);
126
+ }
127
+ if (updates.baseBranch !== undefined) {
128
+ sets.push(`base_branch = $${paramIdx++}`);
129
+ values.push(updates.baseBranch);
130
+ }
131
+ if (updates.workerId !== undefined) {
132
+ sets.push(`worker_id = $${paramIdx++}`);
133
+ values.push(updates.workerId);
134
+ }
135
+ if (updates.leaseExpiresAt !== undefined) {
136
+ sets.push(`lease_expires_at = $${paramIdx++}`);
137
+ values.push(updates.leaseExpiresAt);
138
+ }
139
+ // Build the WHERE clause — include version guard if provided.
140
+ let whereClause = `WHERE id = $${paramIdx++}`;
79
141
  values.push(id);
80
- await db.query(`UPDATE work_items SET ${sets.join(', ')} WHERE id = $${paramIdx}`, values);
142
+ if (opts?.expectVersion !== undefined) {
143
+ whereClause += ` AND version = $${paramIdx}`;
144
+ values.push(opts.expectVersion);
145
+ }
146
+ const result = await db.query(`UPDATE work_items SET ${sets.join(', ')} ${whereClause} RETURNING version`, values);
147
+ if (result.rows.length === 0) {
148
+ if (opts?.expectVersion !== undefined) {
149
+ throw new VersionConflictError(id, opts.expectVersion);
150
+ }
151
+ throw new Error(`work_item ${id} not found`);
152
+ }
153
+ return result.rows[0].version;
81
154
  }
82
155
  export async function deleteWorkItem(db, id) {
83
156
  await db.query('DELETE FROM work_items WHERE id = $1', [id]);
@@ -1 +1 @@
1
- {"version":3,"file":"work-item-queries.js","sourceRoot":"","sources":["../../src/stores/work-item-queries.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"work-item-queries.js","sourceRoot":"","sources":["../../src/stores/work-item-queries.ts"],"names":[],"mappings":"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"}