mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
ci: specs live in the issue body — body digest in review anchors, gate without a spec file
The spec file solved exactly one problem — proving that a review verdict was passed on a given text — and created two: docs/specs/README.md conflicted between parallel tasks and served as a second, stale status dictionary, and every spec edit cost a commit, a push and a label. The proof moves into the pipeline. - review-doc-guard: normalizeIssueBody / issueBodyDigest (CRLF, trailing whitespace, trailing newlines), the anchor line `Тело issue: <sha256>`, anchorIssueBodyFrom, and issueBodyChanged — the finding "the spec changed after a green spec review", judged against the pipeline's own record in the last green SPEC-REVIEW, never against prose. - reusableGreenVerdict takes the current digest: reuse (#499) skips the model entirely, so without this a spec edit between rounds would pass unseen. Documents without the record (the whole backlog) keep judging by tree. - process.yml: the material step reads the body with `gh issue view` in the same run that fixes the material — the event snapshot describes a text the reviewer may never see; the digest goes into the anchors, into reuse and, when it differs, into the reviewer's prompt. - process-gate: rule 3 judges the text (a `## ТЗ` heading or an AC1) with the archived file still accepted; adding a new file under docs/specs/ warns — the directory is frozen. - task-packet reads AC from the body first, the archived file second. - PROCESS.md §2.3/§5/§7.1/§7.3/§10.5, AGENTS.md and docs/specs/README.md say so; the index table is gone with the long-standing §7.3 debt. Mutants: review-anchor-drops-issue-body, review-ignores-changed-spec-body, reuse-ignores-changed-issue-body, process-gate-requires-spec-file. Issue: #517 User-Visible: no
This commit is contained in:
@@ -8192,6 +8192,50 @@ const MUTANT_DEFINITIONS = [
|
||||
replace: " // mutant: completed means green — a red dispatch falls through to the job check",
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'review-anchor-drops-issue-body',
|
||||
guard: 'node --test test/review-doc-guard.test.mjs',
|
||||
because: 'ТЗ живёт в теле issue, которое GitHub правит без diff и без истории: без хеша тела '
|
||||
+ 'в якорях доказать «вердикт вынесен на этом тексте» нечем (#517 AC1)',
|
||||
patches: [{
|
||||
file: 'scripts/review-doc-guard.mjs',
|
||||
find: ' lines.push(`- Тело issue: \\`${issueBody}\\``);',
|
||||
replace: ' // mutant: anchor without the issue body',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'review-ignores-changed-spec-body',
|
||||
guard: 'node --test test/review-doc-guard.test.mjs',
|
||||
because: 'правка ТЗ после зелёного ревью ТЗ обязана приходить ревьюеру кода находкой; '
|
||||
+ 'сравнение, которое всегда молчит, возвращает ровно ту слепоту, ради которой заведён хеш (#517 AC2)',
|
||||
patches: [{
|
||||
file: 'scripts/review-doc-guard.mjs',
|
||||
find: ' return recorded === digest ? null : { doc: green.name, recorded, current: digest };',
|
||||
replace: ' return null; // mutant: the body never changed',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'reuse-ignores-changed-issue-body',
|
||||
guard: 'node --test test/review-doc-guard.test.mjs',
|
||||
because: 'повторное применение зелёного вердикта пропускает вызов модели целиком: если оно не '
|
||||
+ 'смотрит на хеш тела, правка ТЗ между раундами проходит невидимой (#517 AC6)',
|
||||
patches: [{
|
||||
file: 'scripts/review-doc-guard.mjs',
|
||||
find: ' if (recordedBody && issueBodyDigest && recordedBody !== issueBodyDigest) return null;',
|
||||
replace: ' // mutant: reuse ignores the issue body',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'process-gate-requires-spec-file',
|
||||
guard: 'node --test test/process-gate.test.mjs',
|
||||
because: 'после #517 файла ТЗ не создаёт ни одна новая задача: гейт, требующий файл, краснеет '
|
||||
+ 'на каждом классе A и учит игнорировать себя (#517 AC3)',
|
||||
patches: [{
|
||||
file: 'scripts/process-gate.mjs',
|
||||
find: ' if (hasSpecText(body)) continue;',
|
||||
replace: ' if (body !== null) continue; // mutant: only the file counts',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'review-returns-task-on-cancelled-dispatch',
|
||||
guard: 'node --test test/validate-gate.test.mjs',
|
||||
|
||||
Reference in New Issue
Block a user