docs(changelog): the narrow remediation of the A/B review, decisions 48 and 50, with door lines
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
e8ea98747d
commit
184fbe4633
4 changed files with 119 additions and 4 deletions
|
|
@ -66,3 +66,82 @@ test('Phase 9 names plan-gate --diff and says round 1 is unchanged', () => {
|
|||
test('Phase 9 no longer says the loop ends on a round with no BLOCKER', () => {
|
||||
assert.ok(!P9.includes('ends on a round with no BLOCKER'), 'the stale "ends on a round with no BLOCKER" is gone');
|
||||
});
|
||||
|
||||
// The narrow round of the A/B review (operator decisions 48 and 50): the
|
||||
// CHANGELOG's open Unreleased section records it, Phase 9 says what a merge
|
||||
// keeps, and Handover 4 states the matcher's overlap rule and the distinct id.
|
||||
// The release check is imported as a module namespace, so a missing parseDoors
|
||||
// export fails an assertion, not the load.
|
||||
const releaseCheck = await import('../../scripts/release-check.mjs');
|
||||
|
||||
// The body of the open `## Unreleased` section, up to the next `## ` heading.
|
||||
function unreleasedBody() {
|
||||
const lines = read('CHANGELOG.md').split('\n');
|
||||
const start = lines.findIndex(l => /^## Unreleased\b/.test(l));
|
||||
assert.ok(start >= 0, 'CHANGELOG.md has a "## Unreleased" section');
|
||||
let end = lines.length;
|
||||
for (let i = start + 1; i < lines.length; i++) {
|
||||
if (/^## /.test(lines[i])) { end = i; break; }
|
||||
}
|
||||
return lines.slice(start + 1, end).join('\n');
|
||||
}
|
||||
|
||||
// A `### <name>` body of the Unreleased section, up to the next heading.
|
||||
function subsection(body, name) {
|
||||
const lines = body.split('\n');
|
||||
const start = lines.findIndex(l => l.replace(/\s+$/, '') === `### ${name}`);
|
||||
assert.ok(start >= 0, `the Unreleased section has a "### ${name}" heading`);
|
||||
let end = lines.length;
|
||||
for (let i = start + 1; i < lines.length; i++) {
|
||||
if (/^###? /.test(lines[i])) { end = i; break; }
|
||||
}
|
||||
return lines.slice(start + 1, end).join('\n');
|
||||
}
|
||||
|
||||
// The top-level bullets of a slice: each `- ` line at column 0 with its
|
||||
// wrapped and nested lines, whitespace read as one space.
|
||||
function topBullets(slice) {
|
||||
const out = [];
|
||||
for (const line of slice.split('\n')) {
|
||||
if (/^- /.test(line)) out.push(line);
|
||||
else if (out.length && line.trim() !== '') out[out.length - 1] += `\n${line}`;
|
||||
}
|
||||
return out.map(flat);
|
||||
}
|
||||
|
||||
test('CHANGELOG: the narrow round of operator decisions 48 and 50', () => {
|
||||
assert.equal(typeof releaseCheck.parseDoors, 'function', 'scripts/release-check.mjs exports parseDoors');
|
||||
const body = unreleasedBody();
|
||||
const d = releaseCheck.parseDoors(body);
|
||||
assert.equal(d.found, true, 'the Unreleased section has a "### Doors" heading');
|
||||
assert.deepEqual(d.bad, [], 'every top-level door line reads "- one-way: ..." or "- two-way: ..."');
|
||||
const doors48 = d.entries.filter(e => /operator\s+decision\s+48\b/.test(flat(e.text)));
|
||||
assert.ok(doors48.length >= 3,
|
||||
`at least three door lines name operator decision 48: ${JSON.stringify(d.entries.map(e => e.text))}`);
|
||||
|
||||
const fixed = flat(subsection(body, 'Fixed'));
|
||||
for (const id of ['4ab24b07', 'd03835c4', '69c9cebd', '8782602b', 'ebe164e2']) {
|
||||
assert.ok(fixed.includes(id), `the Fixed slice names review ${id}`);
|
||||
}
|
||||
|
||||
const known = topBullets(subsection(body, 'Known issues'));
|
||||
for (const id of ['8a9b5a17', '8004ea85', 'c257625e', '818b1346']) {
|
||||
const hits = known.filter(b => b.includes(id));
|
||||
assert.equal(hits.length, 1, `exactly one Known-issues bullet names ${id}: ${JSON.stringify(hits)}`);
|
||||
assert.match(hits[0], /operator\s+decision\s+48\b/, `the ${id} Known-issues bullet names operator decision 48: ${JSON.stringify(hits[0])}`);
|
||||
}
|
||||
const residual = known.filter(b => b.includes('4ab24b07'));
|
||||
assert.equal(residual.length, 1, `exactly one Known-issues bullet names 4ab24b07: ${JSON.stringify(residual)}`);
|
||||
assert.match(residual[0], /operator\s+decision\s+50\b/, `the 4ab24b07 Known-issues bullet names operator decision 50: ${JSON.stringify(residual[0])}`);
|
||||
});
|
||||
|
||||
test('Phase 9 says the merge keeps the copy rule B counts more severe', () => {
|
||||
assert.ok(P9.includes('keeps the copy rule B counts more severe'), 'Phase 9 says "keeps the copy rule B counts more severe"');
|
||||
assert.ok(!P9.includes('keeps the more severe of the two severities'), 'the stale "keeps the more severe of the two severities" is gone');
|
||||
});
|
||||
|
||||
test('Handover 4 states the overlap match and the distinct id', () => {
|
||||
const h4 = flat(handover4());
|
||||
assert.ok(h4.includes('only on overlapping text'), 'Handover 4 says the gate matches "only on overlapping text"');
|
||||
assert.ok(h4.includes('`<rule_key>#n`'), 'Handover 4 names `<rule_key>#n`');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue