feat: [ENG-2157] add RuntimeSignalStore with atomic update primitive (2/6)#448
Merged
danhdoan merged 1 commit intoproj/runtime-signalfrom Apr 18, 2026
Merged
feat: [ENG-2157] add RuntimeSignalStore with atomic update primitive (2/6)#448danhdoan merged 1 commit intoproj/runtime-signalfrom
danhdoan merged 1 commit intoproj/runtime-signalfrom
Conversation
(2/6) Second task in the series that moves per-machine ranking signals out of context-tree markdown frontmatter into a sidecar store. Adds IRuntimeSignalStore interface and RuntimeSignalStore implementation, a thin facade over IKeyStorage using composite keys ["signals", ...segments]. Atomicity within a single process comes from IKeyStorage.update's per-key RWLock — no external mutex needed. Cross-process writes have a narrow lost-update window, acceptable for ranking signals (documented in the interface). The store exposes six methods: - get / getMany / list — bulk and single reads - set — full replace (used for seeding, merge, restore) - update — atomic read-modify-write via updater callback - delete — remove an entry - batchUpdate — parallel update across many paths Wired into service-initializer.ts and exposed on CipherAgentServices. No consumer calls the store yet — dual-write lands in commit 3. Mock factory updated for test compatibility. Design decisions worth noting: - Updater callback (not delta-merge) supports both SET and INCREMENT semantics safely inside the atomic critical section. - Path encoding splits relPath on '/' so FileKeyStorage's segment validation accepts it. Path normalization variants (leading/trailing/ consecutive slashes) collapse to the same key. - Zod validation on both read and write; corrupt stored records fall back to defaults with a logged warning. - SemanticFrontmatter type introduced here (deferred from 1/6). Tests: 26 store tests including concurrent-atomicity (20 parallel updates on same path), corrupt-data handling, namespace isolation, path-encoding edge cases, and forward-compat with partial records. Full suite: 6459 passing, 0 failing.
Contributor
|
Claude finished @danhdoan's task in 3m 15s —— View job PR Review: feat: [ENG-2157] RuntimeSignalStore (2/6)Tasks
Overall Assessment: 4 / 5This is clean, well-scoped infrastructure work. The design is sound, the concurrency story is honest and well-documented, scope is correctly constrained, and the 26-test suite covers the important scenarios including the parallel-update atomicity case. The few items below are all minor. What's good
Issues / suggestions
SecurityNo concerns. The store doesn't touch the filesystem directly (delegates to |
bao-byterover
approved these changes
Apr 18, 2026
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.
Summary
importance,recency,maturity,accessCount,updateCount) are currently stored in context-tree markdown frontmatter. Everybrv querybumps them and rewrites the markdown, dirtyingbrv vc statusand causing merge conflicts when teammates share context trees.IRuntimeSignalStoreinterface, thinRuntimeSignalStorefacade over the existingIKeyStorage(composite keys["signals", relPath]), 26 unit tests, wiring inservice-initializer.ts,runtimeSignalStoreadded toCipherAgentServices,SemanticFrontmattertype added to the schema file.Type of change
Scope (select all touched areas)
Linked issues
Root cause (bug fixes only, otherwise write
N/A)Test plan
test/unit/agent/knowledge/runtime-signal-store.test.ts— 26 testsset/getgetreturns defaults for missing pathgetreturns defaults and logs a warning for corrupt stored datagetfills partial records with per-field defaults (forward-compat)updateseeds defaults when no record exists and applies the updaterupdaterejects updater output that violates the schemaupdatecalls on the same path all land with no lost bumps (atomic read-modify-write)batchUpdateapplies all updaters; serializes concurrent bumps on shared paths across batchesgetManyreturns an entry for every requested path, missing ones default; does not read entries outside the requested setlistreturns all entries, falls back to defaults for corrupt, ignores keys outside the signals namespacedeleteremoves an entry so subsequentgetreturns defaults; no-op for missing pathsUser-visible changes
None. This commit adds a module reachable via
CipherAgentServices.runtimeSignalStorebut no consumer calls it yet.Evidence
Concurrent-atomicity test output:
Full store test output: 26 passing (14ms)
Full repo suite: 6459 passing, 0 failing (no regression — +5 tests from commit 1's 6454).
Checklist
npm test)npm run lint) — 0 errors, 201 pre-existing warnings (none new)npm run typecheck)npm run build)mainRisks and mitigations
IKeyStorage.update's RWLock is in-process only. Under concurrent writes, one bump may be lost.importance↔maturityhysteresis invariant. Callers bumpingimportancemust recomputematurityviadetermineTierthemselves; the store accepts any schema-valid combination.rm), its sidecar entry remains forever.list()is only called for admin/diagnostic use, andgetManyis used for ranking. Pruning mechanism captured in the backlog with a clear trigger.test/helpers/mock-factories.tsskips Zod validation — consumer tests using the mock won't catch bugs that rely on validation behaviour.RuntimeSignalStorewithFileKeyStorage({inMemory: true}). Captured in the backlog.Related