v0.42.4.0 fix: think --model fails loud — slash-form ids + never persist empty synthesis (#1698)#1736
Merged
Merged
Conversation
…pty synthesis (#1698) Slash-form model ids (anthropic/claude-sonnet-4-6) silently degraded to the no-LLM stub and wrote empty synthesis pages with exit 0 (reporter saw 200). Three compounding defects, fixed: - normalizeModelId (src/core/model-id.ts): one shared provider:model normalizer replacing 4 colon-only inlines; slash→colon, bare→default, malformed leading-separator (:foo) returned unchanged so resolveRecipe throws loud. - validateModelId + probeChatModel (gateway.ts): shared id-validity + key probe; runThink hard-errors on an explicit --model it can't run (no silent degrade). - synthesisOk + persist-skip (think/index.ts): empty/malformed/empty-JSON synthesis is never persisted; --save with no synthesis exits 1. - auto-think (cycle/auto-think.ts): empty synthesis no longer counts complete or advances the cooldown (the autonomous third caller of persistSynthesis). - hasAnthropicKey consolidated into src/core/ai/anthropic-key.ts (3 copies → 1). MCP think op sets modelExplicit; saved_slug '' maps to null.
#1698 think --model fail-loud wave. Also files the P3 follow-up TODO for the provider-symmetric early gate (D1 accept-as-is). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…l-fail-loud # Conflicts: # CHANGELOG.md # VERSION # package.json
…l-fail-loud # Conflicts: # CHANGELOG.md # VERSION # package.json
mgunnin
added a commit
to mgunnin/gbrain
that referenced
this pull request
Jun 3, 2026
* upstream/master: v0.42.8.0 feat: content-quality gate on sync — quarantine junk + flag boilerplate (garrytan#1699) (garrytan#1756) v0.42.7.0 feat(extract): link/timeline extraction freshness watermark — gbrain extract --stale + doctor lag check (garrytan#1696) (garrytan#1755) v0.42.6.0 feat(enrich): gbrain enrich --thin — brain-internal grounded synthesis for stub pages (garrytan#1700) (garrytan#1757) v0.42.5.0 fix(minions): RSS watchdog opacity + pooler-reap self-heal + silent lens backlog + cycle lint DB-disconnect (garrytan#1678) (garrytan#1735) v0.42.4.0 fix: think --model fails loud — slash-form ids + never persist empty synthesis (garrytan#1698) (garrytan#1736) v0.42.3.0 feat(search): autocut — score-discontinuity result-sizing (garrytan#1663 wave 1) (garrytan#1682) v0.42.2.0 feat: gbrain connect — one-command Claude Code onboarding from a bearer token (garrytan#1683)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes (#1698)
gbrain think --model anthropic/claude-sonnet-4-6 --save(slash form) silentlydegraded to the no-LLM stub and wrote empty synthesis pages with exit 0. The
reporter ran it in a loop and got ~200 blank pages before noticing. This closes the
whole silent-failure class:
anthropic/claude-sonnet-4-6==anthropic:claude-sonnet-4-6; bare names still default to Anthropic.--modelthat can't run is a hard error (exit 1, clear message + paste-ready fix), not a silent stub. Omitting--modelkeeps the graceful no-key gather-only path (exit 0).--savewith no real synthesis exits 1.auto-thinkcycle no longer counts an empty synthesis as complete or advances the cooldown.How
normalizeModelId(src/core/model-id.ts) — one sharedprovider:modelnormalizer, replacing 4 colon-only inlines that mangled slash form. Malformed leading separator (:foo) returned unchanged → resolver throws loud.validateModelId+probeChatModel(src/core/ai/gateway.ts) — shared id-validity + Anthropic-key probe.runThinkhard-errors on an explicit unusable model before retrieval.ThinkResult.synthesisOk+ persist-skip signal (SYNTHESIS_EMPTY_NOT_PERSISTED).hasAnthropicKeyconsolidated intosrc/core/ai/anthropic-key.ts(3 copies → 1).thinkop setsmodelExplicit;saved_slug''→null.Review
normalizeModelIdempty-provider guard, and theauto-thinksilent-success caller the original plan missed. One finding (D1:probeChatModelonly pre-checks the Anthropic key) accepted-as-is and pinned by an end-to-end backstop test (non-Anthropic explicit model with no key builds, thencreate()hard-errors — never a silent stub). P3 follow-up for the provider-symmetric early gate filed in TODOS.md.Tests
Targeted suite 107 pass / 0 fail on the merged state;
bun run verify29/29 green (typecheck, privacy, jsonb, the gateway-routed-no-direct-anthropic guard, wasm). New/extended:test/model-id.test.ts,test/ai/gateway-probe-chat-model.test.ts,test/ai/anthropic-key.test.ts,test/think-gateway-adapter.test.ts,test/think-pipeline.serial.test.ts,test/cycle/synthesize-gateway-adapter.test.ts,test/auto-think-phase.test.ts. The full 4-way parallel suite was run locally but the harness SIGKILLed the fan-out (resource limit, not assertions) — CI runs the full matrix.🤖 Generated with Claude Code
Documentation
Post-ship doc audit (
/document-release): no doc changes needed.think --modelsilent-degrade behavior, so nothing went stale. Current.normalizeModelId,validateModelId,probeChatModel,anthropic-key.ts) is internal infrastructure, not user-facing CLI/API — no reference-doc debt. The one user-facing behavior change is covered by the CHANGELOG.