Skip to content

Commit 9886a8e

Browse files
authored
fix server tests on Node 22.14 (#121)
1 parent 89c4c95 commit 9886a8e

8 files changed

Lines changed: 349 additions & 219 deletions

File tree

.github/actions/setup/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ runs:
1212
- name: Setup Node.js
1313
uses: actions/setup-node@v4
1414
with:
15-
node-version: 22
15+
node-version: "22.14.0"
1616
cache: npm
1717

1818
- name: Install dependencies
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"id": "traj_e3imqupgb81i",
3+
"version": 1,
4+
"task": {
5+
"title": "Fix server tests failing on Node SQLite fake D1"
6+
},
7+
"status": "completed",
8+
"startedAt": "2026-04-17T09:19:06.767Z",
9+
"agents": [
10+
{
11+
"name": "default",
12+
"role": "lead",
13+
"joinedAt": "2026-04-17T09:31:18.022Z"
14+
}
15+
],
16+
"chapters": [
17+
{
18+
"id": "chap_4cnnppxyienx",
19+
"title": "Work",
20+
"agentName": "default",
21+
"startedAt": "2026-04-17T09:31:18.022Z",
22+
"events": [
23+
{
24+
"ts": 1776418278023,
25+
"type": "decision",
26+
"content": "Centralized fake D1 test harness with Node 22.14 compatibility: Centralized fake D1 test harness with Node 22.14 compatibility",
27+
"raw": {
28+
"question": "Centralized fake D1 test harness with Node 22.14 compatibility",
29+
"chosen": "Centralized fake D1 test harness with Node 22.14 compatibility",
30+
"alternatives": [],
31+
"reasoning": "The failing suites duplicated a fake D1 implementation that assumed node:sqlite setReturnArrays and FTS5. A shared helper keeps Drizzle raw row mapping and directory FTS fallback consistent across directory, routing, and workspace engine tests."
32+
},
33+
"significance": "high"
34+
},
35+
{
36+
"ts": 1776418278212,
37+
"type": "decision",
38+
"content": "Pinned shared CI setup to Node 22.14.0: Pinned shared CI setup to Node 22.14.0",
39+
"raw": {
40+
"question": "Pinned shared CI setup to Node 22.14.0",
41+
"chosen": "Pinned shared CI setup to Node 22.14.0",
42+
"alternatives": [],
43+
"reasoning": "Publish workflow is pinned to Node 22.14.0 while CI used floating Node 22, so PR CI could run on a newer patch with SQLite FTS5 and setReturnArrays and miss publish failures."
44+
},
45+
"significance": "high"
46+
}
47+
],
48+
"endedAt": "2026-04-17T09:31:22.324Z"
49+
}
50+
],
51+
"commits": [],
52+
"filesChanged": [],
53+
"projectId": "/Users/khaliqgant/Projects/AgentWorkforce/relaycast",
54+
"tags": [],
55+
"_trace": {
56+
"startRef": "89c4c95c83629858e29ec5a6d15b9751d5a9e4d0",
57+
"endRef": "89c4c95c83629858e29ec5a6d15b9751d5a9e4d0"
58+
},
59+
"completedAt": "2026-04-17T09:31:22.324Z",
60+
"retrospective": {
61+
"summary": "Fixed Node 22.14 server test failures by centralizing fake D1, adding raw array compatibility and FTS fallback, and pinning shared CI setup to publish Node version.",
62+
"approach": "Standard approach",
63+
"confidence": 0.9
64+
}
65+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Trajectory: Fix server tests failing on Node SQLite fake D1
2+
3+
> **Status:** ✅ Completed
4+
> **Confidence:** 90%
5+
> **Started:** April 17, 2026 at 11:19 AM
6+
> **Completed:** April 17, 2026 at 11:31 AM
7+
8+
---
9+
10+
## Summary
11+
12+
Fixed Node 22.14 server test failures by centralizing fake D1, adding raw array compatibility and FTS fallback, and pinning shared CI setup to publish Node version.
13+
14+
**Approach:** Standard approach
15+
16+
---
17+
18+
## Key Decisions
19+
20+
### Centralized fake D1 test harness with Node 22.14 compatibility
21+
- **Chose:** Centralized fake D1 test harness with Node 22.14 compatibility
22+
- **Reasoning:** The failing suites duplicated a fake D1 implementation that assumed node:sqlite setReturnArrays and FTS5. A shared helper keeps Drizzle raw row mapping and directory FTS fallback consistent across directory, routing, and workspace engine tests.
23+
24+
### Pinned shared CI setup to Node 22.14.0
25+
- **Chose:** Pinned shared CI setup to Node 22.14.0
26+
- **Reasoning:** Publish workflow is pinned to Node 22.14.0 while CI used floating Node 22, so PR CI could run on a newer patch with SQLite FTS5 and setReturnArrays and miss publish failures.
27+
28+
---
29+
30+
## Chapters
31+
32+
### 1. Work
33+
*Agent: default*
34+
35+
- Centralized fake D1 test harness with Node 22.14 compatibility: Centralized fake D1 test harness with Node 22.14 compatibility
36+
- Pinned shared CI setup to Node 22.14.0: Pinned shared CI setup to Node 22.14.0

.trajectories/index.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"version": 1,
3-
"lastUpdated": "2026-03-26T11:01:41.987Z",
3+
"lastUpdated": "2026-04-17T09:31:22.420Z",
44
"trajectories": {
55
"traj_o8g8ahqth5fx": {
66
"title": "Wave 0: add repo infrastructure files (docker, turbo, tsconfig, env)",
@@ -1043,6 +1043,13 @@
10431043
"startedAt": "2026-03-26T10:59:34.609Z",
10441044
"completedAt": "2026-03-26T11:01:41.853Z",
10451045
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relaycast/.trajectories/completed/2026-03/traj_m2i8kuknj3d7.json"
1046+
},
1047+
"traj_e3imqupgb81i": {
1048+
"title": "Fix server tests failing on Node SQLite fake D1",
1049+
"status": "completed",
1050+
"startedAt": "2026-04-17T09:19:06.767Z",
1051+
"completedAt": "2026-04-17T09:31:22.324Z",
1052+
"path": "/Users/khaliqgant/Projects/AgentWorkforce/relaycast/.trajectories/completed/2026-04/traj_e3imqupgb81i.json"
10461053
}
10471054
}
10481055
}

