Skip to content

Commit 976a223

Browse files
committed
fix(db): strip ; from -- comment + add regression guard
CI failed again with the same `RangeError: The supplied SQL string contains no statements` from yesterday's lesson — I introduced a `;` inside the freshly-rewritten recipe_recency DDL block comment when applying CodeRabbit nitpick #2 (the lazy-on-read prose fix). Two changes: 1. Replaced "(recordRecipeRun DELETEs stale rows before its upsert); reads stay pure." with em-dash to drop the inner `;`. (Same fix shape as 649f7d2 from the previous round.) 2. **Added a regression guard** in `src/db.test.ts` that splits the `createTables()` template on `;` and asserts no fragment is pure `--` comments. Hitting this lesson twice in one PR is the trigger the existing entry in `.agents/lessons.md` flagged as "candidate roadmap item." Test runs in `bun test` (which Bun's `bun:sqlite` masks), so it catches the regression locally before CI burns a cycle. 887 → 888 tests; CI's `node dist/index.mjs --full` smoke verified locally before push.
1 parent 4a82bf7 commit 976a223

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

src/db.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { describe, expect, it } from "bun:test";
2+
import { readFileSync } from "node:fs";
3+
import { join } from "node:path";
24

35
import {
46
closeDb,
@@ -18,6 +20,35 @@ import {
1820
} from "./db";
1921
import { openCodemapDatabase } from "./sqlite-db";
2022

23+
describe("createTables() DDL — Node split-on-`;` invariant", () => {
24+
// Node uses better-sqlite3 (one statement per `prepare()`), so `runSql()`
25+
// splits the multi-statement DDL on `;`. A `;` inside a `--` line comment
26+
// creates a comment-only fragment that `prepare()` rejects with
27+
// `RangeError: The supplied SQL string contains no statements`. Bun tests
28+
// miss this because `bun:sqlite` accepts multi-statement SQL natively;
29+
// the failure surfaces only when CI runs `node dist/index.mjs --full`.
30+
// See `.agents/lessons.md` "Semicolons inside `--` line comments".
31+
it("contains no comment-only fragments after split-on-`;`", () => {
32+
const src = readFileSync(join(import.meta.dir, "db.ts"), "utf-8");
33+
const match = src.match(/createTables[^`]*`([\s\S]+?)`/);
34+
expect(match).not.toBeNull();
35+
const sql = match![1]!;
36+
const fragments = sql
37+
.split(";")
38+
.map((s) => s.trim())
39+
.filter(Boolean);
40+
const offenders = fragments.filter((f) => {
41+
const stripped = f
42+
.split("\n")
43+
.map((l) => l.trim())
44+
.filter((l) => l && !l.startsWith("--"))
45+
.join(" ");
46+
return stripped === "";
47+
});
48+
expect(offenders).toEqual([]);
49+
});
50+
});
51+
2152
describe("SQLite layer (in-memory)", () => {
2253
it("creates schema and round-trips meta", () => {
2354
const db = openCodemapDatabase(":memory:");

src/db.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ export function createTables(db: CodemapDatabase) {
199199
-- loadRecipeRecency. Like query_baselines / coverage, intentionally absent
200200
-- from dropAll() so --full and SCHEMA_VERSION rebuilds preserve activity
201201
-- history. 90-day window is eager-on-write (recordRecipeRun DELETEs stale
202-
-- rows before its upsert); reads stay pure. recipe_id is loose (no FK; can
203-
-- match bundled or project recipe ids). See docs/architecture.md recipe_recency.
202+
-- rows before its upsert)reads stay pure. recipe_id is loose (no FK,
203+
-- can match bundled or project recipe ids). See docs/architecture.md.
204204
CREATE TABLE IF NOT EXISTS recipe_recency (
205205
recipe_id TEXT PRIMARY KEY,
206206
last_run_at INTEGER NOT NULL,

0 commit comments

Comments
 (0)