test(#3339): fold the state/phase/dispatch & model-profile issue-* cluster — Wave 7

Folds 9 legacy issue-*.test.cjs regression files (140 test() blocks) into
their module's main suite, per H3 (#3315) of the test-hygiene epic (#3053).
LAST of 4 issue-* waves — closes out the 74-file fix-*/issue-* backlog
(pending BUG_FILE_RE extension, held for a follow-up commit until Wave 6
is confirmed merged, per the epic's own zero-backlog precondition).

- issue-2828-flat-roadmap-total-phases.test.cjs (1) + issue-3204-state-
  writer-phase-count.test.cjs (21): both target state-document.cjs
  buildStateFrontmatter via different CLI entrypoints — merged jointly
  into state-document.test.cjs, 0 dropped.
- issue-2945-phase-complete-checkbox-rollback.test.cjs (4) + issue-2949-
  phase-complete-stage3-sentinel.test.cjs (4): both target phase.cts
  cmdPhaseComplete; issue explicitly warned of overlap — verified
  disjoint fixtures/assertions, 0 dropped, merged into phase.test.cjs.
- issue-2927-reviewer-lane-overlay-invocation.test.cjs (10) merged into
  review-lane-descriptor.test.cjs.
- issue-2939-dispatch-flatten-maxdepth.test.cjs (9) merged into
  host-integration.test.cjs, 2 dropped as verified exact duplicates.
- issue-2977-frontmatter-bom.test.cjs (5) merged into frontmatter.test.cjs.
- issue-2045-third-party-skills-surface.test.cjs (6) merged into
  capability-loader.test.cjs.
- issue-2517-runtime-aware-profiles.test.cjs (80, the largest single
  fold in the epic) merged into model-resolver.test.cjs, 1 dropped as a
  verified true duplicate (checked against src/model-resolver.cts logic,
  not just title similarity).

Fixed a genuine eslint irregular-whitespace finding: a literal BOM
character embedded in a doc comment (pre-existing content from the
original #2977 source, illustrating what a BOM looks like) — replaced
with a readable U+FEFF notation.

3 stale doc references found and fixed (docs/adr/2313, 3180, 443).

Zero net test-coverage loss. No production code changed.
This commit is contained in:
sim
2026-08-12 00:51:07 -04:00
parent 4a0b5e26b4
commit 1bc7f7e6b0
19 changed files with 2941 additions and 2912 deletions

View File

@@ -2243,3 +2243,89 @@ describe('#2847: schema name consistency between gsd-planner.md and src/frontmat
});
});
}
// ────────────────────────────────────────────────────────────────────────
// Folded from tests/issue-2977-frontmatter-bom.test.cjs — test-hygiene sweep #3339 (H3 Wave 7)
// ────────────────────────────────────────────────────────────────────────
{
const { describe: __foldDescribe } = require('node:test');
__foldDescribe('folded:issue-2977-frontmatter-bom', () => {
'use strict';
/**
* Regression test for #2977 — `extractFrontmatter` returns {} for any file whose
* frontmatter fence is preceded by a UTF-8 BOM (Windows PowerShell `>`/`Out-File`,
* several editors). The `startsWith('---')` byte-0 check fails on any leading byte,
* so every frontmatter field silently disappears with no error.
*
* The fix strips a leading UTF-8 BOM (U+FEFF) before the fence check. Scope: BOM only
* (acceptance criteria 1-3). The generalized "arbitrary content before the fence" fork
* (tolerate vs diagnose) is a product-intent decision, surfaced in the PR — out of scope.
*
* Matrix: .gsd/bug/fix/2977-frontmatter-bom-tolerance/50-test-matrix.md
*/
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const { extractFrontmatter } = require('../gsd-core/bin/lib/frontmatter.cjs');
const BOM = '\uFEFF';
describe('extractFrontmatter BOM tolerance (#2977)', () => {
test('bomPrefixedFrontmatterParses', () => {
// Row 1 (failing-first regression): a BOM-prefixed frontmatter document parses
// identically to the same document without the BOM.
const clean = '---\ntitle: T\nphase: "01"\nstatus: passed\n---\n\n# Body\n';
const bommed = BOM + clean;
const expected = extractFrontmatter(clean, 'a.md');
const actual = extractFrontmatter(bommed, 'a.md');
assert.deepEqual(actual, expected, 'BOM-prefixed frontmatter must parse identically to no-BOM');
assert.strictEqual(actual.title, 'T', 'title field recovered');
assert.strictEqual(actual.phase, '01', 'phase field recovered');
assert.strictEqual(actual.status, 'passed', 'status field recovered');
});
test('bomWithCrlfParses', () => {
// Row 2 (acceptance #2): BOM + CRLF line endings together still parse correctly.
const clean = '---\r\ntitle: T\r\nphase: "01"\r\n---\r\n\r\n# Body\r\n';
const bommed = BOM + clean;
const actual = extractFrontmatter(bommed, 'a.md');
assert.strictEqual(actual.title, 'T', 'title recovered (BOM + CRLF)');
assert.strictEqual(actual.phase, '01', 'phase recovered (BOM + CRLF)');
});
test('bomWithNoFrontmatterStaysEmpty', () => {
// Row 3 (acceptance #3): a BOM prefixing a document with no frontmatter (or genuinely
// empty frontmatter) returns {} with no false diagnostic — same as no-BOM.
assert.deepEqual(extractFrontmatter(BOM + 'just plain text', 'a.md'), {}, 'BOM + no frontmatter -> {}');
assert.deepEqual(extractFrontmatter(BOM + '', 'a.md'), {}, 'BOM + empty -> {}');
// A thematic-break-first-line Markdown doc (--- then prose) must stay {} — protected by
// the existing false-positive threshold; the BOM strip must not lower that bar.
assert.deepEqual(extractFrontmatter(BOM + '---\n\nA horizontal rule, not frontmatter.\n', 'a.md'), {},
'BOM + thematic-break Markdown -> {} (no false diagnostic)');
});
test('bomAcrossArtifactTypes', () => {
// Row 4 (acceptance #1 across artifact types): each frontmatter-bearing artifact shape
// recovers its fields when BOM-prefixed.
const cases = [
{ name: 'STATE.md', body: '---\ncurrent_phase: "01"\nstatus: "In progress"\n---\n\n# State\n', expect: { current_phase: '01', status: 'In progress' } },
{ name: 'PLAN.md', body: '---\nphase: "01"\nplan: "01-01"\nstatus: "done"\n---\n\n# Plan\n', expect: { phase: '01', plan: '01-01', status: 'done' } },
{ name: 'SUMMARY.md', body: '---\none-liner: "shipped the thing"\n---\n\n# Summary\n', expect: { 'one-liner': 'shipped the thing' } },
{ name: 'UAT.md', body: '---\nphase: "02"\nverdict: "pass"\n---\n\n# UAT\n', expect: { phase: '02', verdict: 'pass' } },
];
for (const c of cases) {
const actual = extractFrontmatter(BOM + c.body, c.name);
assert.deepEqual(actual, c.expect, `${c.name}: BOM-prefixed frontmatter must recover fields`);
}
});
test('controlNoBom', () => {
// Row 5 (no regression): no BOM, valid frontmatter still parses correctly (unchanged).
const actual = extractFrontmatter('---\ntitle: T\nphase: "01"\n---\n\n# Body\n', 'a.md');
assert.strictEqual(actual.title, 'T');
assert.strictEqual(actual.phase, '01');
});
});
});
}