Files
msd-core/tests/audit-open-remainder-count.test.cjs
Jakub Zych a9a7a328e6 refactor: hard-fork GSD -> MSD (Make Software Done)
Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD
across contents and paths, upstream package/repo coordinates -> @golem15/msd-core
and golem15com/msd-core. Deep links into upstream history, sibling upstream
packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is.

Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line,
package/plugin identity, regenerated lockfile, install-tree fixtures, derived
registries and benchmark baseline; migration checksum baseline re-locked
(MSD keeps its own install state, so no install had applied the old sums);
sort-order and regex-escaped expectations in tests adjusted.
2026-10-06 01:47:40 +02:00

121 lines
4.7 KiB
JavaScript

'use strict';
// ─────────────────────────────────────────────────────────────────────────────
// #3817 — audit-open's counts must include the truncation remainder.
//
// The todo scan truncates its detail list at 5 and pushes a synthetic
// {_remainder_count: N} marker; the counting pass filtered that marker out
// alongside scan_error, so counts.todos and counts.total read systematically
// low by exactly N — the remainder existed only in the "… and N more" prose
// (reporter: 19 pending, reported 5). Truncation limits display, never
// counting.
// ─────────────────────────────────────────────────────────────────────────────
const { test, describe } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const { createTempProject, cleanup, runMsdTools } = require('./helpers.cjs');
function runAuditOpen(cwd) {
const r = runMsdTools(['audit-open', '--json'], cwd);
assert.ok(r.success, r.error);
return JSON.parse(r.output);
}
describe('#3817: audit-open counts include the truncation remainder', () => {
test('#3817: more than 5 todo files → counts.todos counts every pending file', (t) => {
const tmpDir = createTempProject('msd-3817-many-');
t.after(() => cleanup(tmpDir));
const pendingDir = path.join(tmpDir, '.planning', 'todos', 'pending');
fs.mkdirSync(pendingDir, { recursive: true });
const TOTAL = 8; // 5 shown + remainder 3
for (let i = 1; i <= TOTAL; i++) {
fs.writeFileSync(path.join(pendingDir, `todo-${String(i).padStart(2, '0')}.md`), [
'---',
'title: Fix thing ' + i,
'area: general',
'created: 2026-08-01',
'---',
'',
'Body ' + i,
'',
].join('\n'));
}
const out = runAuditOpen(tmpDir);
assert.equal(
out.counts.todos,
TOTAL,
`#3817: counts.todos must count every pending todo file (${TOTAL}); got ${out.counts.todos}`,
);
assert.equal(
out.counts.total,
TOTAL,
`#3817: counts.total must include the remainder; got ${out.counts.total}`,
);
// The display contract is unchanged: at most 5 detail objects, and the
// prose still announces the remainder.
assert.ok(
Array.isArray(out.items && out.items.todos),
'todos detail list present',
);
const detailFiles = out.items.todos.filter((i) => i && i.filename);
assert.ok(detailFiles.length <= 5, `display stays truncated; got ${detailFiles.length}`);
});
test('#3817 boundary: exactly 5 files → no marker, counts exact; 6 files → remainder 1', (t) => {
const tmpDir = createTempProject('msd-3817-boundary-');
t.after(() => cleanup(tmpDir));
const pendingDir = path.join(tmpDir, '.planning', 'todos', 'pending');
fs.mkdirSync(pendingDir, { recursive: true });
const seed = (n) => fs.writeFileSync(path.join(pendingDir, `todo-${n}.md`), [
'---',
'title: T ' + n,
'area: general',
'created: 2026-08-01',
'---',
'',
'Body',
'',
].join('\n'));
for (let i = 1; i <= 5; i++) seed(i);
let out = runAuditOpen(tmpDir);
assert.equal(out.counts.todos, 5, 'exactly at the cap: no marker, count exact');
const markers5 = (out.items.todos || []).filter((i) => i && typeof i._remainder_count === 'number');
assert.equal(markers5.length, 0, 'no marker emitted at exactly 5');
seed(6);
out = runAuditOpen(tmpDir);
assert.equal(out.counts.todos, 6, 'one past the cap: remainder 1 counted');
const marker = (out.items.todos || []).find((i) => i && typeof i._remainder_count === 'number');
assert.ok(marker, 'marker present at 6');
assert.equal(marker._remainder_count, 1, 'marker records exactly the dropped count');
});
test('#3817 control: 5 or fewer todo files → counts unchanged', (t) => {
const tmpDir = createTempProject('msd-3817-few-');
t.after(() => cleanup(tmpDir));
const pendingDir = path.join(tmpDir, '.planning', 'todos', 'pending');
fs.mkdirSync(pendingDir, { recursive: true });
for (let i = 1; i <= 3; i++) {
fs.writeFileSync(path.join(pendingDir, `todo-${i}.md`), [
'---',
'title: T ' + i,
'area: general',
'created: 2026-08-01',
'---',
'',
'Body',
'',
].join('\n'));
}
const out = runAuditOpen(tmpDir);
assert.equal(out.counts.todos, 3, 'no truncation → counts exact');
assert.equal(out.counts.total, 3);
});
});