packages/server/src/__tests__/directory.test.ts

Lines changed: 13 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
import { DatabaseSync } from 'node:sqlite';
2-
import { drizzle } from 'drizzle-orm/d1';
31
import { beforeEach, describe, expect, it, vi } from 'vitest';
42
import * as schema from '../db/schema.js';
3+
import { createD1TestDb } from './fake-d1.js';
54
import {
65
createDirectoryAgent,
76
listDirectoryAgents,
87
listDirectoryRatings,
98
searchDirectory,
109
upsertDirectoryRating,
1110
} from '../engine/directory.js';
12-
import { buildFtsQuery } from '../engine/searchQuery.js';
1311

1412
const TEST_SCHEMA_SQL = `
1513
PRAGMA foreign_keys = ON;
@@ -168,71 +166,8 @@ AFTER DELETE ON directory_skills BEGIN
168166
END;
169167
`;
170168

171-
class FakeD1PreparedStatement {
172-
private readonly sqlite: DatabaseSync;
173-
private readonly query: string;
174-
private readonly params: unknown[];
175-
176-
constructor(sqlite: DatabaseSync, query: string, params: unknown[] = []) {
177-
this.sqlite = sqlite;
178-
this.query = query;
179-
this.params = params;
180-
}
181-
182-
bind(...params: unknown[]) {
183-
return new FakeD1PreparedStatement(this.sqlite, this.query, params);
184-
}
185-
186-
async run() {
187-
this.sqlite.prepare(this.query).run(...this.params);
188-
return { success: true, meta: {}, results: [] };
189-
}
190-
191-
async all() {
192-
return {
193-
success: true,
194-
meta: {},
195-
results: this.sqlite.prepare(this.query).all(...this.params),
196-
};
197-
}
198-
199-
async raw() {
200-
const statement = this.sqlite.prepare(this.query);
201-
statement.setReturnArrays(true);
202-
return statement.all(...this.params);
203-
}
204-
205-
async first() {
206-
return this.sqlite.prepare(this.query).get(...this.params);
207-
}
208-
}
209-
210-
class FakeD1Database {
211-
readonly sqlite = new DatabaseSync(':memory:');
212-
213-
constructor() {
214-
this.sqlite.exec(TEST_SCHEMA_SQL);
215-
}
216-
217-
prepare(query: string) {
218-
return new FakeD1PreparedStatement(this.sqlite, query);
219-
}
220-
221-
async batch(statements: Array<FakeD1PreparedStatement>) {
222-
return Promise.all(statements.map((statement) => statement.all()));
223-
}
224-
225-
async exec(query: string) {
226-
this.sqlite.exec(query);
227-
}
228-
}
229-
230169
function createTestDb() {
231-
const d1 = new FakeD1Database();
232-
return {
233-
db: drizzle(d1 as unknown as D1Database, { schema }),
234-
sqlite: d1.sqlite,
235-
};
170+
return createD1TestDb(TEST_SCHEMA_SQL);
236171
}
237172

