/** * Entity property merge semantics, shared by both graph backends so they * cannot drift apart (file: storage/graph-store.ts, sqlite: * storage/sqlite/sqlite-stores.ts). * * Background: entity upsert merged properties with `{...existing, ...input}`, * so a repeated key was overwritten last-writer-wins. That is correct for most * properties but wrong for `scope`. The graph auto-populator stamps every file * and symbol entity with the scope of the decision that touched it * (engine/graph-auto-populator.ts), so a file touched by decisions in two * scopes ended up carrying only the most recent one — irrecoverably, and * rewriting the entity record every time it flipped. * * Measured on this repo before the fix: of 242 file entities carrying a scope, * only 132 had a name starting with that scope. The other 110 had been stamped * with an unrelated scope by a later decision. * * `scope` therefore accumulates as a sorted, deduplicated set. Sorting matters * for two reasons: it makes the stored bytes deterministic (no git churn from * ordering alone), and it makes the cap stable, so a hot entity converges * instead of oscillating. */ /** Split a stored set-valued property back into its members. */ export declare function splitSetProperty(value: string | undefined): string[]; /** Join members into the stored form, sorted, deduplicated, and capped. */ export declare function joinSetProperty(members: string[]): string; /** * Merge incoming entity properties over existing ones. Ordinary keys overwrite * (last writer wins); keys in SET_VALUED_KEYS union into a sorted set. * * Backward compatible: an existing singular value like "src/auth/" is a valid * one-element set, and every consumer of `scope` does substring matching * (engine/context-assembler.ts getRelatedEntities and computeGraphReachability), * which still matches against a joined set. */ export declare function mergeEntityProperties(existing: Record | undefined, incoming: Record | undefined): Record; //# sourceMappingURL=entity-properties.d.ts.map