fix: VFS rename moves the containment edge — no ghost in the old directory
A cross-directory rename added the new parent's Contains edge but skipped
removing the old one (a 'not critical' shortcut), leaving the moved entity
a child of BOTH directories: readdir(oldDir) kept listing it, re-creating
the old path showed the name twice, and tree-walking consumers saw the
file in two places. Reported live by a production deployment (37 stale
containment ghosts; blocks tree-sync integrations).
- rename() now removes the old parent's vfs containment edge(s) by edge
id resolved from the graph's own adjacency (the removal law: removal
never requires reading the removed thing), and a move to the root gets
its containment edge (previously skipped -> orphaned from readdir('/')).
- New vfs.repairContainment(): reconciles every VFS entity's containment
edges against canonical metadata.path — removes stale/duplicate vfs
edges, restores missing ones, never touches user knowledge edges. Wired
into repairIndex() so the one operator ritual heals existing ghosts.
- Regression: tests/integration/vfs-rename-containment.test.ts (7).
This commit is contained in:
parent
1a3a493c27
commit
af8c1795bd
3 changed files with 278 additions and 5 deletions
|
|
@ -15301,6 +15301,21 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
await pruner.rebuildTypeCounts?.()
|
||||
await pruner.rebuildSubtypeCounts?.()
|
||||
|
||||
// VFS containment reconciliation: heal "cosmetic ghost" edges left by
|
||||
// pre-fix renames (an entity Contains-linked from BOTH its old and new
|
||||
// directory — readdir listed it in two places) and duplicate edges from
|
||||
// concurrent writers. Canonical metadata.path is the truth; only VFS
|
||||
// containment edges are touched. Loud per repair.
|
||||
if (this._vfsInitialized && this._vfs) {
|
||||
const containment = await this._vfs.repairContainment()
|
||||
if (containment.removed + containment.restored > 0) {
|
||||
prodLog.warn(
|
||||
`[Brainy] repairIndex() reconciled VFS containment: removed ${containment.removed} ` +
|
||||
`stale/duplicate edge(s), restored ${containment.restored} missing edge(s).`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
await this.metadataIndex.detectAndRepairCorruption()
|
||||
// Lift a failed-rollback write-quarantine: force a full rebuild so the
|
||||
// derived indexes are provably reconciled with canonical, then clear the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue