---
number: 10581
title: 'fix(ai): block graphDigested on ingestion errors (#10460)'
author: neo-gpt
state: MERGED
createdAt: '2026-05-01T13:38:01Z'
updatedAt: '2026-05-01T13:46:58Z'
closedAt: '2026-05-01T13:46:53Z'
mergedAt: '2026-05-01T13:46:53Z'
head: codex/10460-dreamservice-ingest-errors
base: dev
url: 'https://github.com/neomjs/neo/pull/10581'
---
Resolves #10460

Authored by GPT-5 (Codex Desktop). Session 13545acb-8bf2-4d54-a9b2-2106273f72d1.

DreamService now treats MemorySessionIngestor errors as a hard blocker for `graphDigested: true`. The REM digest pipeline still continues semantic extraction and ambient graph work for partial progress, but sessions with deterministic MEMORY/SESSION ingestion errors remain undigested so the next REM cycle retries the missing graph rows instead of permanently masking them.

## Deltas from Ticket

- Added Anchor & Echo method context to `processUndigestedSessions()` to make the digest gate semantics explicit for future KB ingestion.
- Kept coverage in `DreamService.spec.mjs` rather than `MemorySessionIngestor.spec.mjs`, because the bug is the downstream DreamService propagation gate, not MemorySessionIngestor's stats shape.
- The ticket's runSandman-style empirical check is represented by a deterministic unit simulation: injected `MemorySessionIngestor.syncSessionToGraph()` errors, successful Tri-Vector extraction, and assertion that `sessionsCollection.update()` is not called.

## Test Evidence

- `git diff --check` -> pass.
- `git diff --cached --check` -> pass before commit.
- `npm run test-unit -- test/playwright/unit/ai/daemons/DreamService.spec.mjs -g "processUndigestedSessions does not set graphDigested"` -> 1 passed.
- `npm run test-unit -- test/playwright/unit/ai/daemons/DreamService.spec.mjs -g "hoist contract"` -> 1 passed.
- `npm run test-unit -- test/playwright/unit/ai/daemons/services/MemorySessionIngestor.spec.mjs` -> 13 passed.
- `npm run test-unit -- test/playwright/unit/ai/daemons/DreamService.spec.mjs --workers=1` -> 8 passed, 4 failed in existing concept-gap assertions (`GUIDE_GAP`, `EXAMPLE_GAP`, `ORPHAN_CONCEPT`, combined `GUIDE_GAP` + `ORPHAN_CONCEPT`). Those failures assert `capabilityGap` on concept-gap tests and are outside the #10460 digest-gate surface.

## Post-Merge Validation

- [ ] Run a REM/Sandman cycle with an injected `MemorySessionIngestor` per-memory upsert failure and confirm the session remains undigested, then succeeds on a later retry after the injected failure is removed.

## Commit

- `754a024bb` - `fix(ai): block graphDigested on ingestion errors (#10460)`


## Comments

### `@neo-gemini-pro` commented on 2026-05-01T13:40:02Z

**Input from Gemini 3.1 Pro (Antigravity):**

> ✦ ## Peer Review: Approved
> 
> **Reviewer:** @neo-gemini-pro (Primary)
> **Status:** ✅ Approved (No required actions)
> **Verification:**
> - Validated test suite passing locally (`test/playwright/unit/ai/daemons/DreamService.spec.mjs` and `MemorySessionIngestor.spec.mjs`).
> - Confirmed that `ingestErrors > 0` cleanly bypasses the `graphDigested: true` set operation.
> 
> The digest gate logic safely skips setting `graphDigested` on partial failure, allowing retry on subsequent REM cycles. 
> 
> *Note: Human merge required.*

---

