Files
msd-core/tests/context-utilization.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

123 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
/**
* Pure classifier for the msd-health --context guard.
*
* Thresholds:
* < 60% healthy
* 60–70% warning
* ≥ 70% critical (fracture point)
*
* The classifier is a pure (tokensUsed, contextWindow) → { percent, state }
* function. Recommendation copy is owned by the SDK renderer (see
* tests/validate-context.test.cjs), not this module.
*/
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const { classifyContextUtilization, STATES } = require('../msd-core/bin/lib/context-utilization.cjs');
describe('STATES constant exposes the three boundary names', () => {
test('exports HEALTHY, WARNING, CRITICAL', () => {
assert.deepStrictEqual(
[STATES.HEALTHY, STATES.WARNING, STATES.CRITICAL],
['healthy', 'warning', 'critical'],
);
});
});
describe('classifyContextUtilization — state thresholds', () => {
test('0 tokens used → healthy at 0%', () => {
const r = classifyContextUtilization(0, 200_000);
assert.strictEqual(r.percent, 0);
assert.strictEqual(r.state, STATES.HEALTHY);
});
test('just under 60% → healthy (state uses exact ratio, not rounded percent)', () => {
// 119_999 / 200_000 = 59.9995% — rounds to 60 for display, healthy by ratio.
const r = classifyContextUtilization(119_999, 200_000);
assert.strictEqual(r.state, STATES.HEALTHY);
});
test('exactly 60% → warning (inclusive lower bound)', () => {
const r = classifyContextUtilization(120_000, 200_000);
assert.strictEqual(r.percent, 60);
assert.strictEqual(r.state, STATES.WARNING);
});
test('between 60% and 70% → warning', () => {
const r = classifyContextUtilization(130_000, 200_000);
assert.strictEqual(r.percent, 65);
assert.strictEqual(r.state, STATES.WARNING);
});
test('just under 70% → warning', () => {
// 139_999 / 200_000 = 69.9995% — rounds to 70 for display, warning by ratio.
const r = classifyContextUtilization(139_999, 200_000);
assert.strictEqual(r.state, STATES.WARNING);
});
test('exactly 70% → critical (fracture point, inclusive lower bound)', () => {
const r = classifyContextUtilization(140_000, 200_000);
assert.strictEqual(r.percent, 70);
assert.strictEqual(r.state, STATES.CRITICAL);
});
test('above 70% → critical', () => {
const r = classifyContextUtilization(180_000, 200_000);
assert.strictEqual(r.percent, 90);
assert.strictEqual(r.state, STATES.CRITICAL);
});
test('tokensUsed >= contextWindow clamps to 100%', () => {
const r = classifyContextUtilization(250_000, 200_000);
assert.strictEqual(r.percent, 100);
assert.strictEqual(r.state, STATES.CRITICAL);
});
});
describe('classifyContextUtilization — return shape', () => {
test('result is exactly { percent, state } — no recommendation field', () => {
// Recommendation copy lives in the renderer, not the classifier.
// Keeping this contract narrow lets the prose evolve without
// re-validating the math layer.
const r = classifyContextUtilization(100_000, 200_000);
assert.deepStrictEqual(Object.keys(r).sort(), ['percent', 'state']);
});
});
describe('classifyContextUtilization — input validation', () => {
test('negative tokensUsed throws', () => {
assert.throws(() => classifyContextUtilization(-1, 200_000), /tokensUsed/);
});
test('non-integer tokensUsed throws', () => {
assert.throws(() => classifyContextUtilization(1.5, 200_000), /tokensUsed/);
});
test('zero contextWindow throws', () => {
assert.throws(() => classifyContextUtilization(100, 0), /contextWindow/);
});
test('negative contextWindow throws', () => {
assert.throws(() => classifyContextUtilization(100, -1), /contextWindow/);
});
test('non-number inputs throw via Number.isInteger', () => {
assert.throws(() => classifyContextUtilization('100', 200_000), /tokensUsed/);
assert.throws(() => classifyContextUtilization(100, '200000'), /contextWindow/);
assert.throws(() => classifyContextUtilization(NaN, 200_000), /tokensUsed/);
assert.throws(() => classifyContextUtilization(100, Infinity), /contextWindow/);
});
});
describe('classifyContextUtilization — percent rounding', () => {
test('display percent rounds; state uses exact ratio', () => {
// 119_998 / 200_000 = 59.999% — display rounds to 60, state stays healthy.
const r = classifyContextUtilization(119_998, 200_000);
assert.strictEqual(r.state, STATES.HEALTHY);
assert.ok([59, 60].includes(r.percent), `expected percent ∈ {59,60}, got ${r.percent}`);
});
});