238173
async function seedWorkspace(db: ReturnType<typeof createTestDb>['db']) {
@@ -343,8 +278,8 @@ describe('directory engine', () => {
343278
expect(ratedEntries[0]?.rating_avg).toBe(4);
344279
});
345280

346-
it('matches FTS5 queries across skills and agent descriptions', async () => {
347-
const { db, sqlite } = createTestDb();
281+
it('matches search queries across skills and agent descriptions', async () => {
282+
const { db } = createTestDb();
348283
await seedWorkspace(db);
349284
await seedAgent(db, { id: 'agent_research', name: 'ResearchBot' });
350285
await seedAgent(db, { id: 'agent_support', name: 'SupportBot' });
@@ -381,25 +316,14 @@ describe('directory engine', () => {
381316
],
382317
});
383318

384-
const skillQuery = buildFtsQuery('entity extraction pipelines');
385-
const skillMatchRows = sqlite.prepare(`
386-
SELECT da.slug
387-
FROM directory_skills_fts
388-
JOIN directory_skills ds ON ds.rowid = directory_skills_fts.rowid
389-
JOIN directory_agents da ON da.id = ds.directory_agent_id
390-
WHERE directory_skills_fts MATCH ?
391-
ORDER BY da.slug ASC
392-
`).all(skillQuery) as Array<{ slug: string }>;
393-
expect(skillMatchRows.map((row) => row.slug)).toContain('researchbot');
394-
395-
const descriptionQuery = buildFtsQuery('subscription billing specialist');
396-
const descriptionMatchRows = sqlite.prepare(`
397-
SELECT da.slug
398-
FROM directory_agents_fts
399-
JOIN directory_agents da ON da.rowid = directory_agents_fts.rowid
400-
WHERE directory_agents_fts MATCH ?
401-
ORDER BY da.slug ASC
402-
`).all(descriptionQuery) as Array<{ slug: string }>;
403-
expect(descriptionMatchRows.map((row) => row.slug)).toContain('supportbot');
319+
const skillResults = await searchDirectory(db, 'ws_test', {
320+
q: 'entity extraction pipelines',
321+
});
322+
expect(skillResults.map((row) => row.slug)).toContain('researchbot');
323+
324+
const descriptionResults = await searchDirectory(db, 'ws_test', {
325+
q: 'subscription billing specialist',
326+
});
327+
expect(descriptionResults.map((row) => row.slug)).toContain('supportbot');
404328
});
405329
});

0 commit comments

Comments
 (0)