section-source-mcp-spec.test.mjs
130 lines 5.6 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 1 day ago
1 /**
2 * SectionSource self-hosted MCP implementation tests.
3 *
4 * Phase 1G accepts the self-hosted MCP implementation only. It must not add
5 * hosted MCP, Hub, search, persistence, Scooling runtime behavior, section
6 * bodies, snippets, summaries, PageIndex, OCR, LLM calls, or provider routing.
7 */
8 import { describe, it } from 'node:test';
9 import assert from 'node:assert/strict';
10 import fs from 'fs';
11 import path from 'path';
12 import { fileURLToPath } from 'url';
13
14 import { readSectionSource } from '../lib/section-source-note.mjs';
15
16 const __dirname = path.dirname(fileURLToPath(import.meta.url));
17 const repoRoot = path.dirname(__dirname);
18 const fixtureVault = path.join(__dirname, 'fixtures', 'vault-fs');
19 const specPath = path.join(repoRoot, 'docs', 'SECTION-SOURCE-MCP-IMPLEMENTATION-SPEC.md');
20
21 function readRepoFile(relativePath) {
22 return fs.readFileSync(path.join(repoRoot, relativePath), 'utf8');
23 }
24
25 describe('SectionSource self-hosted MCP implementation spec', () => {
26 it('unit: spec covers the required self-hosted MCP decision areas', () => {
27 const spec = fs.readFileSync(specPath, 'utf8');
28 const requiredSections = [
29 '## Proposed Tool',
30 '## Input Schema',
31 '## Accepted Output',
32 '## Explicitly Excluded Output',
33 '## Error Behavior',
34 '## Authorization And Path Safety',
35 '## Transport Boundaries',
36 '## Resource Boundary',
37 '## Seven-Tier Test Requirements',
38 '## Stop Conditions',
39 '## Acceptance Criteria',
40 ];
41
42 for (const section of requiredSections) {
43 assert.equal(spec.includes(section), true, `${section} is documented`);
44 }
45 assert.match(spec, /get_section_source/);
46 assert.match(spec, /This phase implements only the self-hosted MCP tool/);
47 });
48
49 it('integration: current SectionSource local integration remains the expected MCP target', () => {
50 const source = readSectionSource(fixtureVault, 'inbox/one.md');
51 const serialized = JSON.stringify(source);
52
53 assert.equal(source.schema, 'knowtation.section_source/v0');
54 assert.equal(source.path, 'inbox/one.md');
55 assert.equal(source.sections.every((section) => section.body_returned === false), true);
56 assert.equal(source.sections.every((section) => section.snippet_returned === false), true);
57 assert.equal(Object.hasOwn(source, 'body'), false);
58 assert.equal(Object.hasOwn(source, 'frontmatter'), false);
59 assert.equal(Object.hasOwn(source, 'snippet'), false);
60 assert.equal(serialized.includes('Body of inbox one'), false);
61 });
62
63 it('end-to-end: self-hosted and hosted MCP are wired while Hub and Scooling remain blocked', () => {
64 const selfHostedMcp = readRepoFile('mcp/create-server.mjs');
65 const hostedMcp = readRepoFile('hub/gateway/mcp-hosted-server.mjs');
66 const hostedAcl = readRepoFile('hub/gateway/mcp-tool-acl.mjs');
67 const hubServer = readRepoFile('hub/gateway/server.mjs');
68 assert.equal(selfHostedMcp.includes('get_section_source'), true);
69 assert.equal(selfHostedMcp.includes('readSectionSource'), true);
70 assert.equal(hostedMcp.includes('get_section_source'), true);
71 assert.equal(hostedMcp.includes('buildSectionSource'), true);
72 assert.equal(hostedAcl.includes('get_section_source'), true);
73 assert.equal(hostedMcp.includes('readSectionSource'), false);
74 assert.equal(hubServer.includes('get_section_source'), false);
75 assert.equal(hubServer.includes('section_source/v0'), false);
76 });
77
78 it('stress: MCP spec checks remain bounded to contract files', () => {
79 const started = Date.now();
80 const files = [
81 'docs/SECTION-SOURCE-MCP-IMPLEMENTATION-SPEC.md',
82 'docs/SECTION-SOURCE-CLI-IMPLEMENTATION-SPEC.md',
83 'docs/SECTION-SOURCE-TRANSPORT-PLAN.md',
84 'docs/SECTION-SOURCE-V0-SPEC.md',
85 'lib/section-source-note.mjs',
86 ].map((relativePath) => readRepoFile(relativePath));
87 const elapsedMs = Date.now() - started;
88
89 assert.equal(files.length, 5);
90 assert.ok(elapsedMs < 200, `expected bounded MCP spec check under 200ms, got ${elapsedMs}ms`);
91 });
92
93 it('data-integrity: MCP implementation adds no writes, sidecars, indexes, vectors, or summaries', () => {
94 const implementation = [
95 readRepoFile('lib/section-source.mjs'),
96 readRepoFile('lib/section-source-note.mjs'),
97 readRepoFile('mcp/create-server.mjs'),
98 ].join('\n');
99
100 assert.doesNotMatch(implementation, /\bwriteFile(Sync)?\s*\(/);
101 assert.doesNotMatch(implementation, /\bappendFile(Sync)?\s*\(/);
102 assert.doesNotMatch(implementation, /\bsidecar[A-Za-z0-9_]*\s*=/);
103 assert.doesNotMatch(implementation, /\bvector[A-Za-z0-9_]*\s*=/);
104 assert.doesNotMatch(implementation, /\bsummary[A-Za-z0-9_]*\s*=/);
105 });
106
107 it('performance: spec requires one-note reads and no external providers', () => {
108 const spec = fs.readFileSync(specPath, 'utf8');
109
110 assert.match(spec, /The tool reads one note only/);
111 assert.match(spec, /The tool does not scan the whole vault/);
112 assert.match(spec, /The tool does not call external providers/);
113 });
114
115 it('security: implementation spec blocks body, snippet, hosted, search, persistence, and Scooling exposure', () => {
116 const spec = fs.readFileSync(specPath, 'utf8');
117 const blockedPhrases = [
118 'No note body text appears in output.',
119 'No section body text appears in output.',
120 'No snippets appear in output.',
121 'No full frontmatter appears in output.',
122 'No MCP resource URI appears in output.',
123 'Hosted, Scooling, classroom, search, and persistence exposure remain blocked.',
124 ];
125
126 for (const phrase of blockedPhrases) {
127 assert.equal(spec.includes(phrase), true, `${phrase} is documented`);
128 }
129 });
130 });
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 1 day ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 1 day ago