fix(uat): close two UAT-path correctness defects #59

Merged
crenshawdev merged 2 commits from task/uat-path-fixes into main 2026-07-27 17:53:16 +00:00
crenshawdev commented 2026-07-27 17:52:18 +00:00 (Migrated from github.com)

Two confirmed MEDIUM defects from the post-v1.3.1 backlog, one atomic commit each. Both were reproduced live before the fix and verified after, and both regression tests were confirmed failing-capable by reverting the source and watching them go red.

1. usableName trim asymmetry (5d4b07f)

find compared i.name === ref.name untrimmed while usableName trimmed on the append path, so a gap named "Login works " missed the stored "Login works" and appended a byte-identical duplicate. The duplicate was unreachable by name on every later merge, so its fail status blocked uatComplete permanently. That is the same phantom usableName was added to prevent, reached from the read side.

Rather than adding a second trim inside find, usableName is hoisted above it and find now matches through it, so the read and write paths cannot drift apart again. A null name still matches nothing, keeping an unnamed ref rejected rather than colliding with the first item.

Reproduced as {gaps:1, added:1, skipped:0, rejected:0} with two identical ### N. Login works headings.

2. UAT extras fence bound (a1b33bb)

The extras collector stopped at any /^## / line, so a ## build output line inside a ```sh block truncated the section mid-fence. That destroyed the closing fence and the trailing prose and left an odd fence count, so the regenerated ## Summary rendered as code, contradicting templates/UAT.md's promise that a hand-added section survives a seam rewrite verbatim.

New sectionBound returns the first ## outside a fenced block, tracking the opener's character and length so only a matching closer ends it. Both the extras loop and the item field loop use it, making true the comment that already claimed they shared a bound.

Reproduced as a fence count dropping 2 to 1 with ## Summary swallowed into an unclosed block.

Verification

  • 338 tests pass, 0 fail
  • tsc -p tsconfig.ci.json clean
  • self-verify green

Note: CAPTURE.md is gitignored, so the two closing marks there are a working-tree edit and not part of this diff. CAPTURE recorded the path as cadence-core/lib/planning-files.mjs, which does not exist; the file is at cadence-core/bin/lib/.

Two confirmed MEDIUM defects from the post-v1.3.1 backlog, one atomic commit each. Both were reproduced live before the fix and verified after, and both regression tests were confirmed failing-capable by reverting the source and watching them go red. ### 1. `usableName` trim asymmetry (5d4b07f) `find` compared `i.name === ref.name` untrimmed while `usableName` trimmed on the append path, so a gap named `"Login works "` missed the stored `"Login works"` and appended a byte-identical duplicate. The duplicate was unreachable by name on every later merge, so its `fail` status blocked `uatComplete` permanently. That is the same phantom `usableName` was added to prevent, reached from the read side. Rather than adding a second trim inside `find`, `usableName` is hoisted above it and `find` now matches through it, so the read and write paths cannot drift apart again. A null name still matches nothing, keeping an unnamed ref rejected rather than colliding with the first item. Reproduced as `{gaps:1, added:1, skipped:0, rejected:0}` with two identical `### N. Login works` headings. ### 2. UAT extras fence bound (a1b33bb) The extras collector stopped at any `/^## /` line, so a `## build output` line inside a ```sh block truncated the section mid-fence. That destroyed the closing fence and the trailing prose and left an odd fence count, so the regenerated `## Summary` rendered as code, contradicting `templates/UAT.md`'s promise that a hand-added section survives a seam rewrite verbatim. New `sectionBound` returns the first `## ` outside a fenced block, tracking the opener's character and length so only a matching closer ends it. Both the extras loop and the item field loop use it, making true the comment that already claimed they shared a bound. Reproduced as a fence count dropping 2 to 1 with `## Summary` swallowed into an unclosed block. ### Verification - 338 tests pass, 0 fail - `tsc -p tsconfig.ci.json` clean - `self-verify` green Note: `CAPTURE.md` is gitignored, so the two closing marks there are a working-tree edit and not part of this diff. CAPTURE recorded the path as `cadence-core/lib/planning-files.mjs`, which does not exist; the file is at `cadence-core/bin/lib/`.
Sign in to join this conversation.
No description provided.