/** * floor-exclusion — the deterministic veto that runs BEFORE the subtraction * judge sees anything (v5.13, brief §6.0 / §7 q2). * * The subtraction lens asks "what no longer earns its always-loaded rent?", and * that question is only safe to ask because this module answers a prior one * first: **which blocks are not eligible to be asked about at all?** * * Brief §6.0 splits CLAUDE.md content on one axis: * * compensatory — corrects model *behaviour* ("think before you code"). * A more capable model does it unprompted. Deletable. * load-bearing — a *local fact* no amount of intelligence derives from the * codebase ("only Forgejo at git.example.test", "system bash * is 3.2"). FLOOR. Never a deletion candidate. * * Why this is deterministic and not the judge's call: precision is asymmetric. * A missed dead line costs a few tokens per turn; a deleted load-bearing line * costs a wrong remote, a broken script, or a lost afternoon. A blocking * guarantee must not rest on a probabilistic prose judgement, so the floor is * decided here, in code, and the judge only ever ranks what survives. * * The veto keys on **underivable local literals** — the textual fingerprints of * a fact that came from this machine rather than from general engineering * knowledge: an inline code span, a path, a domain, a version pin, a concrete * filename. Plus §6.0's explicit carve-out: policy invariants (secrets, * credentials, production, destructive operations) are floor *by decision, not * by classification* — the model would probably honour them unprompted, but the * cost of being wrong is asymmetric and their token cost is trivial. * * Deliberately over-broad. A false veto costs recall (a dead line survives * another turn); a false clearance costs the guarantee. When in doubt: floor. * * Zero external dependencies. Pure: input text → boolean. */ /** An inline code span — the single strongest local-literal signal. */ const CODE_SPAN_RE = /`[^`\n]+`/; /** A URL or a bare hostname. `.test`/`.local` included for fixtures. */ const URL_RE = /https?:\/\/|\b[a-z0-9][a-z0-9-]*(?:\.[a-z0-9-]+)+\.(?:com|org|net|io|dev|sh|no|test|local|ai)\b/i; /** * A rooted path (`~/x`, `./x`, `/Users/x`) or a glob. Deliberately does NOT * match a bare `word/word`: "pros/cons" is not a path, and treating it as one * vetoed the single largest deletable block in the dogfood run. Real filenames * are FILENAME_RE's job, and backticked paths are CODE_SPAN_RE's. */ const PATH_RE = /(?:^|[\s(«"'])(?:~|\.{1,2})?\/[\w.~/*-]+|\*\*?\//; /** A concrete filename with a known extension (STATE.md, .zshenv, foo.sh). */ const FILENAME_RE = /\b[\w.-]+\.(?:ts|tsx|js|jsx|mjs|cjs|py|md|json|ya?ml|toml|go|rs|java|rb|php|c|cpp|h|hpp|sh|sql|css|scss|html|env|template|lock)\b|(?:^|\s)\.\w+rc\b|\bzshenv\b/; /** * A version pin — "bash 3.2", "Opus 4.8", "v5.12.5". A number that specific is * a fact about this machine's world, not general knowledge. */ const VERSION_RE = /\bv?\d+\.\d+(?:\.\d+)?\b/; /** * §6.0's carve-out. These stay in the floor by decision: the downside is * asymmetric and the lines are cheap. Do not let a "the model knows this now" * argument reach them. */ const POLICY_RE = /\b(?:secret|secrets|credential|credentials|password|passphrase|api[\s-]?key|access[\s-]?token|keychain|\.env|production|prod|force[\s-]push|rm\s+-rf|destructive|hemmelighet|passord|untrusted|injection|prompt[\s-]injection|angrepsflate|attack[\s-]surface|exfiltrat\w*)\b/i; /** * An unresolved local entity: a mixed-case capitalized word appearing * mid-sentence. In config prose that is almost always a product, service or * tool name — "push til deres egne Forgejo-remotes", "Bruk Explore for søk" — * i.e. exactly the local vocabulary that makes a line underivable, but with no * literal syntax for the other markers to key on. * * This marker is the CONSERVATIVE DEFAULT, and it is deliberately blunt: the * mechanism cannot tell "Forgejo" from an ordinary capitalized word without a * dictionary, so it declines to decide and keeps the block. Any finer rule * (lowercase-form-appears-elsewhere, curated entity lists) is a proxy for a * dictionary that would be tuned against one machine's config and fail silently * on the next one. Paying in recall is the direction brief §6.0 mandates. * * All-caps tokens are exempt: this config's emphasis convention is ALDRI / * ALLTID / FØR / MÅ, and acronyms like AI and TDD are generic, not local. * * "Mid-sentence" is keyed on a preceding LOWERCASE letter (or comma) — not on * "anything that is not a full stop". The looser version cost 4 of 11 deletable * groups in the dogfood run by firing on `**Bold labels:**` and on quoted * sentence starts (`"Som AI kan jeg ikke…"`), both of which are sentence * openings dressed in punctuation rather than local vocabulary. */ const ENTITY_RE = /[a-zæøå,;]\s+(?![A-ZÆØÅ]{2,}\b)[A-ZÆØÅ][a-zæøå][\wæøåÆØÅ-]*/; /** The ordered veto table — exported so a finding can cite *why* it was floored. */ export const FLOOR_MARKERS = Object.freeze([ { name: 'code-span', re: CODE_SPAN_RE, why: 'contains an inline code literal' }, { name: 'url', re: URL_RE, why: 'names a specific host or URL' }, { name: 'filename', re: FILENAME_RE, why: 'names a concrete file' }, { name: 'path', re: PATH_RE, why: 'names a concrete path' }, { name: 'version', re: VERSION_RE, why: 'pins a specific version' }, { name: 'policy', re: POLICY_RE, why: 'is a policy invariant (floor by decision, §6.0)' }, { name: 'unresolved-entity', re: ENTITY_RE, why: 'names a capitalized entity the mechanism cannot resolve' }, ]); /** * The first floor marker present in `text`, or null if the text carries no * underivable local fact. * @param {string} text * @returns {{name:string, why:string}|null} */ export function floorMarker(text) { const s = String(text == null ? '' : text); for (const m of FLOOR_MARKERS) { if (m.re.test(s)) return { name: m.name, why: m.why }; } return null; } /** * True when the block must never be proposed for deletion. * @param {string} text * @returns {boolean} */ export function isLoadBearing(text) { return floorMarker(text) !== null; }