diff --git a/scripts/check-sql-column-literals.mjs b/scripts/check-sql-column-literals.mjs
index a4a8129e01..77f6cd75b0 100644
--- a/scripts/check-sql-column-literals.mjs
+++ b/scripts/check-sql-column-literals.mjs
@@ -37,6 +37,30 @@ import ts from "typescript";
const REPO = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const PACKAGES = join(REPO, "packages");
+/*
+FNXC:LifecycleColumnCensus 2026-07-30-23:58:
+`scripts/` is scanned, and `.mjs` counts — the operator scripts were the one place raw SQL actually
+lived, and this gate could not see any of it.
+
+Found by removing a raw-SQL lane literal from `scripts/reconcile-leaked-soft-deletes.mjs` and watching
+this gate report "22 known, none added" — unchanged and green. Its own header promises the opposite
+("a LOWER count fails too so the baseline is ratcheted down"), so the silence was the tell.
+
+TWO changes, and either alone still sees nothing: the walk started at `packages` only, and the filter
+took `.tsx?`, while every operator script is a repo-root `.mjs`. Adding one without the other scans
+nothing new and reports a reassuring zero — the same trap #2978 hit widening the lane-wiring census.
+
+This does NOT contradict the `.sql` note below. That reasoning is about feeding DDL to a TypeScript
+parser; `.mjs` IS JavaScript, so the existing AST walk applies unchanged.
+
+The ScriptKind move is DEFENSIVE, and I could not demonstrate it was necessary — stated plainly
+because the opposite claim would be easy to make and wrong. TSX reads `<` as JSX, so an ordinary
+comparison in a plain script is a plausible misparse; I tried three shapes for it
+(`x
y`, `f(d)`, a literal between `<` and `>` comparisons) and TSX recovered from all of
+them, returning the same count as JS. So JS is used for `.mjs` because it is the correct kind for the
+file, not because a miss was observed.
+*/
+const SCRIPTS = join(REPO, "scripts");
const BASELINE = join(REPO, "scripts", "lib", "sql-column-literals-baseline.json");
const SKIP_DIRS = new Set(["node_modules", "dist", "__tests__", "__mocks__", "e2e", ".gate-bundle", "coverage"]);
@@ -132,7 +156,7 @@ function* walk(dir) {
data backfill (`UPDATE tasks SET column = ...`) landing in a migration. If one ever does, this
needs a separate raw-text matcher against `COMPARISON`, not an entry in the filter below.
*/
- else if (/\.tsx?$/.test(full) && !/\.d\.ts$/.test(full)) yield full;
+ else if (/\.(tsx?|mjs)$/.test(full) && !/\.d\.ts$/.test(full)) yield full;
}
}
@@ -326,9 +350,11 @@ const matches = [];
function scan() {
const counts = {};
- for (const file of walk(PACKAGES)) {
+ for (const file of [...walk(PACKAGES), ...walk(SCRIPTS)]) {
const source = readFileSync(file, "utf8");
- const sf = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
+ /* The correct kind for the file. Defensive rather than a proven fix — see the header. */
+ const kind = file.endsWith(".mjs") ? ts.ScriptKind.JS : ts.ScriptKind.TSX;
+ const sf = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true, kind);
const consts = collectStringConsts(sf);
let hits = 0;
const visit = (node) => {
diff --git a/scripts/lib/sql-column-literals-baseline.json b/scripts/lib/sql-column-literals-baseline.json
index 5afd8218b7..c393aa8b0f 100644
--- a/scripts/lib/sql-column-literals-baseline.json
+++ b/scripts/lib/sql-column-literals-baseline.json
@@ -12,5 +12,6 @@
"packages/core/src/task-store/task-artifacts-ops.ts": 1,
"packages/core/src/task-store/workflow-definitions.ts": 2,
"packages/core/src/team-analytics.ts": 3,
- "packages/core/src/workflow-analytics.ts": 3
+ "packages/core/src/workflow-analytics.ts": 3,
+ "scripts/audit-branch-cross-contamination.mjs": 4
}