Skip to content

Commit d6ed76b

Browse files
committed
sync(bfmono): fix(gambit): address sqlite cutover review regressions (+19 more) (bfmono@4c37237a2)
This PR is an automated gambitmono sync of bfmono Gambit packages. - Source: `packages/gambit/` - Core: `packages/gambit/packages/gambit-core/` - bfmono rev: 4c37237a2 Changes: - 4c37237a2 fix(gambit): address sqlite cutover review regressions - 0a8233b0c fix(gambit): finish sqlite cutover cleanup - 1fee78d0f fix(gambit): show feedback rejection errors in test ui - 3386bf209 chore(gambit): regenerate feedback save graphql artifacts - 2321b92ca fix(gambit): quiet feedback rejection handling - bc574c906 test(gambit): update sqlite cutover test expectations - 7bc9ea312 fix(gambit): restore package exports and lint cleanup - 3a9e5c635 feat(gambit): synthesize chip-only build prompts - 514f34d9b feat(gambit): log workbench build chat payloads - c92f3849b fix(gambit): refresh simulator workspace meta queries - 8734862cb feat(gambit): remove legacy simulator state files - fa6d84f0d feat(gambit): cut simulator storage reads to sqlite - 620167b04 fix(gambit): stabilize scenario transcript ordering - 8cf906fa1 test(gambit): verify sqlite-authoritative simulator reloads - c6f7cc0fa feat(gambit): move simulator runtime authority into workspace sqlite - 0d79fc83e fix(gambit): honor claude workbench provider selection - 48be9821d fix(simulator-ui): make verify description tooltips keyboard accessible - 0ce337e1c feat(gambit-simulator): split verify results into tabs - c496b4cce feat(simulator-ui): streamline verify batch controls - de43c6b8a fix(gambit): keep manual Grade test run selection stable Do not edit this repo directly; make changes in bfmono and re-run the sync.
1 parent ddb03dd commit d6ed76b

2 files changed

Lines changed: 75 additions & 57 deletions

File tree

src/server/workspace/scenario_history.ts

