fix(enforce): hole 7 — ремонт инфраструктуры requires justification line

Brain-retro #5 candidate C, hole 7: the 'ремонт инфраструктуры' phrase
suppressed ALL rule keys with no constraint. Now requires a 'ремонт: <what>'
line in the same prompt documenting the target.

enforce-override-vocab.json: added 'requires_justification: "ремонт:"' to
the entry.
enforce-hook-helpers.mjs findOverride(): honors requires_justification — when
set, the user prompt must contain '<prefix> <non-empty-text>' or the override
is rejected.
This commit is contained in:
Дмитрий
2026-05-26 11:23:19 +03:00
parent 0ea3b5d70d
commit 57a7f55bf1
3 changed files with 41 additions and 2 deletions
+10 -1
View File
@@ -200,7 +200,16 @@ export function findOverride(userPrompt, ruleKey, vocab) {
for (const p of v.phrases || []) {
if (!p.phrase || !Array.isArray(p.suppresses)) continue;
if (!lo.includes(p.phrase.toLowerCase())) continue;
if (p.suppresses.includes(ruleKey)) return p;
if (!p.suppresses.includes(ruleKey)) continue;
if (p.requires_justification) {
// Hole 7 fix: master overrides require a line "<prefix> <non-empty>"
// in the same prompt documenting what is being repaired.
const prefix = p.requires_justification.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const re = new RegExp(prefix + '\\s+(\\S[^\\n]*)', 'i');
const m = userPrompt.match(re);
if (!m || !m[1] || !m[1].trim()) continue;
}
return p;
}
return null;
}
+29
View File
@@ -151,6 +151,35 @@ describe('loadOverrideVocab / findOverride', () => {
});
});
describe('findOverride — requires_justification (hole 7)', () => {
const testVocab = {
phrases: [
{
phrase: 'ремонт инфраструктуры',
suppresses: ['classifier-mismatch'],
requires_justification: 'ремонт:',
description: 'master kill — requires justification',
},
],
};
it('rejects when phrase present but justification line missing (hole 7)', () => {
const r = findOverride('ремонт инфраструктуры', 'classifier-mismatch', testVocab);
expect(r).toBeNull();
});
it('accepts when justification line provides target', () => {
const r = findOverride('ремонт инфраструктуры\nремонт: enforce-hook-helpers.mjs', 'classifier-mismatch', testVocab);
expect(r).not.toBeNull();
expect(r.phrase).toBe('ремонт инфраструктуры');
});
it('rejects when justification line empty after the prefix', () => {
const r = findOverride('ремонт инфраструктуры\nремонт: ', 'classifier-mismatch', testVocab);
expect(r).toBeNull();
});
});
describe('isProductionCodePath', () => {
it('classifies tools/*.mjs as production', () => {
expect(isProductionCodePath('tools/router-classifier.mjs')).toBe(true);
+2 -1
View File
@@ -35,7 +35,8 @@
{
"phrase": "ремонт инфраструктуры",
"suppresses": ["tdd-gate", "verify-before-commit", "verify-before-push", "writing-plans-required", "skill-required", "memory-sync-coverage", "classifier-mismatch", "coverage-skill-match"],
"description": "Bypass all rules (full opt-out). Use only when literally fixing the enforce-infrastructure itself."
"requires_justification": "ремонт:",
"description": "Bypass all rules (full opt-out). Requires 'ремонт: <what>' line in same prompt."
}
]
}