---
id: 12059
title: Fix Sandman graph provider routing
state: CLOSED
labels:
  - bug
  - ai
  - regression
  - architecture
assignees:
  - neo-gpt
createdAt: '2026-05-26T23:47:31Z'
updatedAt: '2026-06-07T17:16:10Z'
githubUrl: 'https://github.com/neomjs/neo/issues/12059'
author: neo-gpt
commentsCount: 0
parentIssue: null
subIssues: []
subIssuesCompleted: 0
subIssuesTotal: 0
blockedBy: []
blocking: []
closedAt: '2026-05-27T12:09:33Z'
---
# Fix Sandman graph provider routing

## Context

Operator reported a P0 regression while running `npm run ai:run-sandman` manually on May 26, 2026. The run initialized Memory Core, found undigested sessions, successfully ran deterministic Memory/Session graph ingestion for the first session, then failed during Tri-Vector extraction:

```text
buildGraphProvider: unsupported modelProvider 'gemini'. Expected one of: 'ollama', 'openAiCompatible'.
```

The operator also observed that the resulting handoff file is incomplete and stated the Sandman/Dream pipeline should never use Gemini for this path.

## The Problem

The closed provider-routing work in #11965 deliberately made graph dispatch support `ollama` and `openAiCompatible`, and `providerDispatch.mjs` correctly rejects `gemini` rather than silently falling back. However, Sandman/Dream graph call sites still read the generic Memory Core `modelProvider` value. The Tier-1 default remains `gemini`, so manual Sandman can crash before completing semantic extraction and Golden Path handoff generation.

This is not a request to add Gemini support to graph dispatch. The regression is that the Sandman/Dream graph-generation path is using the wrong provider axis.

## The Architectural Reality

- `ai/config.mjs:70` and `ai/config.mjs:79` default `chatProvider` / `modelProvider` to `gemini`.
- `ai/services/graph/providerDispatch.mjs:19` documents graph dispatch support as `ollama` or `openAiCompatible`; `providerDispatch.mjs:51-55` throws for unsupported providers.
- `ai/services/graph/SemanticGraphExtractor.mjs:96-100` passes `aiConfig.modelProvider` into `buildGraphProvider()`.
- `ai/services/graph/TopologyInferenceEngine.mjs:57-61` does the same for topology extraction.
- `ai/services/graph/GoldenPathSynthesizer.mjs` also instantiates graph provider dispatch from `aiConfig.modelProvider`.
- `learn/agentos/DreamPipeline.md:321` already documents the Dream extraction provider default as `openAiCompatible`, so current code and docs disagree.
- Related closed authority: #11965 AC included "Dream/REM graph-mutator provider reachability is not hardwired to the wrong provider family." PR #11966 implemented provider dispatch and tests that `gemini` is unsupported for graph dispatch.

## The Fix

Introduce or reuse a graph-generation provider selector that defaults Sandman/Dream graph work to `openAiCompatible`, while preserving explicit `ollama` support and explicit failure for unknown provider names.

The fix should update all graph-generation call sites consistently:

- `SemanticGraphExtractor.executeTriVectorExtraction()`
- `SemanticGraphExtractor.extractMessageConcepts()`
- `TopologyInferenceEngine.extractTopology()`
- `GoldenPathSynthesizer.synthesizeGoldenPath()`

Manual Sandman should probe and use the same provider axis it will later dispatch through. It must not claim OpenAI-compatible readiness while the graph dispatch path still points at `gemini`.

## Contract Ledger Matrix

| Target Surface | Source of Authority | Proposed Behavior | Fallback | Docs | Evidence |
|---|---|---|---|---|---|
| Sandman/Dream graph provider selector | #11965 graph dispatch contract + operator P0 reproducer | Graph-generation call sites use `openAiCompatible` by default, or `ollama` when explicitly configured for graph work | Unknown values fail before partial handoff generation | `DreamPipeline.md` and config JSDoc | Unit test with `modelProvider: 'gemini'` and graph provider default |
| Manual `ai:run-sandman` readiness gate | Operator P0 reproducer | Readiness probe checks the provider family that graph dispatch will use | Unsupported graph provider exits with a clear diagnostic before REM mutation | runner JSDoc/log message | Unit test for provider mismatch diagnostic |
| Handoff integrity | `sandman_handoff.md` consumer contract | A provider-axis mismatch must not produce a misleading "complete" Sandman run or incomplete handoff without a failure state | Preserve existing heavy-maintenance lease and graph-decay safeguards | PR body | Focused runner/DreamService tests |

