Files
msd-core/tests/review-reviewer-selection.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

318 lines
12 KiB
JavaScript

'use strict';
/**
* Characterization tests for the reviewer selection module.
* Locks the normalizeConfiguredDefaultReviewers and resolveReviewerSelection
* export shapes and key policy decisions.
*/
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const {
KNOWN_REVIEWER_SLUGS,
normalizeConfiguredDefaultReviewers,
resolveReviewerSelection,
} = require('../msd-core/bin/lib/review-reviewer-selection.cjs');
describe('KNOWN_REVIEWER_SLUGS', () => {
test('known slug appears in selected with no warning; unknown slug produces a warning and is dropped', () => {
const knownSlug = KNOWN_REVIEWER_SLUGS[0];
const unknownSlug = '__not_a_real_reviewer__';
const knownResult = resolveReviewerSelection({
detected: [knownSlug],
explicitFlags: [],
allFlag: false,
configuredDefaultReviewers: [knownSlug],
});
assert.ok(
knownResult.selected.includes(knownSlug),
`expected known slug "${knownSlug}" to appear in selected`,
);
assert.ok(
knownResult.warnings.length === 0,
`expected no warnings for known slug "${knownSlug}", got: ${JSON.stringify(knownResult.warnings)}`,
);
const unknownResult = resolveReviewerSelection({
detected: [unknownSlug],
explicitFlags: [],
allFlag: false,
configuredDefaultReviewers: [unknownSlug],
});
assert.ok(
!unknownResult.selected.includes(unknownSlug),
`expected unknown slug "${unknownSlug}" to be dropped from selected`,
);
assert.ok(
unknownResult.warnings.some((w) => w.includes(unknownSlug)),
`expected a warning mentioning "${unknownSlug}", got: ${JSON.stringify(unknownResult.warnings)}`,
);
});
});
describe('normalizeConfiguredDefaultReviewers', () => {
test('returns absent=true for undefined', () => {
const r = normalizeConfiguredDefaultReviewers(undefined);
assert.ok(r.absent);
assert.deepStrictEqual(r.values, []);
assert.deepStrictEqual(r.errors, []);
});
test('returns absent=true for null', () => {
const r = normalizeConfiguredDefaultReviewers(null);
assert.ok(r.absent);
});
test('returns error for non-array', () => {
const r = normalizeConfiguredDefaultReviewers('gemini');
assert.ok(!r.absent);
assert.ok(r.errors.length > 0);
});
test('returns error for empty array', () => {
const r = normalizeConfiguredDefaultReviewers([]);
assert.ok(!r.absent);
assert.ok(r.errors.length > 0);
});
test('normalizes slugs to lowercase', () => {
const r = normalizeConfiguredDefaultReviewers(['Gemini', 'CLAUDE']);
assert.ok(!r.absent);
assert.ok(r.values.includes('gemini'));
assert.ok(r.values.includes('claude'));
});
test('deduplicates slugs case-insensitively', () => {
const r = normalizeConfiguredDefaultReviewers(['gemini', 'GEMINI']);
assert.ok(!r.absent);
assert.strictEqual(r.values.filter((s) => s === 'gemini').length, 1);
});
test('records error for invalid slug format', () => {
const r = normalizeConfiguredDefaultReviewers(['gem@ini']);
assert.ok(r.errors.some((e) => e.includes('invalid reviewer slug')));
});
});
describe('resolveReviewerSelection', () => {
test('explicit_flags source — returns intersection of flags and detected', () => {
const r = resolveReviewerSelection({
detected: ['gemini', 'claude'],
explicitFlags: ['gemini'],
allFlag: false,
});
assert.equal(r.source, 'explicit_flags');
assert.deepStrictEqual(r.selected, ['gemini']);
});
test('all_flag source — returns all detected', () => {
const r = resolveReviewerSelection({
detected: ['gemini', 'claude'],
explicitFlags: [],
allFlag: true,
});
assert.equal(r.source, 'all_flag');
assert.ok(r.selected.includes('gemini'));
assert.ok(r.selected.includes('claude'));
});
test('no_config_all_detected source — returns all detected when no config', () => {
const r = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: [],
allFlag: false,
});
assert.equal(r.source, 'no_config_all_detected');
assert.deepStrictEqual(r.selected, ['gemini']);
});
test('selected is sorted alphabetically', () => {
const r = resolveReviewerSelection({
detected: ['claude', 'gemini'],
explicitFlags: [],
allFlag: true,
});
assert.deepStrictEqual(r.selected, [...r.selected].sort());
});
test('empty detected with no flags/config falls back to no_config_all_detected with empty selected, warnings, and errors', () => {
const r = resolveReviewerSelection({ detected: [] });
assert.equal(r.source, 'no_config_all_detected');
assert.deepStrictEqual(r.selected, []);
assert.deepStrictEqual(r.warnings, []);
assert.deepStrictEqual(r.errors, []);
});
});
/**
* ADR-2782 D4 (#2794) — absent-safe governs DISCOVERY, never explicit selection.
*
* "Not finding a lane nobody asked for is normal; failing to run a lane somebody
* asked for is an error."
*
* Before this change every explicit miss was an `info`. A TOTAL miss still
* errored, but only as a side effect of the selected set coming out empty — so
* the PARTIAL miss (`--gemini --qwen` on a host without qwen) had no signal at
* all: the review ran with a thinner reviewer set and present_results reported
* success. The workflow's own guidance names why that is wrong — "a cross-AI
* review that silently drops a lane is blind in one eye".
*/
describe('resolveReviewerSelection — explicit flags are an assertion (ADR-2782 D4)', () => {
const errorsMentioning = (r, slug) => r.errors.filter((e) => e.includes(slug));
test('an explicit flag for a detected reviewer selects it with no message', () => {
const r = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: ['gemini'],
});
assert.deepStrictEqual(r.selected, ['gemini']);
assert.deepStrictEqual(r.errors, []);
assert.deepStrictEqual(r.infos, []);
});
test('a partial explicit miss errors instead of degrading silently', () => {
// THE regression row. Pre-fix this produced errors: [] and an info note,
// and the run proceeded one-eyed.
const r = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: ['gemini', 'qwen'],
});
assert.deepStrictEqual(r.selected, ['gemini'], 'the detected lane is still selected');
assert.strictEqual(
errorsMentioning(r, 'qwen').length,
1,
`expected exactly one error naming qwen, got: ${JSON.stringify(r.errors)}`,
);
assert.deepStrictEqual(r.infos, [], 'the miss must not be downgraded to an info');
});
test('a sole explicit flag that is undetected errors per-slug and in aggregate', () => {
const r = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: ['qwen'],
});
assert.deepStrictEqual(r.selected, []);
assert.strictEqual(errorsMentioning(r, 'qwen').length, 1);
// The pre-existing aggregate message is preserved, not replaced — the
// per-slug errors must not suppress it.
assert.ok(
r.errors.some((e) => e.includes('no selected reviewers are available')),
`expected the aggregate error to survive, got: ${JSON.stringify(r.errors)}`,
);
});
test('every missing explicit flag produces its own error, in a stable order', () => {
const forward = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: ['gemini', 'qwen', 'codex'],
});
const reversed = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: ['gemini', 'codex', 'qwen'],
});
assert.strictEqual(errorsMentioning(forward, 'qwen').length, 1);
assert.strictEqual(errorsMentioning(forward, 'codex').length, 1);
// Order must not depend on the order flags appeared on the command line.
assert.deepStrictEqual(forward.errors, reversed.errors);
});
test('a duplicate explicit flag produces exactly one error', () => {
const r = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: ['qwen', 'qwen'],
});
assert.strictEqual(errorsMentioning(r, 'qwen').length, 1);
});
test('explicit flag matching is case-insensitive', () => {
const r = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: ['QWEN'],
});
assert.strictEqual(errorsMentioning(r, 'qwen').length, 1);
});
test('an explicit flag with nothing detected at all errors', () => {
const r = resolveReviewerSelection({
detected: [],
explicitFlags: ['gemini'],
});
assert.deepStrictEqual(r.selected, []);
assert.strictEqual(errorsMentioning(r, 'gemini').length, 1);
});
test('pre-existing config errors do not suppress per-slug explicit errors', () => {
const r = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: ['qwen'],
configuredDefaultReviewers: 'not-an-array',
});
assert.strictEqual(errorsMentioning(r, 'qwen').length, 1);
assert.ok(r.errors.some((e) => e.includes('must be a JSON array')));
// Guarded on the PRE-branch error count, so the aggregate fires exactly when
// it did before this change — i.e. not here, because a config error already
// existed.
assert.ok(!r.errors.some((e) => e.includes('no selected reviewers are available')));
});
test('non-string explicit flags are coerced, never thrown on', () => {
const r = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: [null, 0, { a: 1 }],
});
assert.strictEqual(r.source, 'explicit_flags');
assert.strictEqual(r.errors.length, 3 + 1, 'three unknown flags plus the aggregate');
});
});
/**
* The other half of D4, and the reason the carve-out is scoped to explicit
* flags only: discovery paths stay lenient. `--all` is a quantifier over what
* exists; `review.default_reviewers` is a preference evaluated across many
* hosts. Neither is an assertion about a specific lane, so neither errors.
*/
describe('resolveReviewerSelection — discovery paths stay lenient (ADR-2782 D4)', () => {
test('--all does not error on undetected lanes', () => {
const r = resolveReviewerSelection({
detected: ['gemini'],
allFlag: true,
});
assert.equal(r.source, 'all_flag');
assert.deepStrictEqual(r.selected, ['gemini']);
assert.deepStrictEqual(r.errors, []);
assert.deepStrictEqual(r.infos, []);
});
test('a configured default that is undetected stays an info, not an error', () => {
// `qwen` is a genuinely KNOWN lane (REVIEWER_LANES) that is simply absent from `detected` here —
// the shape this test needs. `gemini` no longer works as this fixture: it was retired from
// REVIEWER_LANES by #4709, so it now falls into the UNKNOWN-slug branch (a warning) instead of
// the known-but-undetected branch (an info) this test exists to prove.
const r = resolveReviewerSelection({
detected: ['qwen'],
configuredDefaultReviewers: ['qwen', 'codex'],
});
assert.equal(r.source, 'config_default');
assert.deepStrictEqual(r.selected, ['qwen']);
assert.deepStrictEqual(r.errors, [], 'a preference miss must not become an error');
assert.ok(
r.infos.some((i) => i.includes('codex')),
`expected an info naming codex, got: ${JSON.stringify(r.infos)}`,
);
});
test('an unknown configured slug stays a warning', () => {
// `qwen` here plays the genuinely KNOWN, detected lane so `selected`/`errors` behave as expected;
// `__nope__` remains the genuinely UNKNOWN slug under test — `gemini` would ALSO now be a valid
// fixture for the unknown branch (retired from REVIEWER_LANES by #4709), but `__nope__` already
// names that branch unambiguously without relying on retirement history.
const r = resolveReviewerSelection({
detected: ['qwen'],
configuredDefaultReviewers: ['qwen', '__nope__'],
});
assert.deepStrictEqual(r.errors, []);
assert.ok(r.warnings.some((w) => w.includes('__nope__')));
});
});