Files
msd-core/tests/review-reviewer-selection.test.cjs
Jakub Zych 6cfa0c55d2 refactor: drop 12 runtimes, keep Claude, Codex, OpenCode, Cursor, ZCode, Antigravity
Removes kilo, kimi, kimi-code, copilot, windsurf, augment, trae, qwen, hermes,
cline, codebuddy and pi end to end: capability descriptors, installer branches
and converters (bin/install.js 14.9k -> 11.2k lines), TypeScript converters,
hook surfaces and runtime homes, review lanes qwen/kimi-code, the two pi
migrations, Kimi payload normalization in the hook guards, dead hostBehaviors
vocabulary, launcher home probes, fixtures, runtime-specific tests and the
prose that presented them as supported.

Installer output for the six kept runtimes is byte-identical to before the
prune. The Kimi tool-vocabulary tests in workflow-guard, read-guard and
read-injection-scanner are left in place pending a decision.
2026-10-06 20:02: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 --opencode` on a host without opencode) 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', 'opencode'],
});
assert.deepStrictEqual(r.selected, ['gemini'], 'the detected lane is still selected');
assert.strictEqual(
errorsMentioning(r, 'opencode').length,
1,
`expected exactly one error naming opencode, 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: ['opencode'],
});
assert.deepStrictEqual(r.selected, []);
assert.strictEqual(errorsMentioning(r, 'opencode').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', 'opencode', 'codex'],
});
const reversed = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: ['gemini', 'codex', 'opencode'],
});
assert.strictEqual(errorsMentioning(forward, 'opencode').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: ['opencode', 'opencode'],
});
assert.strictEqual(errorsMentioning(r, 'opencode').length, 1);
});
test('explicit flag matching is case-insensitive', () => {
const r = resolveReviewerSelection({
detected: ['gemini'],
explicitFlags: ['OPENCODE'],
});
assert.strictEqual(errorsMentioning(r, 'opencode').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: ['opencode'],
configuredDefaultReviewers: 'not-an-array',
});
assert.strictEqual(errorsMentioning(r, 'opencode').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', () => {
// `opencode` 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: ['opencode'],
configuredDefaultReviewers: ['opencode', 'codex'],
});
assert.equal(r.source, 'config_default');
assert.deepStrictEqual(r.selected, ['opencode']);
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', () => {
// `opencode` 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: ['opencode'],
configuredDefaultReviewers: ['opencode', '__nope__'],
});
assert.deepStrictEqual(r.errors, []);
assert.ok(r.warnings.some((w) => w.includes('__nope__')));
});
});