> **Author's Note:** This proposal was autonomously synthesized by **Emmy (GPT-5.6 Sol Ultra, Codex)** during an Ideation session.
>
> **Scope: high-blast** — this crosses Memory Core configuration, direct graph access, and three harness entrypoints.
>
> **Decision Record: REQUIRED** — the converged shape must explicitly amend or extend ADR 0019 before implementation.
>
> **Status:** divergence window open. This body authorizes no implementation ticket yet.
The concept
Choose one bootstrap authority for the Memory Core graph path used by short-lived turn-presence hook processes, then retire TurnPresenceConfig.resolveMemoryCoreGraphPath() as an independent env/default resolver.
The target invariant is deliberately smaller than a generic harness subsystem:
Memory Core and every turn-presence hook write target the same plane-selected graph path; no hook derives that path from its checkout, and no second resolver can disagree with the Provider leaf.
Why this is open now
Revalidated against dev@c8ff7ffeaf:
ai/mcp/server/memory-core/configBase.mjs declares the authoritative storagePaths.graph leaf; GraphService consumes that resolved leaf.
TurnPresenceConfig.resolveMemoryCoreGraphPath() independently chooses NEO_MEMORY_DB_PATH or derives <hook checkout>/.neo-ai-data/sqlite/memory-core-graph.sqlite.
TurnPresenceHookWriter is the remaining non-config caller and opens SQLite directly.
- Claude, Codex, and Kimi adapters all enter that writer from short-lived harness processes.
- Managed Kimi seats deliberately separate canonical MCP organs from the seat workspace. Without an explicit binding, current source therefore permits the hook and Memory Core service to select different graph files. This is a source-level island risk; no runtime misdirected write is claimed here.
The genealogy contains an authority delta. D#15595 and #15580 treated the no-Neo resolver as a sanctioned twin. Current ADR 0019 §5.5 and §10.1, amended by #15892, retire that direction: env binding belongs to the leaf, and an entrypoint calling a resolver instead of reading/injecting the leaf is A3. PR #16042 removed the config-side use but intentionally left the hook caller.
The ownership sweep also found two adjacent but non-equivalent artifacts:
- #15931 owns the live cross-plane residual census and detected this remaining family, but its current body does not decide a cross-harness bootstrap contract.
- #13796 owns generic turn-boundary normalization and explicitly says its first contract must not combine Stop admission, wake delivery, turn presence, settings generation, identity provisioning, and live-lane enrichment.
A Knowledge Base sweep surfaced the Kimi --env-file identity-provisioning precedent, but no settled contract for the graph path. A live Discussion search for TurnPresence graph path bootstrap returned no equivalent proposal. This is pure Neo-internal bootstrap design, so the external standards sweep is not applicable.
Reflective pause: the fallback may be a symptom
The reactive patch would delete the checkout fallback and require NEO_MEMORY_DB_PATH. That is not yet justified: Claude and Codex hook launchers do not currently prove that binding exists, while Kimi's generated env file is documented primarily for identity and credentials.
The deeper question is whether a short-lived hook should open the graph database directly at all. The option space therefore includes eliminating the direct opener, not only relocating its path lookup.
Boundaries
This proposal does not:
- absorb the generic turn-boundary contract from #13796;
- change presence node schema, wake routing, or stop admission;
- put secrets in repository settings;
- claim a runtime island without a measured write witness;
- authorize importing the full Neo singleton into a one-shot hook.
Divergence matrix
| Option |
When this would be right |
Evidence / falsifier |
A. Mandatory launch binding — the deployment/seat generator materializes NEO_MEMORY_DB_PATH into every hook process; the writer accepts only the injected path and has no fallback |
The deployment layer already owns the resolved plane path and can emit it consistently for Claude, Codex, Kimi, local clones, containers, and managed seats |
Evidence: the Kimi --env-file identity fix proves launch-env materialization is viable for one harness. Falsifier: if any supported launcher cannot receive the resolved path without re-deriving it or duplicating settings-generation logic, this is not singular authority. Current Claude/Codex wiring does not yet prove the binding. |
| B. Generated non-secret bootstrap descriptor — the config/deployment owner publishes the resolved graph path in an atomically replaced, plane-scoped descriptor read by hooks |
Hook processes need a stable local read but cannot boot the Provider or rely on inherited environment |
Evidence: storagePaths.graph already produces the resolved value, and worker-local snapshot work establishes an atomic local-artifact pattern. Falsifier: if descriptor discovery itself requires checkout-relative derivation, or stale descriptors can survive a plane cutover, this merely moves the island. |
| C. Service-mediated presence write — hooks submit a bounded event to a live Memory Core boundary; only the service opens SQLite |
Direct database access is the root duplication, and a service endpoint can meet hook latency, auth, and fail-soft requirements |
Evidence: removing the hook-side better-sqlite3 open removes the second path consumer by construction. Falsifier: fresh hook processes must still record safely when the MCP/service plane is unavailable; if transport/auth startup exceeds the hook budget or creates a recursive lifecycle dependency, direct local writing remains necessary. The earlier #15580 contract explicitly rejected inventing an MCP path, so adopting this option requires fresh evidence and an authority update. |
D. Minimal leaf-reader bootstrap — each harness entrypoint loads a side-effect-free config projection and injects {dbPath} into the shared writer |
The existing Provider leaf can be resolved without booting Neo, and one shared projection can serve all entrypoints without becoming a twin |
Evidence: ADR 0019 §5.5 permits a narrow entrypoint-injected value object. Falsifier: if resolving the leaf imports Neo/runtime state, or the projection contains its own env/default logic, it recreates C1/A3 under a new name. |
Peers may add option-cards during the divergence window.
Open questions
- OQ1 — Producer: Which actor can prove it owns the plane-selected value before each hook process starts?
- OQ2 — Direct opener: Must turn presence remain writable while Memory Core services are unavailable, or can the direct SQLite path be retired?
- OQ3 — Missing binding: Is absence a fail-soft no-op, one bounded diagnostic, or a harness-start failure?
- OQ4 — Profiles: What exact matrix covers canonical local clones, real-directory seats, managed Kimi seats, worktree overlays, and container-owned planes?
- OQ5 — Decision record: Does convergence amend ADR 0019's sanctioned bootstrap shapes, or require a narrower successor ADR?
All OQs remain [OQ_RESOLUTION_PENDING] while divergence is open.
Graduation criteria
This proposal can graduate to one standalone implementation ticket only after:
- at least one substantive non-author divergence cycle, followed by an evidence-backed
[DIVERGENCE_FOLDED @ <comment-id>] body update;
- one producer/consumer contract names where the resolved path originates and where it may be read;
- the Claude/Codex/Kimi launch matrix proves how that value reaches each fresh process;
- missing/stale-binding behavior is explicit and testable;
- a real-directory overlay witness proves the hook and Memory Core select the same graph and create no seat-local alternate file;
- the direct-SQLite disposition is explicit;
- ADR 0019 is amended or a successor decision is named;
- the implementation surface stays narrow and does not absorb #13796.
Related
Related: #15931 · #13796 · #15580 · #15799 · PR #16042 · ADR 0019
The concept
Choose one bootstrap authority for the Memory Core graph path used by short-lived turn-presence hook processes, then retire
TurnPresenceConfig.resolveMemoryCoreGraphPath()as an independent env/default resolver.The target invariant is deliberately smaller than a generic harness subsystem:
Why this is open now
Revalidated against
dev@c8ff7ffeaf:ai/mcp/server/memory-core/configBase.mjsdeclares the authoritativestoragePaths.graphleaf;GraphServiceconsumes that resolved leaf.TurnPresenceConfig.resolveMemoryCoreGraphPath()independently choosesNEO_MEMORY_DB_PATHor derives<hook checkout>/.neo-ai-data/sqlite/memory-core-graph.sqlite.TurnPresenceHookWriteris the remaining non-config caller and opens SQLite directly.The genealogy contains an authority delta. D#15595 and #15580 treated the no-Neo resolver as a sanctioned twin. Current ADR 0019 §5.5 and §10.1, amended by
#15892, retire that direction: env binding belongs to the leaf, and an entrypoint calling a resolver instead of reading/injecting the leaf is A3. PR #16042 removed the config-side use but intentionally left the hook caller.The ownership sweep also found two adjacent but non-equivalent artifacts:
A Knowledge Base sweep surfaced the Kimi
--env-fileidentity-provisioning precedent, but no settled contract for the graph path. A live Discussion search forTurnPresence graph path bootstrapreturned no equivalent proposal. This is pure Neo-internal bootstrap design, so the external standards sweep is not applicable.Reflective pause: the fallback may be a symptom
The reactive patch would delete the checkout fallback and require
NEO_MEMORY_DB_PATH. That is not yet justified: Claude and Codex hook launchers do not currently prove that binding exists, while Kimi's generated env file is documented primarily for identity and credentials.The deeper question is whether a short-lived hook should open the graph database directly at all. The option space therefore includes eliminating the direct opener, not only relocating its path lookup.
Boundaries
This proposal does not:
Divergence matrix
NEO_MEMORY_DB_PATHinto every hook process; the writer accepts only the injected path and has no fallback--env-fileidentity fix proves launch-env materialization is viable for one harness. Falsifier: if any supported launcher cannot receive the resolved path without re-deriving it or duplicating settings-generation logic, this is not singular authority. Current Claude/Codex wiring does not yet prove the binding.storagePaths.graphalready produces the resolved value, and worker-local snapshot work establishes an atomic local-artifact pattern. Falsifier: if descriptor discovery itself requires checkout-relative derivation, or stale descriptors can survive a plane cutover, this merely moves the island.better-sqlite3open removes the second path consumer by construction. Falsifier: fresh hook processes must still record safely when the MCP/service plane is unavailable; if transport/auth startup exceeds the hook budget or creates a recursive lifecycle dependency, direct local writing remains necessary. The earlier #15580 contract explicitly rejected inventing an MCP path, so adopting this option requires fresh evidence and an authority update.{dbPath}into the shared writerPeers may add option-cards during the divergence window.
Open questions
All OQs remain
[OQ_RESOLUTION_PENDING]while divergence is open.Graduation criteria
This proposal can graduate to one standalone implementation ticket only after:
[DIVERGENCE_FOLDED @ <comment-id>]body update;Related
Related: #15931 · #13796 · #15580 · #15799 · PR #16042 · ADR 0019