feat(ruflo): govern ruflo memory on the ruvector-postgres sidecar (ADR-2123) - #19
Merged
Merged
Conversation
…ADR-2123) ruflo 3.51.1's memory subsystem is local-only: sql.js under .swarm/, an AgentDB mirror, the native engine's ./ruvector.db in the CWD and a MiniLM ONNX embedder. Its --backend flag is a label written into a metadata table; no value reaches Postgres and no setting selects an embedding endpoint. Its MCP server given the sidecar's full RUVECTOR_PG_*/PG* env still searched an empty local store (tested 2026-10-03). Every `ruflo` call, --help included, autostarted a daemon into the CWD. The ruflo-console memory pane reaches memory only via `ruflo memory stats|list --format json`, so with the stock binary it shows an empty local store, never the governed corpus. The image's `ruflo`/`claude-flow` bins are now governed wrappers (rufloGovernedPkg): - `ruflo memory …` execs mcp/servers/ruflo-memory-cli.cjs, which reuses lib/memory-tools.js with the MCP server's pool, Xinference embedder and `agentbox:<ns>:<key>` entry ids, serves store/retrieve/search/list/delete/ stats from the sidecar, and emits ruflo 3.51.1's --format json shapes so the console's parsers are unchanged. init/configure/cleanup/compress/ export/import/purge/distill/backup/classify/select-operator/migrate are refused (exit 2, no file). Fails closed without pg or an embedding. - every other subcommand runs the real CLI with overridable defaults, also exported at boot: RUFLO_DAEMON_AUTOSTART=0, CLAUDE_FLOW_DISABLE_BRIDGE=1, CLAUDE_FLOW_MEMORY_PATH=~/.cache/ruflo/memory. - claude-flow-mcp (the ADR-2082 proxy child) passes through unchanged; the gate is unchanged, so a gate-off image is byte-identical (ADR-2020). Verified live against the sidecar (213,332 rows, 464 namespaces): stats and list in the ruflo shapes, HNSW search via hnsw-xinference (0.795/0.776), a store→search→retrieve→delete round trip in `cli-probe`, refusals exit 2 with a clean tree. The simulated wrapper run against the real binary in an empty directory: no daemon, no files; `swarm status` works; `memory stats` routed. tests/contract/ruflo-memory-cli.contract.spec.js (23 stub-backed cases) and tests/config/ruflo-memory-governed.test.sh pass. Co-Authored-By: jjohare <github@thedreamlab.uk>
…(ADR-2123) RUFLO_DAEMON_AUTOSTART, CLAUDE_FLOW_DISABLE_BRIDGE and CLAUDE_FLOW_MEMORY_PATH are switches and a path, exported at boot and defaulted by the ruflo wrapper; env-secret-inventory requires every name the boot path reads to be classed. Co-Authored-By: jjohare <github@thedreamlab.uk>
1fc26c7); ADR-2123 verified Co-Authored-By: jjohare <github@thedreamlab.uk>
… as a root-side literal (RC-X1-01) The runtime-env export defaulted the path to a literal /home/devuser, which the runtime contract forbids for any PATH-named assignment executed by root. Escaped, it resolves to the sourcing user's $HOME/.cache/ruflo/memory. Co-Authored-By: jjohare <github@thedreamlab.uk>
…f5e42) Co-Authored-By: jjohare <github@thedreamlab.uk>
…e-affirm ADR-2014 Grounded in ruvnet-kb: ruvector-core is one library in two products (embedded engine, Postgres extension) sharing algorithms, not storage. ruflo's memory is local-first by design (claude-flow ADR-009/017/057/342); Postgres was deferred and later scoped as a bridge (ruflo ADR-027, Proposed). The extension is current (v2.0.6, ruvector ADR-044 v0.3 in progress); this image runs 2.0.5 / ext 0.3.0. Rule added: same vendor and dimension do not mean same wire; prove it live. Co-Authored-By: jjohare <github@thedreamlab.uk>
jjohare
added a commit
that referenced
this pull request
Oct 5, 2026
Co-Authored-By: jjohare <github@thedreamlab.uk>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
ruflo 3.51.1's memory subsystem is local-only (sql.js under
.swarm/, an AgentDB mirror, the native engine's./ruvector.dbin the CWD, a MiniLM ONNX embedder). Its--backendflag is a label; no value reaches Postgres and no setting selects an embedding endpoint. Its MCP server given the sidecar's fullRUVECTOR_PG_*/PG*env still searched an empty local store (live stdio test, 2026-10-03). Everyrufloinvocation,--helpincluded, autostarted a daemon into the CWD. The ruflo-console memory pane reaches memory only by shelling out toruflo memory stats|list --format json, so with the stock binary it shows an empty local store. Onememory initrun left three local stores in a repository, one not gitignored.What
The image's
ruflo/claude-flowbins are governed wrappers (rufloGovernedPkg, ADR-2123):ruflo memory …→mcp/servers/ruflo-memory-cli.cjs, reusinglib/memory-tools.jswith the MCP server's pool, Xinference embedder (bge-small-en-v1.5, 384-d, GPU) andagentbox:<ns>:<key>entry ids. Serves store/retrieve/search/list/delete/stats from the sidecar in ruflo 3.51.1's--format jsonshapes, so the console's parsers are unchanged and its memory pane shows the governed corpus.init,configure,cleanup,compress,export,import,purge,distill,backup,classify,select-operator,migrateare refused (exit 2, no file). Fails closed without pg or an embedding (ADR-2014).RUFLO_DAEMON_AUTOSTART=0,CLAUDE_FLOW_DISABLE_BRIDGE=1,CLAUDE_FLOW_MEMORY_PATH=~/.cache/ruflo/memory.claude-flow-mcp(ADR-2082 proxy child) passes through unchanged. Gate unchanged: gate-off image byte-identical (ADR-2020).Evidence
hnsw-xinference(0.795 / 0.776); store → search (0.769) → retrieve → delete round trip incli-probe; refusals exit 2, tree clean.swarm statusworks;memory statsrouted.tests/contract/ruflo-memory-cli.contract.spec.js: 23 stub-backed cases.tests/config/ruflo-memory-governed.test.sh: static wrapper/gate/env/refusal checks plus a live check inside the image.flake-checkhere is the first real evaluation. The baked wrapper is verified at the host rebuild.ADR ledger
invariantsis red on main for its last three runs: 19 records went stale onflake.nix/agentbox.tomlfrom the sidechain, poker and console commits after the pins' last re-verification (09e6271e9). A follow-up commit on this branch re-verifies them and sets ADR-2123'sverified_commit.🤖 Generated by Claude Code