Files
2026-08-24 19:34:16 -03:00

64 lines
3.4 KiB
JavaScript

import { existsSync, readFileSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import test from 'node:test';
import assert from 'node:assert/strict';
const here = path.dirname(fileURLToPath(import.meta.url));
const skillRoot = path.join(here, '..');
const skill = readFileSync(path.join(skillRoot, 'SKILL.md'), 'utf8');
const authoringContract = readFileSync(path.join(skillRoot, 'references', 'authoring-contract.md'), 'utf8');
const frontmatter = skill.match(/^---\n([\s\S]*?)\n---/);
test('skill description is portable across 1024-character runtimes and remains searchable', () => {
assert.ok(frontmatter, 'SKILL.md must start with YAML frontmatter');
const description = frontmatter[1].match(/^description:\s*(.+)$/m)?.[1]?.trim();
assert.ok(description, 'frontmatter must include a one-line description');
assert.ok(description.length <= 1024, `description is ${description.length} characters; maximum is 1024`);
assert.ok(Buffer.byteLength(description, 'utf8') <= 1024, 'description must also fit a 1024-byte runtime limit');
for (const trigger of ['architecture', 'workflow', 'sequence', 'data-flow', 'lifecycle', 'Mermaid']) {
assert.match(description, new RegExp(`\\b${trigger}\\b`, 'i'), `description must retain the ${trigger} trigger`);
}
assert.match(description, /standalone HTML/i);
assert.match(description, /Use when/i);
});
test('literal packaged-skill path references resolve inside the installed skill root', () => {
const references = [...skill.matchAll(/`((?:assets|bin|examples|recipes|references|renderers|schemas|scripts)\/[^`\s]+)`/g)]
.map((match) => match[1])
.filter((reference) => !/[<>{}*\[\]]/.test(reference));
assert.ok(references.length > 0, 'expected literal packaged-skill references');
for (const reference of new Set(references)) {
assert.equal(existsSync(path.join(skillRoot, reference)), true, `SKILL.md references missing packaged path ${reference}`);
}
});
test('main skill stays a bounded authoring router with progressive references', () => {
const lines = skill.trimEnd().split('\n');
assert.ok(lines.length <= 160, `SKILL.md is ${lines.length} lines; keep the entrypoint at 160 or fewer`);
for (const reference of [
'references/authoring-contract.md',
'references/viewer-runtime.md',
'references/delivery-contract.md',
]) {
assert.match(skill, new RegExp(reference.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
assert.equal(existsSync(path.join(skillRoot, reference)), true, `${reference} must ship with the skill`);
}
});
test('authored diagram copy follows the user language without translating technical identity', () => {
assert.match(skill, /language of the user's request/);
assert.match(skill, /guided-view labels\/notes.*legend label overrides.*card titles\/items/);
assert.match(skill, /product names.*code identifiers.*protocols.*API paths.*environment names/);
assert.match(authoringContract, /non-English diagram[\s\S]*`meta\.legend\.entries`/);
assert.match(authoringContract, /renderer-owned viewer controls remain separate/);
});
test('skill keeps the title hierarchy compact by default', () => {
assert.match(skill, /Omit `meta\.subtitle` by default/);
assert.match(skill, /Never invent a subtitle that restates the title, nodes, or cards/);
assert.match(authoringContract, /omitted or blank subtitle must not leave an empty visual row/);
});