Lines changed: 66 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -95,34 +95,41 @@ export const readPersistedTestRunStatusById = (
9595
if (!sqlitePath) return null;
9696
try {
9797
const db = new DatabaseSync(sqlitePath);
98-
let latest: TestBotRunStatus | null = null;
99-
const rows = db.prepare(
100-
`SELECT payload_json
101-
FROM ${WORKSPACE_EVENTS_SQLITE_TABLE}
102-
WHERE workspace_id = ? AND domain = 'test'
103-
ORDER BY offset ASC`,
104-
).all(workspaceId) as Array<{ payload_json?: string }>;
105-
for (const row of rows) {
106-
let parsed: Record<string, unknown> | null = null;
107-
try {
108-
parsed = JSON.parse(row.payload_json ?? "") as Record<string, unknown>;
109-
} catch {
110-
continue;
98+
try {
99+
let latest: TestBotRunStatus | null = null;
100+
const rows = db.prepare(
101+
`SELECT payload_json
102+
FROM ${WORKSPACE_EVENTS_SQLITE_TABLE}
103+
WHERE workspace_id = ? AND domain = 'test'
104+
ORDER BY offset ASC`,
105+
).all(workspaceId) as Array<{ payload_json?: string }>;
106+
for (const row of rows) {
107+
let parsed: Record<string, unknown> | null = null;
108+
try {
109+
parsed = JSON.parse(row.payload_json ?? "") as Record<
110+
string,
111+
unknown
112+
>;
113+
} catch {
114+
continue;
115+
}
116+
if (!parsed || typeof parsed !== "object") continue;
117+
const payload = extractPersistedWorkspacePayload(parsed);
118+
if (
119+
payload.type !== "testBotStatus" &&
120+
payload.type !== "gambit.test.status"
121+
) continue;
122+
const normalized = normalizePersistedTestRunStatus(
123+
payload.run,
124+
workspaceId,
125+
);
126+
if (!normalized || normalized.id !== requestedRunId) continue;
127+
latest = normalized;
111128
}
112-
if (!parsed || typeof parsed !== "object") continue;
113-
const payload = extractPersistedWorkspacePayload(parsed);
114-
if (
115-
payload.type !== "testBotStatus" &&
116-
payload.type !== "gambit.test.status"
117-
) continue;
118-
const normalized = normalizePersistedTestRunStatus(
119-
payload.run,
120-
workspaceId,
121-
);
122-
if (!normalized || normalized.id !== requestedRunId) continue;
123-
latest = normalized;
129+
return latest;
130+
} finally {
131+
db.close();
124132
}
125-
return latest;
126133
} catch {
127134
return null;
128135
}
@@ -140,34 +147,41 @@ export const listPersistedTestRunStatuses = (
140147
if (!sqlitePath) return [];
141148
try {
142149
const db = new DatabaseSync(sqlitePath);
143-
const latestByRunId = new Map<string, TestBotRunStatus>();
144-
const rows = db.prepare(
145-
`SELECT payload_json
146-
FROM ${WORKSPACE_EVENTS_SQLITE_TABLE}
147-
WHERE workspace_id = ? AND domain = 'test'
148-
ORDER BY offset ASC`,
149-
).all(workspaceId) as Array<{ payload_json?: string }>;
150-
for (const row of rows) {
151-
let parsed: Record<string, unknown> | null = null;
152-
try {
153-
parsed = JSON.parse(row.payload_json ?? "") as Record<string, unknown>;
154-
} catch {
155-
continue;
150+
try {
151+
const latestByRunId = new Map<string, TestBotRunStatus>();
152+
const rows = db.prepare(
153+
`SELECT payload_json
154+
FROM ${WORKSPACE_EVENTS_SQLITE_TABLE}
155+
WHERE workspace_id = ? AND domain = 'test'
156+
ORDER BY offset ASC`,
157+
).all(workspaceId) as Array<{ payload_json?: string }>;
158+
for (const row of rows) {
159+
let parsed: Record<string, unknown> | null = null;
160+
try {
161+
parsed = JSON.parse(row.payload_json ?? "") as Record<
162+
string,
163+
unknown
164+
>;
165+
} catch {
166+
continue;
167+
}
168+
if (!parsed || typeof parsed !== "object") continue;
169+
const payload = extractPersistedWorkspacePayload(parsed);
170+
if (
171+
payload.type !== "testBotStatus" &&
172+
payload.type !== "gambit.test.status"
173+
) continue;
174+
const normalized = normalizePersistedTestRunStatus(
175+
payload.run,
176+
workspaceId,
177+
);
178+
if (!normalized || !normalized.id) continue;
179+
latestByRunId.set(normalized.id, normalized);
156180
}
157-
if (!parsed || typeof parsed !== "object") continue;
158-
const payload = extractPersistedWorkspacePayload(parsed);
159-
if (
160-
payload.type !== "testBotStatus" &&
161-
payload.type !== "gambit.test.status"
162-
) continue;
163-
const normalized = normalizePersistedTestRunStatus(
164-
payload.run,
165-
workspaceId,
166-
);
167-
if (!normalized || !normalized.id) continue;
168-
latestByRunId.set(normalized.id, normalized);
181+
return [...latestByRunId.values()];
182+
} finally {
183+
db.close();
169184
}
170-
return [...latestByRunId.values()];
171185
} catch {
172186
return [];
173187
}

src/workspace_sqlite.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,7 @@ function normalizePersistedTraceRecord(
5858
export function resolveWorkspaceSqlitePath(
5959
inputPath: string,
6060
): string | undefined {
61-
const normalized = path.resolve(inputPath);
62-
const candidate = path.basename(normalized) === WORKSPACE_SQLITE_FILENAME
63-
? normalized
64-
: path.join(path.dirname(normalized), WORKSPACE_SQLITE_FILENAME);
61+
const candidate = normalizeWorkspaceSqlitePath(inputPath);
6562
try {
6663
const stat = Deno.statSync(candidate);
6764
return stat.isFile ? candidate : undefined;
@@ -70,6 +67,13 @@ export function resolveWorkspaceSqlitePath(
7067
}
7168
}
7269

70+
export function normalizeWorkspaceSqlitePath(inputPath: string): string {
71+
const normalized = path.resolve(inputPath);
72+
return path.basename(normalized) === WORKSPACE_SQLITE_FILENAME
73+
? normalized
74+
: path.join(path.dirname(normalized), WORKSPACE_SQLITE_FILENAME);
75+
}
76+
7377
export function readWorkspaceStateFromSqlite(
7478
sqlitePath: string,
7579
workspaceId?: string,
@@ -202,7 +206,7 @@ export function saveCanonicalWorkspaceState(
202206
sqlitePath: string,
203207
state: SavedState,
204208
): { sqlitePath: string; workspaceId: string; state: SavedState } {
205-
const resolvedPath = path.resolve(sqlitePath);
209+
const resolvedPath = normalizeWorkspaceSqlitePath(sqlitePath);
206210
Deno.mkdirSync(path.dirname(resolvedPath), { recursive: true });
207211
const workspaceId = resolveWorkspaceIdFromPath(state, resolvedPath);
208212
const nextState: SavedState = {

0 commit comments

Comments
 (0)