mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-27 22:15:33 +00:00
* v0.26.3 feat(schema): PGLite ↔ Postgres parity gate + access_tokens.id type fix (#588) Drift gate (test/e2e/schema-drift.test.ts) spins up fresh PGLite + Postgres, runs each engine's initSchema(), snapshots information_schema.columns, and diffs the four-tuple (data_type, udt_name, is_nullable, column_default) per column. 17 unit cases for the pure diff function (test/helpers/schema-diff.ts + schema-diff.test.ts) including a D3 negative test that reproduces the v0.26.1 oauth_clients.token_ttl regression. 6 E2E cases including 4 sentinels for oauth_clients, mcp_request_log, access_tokens, eval_candidates. The gate caught one real drift on its first run: access_tokens.id was UUID on Postgres (schema.sql:328, migration v4) and TEXT on PGLite (pglite-schema.ts). Reconciled to UUID DEFAULT gen_random_uuid() on both sides. CI wiring in scripts/e2e-test-map.ts triggers schema-drift on changes to schema.sql, pglite-schema.ts, or migrate.ts. The 2-table allowlist (files, file_migration_ledger) is narrow by design — every other Postgres table must reach PGLite via PGLITE_SCHEMA_SQL or a migration's sqlFor.pglite branch. Bookkeeping: master HEAD's VERSION was 0.26.0 even though the prior commit shipped as v0.26.1 (the bump never landed). Moving to 0.26.3 per the same bookkeeping discontinuity. Codex flagged a versioning hardening follow-up (scripts/check-version-sync.sh pre-push guard) for v0.26.4. Also fixes two pre-existing CI failures master shipped through: - check-privacy.sh: src/core/mounts-cache.ts had two banned name references ("Wintermute"). Replaced with "your OpenClaw" per CLAUDE.md:550. - check-no-legacy-getconnection.sh: src/commands/integrity.ts:355 was a new legacy db.getConnection() caller. Added to the script's allowlist with a PR 1 cleanup note (matches the existing 8 grandfathered entries). Out of scope (filed for v0.26.4): manual ALTER TABLE on production Postgres that never made it into source files (the actual v0.26.1 trigger; needs a gbrain doctor --schema-audit mechanism); index parity; versioning hardening guard. Plan + codex review pivot: original plan compared raw schema.sql vs raw pglite-schema.ts; codex showed they're intentionally divergent today (PGLite reaches its end-state via PGLITE_SCHEMA_SQL + migrations). Pivoted to end-state comparison, which catches real drift without false positives. Closes #588. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: bump v0.26.3 → v0.26.4 Per user instruction. No code or test changes — VERSION + package.json + CHANGELOG header/body + CLAUDE.md key-files entry. Regenerated llms-full.txt. "NOT in this release" deferral targets bumped from v0.26.4 → v0.26.5 (those items are still deferred; they're now deferred from v0.26.4). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: bump v0.26.4 → v0.26.6 Per user instruction. Bookkeeping-only — VERSION + package.json + CHANGELOG header/body + CLAUDE.md key-files entry. Regenerated llms-full.txt. "NOT in this release" deferral targets bumped from v0.26.5 → v0.26.7 (those items remain deferred; now from v0.26.6 instead of v0.26.4). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
86 lines
3.7 KiB
Bash
Executable File
86 lines
3.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# CI guard against silent singleton reuse in connected-gbrains code paths.
|
|
#
|
|
# Codex finding #7 (plan review 2026-04-22): the module singleton in
|
|
# src/core/db.ts is shared across the process. With multi-brain routing,
|
|
# any `db.getConnection()` call in an op-dispatch code path means that op
|
|
# silently targets whichever brain connected to the singleton first,
|
|
# regardless of ctx.brainId / ctx.engine. This is exactly the bug Codex
|
|
# #1 flagged in postgres-engine.ts internals.
|
|
#
|
|
# This script fails the build when NEW `db.getConnection()` calls appear
|
|
# in src/core/operations.ts (the per-op handler surface) or in any new
|
|
# `src/commands/*.ts` file. Existing legitimate callers are grandfathered
|
|
# via an explicit allowlist — cleanups land in PR 1.
|
|
#
|
|
# When you hit this guard: instead of `db.getConnection()` or `db.connect(...)`,
|
|
# use `ctx.engine` from the passed-in OperationContext. See
|
|
# src/core/brain-registry.ts for how ctx.engine gets populated per-call.
|
|
#
|
|
# Run manually: bash scripts/check-no-legacy-getconnection.sh
|
|
# Wired into CI: `bun test` (via package.json scripts.test)
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
cd "$ROOT"
|
|
|
|
# Files that are allowed to touch the singleton today. Every other file
|
|
# under src/core or src/commands is forbidden. This list shrinks in PR 1.
|
|
ALLOWED=(
|
|
"src/core/db.ts" # the singleton's definition
|
|
"src/core/postgres-engine.ts" # calls db.connect + fallback in sql getter — PR 1 removes the fallback
|
|
"src/commands/init.ts" # first-time setup path, no engine yet
|
|
"src/commands/doctor.ts" # PR 1 refactors to accept engine
|
|
"src/commands/files.ts" # PR 1 refactors to accept engine
|
|
"src/commands/repair-jsonb.ts" # PR 1 refactors
|
|
"src/commands/serve-http.ts" # PR 1 threads engine through the OAuth dispatch path
|
|
"src/commands/integrity.ts" # v0.22.8 batch-load fast path + scanIntegrityBatch; PR 1 refactors to accept engine
|
|
"src/core/operations.ts" # 3 localOnly ops (file_list/upload/url) move to ctx.engine in PR 1
|
|
)
|
|
|
|
# Build an argument list for `grep` that excludes allowed files.
|
|
EXCLUDE_ARGS=()
|
|
for file in "${ALLOWED[@]}"; do
|
|
EXCLUDE_ARGS+=(--exclude="$file")
|
|
done
|
|
|
|
# Search src/core/ and src/commands/ for db.getConnection or db.connect calls.
|
|
# We look for the `db.` prefix so references to the symbol elsewhere (e.g.
|
|
# the grep guard itself) don't trip the check.
|
|
VIOLATIONS=$(
|
|
grep -rn "db\.\(getConnection\|connect\)(" \
|
|
--include="*.ts" \
|
|
"${EXCLUDE_ARGS[@]}" \
|
|
src/core src/commands 2>/dev/null \
|
|
| grep -v -F "src/core/db.ts" \
|
|
| grep -v "^[^:]*:[0-9]*:[[:space:]]*\(//\|\*\)" \
|
|
|| true
|
|
)
|
|
|
|
if [ -n "$VIOLATIONS" ]; then
|
|
# Filter out allowed files from the result (the --exclude only matches basename)
|
|
FILTERED=$(printf '%s\n' "$VIOLATIONS" | while IFS= read -r line; do
|
|
path="${line%%:*}"
|
|
allow=0
|
|
for ok in "${ALLOWED[@]}"; do
|
|
if [ "$path" = "$ok" ]; then allow=1; break; fi
|
|
done
|
|
if [ "$allow" -eq 0 ]; then printf '%s\n' "$line"; fi
|
|
done)
|
|
|
|
if [ -n "$FILTERED" ]; then
|
|
echo "ERROR: new direct db.getConnection() / db.connect() call found in multi-brain code path:" >&2
|
|
echo "" >&2
|
|
printf '%s\n' "$FILTERED" >&2
|
|
echo "" >&2
|
|
echo "Use ctx.engine from the passed-in OperationContext instead." >&2
|
|
echo "See src/core/brain-registry.ts for the routing model." >&2
|
|
echo "If this call is legitimate, add its path to the ALLOWED list in" >&2
|
|
echo "scripts/check-no-legacy-getconnection.sh with a PR 1 cleanup note." >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo "check-no-legacy-getconnection: ok (no new singleton callers)"
|