fix(setup-gbrain): warn about the ZeroEntropy sunset before Sept 4

ZeroEntropy was acquired by Notion and sunsets its hosted API on September 4, 2026. A gbrain configured with the zeroentropyai embedding recipe keeps importing pages after that date but embedding silently fails — pages land structurally with no semantic search, this repo's tracker P1 (TODOS.md NEXT PRIORITY). Nothing in gstack ever recommended ZeroEntropy (the dependency is gbrain-internal), so the gstack side is detection + advisory: the wireup helper warns when ~/.gbrain/config.json names the recipe (fail-open grep — a missing, unreadable, or other-provider config stays silent and never blocks a working setup), the setup-gbrain provider-default comments say never to select the legacy recipe for a new brain, and USING_GBRAIN_WITH_GSTACK.md gains a troubleshooting entry. The gbrain-side provider migration stays open upstream.

Refs #2365
This commit is contained in:
Garry Tan
2026-08-22 02:02:33 +00:00
parent 361dfebcbe
commit 8b426b3050
5 changed files with 61 additions and 0 deletions
+4
View File
@@ -364,6 +364,10 @@ gbrain sync --source <source-id> --skip-failed
Watermark advances past the offending commit. The same file fails again if it changes; re-skip when that happens.
### ZeroEntropy embeddings stop working after September 4, 2026
ZeroEntropy was acquired by Notion and sunsets its hosted API on **September 4, 2026** (new signups already disabled). A gbrain configured with the `zeroentropyai` embedding recipe keeps importing pages after that date, but embedding silently fails — pages land structurally with no semantic search. The wireup helper warns when your `~/.gbrain/config.json` names the recipe; migrate to another provider (Voyage via `VOYAGE_API_KEY`, or OpenAI via `OPENAI_API_KEY`) before the deadline. Details, self-hosting caveats, and migration discussion: [garrytan/gstack#2365](https://github.com/garrytan/gstack/issues/2365).
### Switching PGLite → Supabase hangs
Another gstack session in a sibling Conductor workspace may be holding a lock on your local PGLite file via its preamble's `gstack-brain-sync` call. Close other workspaces, re-run `/setup-gbrain --switch`. The timeout is bounded at 180s so you'll never actually wait forever.
+9
View File
@@ -316,6 +316,15 @@ do_wireup() {
;;
esac
# ZeroEntropy sunset advisory (#2365): the provider shuts down Sept 4, 2026,
# after which brains on gbrain's zeroentropyai recipe stop embedding new
# pages silently. Detection is a fail-open grep of gbrain's config — any
# missing/unreadable/other-provider config stays silent (grep -qs), never
# blocking a working setup.
if grep -qsi 'zeroentropyai' "$GBRAIN_CONFIG" 2>/dev/null; then
warn "gbrain config appears to use the ZeroEntropy embedding recipe. ZeroEntropy sunsets on September 4, 2026 — after that, new pages stop embedding silently. Migration options: https://github.com/garrytan/gstack/issues/2365"
fi
if [ "${GSTACK_BRAIN_NO_SYNC:-0}" = "1" ]; then
echo "source_id=$id"
echo "worktree=$WORKTREE"
+4
View File
@@ -916,6 +916,8 @@ mv "$HOME/.gbrain/config.json" "$BACKUP"
# gstack default: voyage-code-3 (1024d) when VOYAGE_API_KEY is set — best for
# code retrieval. Without the key, fall back to gbrain's own auto-selected
# embedding provider chain (OpenAI 1536d when OPENAI_API_KEY is present, etc.).
# Never select gbrain's legacy zeroentropyai recipe for a new brain: the hosted
# API sunsets September 4, 2026 (#2365); the wireup helper warns existing installs.
set -- # flags ride the positional params — unquoted $VAR breaks under zsh word-splitting (#1798)
if [ -n "${VOYAGE_API_KEY:-}" ]; then
set -- --embedding-model voyage:voyage-code-3 --embedding-dimensions 1024
@@ -1175,6 +1177,8 @@ Then follow the same secret-read + verify + init flow as Path 1.
# gstack default: voyage-code-3 (1024d) when VOYAGE_API_KEY is set — code
# retrieval beats general-purpose embeddings on real code queries (validated
# A/B). Without the key, gbrain auto-selects (OpenAI 1536d when available).
# Never select gbrain's legacy zeroentropyai recipe for a new brain: the hosted
# API sunsets September 4, 2026 (#2365); the wireup helper warns existing installs.
set -- # flags ride the positional params — unquoted $VAR breaks under zsh word-splitting (#1798)
if [ -n "${VOYAGE_API_KEY:-}" ]; then
set -- --embedding-model voyage:voyage-code-3 --embedding-dimensions 1024
+4
View File
@@ -134,6 +134,8 @@ mv "$HOME/.gbrain/config.json" "$BACKUP"
# gstack default: voyage-code-3 (1024d) when VOYAGE_API_KEY is set — best for
# code retrieval. Without the key, fall back to gbrain's own auto-selected
# embedding provider chain (OpenAI 1536d when OPENAI_API_KEY is present, etc.).
# Never select gbrain's legacy zeroentropyai recipe for a new brain: the hosted
# API sunsets September 4, 2026 (#2365); the wireup helper warns existing installs.
set -- # flags ride the positional params — unquoted $VAR breaks under zsh word-splitting (#1798)
if [ -n "${VOYAGE_API_KEY:-}" ]; then
set -- --embedding-model voyage:voyage-code-3 --embedding-dimensions 1024
@@ -393,6 +395,8 @@ Then follow the same secret-read + verify + init flow as Path 1.
# gstack default: voyage-code-3 (1024d) when VOYAGE_API_KEY is set — code
# retrieval beats general-purpose embeddings on real code queries (validated
# A/B). Without the key, gbrain auto-selects (OpenAI 1536d when available).
# Never select gbrain's legacy zeroentropyai recipe for a new brain: the hosted
# API sunsets September 4, 2026 (#2365); the wireup helper warns existing installs.
set -- # flags ride the positional params — unquoted $VAR breaks under zsh word-splitting (#1798)
if [ -n "${VOYAGE_API_KEY:-}" ]; then
set -- --embedding-model voyage:voyage-code-3 --embedding-dimensions 1024
+40
View File
@@ -341,6 +341,46 @@ describe('gstack-gbrain-source-wireup — wireup mode', () => {
});
});
describe('gstack-gbrain-source-wireup — ZeroEntropy sunset advisory (#2365)', () => {
// The hosted ZeroEntropy API dies Sept 4, 2026; a gbrain on the zeroentropyai
// recipe keeps importing but stops embedding SILENTLY. Detection is a
// fail-open grep of ~/.gbrain/config.json — missing/other-provider configs
// must stay silent and never block the wireup.
test('config naming zeroentropyai → sunset warning, wireup still succeeds', () => {
setupGstackRepo('git@github.com:user/gstack-brain-user.git');
makeFakeGbrain({});
fs.mkdirSync(path.join(tmpHome, '.gbrain'), { recursive: true });
fs.writeFileSync(
path.join(tmpHome, '.gbrain', 'config.json'),
JSON.stringify({ embedding: { recipe: 'zeroentropyai' } }),
);
const r = run([], { env: { GSTACK_BRAIN_NO_SYNC: '1' } });
expect(r.status).toBe(0);
expect(r.stderr).toContain('ZeroEntropy');
expect(r.stderr).toContain('2365');
});
test('config on another provider → no warning (fail-open, no false positive)', () => {
setupGstackRepo('git@github.com:user/gstack-brain-user.git');
makeFakeGbrain({});
fs.mkdirSync(path.join(tmpHome, '.gbrain'), { recursive: true });
fs.writeFileSync(
path.join(tmpHome, '.gbrain', 'config.json'),
JSON.stringify({ embedding: { recipe: 'voyage:voyage-code-3' } }),
);
const r = run([], { env: { GSTACK_BRAIN_NO_SYNC: '1' } });
expect(r.status).toBe(0);
expect(r.stderr).not.toContain('ZeroEntropy');
});
test('advisory docs entry exists (USING_GBRAIN_WITH_GSTACK.md content pin)', () => {
const doc = fs.readFileSync(path.join(ROOT, 'USING_GBRAIN_WITH_GSTACK.md'), 'utf-8');
expect(doc).toContain('September 4, 2026');
expect(doc).toContain('#2365');
});
});
describe('gstack-gbrain-source-wireup — --database-url lock (defends against external config rewrites)', () => {
test('--database-url flag is exported as GBRAIN_DATABASE_URL to child gbrain calls', () => {
setupGstackRepo('git@github.com:user/gstack-brain-user.git');