fix: health ring never fakes a learning backslide across projects - #53
Merged
Merged
Conversation
The health-history ring is machine-global (kit.json) but learningRows is project-local (the sync cwd's .claude-flow/neural/stats.json), and an absent store was recorded as a literal 0. A sync run from a project with no learning store therefore compared 0 against another project's real count and fired a false 'learning rows shrank 75 -> 0' alarm. Two-part fix, mirroring the admin page's honesty rule (unknown is never a fabricated zero): - sync stamps each snapshot with its project (cwd) and records learningRows: null when the store is absent - detectRegression compares learningRows only against the most recent prior entry from the SAME project with a KNOWN count; other projects, legacy unstamped entries, and unknown readings are never baselines. Machine-global metrics (nativeSlots, drift, security) still compare the last two entries as before. The alarm message now names the project so a real backslide says where it happened.
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.
The defect
ak statusalarmedregression: learning rows shrank 75 → 0after a routineak sync— but no learning data was lost (ak x verify learningpasses; the 75-pattern store is intact).Root cause: the health-history ring is machine-global (kit.json), but
learningRowsis project-local — read from whatever cwdsyncran in, with an absent store recorded as a literal0. A sync run from a project with no learning store (claude-autopilot) recorded 0, anddetectRegression()compared it against the previous entry — recorded from a different project (agentic-kit, 75) — and cried backslide.The fix
Two parts, mirroring the admin page's honesty rule (unknown is never a fabricated zero):
syncstamps each snapshot with itsproject(cwd) and recordslearningRows: nullwhen the store is absent.detectRegression()pairslearningRowsonly with the most recent prior entry from the same project with a known count; other projects, legacy unstamped entries, and unknown readings are never baselines. Machine-global metrics (nativeSlots, drift, security) keep the existing last-two comparison. The alarm message now names the project.Legacy rings need no migration: pre-fix entries have no project stamp, so they simply never serve as baselines.
Tests
6 new cases in
tests/health-history.test.cjs(31 total in the file), including a direct repro of the false positive, cross-project isolation, unknown-skipping baseline search, legacy-entry handling, and Windows path labels. Full suite: 314 kit tests + cjs suites pass; eslint clean.🤖 Generated with Claude Code