---
number: 12171
title: 'fix(data): api stores no longer auto-create a default Pipeline (#12170)'
author: neo-opus-ada
state: MERGED
createdAt: '2026-05-29T12:04:53Z'
updatedAt: '2026-05-29T12:22:36Z'
closedAt: '2026-05-29T12:22:32Z'
mergedAt: '2026-05-29T12:22:32Z'
head: claude/inspiring-villani-0feb1f
base: dev
url: 'https://github.com/neomjs/neo/pull/12171'
---
Authored by Claude Opus 4.8 (Claude Code). Memory-core orchestrator was deactivated this session, so no Origin Session ID is available.

FAIR-band: operator-directed PR (explicit request) — not autonomous lane self-selection; swarm band-gating N/A.

Resolves #12170

api-configured stores were silently getting a default `Pipeline` instance, so `Store.load()`'s `if (me.pipeline)` branch always shadowed the `else if (me.api)` remotes-api branch — an `autoLoad: true` api store never fired its RPC. Surfaced while dogfooding #12134 in a real websocket-backed remotes-api app. A one-line guard in `beforeSetPipeline()` keeps api stores at `pipeline === null` so they reach the api branch (which already carries the #12132/#12134 fix).

Evidence: L1 (unit: api store → `pipeline === null` + non-api default preserved; api-branch reachability is deterministic once `pipeline === null`) → L3 live RPC confirmation deferred to the consuming app post dependency-bump. Residual: live autoLoad ws RPC.

## Root cause

`ClassSystemUtil.beforeSetInstance(value, Pipeline, …)` mints a default instance for a falsy value (`if (!config && DefaultClass) Neo.create(...)`). `beforeSetPipeline()` only skipped that path for the url case, so every api store got a spurious `Pipeline` (plus its `onPipelinePush` listener) and `load()` never reached the api branch.

## The fix

`src/data/Store.mjs` `beforeSetPipeline()`: return `null` early when `me.api` is set — api stores load via remotes-api, never a pipeline. The url guard simplifies to `!value && me.url` (the `!me.api` term is now subsumed by the early return). Order-independent: Neo resolves reactive configs on demand via `configSymbol`, so `me.api` reads correctly regardless of config processing order.

## Deltas from ticket

None of substance — implements #12170's prescribed `if (me.api) return null` guard verbatim (strict `api XOR pipeline` form). The `!value && me.api` permissive variant (which would preserve runtime api→pipeline switching) was considered and rejected per the ticket, weighed as a ~0.001% case.

## Test Evidence

New `test/playwright/unit/data/StoreApiPipeline.spec.mjs` — 3 cases: api → `pipeline===null`; api + `autoLoad:true` → `pipeline===null`; non-api → default `Pipeline` preserved.

- `npm run test-unit -- test/playwright/unit/data/StoreApiPipeline.spec.mjs` → **3 passed** (555ms)
- `npm run test-unit -- test/playwright/unit/data/` → **56 passed** (830ms) — no regression across the Store/TreeStore suite

## Post-Merge Validation

- [ ] A consuming remotes-api app (api store + `autoLoad: true`) renders data over the websocket after `npm update neo.mjs` — i.e. `load()` fires the RPC end-to-end.


## Comments

### `@github-actions` commented on 2026-05-29T12:05:04Z

## 🚨 Agent PR Body Lint Violation

@neo-opus-ada — your [PR body on PR #12171](https://github.com/neomjs/neo/pull/12171) does not match the pull-request template structure.

**Required action**: read `.agents/skills/pull-request/SKILL.md` BEFORE editing the PR body. The skill points at:
  - Minimum-viable PR body structure: `.agents/skills/pull-request/references/pull-request-workflow.md §9`
  - Self-Identification mandate: `.agents/skills/pull-request/references/pull-request-workflow.md §5`

Do NOT compose a substitute template or hallucinate section headings. The validator
checks more structural anchors than this comment names. The only reliable path to
passing is reading the actual workflow file and following its structure.

**Diagnostic hint**: visible anchors appear present but the structural template anchors do not.

<details>
<summary>Visible anchors missing (full list)</summary>

(none — visible layer passed; invisible structural layer caught the miss)

</details>

<sub>This is the CI tool-boundary lint companion to PR #11494's MCP `manage_pr_review` validator and PR #11502's `agent-pr-review-body-lint.yml` reviewer-side lint.
Resolves #11501.</sub>

---

