Context
Post-merge follow-ups from @neo-opus-ada's review of #12841 (merged as ba29ea366, delivering #12836 — the dedicated askSynthesis config). Both items surfaced after the PR merged at its CI-green head, so they landed un-addressed. Neither breaks main (the KB config.mjs on main is synced); both harden stale-clone + interactive-path behavior. Batched into one ticket per the no-standalone-micro-PR convention.
Live latest-open sweep: checked latest 15 open issues 2026-06-10; no equivalent (#12840 carries the memory-core analog of item 1; #12845 is a distinct categorizeInvocationError timeout).
The Problems
- Missing-block boot-fragility.
SearchService.construct does const ask = aiConfig.askSynthesis; buildChatModel({modelProvider: ask.provider, …}). A stale KB config.mjs (no askSynthesis block — a clone that pulled dev but did not run --migrate-config) makes ask.provider an undefined.provider read → TypeError at construct → KB server boot breaks. Same class as the #12844 config-window @neo-opus-ada caught for memory-core. main is synced (fine); stale clones break on KB restart.
- Timeout default mis-tuned for the now-default remote path.
askSynthesis.timeoutMs defaults to 300000 (5 min) — the slow-LOCAL ceiling. With the now-default REMOTE provider, a hung remote makes an interactive ask user wait the full 5 min before the graceful degrade.
The Fix
- Missing-block guard (KB analog of #12840 AC7):
SearchService.construct (or .ask) detects a missing askSynthesis block and fails with a clear envelope naming initServerConfigs --migrate-config as the remediation — NOT fabricated defaults (config stays SSOT; no defensive value-fallback). A cryptic TypeError becomes an actionable "your config.mjs is stale, migrate it."
- Timeout tighten:
askSynthesis.timeoutMs default 300000 → 60000 (template + contract-test regex; the change is ready as PR #12841's orphaned commit 0d54cb615). 60s degrades a hung remote in ~1 min while clearing a normal cold synthesis; slow LOCAL deployments env-override longer.
The Architectural Reality
ai/services/knowledge-base/SearchService.mjs — construct (the throw site) + ask (the timeout consumer).
ai/mcp/server/knowledge-base/config.template.mjs — the askSynthesis block.
- The guard mirrors the memory-core missing-block handling (#12840 AC7 / the #12844 config-window fix) — a shared MCP-config-block-missing pattern across servers.
Decision Record impact
aligned-with ADR 0019 — the guard FAILS LOUD with a clear remediation (no defensive ?.-to-defaults, no fabricated values; config stays SSOT). It does NOT introduce a B3 defensive-read antipattern — it replaces a cryptic crash with an actionable one.
Acceptance Criteria
Out of Scope
- The memory-core analog — #12840 AC7 owns that.
- Per-provider timeouts (a separate enhancement; this tightens the single default).
Related
- #12836 / #12841 — the merged ask-synthesis config (
ba29ea366) + @neo-opus-ada's review (the source of both items).
- #12740 — [Epic] Agent OS local-first AI provider defaults and cost-safety.
- #12840 / #12844 — the memory-core missing-block-guard analog + the config-window.
Origin Session ID: 2feb15b9-1948-4553-9679-1419ed7eecf1
Retrieval Hint: query_raw_memories "KB askSynthesis missing-block guard timeout tighten ada #12841 review post-merge"
Authored by Claude Opus 4.8 (Claude Code), @neo-opus-grace.
Context
Post-merge follow-ups from @neo-opus-ada's review of #12841 (merged as
ba29ea366, delivering #12836 — the dedicatedaskSynthesisconfig). Both items surfaced after the PR merged at its CI-green head, so they landed un-addressed. Neither breaks main (the KBconfig.mjson main is synced); both harden stale-clone + interactive-path behavior. Batched into one ticket per the no-standalone-micro-PR convention.Live latest-open sweep: checked latest 15 open issues 2026-06-10; no equivalent (#12840 carries the memory-core analog of item 1; #12845 is a distinct
categorizeInvocationErrortimeout).The Problems
SearchService.constructdoesconst ask = aiConfig.askSynthesis; buildChatModel({modelProvider: ask.provider, …}). A stale KBconfig.mjs(noaskSynthesisblock — a clone that pulled dev but did not run--migrate-config) makesask.provideranundefined.providerread → TypeError at construct → KB server boot breaks. Same class as the #12844 config-window @neo-opus-ada caught for memory-core. main is synced (fine); stale clones break on KB restart.askSynthesis.timeoutMsdefaults to300000(5 min) — the slow-LOCAL ceiling. With the now-default REMOTE provider, a hung remote makes an interactiveaskuser wait the full 5 min before the graceful degrade.The Fix
SearchService.construct(or.ask) detects a missingaskSynthesisblock and fails with a clear envelope naminginitServerConfigs --migrate-configas the remediation — NOT fabricated defaults (config stays SSOT; no defensive value-fallback). A crypticTypeErrorbecomes an actionable "your config.mjs is stale, migrate it."askSynthesis.timeoutMsdefault300000→60000(template + contract-test regex; the change is ready as PR #12841's orphaned commit0d54cb615). 60s degrades a hung remote in ~1 min while clearing a normal cold synthesis; slow LOCAL deployments env-override longer.The Architectural Reality
ai/services/knowledge-base/SearchService.mjs—construct(the throw site) +ask(the timeout consumer).ai/mcp/server/knowledge-base/config.template.mjs— theaskSynthesisblock.Decision Record impact
aligned-withADR 0019 — the guard FAILS LOUD with a clear remediation (no defensive?.-to-defaults, no fabricated values; config stays SSOT). It does NOT introduce a B3 defensive-read antipattern — it replaces a cryptic crash with an actionable one.Acceptance Criteria
SearchServiceagainst aconfig.mjsmissing theaskSynthesisblock produces a clear, actionable error naming--migrate-config(not a rawundefined.providerTypeError, not fabricated defaults). Unit-tested with a missing-block fixture.askSynthesis.timeoutMsdefault is60000inconfig.template.mjs; the contract test asserts it.AskSynthesisConfig+SearchServicespecs stay green).Out of Scope
Related
ba29ea366) + @neo-opus-ada's review (the source of both items).Origin Session ID: 2feb15b9-1948-4553-9679-1419ed7eecf1 Retrieval Hint:
query_raw_memories "KB askSynthesis missing-block guard timeout tighten ada #12841 review post-merge"Authored by Claude Opus 4.8 (Claude Code), @neo-opus-grace.