Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions LifeOS/install/LIFEOS/TOOLS/ProposalGC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,16 @@ function appliedTs(entry: string): string {
return m ? m[1].trim() : "";
}

/** Substantive core of an entry (first ~60 normalized chars) for absorption test. */
function core(entry: string): string {
return normalize(entry).slice(0, 60);
/**
* Absorption test: the ENTIRE normalized entry must already appear in the
* canonical body. A prefix match is not proof of absorption — the reviewer
* routinely restates an existing rule in order to extend it, and a prefix
* test reads that restatement as redundancy and deletes the extension with
* it. The 30-char floor keeps a one-word fragment from matching anything.
*/
function absorbed(entry: string, bodyNorm: string): boolean {
const norm = normalize(entry);
return norm.length >= 30 && bodyNorm.includes(norm);
}

function gcFile(relPath: string): { removals: Removal[]; nextContent: string | null } {
Expand Down Expand Up @@ -115,7 +122,7 @@ function gcFile(relPath: string): { removals: Removal[]; nextContent: string | n
if (/\[SUPERSEDED/i.test(e.text)) {
removals.push({ file: relPath, reason: "superseded", text: e.text.trim() });
removeIdx.add(e.i);
} else if (core(e.text).length >= 30 && bodyNorm.includes(core(e.text))) {
} else if (absorbed(e.text, bodyNorm)) {
removals.push({ file: relPath, reason: "absorbed", text: e.text.trim() });
removeIdx.add(e.i);
}
Expand Down