diff --git a/USING_GBRAIN_WITH_GSTACK.md b/USING_GBRAIN_WITH_GSTACK.md index de54abeb3..4d5575592 100644 --- a/USING_GBRAIN_WITH_GSTACK.md +++ b/USING_GBRAIN_WITH_GSTACK.md @@ -364,6 +364,10 @@ gbrain sync --source --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. diff --git a/bin/gstack-gbrain-source-wireup b/bin/gstack-gbrain-source-wireup index a3c20b9c6..a364db921 100755 --- a/bin/gstack-gbrain-source-wireup +++ b/bin/gstack-gbrain-source-wireup @@ -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" diff --git a/setup-gbrain/SKILL.md b/setup-gbrain/SKILL.md index 8c2c6efcc..327184b08 100644 --- a/setup-gbrain/SKILL.md +++ b/setup-gbrain/SKILL.md @@ -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 diff --git a/setup-gbrain/SKILL.md.tmpl b/setup-gbrain/SKILL.md.tmpl index 3636a4f9b..8115f9d87 100644 --- a/setup-gbrain/SKILL.md.tmpl +++ b/setup-gbrain/SKILL.md.tmpl @@ -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 diff --git a/test/gstack-gbrain-source-wireup.test.ts b/test/gstack-gbrain-source-wireup.test.ts index b9995b678..e40d3b6cc 100644 --- a/test/gstack-gbrain-source-wireup.test.ts +++ b/test/gstack-gbrain-source-wireup.test.ts @@ -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');