Skip to content

Commit 5701806

Browse files
test(webmcp): cover fresh-making and repository targets
1 parent 9aa42c9 commit 5701806

1 file changed

Lines changed: 34 additions & 33 deletions

File tree

tests/webmcp.test.mjs

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import { readFile } from 'node:fs/promises';
44
import { normalizeRegistry, readFallback } from '../scripts/fetch-skill-registry.mjs';
55
import { createSkillRegistry } from '../src/assets/js/webmcp-registry.js';
66

7-
// Usage: run with `npm test`; these checks verify registry provenance, the shared curated human/agent catalogue, current WebMCP Document API usage, click-driven human selection, explicit human handoff publication, and the visible remote MCP endpoint without requiring a WebMCP-capable test browser.
8-
97
const BOOTSTRAP_SNAPSHOT_COMMIT = '260671303733a45c8f8d5563e41d8854e09856e6';
108
const SNAPSHOT_PATH = 'src/_data/snapshots/skill-registry.last-known-good.json';
119

@@ -18,6 +16,7 @@ const sourceRegistry = JSON.stringify({
1816
{ name: 'msdmd', path: 'msdmd/SKILL.md', kind: 'metadata-block', description: 'foundational metadata convention' },
1917
{ name: 'cap-build', path: 'cap-build/SKILL.md', kind: 'metadata-block', depends_on: ['msdmd'], description: 'capability inventory' },
2018
{ name: 'meta', path: 'meta/SKILL.md', kind: 'procedural', description: 'METAPAT consultation router' },
19+
{ name: 'fresh-making', path: 'fresh-making/SKILL.md', kind: 'procedural', description: 'deterministic restoration of derived artifact consistency' },
2120
{ name: 'repo-audit-repair', path: 'repo-audit-repair/SKILL.md', kind: 'procedural', description: 'audit and repair a repository' }
2221
]
2322
});
@@ -64,32 +63,32 @@ test('committed or refreshed fallback snapshot is exact, usable, and retains sou
6463
assert.ok(snapshot.skills.some(skill => skill.name === 'repo-audit-repair'));
6564
});
6665

