---
number: 11851
title: >-
  refactor(agentos): cross-daemon services bucket ai/services/{graph,ingestion}/
  (#11846)
author: neo-opus-ada
state: MERGED
createdAt: '2026-05-23T15:34:47Z'
updatedAt: '2026-05-23T15:44:51Z'
closedAt: '2026-05-23T15:44:47Z'
mergedAt: '2026-05-23T15:44:46Z'
head: tobiu/11846-cross-daemon-services-bucket
base: dev
url: 'https://github.com/neomjs/neo/pull/11851'
---
Authored by Claude Opus 4.7 (Claude Code). Session 5572d9a5-558d-4bea-b416-e31496c289c4.

FAIR-band: in-band [verify @ merge-gate]

Resolves #11846

## Summary

Sub 10 of Epic #11831 — moves the 10 cross-daemon services out of `ai/daemons/services/` (cleared by Subs 8 + 9) into thematic `ai/services/{graph,ingestion}/` folders mirroring the existing `ai/services/{github-workflow,gitlab-workflow,knowledge-base,memory-core,neural-link}/` buckets. The empty `ai/daemons/services/` folder + `test/playwright/unit/ai/daemons/services/` mirror are removed.

Evidence: L1 (61/61 moved-spec + 119/119 orchestrator + 130/130 touched-consumer; 2011 pass / 19 pre-existing flakes on full unit) → L1 required for substrate refactor (pure structural moves + mechanical import rewires; no behavioral change).

## Source moves (10)

**To `ai/services/graph/` (6):**
- `GapInferenceEngine.mjs`, `GoldenPathSynthesizer.mjs`, `GraphMaintenanceService.mjs`
- `LazyEdgeDrainer.mjs`, `SemanticGraphExtractor.mjs`, `TopologyInferenceEngine.mjs`

**To `ai/services/ingestion/` (4):**
- `ConceptDiscoveryService.mjs`, `ConceptIngestor.mjs`, `IssueIngestor.mjs`, `MemorySessionIngestor.mjs`

## Test moves (7)

Mirror source structure: 3 → `test/playwright/unit/ai/services/graph/`, 4 → `test/playwright/unit/ai/services/ingestion/`. (3 of the moved services have no spec files currently — GapInferenceEngine, GraphMaintenanceService, TopologyInferenceEngine.)

## Folder cleanup

- `ai/daemons/services/` removed (now empty post-Subs 8+9+10)
- `test/playwright/unit/ai/daemons/services/` removed

## Consumer updates

Depth preserved (both old `ai/daemons/services/X` and new `ai/services/{graph,ingestion}/X` are 2-deep under `ai/`). Most consumer imports needed only substring substitution `daemons/services/X.mjs` → `services/{folder}/X.mjs`. Manual fixes for relative-path consumers whose strings don't contain the literal `daemons/` segment:
- `Orchestrator.mjs:32` — `'../services/GoldenPathSynthesizer.mjs'` (resolves to old `ai/daemons/services/`) → `'../../services/graph/...'`
- `DreamService.mjs:14-23` — 9× `'../../services/X.mjs'` pattern → `'../../../services/{folder}/...'`

22 consumer files updated total (covers `ai/services/`, `ai/services/memory-core/`, `ai/services/github-workflow/`, `ai/scripts/priorityBackfill.mjs`, `ai/mcp/server/memory-core/config.template.mjs`, `buildScripts/ai/runSandman.mjs`, plus 15 spec files).

## V-B-A discipline (#11845 lesson)

Sub 9's missed relative-path patterns (`SummarizationCoordinator's relative bridge-queries import`) prompted me to follow substring-sweep with a **second-stage grep for proximity-relative patterns**:

```
grep -rnE "from\s+['\"]\\.\\.([./]+)services/(Gap|Golden|Graph|Lazy|Semantic|Topology|Concept|Issue|MemorySession)" ai/daemons/orchestrator/
```

That caught the 10 stale Orchestrator + DreamService refs that substring substitution missed. Same dual-sweep applied for dynamic `await import()` — none found.

## Test Evidence

- Moved-spec subsuite (`test/playwright/unit/ai/services/{graph,ingestion}/`): **61/61 pass (1.9s)**
- Orchestrator suite: **119/119 pass (6.5s)** — DreamService spec needed individual rerun due to parallel-worker Chroma contention flake; passes deterministically when run alone
- Touched consumer specs (GraphService + MailboxService + MemoryService.Frontier + WakeSubscription + SyncService.Stage2): **130/130 pass (1.5s)**
- **Full unit suite**: 2011 pass / 19 fail / 2 skip / 10 did-not-run. All 19 failures pre-existing (mcp/Authorization, scripts/checkAllAgentIdle×2, scripts/checkSunsetted×5, services/memory-core/{QueryReRanker, SessionSummarization, TextEmbeddingService.retry}, grid/{LockedColumns×2, Pooling×3, Teleportation×2}, vdom/table/Container); verified ZERO references to moved files via grep.

## Post-Merge Validation

- [ ] Operator restarts orchestrator → DreamService boots, all 9 services resolve from `ai/services/{graph,ingestion}/`
- [ ] Operator confirms `npm run ai:dream` (if exposed) + scheduled DREAM_TASK cycle runs cleanly
- [ ] Integration suite passes on dev post-merge

## Deltas from ticket

None — implementation matches #11846 ACs verbatim. (Did NOT include any cosmetic JSDoc `@class Neo.ai.daemons.services.X` namespace re-anchoring — that's a follow-up cleanup, separate scope; the file moves alone are functionally complete.)

## Depends on

- Sub 8 #11844 — merged ✓
- Sub 9 #11845 — merged ✓ (cleared `ai/daemons/services/` of orchestrator-private + sub-daemon-specific files; this PR moves the remainder)

## Unblocks

- Sub 11 #11847 (ai/scripts/ thematic split)
- Sub 12 #11848 (buildScripts/ai/ collapse)

Per @tobiu's "you and me" instruction: no peer-review broadcast on this lane.

## Reviews

### `@tobiu` (APPROVED) reviewed on 2026-05-23T15:44:32Z

*No review body provided.*

---

