Skip to content

v0.31.0 — cooperative index yield + concurrency/self-heal fixes - #6

Merged
hamr0 merged 2 commits into
mainfrom
feat/index-fix
Jul 28, 2026
Merged

v0.31.0 — cooperative index yield + concurrency/self-heal fixes#6
hamr0 merged 2 commits into
mainfrom
feat/index-fix

Conversation

@hamr0

@hamr0 hamr0 commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Summary

Ships the index-fix work as one release (0.31.0):

Feature (LC-3): index({ yield: true }) — cooperatively release the event loop between per-file parses (setImmediate) so a co-hosted timer/socket breathes during a large/force pass. Byte-identical stored index; default false unchanged. (bareloop upstream ask LC-3.)

Fixes (all validated + regression-tested, mutation-verified):

  • Atomic force/self-heal rebuild — the destructive clear is folded into applyChanges' transaction, so a concurrent reader (e.g. the 0.30.0 background warm-index firing while the model recalls) never sees an empty index. Reproduced: recall returned 0 mid-rebuild; now returns the full set.
  • Separate mem_embeddings table — written-memory vectors no longer share file_embeddings, where a global-tier remember() whose id equalled a file path clobbered that file's vector (and a forget deleted it). Kind-scoped getEmbeddings + one-time auto-migration on open.
  • Backfill drift guard — skip a file whose disk bytes drifted from its stored hash; batch backfilled vectors in one transaction.
  • MCP — retry a failed warm-index on the next initialize.

Verification

  • node --test416 pass / 0 fail / 1 skip (pre-existing embeddings-dep skip); +6 new regression tests (LC-3 yield, concurrency ×3, embeddings ×2).
  • tsc --noEmit → exit 0.
  • /ship, /security, independent /diff-review on the range → all clean (0 Critical / 0 Warning).

Notes

  • Pre-existing, non-blocking (flagged, not fixed here): index({ force:true, paths:[…] }) still clears the whole index while re-inserting only the scoped subset — identical to prior behavior, not reachable via CLI/MCP.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MEtvo8nTSpwN59712wEPEt

hamr0 and others added 2 commits July 28, 2026 11:25
Two shipping-together pieces for the index-fix release:

LC-3 — index({ yield: true }): release the event loop between per-file
parses (setImmediate) so a co-hosted timer/socket breathes during a large
or force pass. Byte-identical stored index; default false unchanged.

Code-review fixes (validated + regression-tested, mutation-verified):
- Atomic force/self-heal rebuild: fold the destructive clear into
  applyChanges' transaction so a concurrent reader never sees the empty
  window between clear and re-populate (the warm-index-vs-recall race).
- Separate mem_embeddings table: written-memory vectors no longer share
  file_embeddings, where a global-tier id equal to a file path clobbered
  that file's vector. Kind-scoped getEmbeddings + one-time migration.
- Backfill drift guard: skip a file whose disk bytes drifted from its
  stored hash; batch backfilled vectors in one transaction.
- MCP: retry a failed warm-index on the next initialize.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MEtvo8nTSpwN59712wEPEt
- index({ yield: true }) — LC-3 cooperative event-loop yielding
- atomic force/self-heal rebuild (no empty-index window for concurrent readers)
- separate mem_embeddings table (fixes global-tier id==path vector clobber) + migration
- embeddings backfill drift guard + batched writes
- MCP: retry a failed warm-index on next initialize

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MEtvo8nTSpwN59712wEPEt
@hamr0
hamr0 merged commit 1c05108 into main Jul 28, 2026
2 checks passed
@hamr0
hamr0 deleted the feat/index-fix branch July 28, 2026 09:40
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.

1 participant