test: dedupe coverage gates; route both walks through skill-census

skill-coverage-floor duplicated two matrix assertions (registry
completeness, gate-tier floor) with a DIFFERENT hand-rolled directory
walk — matrix's skipped nothing, floor's skipped node_modules/docs/test.
Two 'same' gates disagreeing on the census is the bug class
test/helpers/skill-census.ts was written to kill. Registry assertions
now live in matrix only (with floor's better error message), both files
walk via skillCensus().authoredSkills, and floor keeps the per-skill
structural checks it owns.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-08-15 08:08:28 -07:00
co-authored by Claude Fable 5
parent da30a3cb5a
commit 3e12d8a26a
2 changed files with 20 additions and 45 deletions
+13 -7
View File
@@ -8,18 +8,17 @@
*/
import { describe, test, expect } from 'bun:test';
import * as fs from 'fs';
import * as path from 'path';
import { SKILL_COVERAGE, type SkillCoverage } from './skill-coverage-matrix';
import { skillCensus } from './helpers/skill-census';
const REPO_ROOT = path.resolve(import.meta.dir, '..');
// Canonical walk (skill-census.ts). This file and skill-coverage-floor
// previously hand-rolled two DIFFERENT walks (one skipped node_modules/docs/
// test, one didn't) — exactly the divergence class the census exists to kill.
function discoverSkills(): string[] {
return fs.readdirSync(REPO_ROOT, { withFileTypes: true })
.filter(e => e.isDirectory() && !e.name.startsWith('.'))
.filter(e => fs.existsSync(path.join(REPO_ROOT, e.name, 'SKILL.md')))
.map(e => e.name)
.sort();
return skillCensus(REPO_ROOT).authoredSkills;
}
describe('skill coverage matrix', () => {
@@ -29,16 +28,23 @@ describe('skill coverage matrix', () => {
});
test('every entry has the right shape', () => {
const missingGate: string[] = [];
for (const [skill, coverage] of Object.entries(SKILL_COVERAGE)) {
expect(Array.isArray(coverage.gate)).toBe(true);
expect(Array.isArray(coverage.periodic)).toBe(true);
expect(coverage.gate.length).toBeGreaterThan(0);
if (!coverage.gate || coverage.gate.length === 0) missingGate.push(skill);
for (const p of [...coverage.gate, ...coverage.periodic]) {
expect(typeof p).toBe('string');
expect(p.startsWith('test/')).toBe(true);
expect(p.endsWith('.test.ts')).toBe(true);
}
}
if (missingGate.length > 0) {
throw new Error(
`Skills with no gate-tier eval: ${missingGate.join(', ')}. ` +
`Eval-first foundation requires at least one CI-blocking check per skill.`,
);
}
});
test('every skill on disk has a registry entry', () => {