A merged PR may require knowledge-base updates. Review the change and update library/ as needed.
Source PR
- PR: #308 - feat: memory-graph persistence follows the memory switch, applies live, and reports why-empty (ISS-002)
- Author: @thenotoriousllama
- Merged into:
main
- Files changed: 20
PR description
feat: memory-graph persistence follows the memory switch, applies live, and reports why-empty (ISS-002)
The problem
The Memory Graph view works end-to-end, but its source tables (entities, entity_dependencies) were never written: graph persistence hid behind TWO default-off env flags (HONEYCOMB_PIPELINE_GRAPH_ENABLED + HONEYCOMB_PIPELINE_GRAPH_EXTRACTION_WRITES, pipeline/config.ts) that no product surface ever set — systemic pattern SP-2. Since 0.17.0 the upstream prerequisites are fixed (queue default-on, Portkey extraction working); the gates were the last blocker.
The product decision (approved)
Graph persistence FOLLOWS THE MEMORY MASTER SWITCH by default. One vault-first setting, graph.enabled, replaces the two hidden env flags as the product-facing switch.
Precedence (documented at the resolution site, assemble.ts buildPipelineWorker + config.ts resolveGraphEnabledVaultFirst)
- Explicit env — either legacy flag set (non-blank) → the env decides (back-compat / operator opt-out). The two flags AND together; an unset one defaults ON, so a single explicit
false opts out and a single explicit true opts in (the old two-flag trap is gone).
- Vault
graph.enabled — present (true OR false) → it decides. Writable via POST /api/settings/graph.enabled.
- Default-follows-memory — the resolved vault-first memory master switch. Memory formation on → graph on.
The old extractionWritesEnabled sub-gate collapses into the same switch: ONE resolved boolean drives the graph-persist stage.
What changed
- Unified gate (
pipeline/config.ts, vault/api.ts, pipeline/graph-persist.ts): readGraphEnvDecision + resolveGraphEnabledVaultFirst (pure, unit-tested); GRAPH_ENABLED_KEY joins KNOWN_SETTING_KEYS; the stage gates on one boolean (legacy conjunction preserved for pure-config callers).
- Live application (
vault/api.ts, assemble.ts): graph.enabled joins `PIPELINE_WATCHED_SETTI
Files touched
.claude-plugin/marketplace.json (+2/-2)
.claude-plugin/plugin.json (+1/-1)
CHANGELOG.md (+4/-0)
harnesses/claude-code/.claude-plugin/plugin.json (+1/-1)
harnesses/codex/package.json (+1/-1)
harnesses/openclaw/openclaw.plugin.json (+1/-1)
harnesses/openclaw/package.json (+1/-1)
package-lock.json (+2/-2)
package.json (+1/-1)
src/daemon/runtime/assemble.ts (+75/-23)
src/daemon/runtime/dashboard/api.ts (+71/-6)
src/daemon/runtime/pipeline/config.ts (+73/-0)
src/daemon/runtime/pipeline/graph-persist.ts (+28/-9)
src/daemon/runtime/pipeline/index.ts (+3/-0)
src/daemon/runtime/vault/api.ts (+19/-0)
src/dashboard/contracts.ts (+28/-1)
tests/daemon/runtime/dashboard/api.test.ts (+89/-0)
tests/daemon/runtime/pipeline/config.test.ts (+94/-0)
tests/daemon/runtime/pipeline/graph-persist.test.ts (+185/-0)
tests/daemon/runtime/vault/settings-reload-trigger.test.ts (+3/-0)
Auto-generated by .github/workflows/kb-issue-on-merge.yaml on merge.
A merged PR may require knowledge-base updates. Review the change and update
library/as needed.Source PR
mainPR description
feat: memory-graph persistence follows the memory switch, applies live, and reports why-empty (ISS-002)
The problem
The Memory Graph view works end-to-end, but its source tables (
entities,entity_dependencies) were never written: graph persistence hid behind TWO default-off env flags (HONEYCOMB_PIPELINE_GRAPH_ENABLED+HONEYCOMB_PIPELINE_GRAPH_EXTRACTION_WRITES,pipeline/config.ts) that no product surface ever set — systemic pattern SP-2. Since 0.17.0 the upstream prerequisites are fixed (queue default-on, Portkey extraction working); the gates were the last blocker.The product decision (approved)
Graph persistence FOLLOWS THE MEMORY MASTER SWITCH by default. One vault-first setting,
graph.enabled, replaces the two hidden env flags as the product-facing switch.Precedence (documented at the resolution site,
assemble.tsbuildPipelineWorker+config.tsresolveGraphEnabledVaultFirst)falseopts out and a single explicittrueopts in (the old two-flag trap is gone).graph.enabled— present (true OR false) → it decides. Writable viaPOST /api/settings/graph.enabled.The old
extractionWritesEnabledsub-gate collapses into the same switch: ONE resolved boolean drives the graph-persist stage.What changed
pipeline/config.ts,vault/api.ts,pipeline/graph-persist.ts):readGraphEnvDecision+resolveGraphEnabledVaultFirst(pure, unit-tested);GRAPH_ENABLED_KEYjoinsKNOWN_SETTING_KEYS; the stage gates on one boolean (legacy conjunction preserved for pure-config callers).vault/api.ts,assemble.ts):graph.enabledjoins `PIPELINE_WATCHED_SETTIFiles touched
.claude-plugin/marketplace.json(+2/-2).claude-plugin/plugin.json(+1/-1)CHANGELOG.md(+4/-0)harnesses/claude-code/.claude-plugin/plugin.json(+1/-1)harnesses/codex/package.json(+1/-1)harnesses/openclaw/openclaw.plugin.json(+1/-1)harnesses/openclaw/package.json(+1/-1)package-lock.json(+2/-2)package.json(+1/-1)src/daemon/runtime/assemble.ts(+75/-23)src/daemon/runtime/dashboard/api.ts(+71/-6)src/daemon/runtime/pipeline/config.ts(+73/-0)src/daemon/runtime/pipeline/graph-persist.ts(+28/-9)src/daemon/runtime/pipeline/index.ts(+3/-0)src/daemon/runtime/vault/api.ts(+19/-0)src/dashboard/contracts.ts(+28/-1)tests/daemon/runtime/dashboard/api.test.ts(+89/-0)tests/daemon/runtime/pipeline/config.test.ts(+94/-0)tests/daemon/runtime/pipeline/graph-persist.test.ts(+185/-0)tests/daemon/runtime/vault/settings-reload-trigger.test.ts(+3/-0)Auto-generated by
.github/workflows/kb-issue-on-merge.yamlon merge.