Repro
On a Mac with gbrain v0.27.0 configured against a postgres engine over PgBouncer (transaction mode, port 6543):
$ SLUG="syncprobe59380"
$ echo "ping" | gbrain put "$SLUG"
# (no visible error, exit 0)
$ gbrain search "$SLUG"
No results.
$ gbrain delete "$SLUG"
{
"status": "soft_deleted",
"slug": "syncprobe59380",
"recoverable_until": "now + 72h via restore_page"
}
The page was clearly stored — gbrain delete found and soft-deleted it. But gbrain search returned "No results" for the same slug immediately after the put.
Every gbrain invocation also prints this header:
[gbrain] Prepared statements disabled (PgBouncer transaction-mode convention on port 6543). Override with GBRAIN_PREPARE=true if your pooler runs in session mode.
gbrain doctor --fast reports OK, so this isn't visible to gstack's normal probes. The /sync-gbrain skill's CAPABILITY_OK check (put + search round-trip) correctly drops to 0 and skips writing the ## GBrain Search Guidance block, but the underlying capability is broken and silent under doctor --fast.
Why this matters for gstack
/sync-gbrain Step 4 (capability check) is what gates the ## GBrain Search Guidance block in CLAUDE.md. With this bug, the block never gets written on machines using a transaction-mode PgBouncer pooler — even when memory + brain-sync stages succeed. Agents on those machines never learn to prefer gbrain search over Grep, defeating the point of the integration.
Likely cause (guess, not confirmed)
The search index (tsvector or embedding-based) appears to not update synchronously after a gbrain put under transaction-mode pooling. Delete works because it looks up by slug, but search requires an index lookup that either:
- Requires prepared statements (which were disabled), or
- Runs in a deferred/async pass that's not triggered before the next CLI call, or
- Writes to a different source/index than the put.
The [gbrain] Prepared statements disabled warning hints at (1). The GBRAIN_PREPARE=true override mentioned in the warning is not exposed through any gstack env or config — users hitting this have no documented escape hatch.
Suggested fixes (any of)
- Pass
GBRAIN_PREPARE=true through gstack env when the user is on a postgres engine over port 6543 — or whenever gstack detects the prepared-statements warning. Document this in /setup-gbrain.
- Make
gbrain doctor exercise the full put → search → delete round-trip (not just --fast), so this is visible in standard health output. Right now the only way to detect it is /sync-gbrain's capability probe.
- If search really does need prepared statements under transaction-mode pooling, surface a clear setup error during
/setup-gbrain instead of letting subsequent skills mysteriously fail to write the guidance block.
Environment
- gstack v1.26.4.0
- gbrain v0.27.0 (postgres engine)
- Pooler: PgBouncer, transaction mode, port 6543
- macOS
Related
Companion issue filed separately: #1434 (code source ID exceeds 32-char limit). Both surfaced in the same /sync-gbrain run.
Filed via Claude Code at the user's request.
Repro
On a Mac with gbrain v0.27.0 configured against a postgres engine over PgBouncer (transaction mode, port 6543):
The page was clearly stored —
gbrain deletefound and soft-deleted it. Butgbrain searchreturned "No results" for the same slug immediately after the put.Every
gbraininvocation also prints this header:gbrain doctor --fastreports OK, so this isn't visible to gstack's normal probes. The/sync-gbrainskill'sCAPABILITY_OKcheck (put + search round-trip) correctly drops to 0 and skips writing the## GBrain Search Guidanceblock, but the underlying capability is broken and silent underdoctor --fast.Why this matters for gstack
/sync-gbrainStep 4 (capability check) is what gates the## GBrain Search Guidanceblock in CLAUDE.md. With this bug, the block never gets written on machines using a transaction-mode PgBouncer pooler — even when memory + brain-sync stages succeed. Agents on those machines never learn to prefergbrain searchover Grep, defeating the point of the integration.Likely cause (guess, not confirmed)
The search index (tsvector or embedding-based) appears to not update synchronously after a
gbrain putunder transaction-mode pooling. Delete works because it looks up by slug, but search requires an index lookup that either:The
[gbrain] Prepared statements disabledwarning hints at (1). TheGBRAIN_PREPARE=trueoverride mentioned in the warning is not exposed through any gstack env or config — users hitting this have no documented escape hatch.Suggested fixes (any of)
GBRAIN_PREPARE=truethrough gstack env when the user is on a postgres engine over port 6543 — or whenever gstack detects the prepared-statements warning. Document this in/setup-gbrain.gbrain doctorexercise the full put → search → delete round-trip (not just--fast), so this is visible in standard health output. Right now the only way to detect it is/sync-gbrain's capability probe./setup-gbraininstead of letting subsequent skills mysteriously fail to write the guidance block.Environment
Related
Companion issue filed separately: #1434 (code source ID exceeds 32-char limit). Both surfaced in the same
/sync-gbrainrun.Filed via Claude Code at the user's request.