## Decision Record impact

Aligned with ADR 0015 graph-store backend posture and with #11965 provider-routing closure. No ADR amendment expected.

## Acceptance Criteria

- [ ] `npm run ai:run-sandman` no longer routes graph extraction through `gemini` when no graph-specific provider is configured.
- [ ] Graph-generation call sites share one selector/helper instead of each reading generic `modelProvider` directly.
- [ ] Explicit `ollama` graph routing remains supported.
- [ ] Unsupported graph provider values fail with a clear diagnostic before partial REM/handoff work proceeds.
- [ ] Tests cover the regression: `modelProvider: 'gemini'` with no graph override routes graph work to `openAiCompatible`, not to `gemini`.
- [ ] PR evidence includes the operator reproducer, focused unit tests, and a syntax/static check. Full local `ai:run-sandman` may be skipped if it would mutate live Memory Core, but the reason must be documented.

## Out of Scope

- Adding Gemini support to `providerDispatch.mjs`.
- Changing embedding provider defaults.
- Reworking all Tier-1 provider key migration.
- Running destructive or broad Sandman cycles against production Memory Core without explicit operator direction.

## Related

- Parent provider-routing work: #11965 / PR #11966
- Parent config epic: #10103
- Dream pipeline docs: `learn/agentos/DreamPipeline.md`

Origin Session ID: d84ad2f1-c71c-4ce4-bec7-1167b9183637

Handoff Retrieval Hint: `query_raw_memories("runSandman unsupported modelProvider gemini DreamService SemanticGraphExtractor providerDispatch")`

## Timeline

- 2026-05-26T23:47:32Z @neo-gpt assigned to @neo-gpt
- 2026-05-26T23:47:32Z @neo-gpt added the `bug` label
- 2026-05-26T23:47:33Z @neo-gpt added the `ai` label
- 2026-05-26T23:47:33Z @neo-gpt added the `regression` label
- 2026-05-26T23:47:33Z @neo-gpt added the `architecture` label
- 2026-05-27T00:19:19Z @neo-gpt cross-referenced by PR #12061
- 2026-05-27T01:25:30Z @neo-opus-ada cross-referenced by #12063
- 2026-05-27T01:27:44Z @neo-opus-ada cross-referenced by PR #12064
- 2026-05-27T01:40:53Z @neo-opus-ada cross-referenced by #12065
- 2026-05-27T01:41:28Z @neo-gpt cross-referenced by #12066
- 2026-05-27T06:17:13Z @neo-gpt referenced in commit `434356b` - "fix(ai): route Sandman graph providers explicitly (#12059)"
- 2026-05-27T07:41:19Z @neo-gpt referenced in commit `0b8879c` - "fix(ai): preserve graphProvider null default (#12059)"
- 2026-05-27T07:42:49Z @neo-gpt referenced in commit `89a2fb0` - "fix(ai): inherit graphProvider overlay verbatim (#12059)"
- 2026-05-27T09:06:58Z @neo-gpt referenced in commit `95ee553` - "fix(ai): derive graph consumer model from provider config (#12059)"
- 2026-05-27T09:48:50Z @neo-gpt referenced in commit `eb8f99f` - "fix(ai): replace graph provider null default (#12059)"
- 2026-05-27T09:59:51Z @neo-gpt referenced in commit `33ce624` - "fix(ai): make graph provider config explicit (#12059)"
- 2026-05-27T12:09:34Z @tobiu referenced in commit `d1a4980` - "fix(ai): route Sandman graph providers explicitly (#12059) (#12061)

* fix(ai): route Sandman graph providers explicitly (#12059)

* fix(ai): preserve graphProvider null default (#12059)

* fix(ai): inherit graphProvider overlay verbatim (#12059)

* fix(ai): derive graph consumer model from provider config (#12059)

* fix(ai): replace graph provider null default (#12059)

* fix(ai): make graph provider config explicit (#12059)

---------

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
- 2026-05-27T12:09:34Z @tobiu closed this issue
- 2026-06-03T07:48:42Z @neo-gpt cross-referenced by #10484

