Stop the repo-ownership audit from flagging projected rationale nodes - #521
Merged
Merged
Conversation
Every daemon start on a workspace holding repo-scoped development memories logged the ownership audit at Error — "repo ownership is inconsistent, repo-scoped reads will silently return a subset of the graph" — with a handful of `rationale::mem…` IDs as the named offenders. The graph was fine: owned=644746, unowned=0, no ghost population. Only the misprefixed count was non-zero, and every node in it was a false positive. The audit exempts the identity namespaces whose IDs deliberately do not mirror a source path — contracts, contract bridges, topics. The memory projection mints nodes of exactly that shape: `rationale::<memory-id>` over the virtual .gortex/rationale path, with the owning repo still stamped on RepoPrefix. Their identity can never start with "<repo>/", so the audit read the stamped field and the minted identity as disagreeing, Clean() went false, and the whole line escalated to Error with copy describing a data-loss bug that was not happening. index_health reported the same thing through repo_ownership.consistent and its remediation string. Exempt KindRationale alongside the other identity namespaces, in the in-memory classifier and in the SQLite predicate that transcribes it, so the two backends stay in lockstep. Both paths are fenced: the classifier table gains the rationale case and the cross-backend conformance fixture gains a projected rationale node, each of which fails without the corresponding fix.
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.
What
Exempt
KindRationalefrom the repo-prefix ownership audit, in both the in-memory classifier and the SQLite predicate that transcribes it.Why
Every daemon start on a workspace holding repo-scoped development memories logged this at Error:
The graph was healthy.
owned=644746 / unowned=0means not mixed — no ghost population, which is the failure the detector exists for. Onlymisprefixedwas non-zero, and every node in it was a false positive.ClassifyNodePrefixalready exempts the identity namespaces whose IDs deliberately do not mirror a source path: contracts, contract bridges, topics.projectMemoriesmints nodes of exactly that shape:A repo is stamped, but the identity is namespaced and the path is virtual, so
strings.HasPrefix(n.ID, repoPrefix+"/")can never hold.KindRationalewas simply never added to the exempt switch — so one repo-scoped memory was enough to driveClean()false and escalate the whole audit to Error, with copy describing a data-loss bug that was not occurring.index_healthreported the same false positive, viarepo_ownership.consistent: falseplus the "Graph holds inconsistent repository ownership … untrack and re-track the repo" remediation.Changes
internal/graph/prefix_diagnostics.go— addKindRationaleto the exempt switch inIsAuditableRepoSourceNode; explain why in the doc comment.internal/graph/store_sqlite/prefix_diagnostics.go— mirror it inauditableRepoSourceNodePredicate(kind NOT IN (…, 'rationale')). The file's contract is that the SQL is a transcription of the Go classifier and the two change together.internal/graph/prefix_diagnostics_test.go— classifier case for a projected rationale identity.internal/graph/storetest/storetest.go— projected rationale node in the cross-backend conformance fixture.Only the ownership audit is affected.
buildIndexHealthPayloadCtx's path-liveness probe also callsIsAuditableRepoSourcePath, but it walksNodesByKind(KindFile)only, so rationale nodes never reach it.Verification
Both fences fail without their corresponding fix — confirmed by reverting each and re-running:
With the fix:
go test -race ./internal/graph/ ./internal/graph/storetest/— okgo test -race ./internal/graph/store_sqlite/— ok (full suite, 1438s)golangci-lint run ./internal/graph/...— 0 issues