67-
test('public registry presents the same msdmd-plus-meta catalogue to human and agent surfaces', () => {
66+
test('public registry presents msdmd, meta, and fresh-making while hiding unrelated specialist skills', () => {
6867
const registry = createSkillRegistry(sampleProjection());
69-
assert.deepEqual(registry.listSkills().map(skill => skill.name), ['msdmd', 'cap-build', 'meta']);
68+
assert.deepEqual(registry.listSkills().map(skill => skill.name), ['msdmd', 'cap-build', 'meta', 'fresh-making']);
7069
assert.equal(registry.findSkills({ query: 'audit repository' }).length, 0);
7170
assert.equal(registry.findSkills({ query: 'capability' })[0].name, 'cap-build');
71+
assert.equal(registry.findSkills({ query: 'derived artifact' })[0].name, 'fresh-making');
7272
assert.throws(() => registry.inspectSkill({ name: 'repo-audit-repair' }), /unknown public skill/);
7373

74-
const closure = registry.resolveSkillClosure({ name: 'cap-build' });
75-
assert.deepEqual(closure.map(skill => skill.name), ['msdmd', 'cap-build']);
74+
assert.deepEqual(registry.resolveSkillClosure({ name: 'cap-build' }).map(skill => skill.name), ['msdmd', 'cap-build']);
75+
assert.deepEqual(registry.resolveSkillClosure({ name: 'fresh-making' }).map(skill => skill.name), ['fresh-making']);
7676
const status = registry.getRegistryStatus();
77-
assert.equal(status.skill_count, 3);
78-
assert.equal(status.source_skill_count, 4);
79-
assert.equal(status.public_scope, 'metadata-block plus meta');
77+
assert.equal(status.skill_count, 4);
78+
assert.equal(status.source_skill_count, 5);
79+
assert.equal(status.public_scope, 'metadata-block plus meta plus fresh-making');
8080
});
8181

82-
test('WebMCP provider registers five base registry tools and one explicit dynamic handoff tool through document.modelContext', async () => {
82+
test('WebMCP provider registers five base registry tools and one explicit dynamic browser handoff', async () => {
8383
const source = await readFile('src/assets/js/webmcp.js', 'utf8');
8484
for (const name of [
8585
'tiw_registry_status',
8686
'tiw_list_skills',
8787
'tiw_find_skill',
8888
'tiw_inspect_skill',
8989
'tiw_resolve_skill_closure'
90-
]) {
91-
assert.match(source, new RegExp(`name: '${name}'`));
92-
}
90+
]) assert.match(source, new RegExp(`name: '${name}'`));
91+
9392
assert.match(source, /HANDOFF_TOOL_NAME = 'tiw_human_handoff'/);
9493
assert.match(source, /name: HANDOFF_TOOL_NAME/);
9594
assert.equal((source.match(/annotations: \{ readOnlyHint: true/g) || []).length, 6);
@@ -98,34 +97,36 @@ test('WebMCP provider registers five base registry tools and one explicit dynami
9897
assert.match(source, /\{ signal: controller\.signal \}/);
9998
assert.match(source, /globalThis\.document\?\.modelContext/);
10099
assert.doesNotMatch(source, /navigator\?\.modelContext|provideContext/);
101-
assert.doesNotMatch(source, /install_skill|propagate_skill|update_file|create_file/);
100+
assert.doesNotMatch(source, /\/handoff\/|remote_session|writeKey|install_skill|propagate_skill|update_file|create_file/);
102101
});
103102

104-
test('human selection carries exact registry identity without typed internal skill names', async () => {
103+
test('human selection carries exact skill and repository identity without typed machine identifiers', async () => {
105104
const source = await readFile('src/assets/js/webmcp.js', 'utf8');
106-
assert.match(source, /bindHumanCatalogue\(registry\)/);
107105
assert.match(source, /dataset\.skillName/);
108-
assert.match(source, /registry\.inspectSkill\(\{ name \}\)/);
106+
assert.match(source, /data-human-repository-target/);
107+
assert.match(source, /dataset\.repositoryHead/);
108+
assert.match(source, /target_repository: repository/);
109+
assert.match(source, /observed_head_sha/);
109110
assert.match(source, /searchParams\.set\('skill', skill\.name\)/);
111+
assert.match(source, /searchParams\.set\('repo', repository\.name\)/);
110112
assert.match(source, /history\.replaceState/);
111-
assert.match(source, /data-selected-action/);
112113
});
113114

114-
test('human handoff requires explicit submit and carries selected skill, closure, provenance, and human request without persistence', async () => {
115+
test('fresh-making supplies an editable default refresh request and still requires explicit Send', async () => {
115116
const source = await readFile('src/assets/js/webmcp.js', 'utf8');
116-
assert.match(source, /data-human-handoff-form/);
117+
assert.match(source, /FRESH_MAKING_INTENT/);
118+
assert.match(source, /name === 'fresh-making'/);
119+
assert.match(source, /minimal affected closure/);
117120
assert.match(source, /new FormData\(event\.currentTarget\)\.get\('intent'\)/);
118121
assert.match(source, /registry\.resolveSkillClosure\(\{ name: selectedName \}\)/);
119122
assert.match(source, /human_request: intent/);
120-
assert.match(source, /remote_mcp_storage: false/);
123+
assert.match(source, /repository_write_authority: 'not granted by this handoff'/);
121124
assert.match(source, /persistence: 'page session only'/);
122125
assert.match(source, /publishHandoffTool\(handoff\)/);
123-
assert.match(source, /clearPublishedHandoff\('Request text changed/);
124-
assert.match(source, /clearPublishedHandoff\('Skill selection changed/);
125126
assert.doesNotMatch(source, /localStorage|sessionStorage|indexedDB/);
126127
});
127128

128-
test('dedicated WebMCP route presents collapsible click-select cards and one ordinary-language send box', async () => {
129+
test('dedicated WebMCP route presents collapsible skill cards, every generated repo target, and one send box', async () => {
129130
const [page, layout, packageJson] = await Promise.all([
130131
readFile('src/webmcp/index.njk', 'utf8'),
131132
readFile('src/_includes/layouts/base.njk', 'utf8'),
@@ -134,22 +135,22 @@ test('dedicated WebMCP route presents collapsible click-select cards and one ord
134135
assert.match(page, /permalink: \/webmcp\//);
135136
assert.match(page, /webmcp: true/);
136137
assert.match(page, /The page is the provider/);
137-
assert.match(page, /https:\/\/the-interdependency-mcp\.onrender\.com\/mcp/);
138138
assert.match(page, /skill\.kind == "metadata-block"/);
139139
assert.match(page, /skill\.name == "meta"/);
140+
assert.match(page, /skill\.name == "fresh-making"/);
140141
assert.match(page, /<details data-skill-description>/);
141142
assert.match(page, /<summary>Description<\/summary>/);
142-
assert.match(page, /data-select-skill/);
143-
assert.match(page, /data-selected-skill/);
144-
assert.match(page, /data-selected-action="inspect"/);
145-
assert.match(page, /data-selected-action="closure"/);
143+
assert.match(page, /generated\.repos\.repositories/);
144+
assert.match(page, /data-human-repository-target/);
145+
assert.match(page, /data-repository-head=/);
146+
assert.match(page, /data-selected-repository/);
146147
assert.match(page, /data-human-handoff-form/);
147148
assert.match(page, /<textarea[^>]+data-human-handoff-intent/);
148149
assert.match(page, /data-human-handoff-send disabled/);
149-
assert.match(page, /Nothing is sent merely by typing/);
150-
assert.match(page, /Send selected skill \+ request to agent/);
151-
assert.doesNotMatch(page, /data-webmcp-find|data-webmcp-inspect|data-webmcp-closure/);
152-
assert.match(page, /No internal skill name needs to be typed/);
150+
assert.match(page, /Nothing is sent merely by selecting or typing/);
151+
assert.match(page, /Send skill \+ repository \+ request to agent/);
152+
assert.match(page, /No internal skill or repository identifier needs to be typed/);
153153
assert.match(layout, /\{% if webmcp %\}<script src="\/assets\/js\/webmcp\.js" type="module"><\/script>\{% endif %\}/);
154+
assert.match(packageJson, /"refresh:github": "node scripts\/fetch-github-org\.mjs"/);
154155
assert.match(packageJson, /"refresh:skills": "node scripts\/fetch-skill-registry\.mjs"/);
155156
});

0 commit comments

Comments
 (0)