fix(#2128): address shared-seam review regressions (#557, action-scan, comment-strip)

Final convergence review found the shared <tag> seam introduced 3 behavior
regressions; fixed all + locked with tests:

- #557 REGRESSION: stripTaggedBlocks's attribute-tolerance stripped `<details open>`
  (the ACTIVE-milestone marker) that the old `<details>`-only regex preserved. The
  seam now takes `allowAttributes` (default false) — details/decisions strip is
  attr-INTOLERANT (preserves `<details open>`); only `<task type="…">` opts in.
  Regression test added to roadmap-parser + markdown-sectionizer suites.
- verify.cts actionZones (negative-grep-echo security scan): reverted to a bounded
  to-first-close scan `<action>([\s\S]{0,20000}?)</action>` so a grep-echo trick
  can't hide behind an unterminated inner <action> (the seam's stop-at-next-open
  would drop it). ReDoS-safe via the cap.
- check-command-router HTML-comment strip: `(?:-->|$)` fallback wiped to EOF
  (fail-closed spurious gate block) — replaced with stop-at-next-open so an
  unclosed `<!--` leaves downstream tags intact.
- Updated the extractTaggedBlocks nested-tag tests to the new (stop-at-next-open)
  behavior: `<x><x>inner</x></x>` -> ['inner'].

All vectors still linear; every fix verified in-process.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-07-10 11:12:45 -04:00
parent 01b691fae8
commit 8e4ebb49e4
6 changed files with 91 additions and 34 deletions

View File

@@ -77,6 +77,19 @@ describe('roadmap-parser: stripShippedMilestones', () => {
assert.ok(!result.includes('closed content'), 'content removed');
assert.ok(result.includes('after'), 'after content preserved');
});
test('#557: preserves an active <details open> block while stripping shipped bare <details>', () => {
// <details open> marks the ACTIVE milestone (roadmap.analyze must still see its
// phases); only closed/shipped bare <details> blocks are stripped. Regression for
// #557, which the #2128 shared-seam migration briefly reintroduced via the seam's
// attribute-tolerance — the details strip is now attr-INTOLERANT to keep #557 fixed.
const input = '<details>\nshipped phase\n</details>\n<details open>\n- [ ] **Phase 9: Active**\n</details>\nafter';
const result = stripShippedMilestones(input);
assert.ok(!result.includes('shipped phase'), 'shipped bare <details> stripped');
assert.ok(result.includes('<details open>'), 'active <details open> tag preserved');
assert.ok(result.includes('Phase 9: Active'), 'active-milestone phases preserved');
assert.ok(result.includes('after'), 'trailing content preserved');
});
});
// ─── extractCurrentMilestone ──────────────────────────────────────────────────