Files
waggle-os/packages/sdk/tests/wave-g-capability-surface.test.ts
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

125 lines
4.5 KiB
TypeScript

/**
* Wave G — Capability Surface Productization tests.
*
* Verifies:
* 1. Pack catalog structure and completeness
* 2. Pack-to-skill relationships are valid
* 3. Product language consistency (no internal categories leaked)
* 4. Capability summary data shape
*/
import { describe, it, expect } from 'vitest';
import { listCapabilityPacks, getPackManifest } from '../src/capability-packs/index.js';
describe('Wave G: Capability Surface', () => {
describe('Pack Catalog', () => {
it('has exactly 5 curated packs', () => {
const packs = listCapabilityPacks();
expect(packs).toHaveLength(5);
});
it('all packs have required fields', () => {
const packs = listCapabilityPacks();
for (const pack of packs) {
expect(pack.id).toBeTruthy();
expect(pack.name).toBeTruthy();
expect(pack.description).toBeTruthy();
expect(pack.skills.length).toBeGreaterThan(0);
}
});
it('includes the 5 core pack IDs', () => {
const packs = listCapabilityPacks();
const ids = packs.map(p => p.id);
expect(ids).toContain('writing-suite');
expect(ids).toContain('research-workflow');
expect(ids).toContain('planning-master');
expect(ids).toContain('decision-framework');
expect(ids).toContain('team-collaboration');
});
it('each pack has user-facing name (not slug)', () => {
const packs = listCapabilityPacks();
for (const pack of packs) {
// Names should have spaces and be title-cased, not slugs
expect(pack.name).toMatch(/[A-Z]/); // Contains uppercase
expect(pack.name).not.toMatch(/^[a-z-]+$/); // Not a slug
}
});
});
describe('Pack-to-Skill Relationships', () => {
it('each pack references valid skill IDs', () => {
const packs = listCapabilityPacks();
for (const pack of packs) {
for (const skillId of pack.skills) {
expect(typeof skillId).toBe('string');
expect(skillId.length).toBeGreaterThan(0);
// Skill IDs should be kebab-case
expect(skillId).toMatch(/^[a-z][a-z0-9-]*$/);
}
}
});
it('getPackManifest returns correct pack by ID', () => {
const pack = getPackManifest('writing-suite');
expect(pack).not.toBeNull();
expect(pack!.name).toBe('Writing Suite');
expect(pack!.skills).toContain('draft-memo');
});
it('getPackManifest returns null for unknown pack', () => {
const pack = getPackManifest('nonexistent-pack');
expect(pack).toBeNull();
});
});
describe('Product Language', () => {
it('pack descriptions use user-facing language (no internal terms)', () => {
const packs = listCapabilityPacks();
const internalTerms = ['plugin', 'MCP', 'hook', 'mcp_server'];
for (const pack of packs) {
for (const term of internalTerms) {
expect(pack.description.toLowerCase()).not.toContain(term.toLowerCase());
}
}
});
it('pack names do not reference implementation details', () => {
const packs = listCapabilityPacks();
for (const pack of packs) {
expect(pack.name.toLowerCase()).not.toContain('plugin');
expect(pack.name.toLowerCase()).not.toContain('mcp');
expect(pack.name.toLowerCase()).not.toContain('hook');
}
});
});
describe('Capability Summary Shape', () => {
it('can construct a unified capability count from component data', () => {
// Simulates what the UI does: merge implementation counts into product counts
const mockCapabilities = {
tools: { count: 25, native: 20, plugin: 3, mcp: 2 },
skills: [{ name: 'draft-memo' }, { name: 'research-synthesis' }],
workflows: [{ name: 'research-team' }],
plugins: [{ name: 'p1', state: 'active' }],
mcpServers: [{ name: 'm1', healthy: true }],
commands: [{ name: '/help' }, { name: '/cost' }],
};
// Product-level counts (what user sees)
const toolCount = mockCapabilities.tools.count;
const skillCount = mockCapabilities.skills.length;
const workflowCount = mockCapabilities.workflows.length;
const extensionCount = mockCapabilities.plugins.length + mockCapabilities.mcpServers.length;
const commandCount = mockCapabilities.commands.length;
expect(toolCount).toBe(25);
expect(skillCount).toBe(2);
expect(workflowCount).toBe(1);
expect(extensionCount).toBe(2); // unified plugins + MCP
expect(commandCount).toBe(2);
});
});
});