mirror of https://github.com/garrytan/gstack.git
91 lines
3.7 KiB
TypeScript
91 lines
3.7 KiB
TypeScript
/**
|
|
* Unit tests for parity baseline capture.
|
|
*
|
|
* Free. Reads the live repo state via captureBaseline() and asserts
|
|
* shape + invariants, not specific numbers (which drift release-over-release).
|
|
*/
|
|
|
|
import { describe, test, expect } from 'bun:test';
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import { captureBaseline, diffBaselines, type ParityBaseline } from './capture-parity-baseline';
|
|
|
|
const REPO_ROOT = path.resolve(import.meta.dir, '..', '..');
|
|
|
|
describe('capture-parity-baseline', () => {
|
|
test('produces a shaped baseline for the current repo', () => {
|
|
const baseline = captureBaseline({ repoRoot: REPO_ROOT, tag: 'unit-test' });
|
|
expect(baseline.tag).toBe('unit-test');
|
|
expect(baseline.totalSkills).toBeGreaterThan(20);
|
|
expect(baseline.totalCorpusBytes).toBeGreaterThan(100_000);
|
|
expect(baseline.topHeaviest.length).toBeGreaterThan(0);
|
|
expect(baseline.topHeaviest.length).toBeLessThanOrEqual(10);
|
|
expect(baseline.topHeaviest[0]!.skillMdBytes).toBeGreaterThan(0);
|
|
// Top 1 should be ≥ Top 2 (sort invariant)
|
|
if (baseline.topHeaviest.length >= 2) {
|
|
expect(baseline.topHeaviest[0]!.skillMdBytes).toBeGreaterThanOrEqual(
|
|
baseline.topHeaviest[1]!.skillMdBytes,
|
|
);
|
|
}
|
|
});
|
|
|
|
test('each skill entry has byte + line + token estimates', () => {
|
|
const baseline = captureBaseline({ repoRoot: REPO_ROOT });
|
|
for (const skill of Object.values(baseline.skills)) {
|
|
expect(skill.skillMdBytes).toBeGreaterThan(0);
|
|
expect(skill.skillMdLines).toBeGreaterThan(0);
|
|
expect(skill.estTokens).toBeGreaterThan(0);
|
|
// ~4 chars/token heuristic
|
|
expect(skill.estTokens).toBeCloseTo(skill.skillMdBytes / 4, -2);
|
|
}
|
|
});
|
|
|
|
test('diffBaselines returns expected deltas', () => {
|
|
const before: ParityBaseline = {
|
|
tag: 'before',
|
|
capturedAt: '2026-01-01T00:00:00Z',
|
|
capturedFromCommit: 'abc',
|
|
capturedFromBranch: 'main',
|
|
totalSkills: 2,
|
|
totalCorpusBytes: 1000,
|
|
estTotalCatalogTokens: 100,
|
|
topHeaviest: [],
|
|
skills: {
|
|
foo: { skill: 'foo', skillMdBytes: 600, skillMdLines: 10, estTokens: 150, tmplBytes: 300, descriptionLen: 50, hasGateEval: true, hasPeriodicEval: false },
|
|
bar: { skill: 'bar', skillMdBytes: 400, skillMdLines: 8, estTokens: 100, tmplBytes: 200, descriptionLen: 30, hasGateEval: false, hasPeriodicEval: false },
|
|
},
|
|
};
|
|
const after: ParityBaseline = {
|
|
...before,
|
|
tag: 'after',
|
|
totalCorpusBytes: 700,
|
|
estTotalCatalogTokens: 60,
|
|
skills: {
|
|
foo: { ...before.skills.foo!, skillMdBytes: 400 },
|
|
bar: { ...before.skills.bar!, skillMdBytes: 300 },
|
|
},
|
|
};
|
|
const diff = diffBaselines(before, after);
|
|
expect(diff.totalCorpusDelta).toBe(-300);
|
|
expect(diff.totalCorpusDeltaPct).toBeCloseTo(-30, 1);
|
|
expect(diff.catalogTokensDelta).toBe(-40);
|
|
expect(diff.perSkill.length).toBe(2);
|
|
// Sorted by abs delta descending
|
|
expect(diff.perSkill[0]!.skill).toBe('foo');
|
|
expect(diff.perSkill[0]!.deltaBytes).toBe(-200);
|
|
expect(diff.perSkill[1]!.skill).toBe('bar');
|
|
});
|
|
|
|
test('v1.44.1 baseline file exists with expected shape', () => {
|
|
const baselinePath = path.join(REPO_ROOT, 'test', 'fixtures', 'parity-baseline-v1.44.1.json');
|
|
expect(fs.existsSync(baselinePath)).toBe(true);
|
|
const baseline = JSON.parse(fs.readFileSync(baselinePath, 'utf-8')) as ParityBaseline;
|
|
expect(baseline.tag).toBe('v1.44.1');
|
|
expect(baseline.totalSkills).toBeGreaterThan(40);
|
|
// Document the v1.44.1 snapshot as the v1→v2 baseline reference.
|
|
// Compression in v1.45+ should drop totalCorpusBytes; this assertion
|
|
// anchors the "v1 was XX MB" claim in the CHANGELOG to a real file.
|
|
expect(baseline.totalCorpusBytes).toBeGreaterThan(2_000_000);
|
|
});
|
|
});
|