mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-27 21:19:18 +00:00
* fix(sync): op_checkpoints pin write double-encodes jsonb — every sync aborts (#2339) recordCompleted bound JSON.stringify(array) to a $3::jsonb param via postgres.js .unsafe(), double-encoding it into a jsonb string scalar that violates the v119 op_checkpoints_completed_keys_array CHECK — aborting every multi-source sync on real Postgres at the first checkpoint write. PGLite parses the string silently, which is why unit tests stayed green and it shipped. Cast through $3::text::jsonb so the text->jsonb cast parses a genuine array. Adds a DATABASE_URL-gated parity test + a dedicated Postgres CI job so the guard can never silently skip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(db): sweep positional jsonb double-encode sites + AST CI guard (#2324) Every executeRaw/.unsafe site that bound JSON.stringify(x) to a bare positional jsonb cast double-encodes on real Postgres (same class as #2339). Sweep them all to the text::jsonb form across query-cache, sources-ops, llm-base, calibration-profile, impact-capture, subagent, receipt-write, traversal-cache, symbol-resolver, and the agent/sources commands. Adds scripts/check-jsonb-params.mjs (AST-lite scanner for the positional form the legacy template grep misses, incl. generic-typed calls), wired into check-jsonb-pattern.sh, with a self-test. PGLite's native db.query is not scanned — it parses text to jsonb natively, so the bug can't occur there. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(search,eval): alias-hop injected results carry page_id (contradiction-probe crash) applyAliasHop injected synthetic SearchResults without page_id (the `as SearchResult` cast hid the missing field), so listActiveTakesForPages bound undefined/NaN into ANY($1::int[]) and crashed the whole contradiction probe on real Postgres. Stamp page_id=page.id at the injection site and add a finite-id filter in generateIntraPagePairs as a defensive backstop (mirrors hybrid.ts:63). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(engines): positional jsonb binding rule (text::jsonb vs the double-encode trap) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * v0.42.53.0 fix(sync,db): #2339 op_checkpoints jsonb double-encode + bug-class sweep + CI guard Bumps VERSION + package.json to 0.42.53.0, adds the CHANGELOG entry, and regenerates llms-full.txt. Ships the #2339 sync-abort hotfix, the repo-wide positional jsonb double-encode sweep, the alias-hop contradiction-probe crash fix, and the new positional-form CI guard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: post-ship sync — jsonb invariant now covers the positional form + new guard CLAUDE.md JSONB invariant + KEY_FILES (sql-query, check-jsonb-pattern, op-checkpoint) now describe the #2339 positional double-encode class, the $N::text::jsonb fix, and the new check-jsonb-params.mjs guard. Regenerates llms-full.txt. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
61 lines
2.7 KiB
Bash
Executable File
61 lines
2.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# CI guard: fail if any source file uses the buggy `${JSON.stringify(x)}::jsonb`
|
|
# template-string pattern instead of postgres.js's `sql.json(x)`.
|
|
#
|
|
# This is best-effort static analysis. It catches the common copy-paste form
|
|
# that caused the v0.12.0 silent-data-loss bug (JSONB columns stored as
|
|
# string literals on Postgres while PGLite hid the bug). Multi-line and
|
|
# helper-wrapped variants are NOT caught here — those are covered by
|
|
# test/e2e/postgres-jsonb.test.ts which round-trips actual writes through
|
|
# real Postgres and asserts `frontmatter->>'k'` returns objects, not strings.
|
|
#
|
|
# Usage: scripts/check-jsonb-pattern.sh
|
|
# Exit: 0 when no matches, 1 when matches found.
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
|
|
cd "$ROOT"
|
|
|
|
# Match the interpolated form: ${JSON.stringify(...)}::jsonb
|
|
# Using grep -P for Perl-compatible regex (lookahead-free pattern is enough here).
|
|
PATTERN='\$\{JSON\.stringify\([^)]*\)\}::jsonb'
|
|
|
|
if grep -rEn "$PATTERN" src/ 2>/dev/null; then
|
|
echo
|
|
echo "ERROR: Found JSON.stringify(...)::jsonb pattern in src/."
|
|
echo " postgres.js v3 stringifies again, producing JSONB string literals."
|
|
echo " Use sql.json(x) instead. See feedback_postgres_jsonb_double_encode.md."
|
|
exit 1
|
|
fi
|
|
|
|
echo "OK: no JSON.stringify(x)::jsonb interpolation pattern in src/"
|
|
|
|
# v0.13.1 #219: guard against max_stalled DEFAULT 1 regressing in any schema
|
|
# source file. DEFAULT 1 dead-lettered any SIGKILL'd job on first stall, making
|
|
# the "10/10 rescued" claim false for out-of-the-box users. Default is 5 now.
|
|
MAX_STALLED_PATTERN='max_stalled\s+INTEGER\s+NOT\s+NULL\s+DEFAULT\s+1\b'
|
|
|
|
if grep -rEn "$MAX_STALLED_PATTERN" src/schema.sql src/core/migrate.ts src/core/pglite-schema.ts src/core/schema-embedded.ts 2>/dev/null; then
|
|
echo
|
|
echo "ERROR: max_stalled DEFAULT 1 reintroduced in schema."
|
|
echo " Must be DEFAULT 5 to preserve SIGKILL-rescue guarantee. See #219."
|
|
exit 1
|
|
fi
|
|
|
|
echo "OK: max_stalled defaults are 5 in all schema sources"
|
|
|
|
# v0.42.x (#2339 / #2324): positional `$N::jsonb` + JSON.stringify double-encode.
|
|
# The template-string grep above only catches `${JSON.stringify(x)}::jsonb`. It
|
|
# MISSES the positional-param form — executeRaw(`... $N::jsonb ...`,
|
|
# [JSON.stringify(x)]) — which is the exact shape that double-encoded the
|
|
# op_checkpoints pin and aborted every sync in #2339. The AST-lite scanner below
|
|
# catches it. `set -e` propagates its non-zero exit.
|
|
if command -v node >/dev/null 2>&1; then
|
|
node scripts/check-jsonb-params.mjs
|
|
elif command -v bun >/dev/null 2>&1; then
|
|
bun scripts/check-jsonb-params.mjs
|
|
else
|
|
echo "WARN: neither node nor bun on PATH; skipping check-jsonb-params.mjs" >&2
|
|
fi
|