Skip to content

dream(memory): #4137 wire delete-sync into AutoMemoryBridge.importFromAutoMemory() (evaluated, ACCEPT) - #4138

Merged
ruvnet merged 9 commits into
mainfrom
dream/2026-10-13-memory
Oct 20, 2026
Merged

ruvnet merged 9 commits into
mainfrom
dream/2026-10-13-memory

Conversation

@ruvnet

@ruvnet ruvnet commented Oct 13, 2026

Copy link
Copy Markdown
Owner

1. Hypothesis

Given a workload of N previously-imported auto-memory markdown files in AgentDB's auto-memory namespace, when importFromAutoMemory() is extended to diff each file's current parsed heading-keys (and each previously-seen source file's continued existence on disk) against the AgentDB entries tagged with that file's metadata.sourceFile, deleting entries no longer present, then entries for removed headings or vanished files should be deleted from AgentDB within one import call (baseline: they persist indefinitely), subject to: (a) other namespaces/files unaffected; (b) a non-empty-but-zero-entry parse does not trigger deletion; (c) a suspiciously-empty directory listing does not trigger whole-file deletion; (d) a per-file read/parse failure does not abort the rest of the batch or trigger deletion for that file; (e) all existing tests remain green.

2. Candidate

v3/@claude-flow/memory/src/auto-memory-bridge.ts: importFromAutoMemory() now builds a per-source-file key→id index from the existing single bulk query (fetchExistingAutoMemoryIndex(), renamed from fetchExistingContentHashes()), diffs it against each file's current parse, and bulkDelete()s stale ids — plus a second pass for files removed entirely from disk. Zero schema changes (metadata.sourceFile/heading/key already existed per entry). Mirrors the existing same-key eviction pattern in agentdb-adapter.ts's bulkInsert() (2026-09-18).

3. Evaluation Receipt

Vitest 4.1.8, deterministic, $0. 7 new discriminating tests in auto-memory-bridge.test.ts. Stash-isolated (source reverted, tests kept): baseline fails all 7, candidate passes all 7. Full @claude-flow/memory suite: baseline 606/607 (1 pre-existing chmod-under-root flake), candidate 611/614 (+7 new; same chmod flake + 2 CPU-contention-sensitive timing tests in untouched files, confirmed non-deterministic by not reproducing on a repeat baseline run). tsc --noEmit: 0 errors both ways.

4. Baseline Comparison

Baseline: entries for a removed heading or a deleted source file persist in AgentDB's auto-memory namespace forever, retrievable via semantic search. Candidate: deleted within the next importFromAutoMemory() call.

5. Darwin Lineage

Skipped — binary correctness/wiring fix, no continuous parameter for Darwin's fitness search. Same skip class as nearly every ACCEPT since 2026-08-18.

6. Flywheel Evidence

No .claude-flow/flywheel/ state exists in this repo. OBSERVATION (zero delete/bulkDelete calls pre-fix, confirmed by reading + grep) → MEASUREMENT (7 discriminating tests, stash-isolated) → INFERENCE (genuine SOTA gap at the orchestration/agent-memory layer, see issue §12) → DECISION: ACCEPT, scoped to delete-sync wiring only.

7. Reward Hack Check

Independent adversarial critic reviewed the actual diff (not the design) against a 9-point checklist and ran the suite/tsc itself. Verdict CONFIRMED-WITH-CAVEATS: found a real, undisclosed gap (whole-file-removed-from-disk entries were a permanent orphan) — fixed forward in this PR, not just logged; found the try/catch didn't cover the parse step — widened; found a vacuous test assertion — fixed by pre-seeding the stale entry it was supposed to test for. One caveat disclosed, not fixed (the pre-existing 10k query-limit cap now also bounds delete-sync visibility — inherited, not introduced by this diff).

8. Security Review

Delete scope is bounded to namespace === 'auto-memory' (unchanged query filter) and, within that, to entries the affected file previously wrote — confirmed by code tracing and a dedicated cross-file-isolation test. metadata.sourceFile comes from real filenames under the same already-trusted readdirSync(memoryDir) directory already consumed for content import; no new privilege boundary.

9. Regression Analysis

No existing test modified or weakened (diff is a pure 109-line addition pre-critique, then further additions post-critique — zero deletions in the test file). No gold data touched. Full-suite failure set unchanged in kind (same 1-2 pre-existing environmental flakes, confirmed non-deterministic rather than caused by this diff).

10. ADR

Not created — scoped wiring/correctness fix, not an architectural decision (per the Dream Cycle's own ADR-creation criteria).

11. Research Gist

docs/dream-cycle/dream-gist-2026-10-13.md (this branch) — full SOTA report: competitor comparison (LangChain's index() cleanup="scoped_full" is the official reference blueprint; Zep/Graphiti's bi-temporal soft-invalidate is a credible alternative), 5 scored candidates, 5 ranked next steps.

12. Issue

#4137 (full 15-section Dream Cycle report, including two SCAN findings on plugins and automation not implemented in this PR).

13. Witness

Session commit:   55e2c9011c20d25e347a175427ca8084dacde40c
Gist SHA-256:      b377c4bfed43cceb8589ac54c054f17642bc2944c6f67019072ce85b2e96ded1
Witness stamp:     e32bb6776f3d0d96a23dd989a8249de23ed68f757a750d21bd4d4b449c8bfd7b

14. Merge Policy

Human review required. Do not self-merge. Do not autonomously promote Flywheel state.


🤖 Generated with RuFlo

https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

Co-Authored-By: RuFlo ruv@ruv.net
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8


Generated by Claude Code

claude and others added 3 commits October 13, 2026 06:32
…-synced removed/vanished source content

importFromAutoMemory() diffed new content against AgentDB by content-hash
to insert/skip, but never detected or deleted an entry whose source
heading (or whole source file) was removed — deleted memory content
stayed retrievable via semantic search indefinitely. Adds a per-source-
file key diff (reusing the existing single bulk query, zero schema
change) plus a second pass for files removed entirely from disk, each
with a false-full-wipe guard. Evaluated: 7 new discriminating tests,
baseline-fails/candidate-passes via stash isolation; full suite and tsc
clean modulo pre-existing/unrelated flakes. Adversarial critique found
and this session fixed forward the whole-file-removed gap and a vacuous
test assertion before this commit.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8
…ync change

CI's leaf-package-publish audit caught this: @claude-flow/memory is a
non-bundled leaf that resolves from the registry for the release train,
so a publishable source change (auto-memory-bridge.ts) must bump the
leaf's own version or the fix silently never reaches a release. Bumps
the leaf's package.json, the CLI's exact pin (dependencies +
optionalDependencies), and the matching pnpm-lock.yaml specifier.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8
@ruvnet

ruvnet commented Oct 14, 2026

Copy link
Copy Markdown
Owner Author

Review (group 1, not merging): tests reproduce. The 7 new delete-sync tests fail on main and the bridge suite passes 86/86 with this change. One design risk to resolve before this ships, since the change deletes data: entries carry metadata.sourceFile as a bare basename and the key auto-memory:<file>:<heading>, with no record of which memoryDir wrote them. If the same backend is ever imported from a different memory dir (the hook passes a worktree memory dir via worktreeMemoryDir()), the vanished-file pass treats the earlier dir's files as deleted, and a same-named MEMORY.md heading diff deletes the other dir's entries. Suggest writing memoryDir into the entry metadata and only delete-syncing entries whose memoryDir matches (legacy entries without it never deleted), with a test for two dirs on one backend. Also this PR bumps @claude-flow/memory to 3.0.5, which now collides with #4183 (TieredMemoryStore, 3.0.5); whichever lands second should take 3.0.6.

🤖 Generated with RuFlo

…version collision with #4183

Review finding: the backend can be shared across multiple memory dirs
(e.g. the SessionStart hook's main dir vs. a worktree dir from
worktreeMemoryDir()). Without recording which memoryDir wrote an entry,
importing one dir could see another dir's same-named file/heading as
"gone" and delete it. Entries now carry metadata.memoryDir, and both
delete-sync passes (per-heading diff and whole-file-removed) only
consider entries whose memoryDir matches the importing bridge's own —
legacy entries written before this field existed (no memoryDir at all)
are therefore never delete-sync eligible. Two new discriminating tests
cover cross-dir isolation and the legacy-entry case; all 9 existing
delete-sync fixtures updated to carry memoryDir so they still exercise
the intended "same dir" path rather than being silently excluded.

Also bumps @claude-flow/memory to 3.0.6 (CLI pins + lockfile specifier)
since #4183 independently claimed 3.0.5 for the same leaf — whichever
of the two PRs lands second needs a version past the other's.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

ruvnet commented Oct 14, 2026

Copy link
Copy Markdown
Owner Author

Both addressed in 0368564:

  1. memoryDir-scoping (data-loss risk): entries now carry metadata.memoryDir. Both delete-sync passes (per-heading diff and whole-file-removed) only consider entries whose memoryDir matches the importing bridge's own config — legacy entries with no memoryDir recorded are therefore never delete-sync eligible, exactly as suggested. Updated all 9 existing delete-sync fixtures to carry memoryDir (otherwise they'd have been silently excluded and passing for the wrong reason) and added two new discriminating tests: cross-dir isolation (an entry from a different memoryDir sharing the same backend is untouched) and the legacy-entry case. Stash-isolated: both new tests fail on the pre-fix source, pass on the fix. Full suite: 613/616 (same 3 pre-existing environmental flakes as before — chmod-under-root, and 2 CPU-contention-sensitive timing tests in files this diff doesn't touch), tsc --noEmit clean.

  2. Version collision with fix(memory): TieredMemoryStore recalls multi-word and natural-language queries (#4152) [leaf 3.0.5] #4183: bumped to 3.0.6 (leaf package.json, CLI's exact pins, lockfile specifier) so this PR doesn't collide with fix(memory): TieredMemoryStore recalls multi-word and natural-language queries (#4152) [leaf 3.0.5] #4183's 3.0.5 claim regardless of merge order.


🤖 Generated with RuFlo

https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

Co-Authored-By: RuFlo ruv@ruv.net
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8


Generated by Claude Code

An earlier `pnpm install` run in this session (unrelated to this PR's
own change) left pnpm-lock.yaml recording codex/security/shared at
specifier 3.0.6 while v3/@claude-flow/cli/package.json still pins them
at 3.0.5 — a mismatch that got swept into a prior commit by staging the
whole lockfile file. `pnpm install --frozen-lockfile` (what CI runs)
fails on that drift regardless of this PR's actual content. Reverted
those three specifiers back to 3.0.5 to match package.json; the memory
specifier bump to 3.0.6 (this PR's real change) is untouched. Verified
locally: `pnpm install --frozen-lockfile` now succeeds.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

ruvnet commented Oct 14, 2026

Copy link
Copy Markdown
Owner Author

CI red (Windows pnpm install --frozen-lockfile jobs) — root cause: v3/pnpm-lock.yaml had stray @claude-flow/codex/security/shared specifiers recorded as 3.0.6 while v3/@claude-flow/cli/package.json still pins them at 3.0.5 (left over from an unrelated pnpm install run earlier in this session, swept into a prior commit by staging the whole lockfile). Not a real merge conflict or a review finding — self-inflicted drift in this branch, now fixed in f5291f0. Verified locally with pnpm install --frozen-lockfile, which now succeeds.


🤖 Generated with RuFlo

https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

Co-Authored-By: RuFlo ruv@ruv.net
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8


Generated by Claude Code

r and others added 2 commits October 20, 2026 04:58
# Conflicts:
#	docs/dream-cycle/LEDGER.md
#	v3/@claude-flow/cli/package.json
Swept into the previous merge commit by running the test suite to
verify the merge; it's a fresh-run artifact (empty idToLabel/labelToId
maps), not source. Added to .gitignore alongside the other *.rvf
test-pollution exclusions in this package.

Co-Authored-By: RuFlo <ruv@ruv.net>
@ruvnet
ruvnet marked this pull request as ready for review October 20, 2026 08:59
@ruvnet

ruvnet commented Oct 20, 2026

Copy link
Copy Markdown
Owner Author

Reviewed and rebased onto current main (this branch was a week stale). Conflicts were in the append-only docs/dream-cycle/LEDGER.md (resolved by interleaving the 10-13 entry chronologically, same as #4174) and an unrelated @metaharness/darwin transitive version bump in cli/package.json (took main's newer ~0.12.0). v3/@claude-flow/memory/package.json and v3/pnpm-lock.yaml auto-merged cleanly — both sides had independently landed on the identical memory version (3.0.6).

Verified post-merge: the PR's own new test file (auto-memory-bridge.test.ts, 88 tests covering the delete-sync fix) passes cleanly, and the full @claude-flow/memory suite — 626/626 tests across 35 files, 0 failures — after fixing an unrelated pre-existing environment gap (missing bcryptjs in the root node_modules despite being declared in package.json, same issue I'd hit reviewing #4036 earlier). Also dropped a test-run artifact (agentdb.rvf.idmap.json) that got swept into the merge commit — added to this package's existing *.rvf-pollution .gitignore entries.

Marking ready; will merge once CI is green.

AutoMemoryBridge.importFromAutoMemory()'s delete-sync fix in this PR
changed v3/@claude-flow/memory/src/auto-memory-bridge.ts without
bumping the package version. @claude-flow/memory is not bundled into
the release tarballs — it resolves from the registry — so publishing
the three train packages without this bump would ship the old 3.0.6
copy and the fix would reach nobody (#3335, #3390).

Will publish @claude-flow/memory@3.0.7 standalone once this merges.

Co-Authored-By: RuFlo <ruv@ruv.net>
@ruvnet

ruvnet commented Oct 20, 2026

Copy link
Copy Markdown
Owner Author

CI's leaf-package-publish audit caught a real gap: this PR's own fix (auto-memory-bridge.ts) was never accompanied by a version bump — @claude-flow/memory would have stayed at the already-published 3.0.6, so merging this as-is would ship the delete-sync fix in source but never actually publish it (exactly the #3335/#3390 class of mistake). Bumped to 3.0.7. Will run the standalone npm publish for @claude-flow/memory once this merges, matching the procedure used for #4315/@claude-flow/integration earlier today.

…@3.0.7

761b838 bumped the leaf's own package.json version to 3.0.7 but left
v3/@claude-flow/cli/package.json's exact pin (dependencies +
optionalDependencies) and the matching pnpm-lock.yaml specifier at
3.0.6 — the leaf-package-publish audit catches this: an exact pin of
"3.0.6" is not satisfied by workspace version 3.0.7, so a release would
resolve to an older published copy than the source in this repo.
Verified: audit script passes, `pnpm install --frozen-lockfile`
succeeds.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

ruvnet commented Oct 20, 2026

Copy link
Copy Markdown
Owner Author

Caught the same CI failure (leaf-package-publish audit) right as 761b838 landed the same fix — ended up a race. That commit bumped the leaf's own package.json version to 3.0.7 but left v3/@claude-flow/cli/package.json's exact pin and the matching pnpm-lock.yaml specifier at 3.0.6; since it's an exact pin (not a range), 3.0.6 doesn't cover 3.0.7 and the audit still fails ("the CLI pins 3.0.6, which does NOT cover the workspace version 3.0.7"). Pushed 2e979aa to bump both to 3.0.7. Verified locally: audit script passes, pnpm install --frozen-lockfile succeeds.


🤖 Generated with RuFlo

https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

Co-Authored-By: RuFlo ruv@ruv.net
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8


Generated by Claude Code

ruvnet commented Oct 20, 2026

Copy link
Copy Markdown
Owner Author

New failure on 2e979aa, different check: audit-leaf-versions-published.mjs (the #4303 live-registry guard). It's now red for the opposite reason my last fix addressed:

✗ @claude-flow/memory: the CLI pins the exact version "3.0.7", but that version is NOT on the
  npm registry (latest published: 3.0.6). A fresh `npm install` of @claude-flow/cli will fail
  with ETARGET (ruvnet/ruflo#4303).

This is a real tension between two guards at this exact stage, not something I can fix by pushing more version-string edits:

  • audit-leaf-package-publish.mjs wants the CLI's pin bumped ahead of the leaf's own package.json version whenever auto-memory-bridge.ts changes relative to main (satisfied by 3.0.7).
  • audit-leaf-versions-published.mjs wants the CLI's exact pin to already resolve on the live npm registry — which 3.0.7 doesn't, since it isn't published yet.

Both are correctly designed for what they each guard against (#3335/#3390 vs. #4303) but they can't both be green simultaneously for an unpublished leaf bump sitting in an open PR. Your own comment said the plan is to publish @claude-flow/memory@3.0.7 standalone once this merges — which means this specific check is expected to be red until that publish happens, unless I'm missing an intended sequencing (publish before merge, or this check isn't a required/blocking one for this repo). I don't have standalone-npm-publish authorization in scope for this PR task, so I'm flagging rather than guessing: do you want me to do anything here, or is this expected to stay red until you publish 3.0.7 post-merge?


🤖 Generated with RuFlo

https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

Co-Authored-By: RuFlo ruv@ruv.net
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8


Generated by Claude Code

@ruvnet

ruvnet commented Oct 20, 2026

Copy link
Copy Markdown
Owner Author

Also working this PR in parallel — saw the race on 761b838/2e979aaf. Claiming the next step: publishing @claude-flow/memory@3.0.7 to npm now (the audit-leaf-versions-published.mjs failure on 2e979aa is expected until that publish lands). Will report back once it's live and verified.

@ruvnet

ruvnet commented Oct 20, 2026

Copy link
Copy Markdown
Owner Author

`@claude-flow/memory@3.0.7` is live and verified on npm:

  • `npm view @claude-flow/memory@3.0.7 version` → `3.0.7` (took ~4 min to become registry-visible after publish)
  • `dist.integrity` matches the local publish output exactly: `sha512-4K1VhXlpHKLii9186KU4LwHMbv/BxJgHtyN28O+yz2e5YWd08/UuAScTqv+DSq54tBP5CLdb83wGhWNddcrgJQ==`

The `audit-leaf-versions-published.mjs` failure on 2e979aa (expected until this landed) should now clear — re-ran that job. Watching the rest of CI through to merge.

@ruvnet
ruvnet merged commit 9cf2ad5 into main Oct 20, 2026
190 of 191 checks passed
@ruvnet
ruvnet deleted the dream/2026-10-13-memory branch October 20, 2026 09:27
meefs pushed a commit to meefs/claude-code-flow that referenced this pull request Oct 20, 2026
Minor release (new backward-compatible flags: Grok Build CLI host
surface ruvnet#3512, memory list/search tag filter ruvnet#3526) bundled with a
round of correctness fixes merged since 3.58.1: memory delete-sync
(ruvnet#4138), real AgentDB HNSWIndex replacing the dead getController('hnsw')
path with safe exact-search fallback (ruvnet#4249/ruvnet#4322), harness live-process
reporting (ruvnet#3521), RaBitQ on-demand index build (ruvnet#4318/ruvnet#4319),
metaharness ADR-152 cost-dimension and verdict-band fix (ruvnet#3520), swarm
idle-agent heartbeat false-positive (ruvnet#4320), ephemeral-agent termination
idempotency (ruvnet#4323), status/task_list field-mapping and total-count
fixes (ruvnet#4321/ruvnet#4324).

Also fixes the actual cause of broken images/links on
npmjs.com/package/ruflo: `ruflo/package.json`'s `repository.directory:
"ruflo"` field added an extra path layer on top of the README content
(the root README.md, copied in verbatim by `prepublishOnly` at publish
time, which is already written with repo-root-relative paths) — every
relative image/link resolved to e.g. `raw/main/ruflo/ruflo/assets/...`
instead of `raw/main/ruflo/assets/...`. Removed the `directory` field to
match claude-flow's own (directory-less) repository entry. A prior PR
(ruvnet#4325) fixed `ruflo/README.md`'s own relative paths for anyone browsing
that file directly on GitHub, but that file is overwritten by the root
README at publish time and was never the actual npm-rendered content.

Published to npm: @claude-flow/cli@3.59.0, claude-flow@3.59.0,
ruflo@3.59.0, and standalone @claude-flow/memory@3.0.8 (the ruvnet#4249 fix —
not part of the 3-package train, published separately per its own
leaf's npm presence). All three umbrella packages' latest/alpha/v3alpha
dist-tags verified pointing at 3.59.0.

Co-Authored-By: RuFlo <ruv@ruv.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants