File size: 7,242 Bytes
ec8acdf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);
const ROOT = resolve(dirname(__filename), '..');

const view = JSON.parse(readFileSync(join(ROOT, 'public/agent-view.json'), 'utf-8'));
const serverCard = JSON.parse(
  readFileSync(join(ROOT, 'public/.well-known/mcp/server-card.json'), 'utf-8'),
);
const agentCard = JSON.parse(
  readFileSync(join(ROOT, 'public/.well-known/agent-card.json'), 'utf-8'),
);
const vercelConfig = JSON.parse(readFileSync(join(ROOT, 'vercel.json'), 'utf-8'));

// Guards for the ?mode=agent machine-readable homepage view (orank Identity
// `agent-mode-view` bonus): the static JSON must stay in parity with the real
// discovery artifacts it summarizes, and the query-gated rewrite must fire
// BEFORE the / → welcome rewrite or the marketing page wins.
describe('agent-mode view (/?mode=agent)', () => {
  it('agent-view.json carries the machine-readable essentials', () => {
    assert.equal(view.kind, 'agent-view');
    for (const key of ['product', 'url', 'description', 'endpoints', 'authentication', 'rateLimits', 'documentation', 'capabilities', 'discovery']) {
      assert.ok(key in view, `agent-view.json missing ${key}`);
    }
    assert.ok(Array.isArray(view.capabilities) && view.capabilities.length >= 5);
    assert.ok(view.authentication.apiKey.header === 'X-WorldMonitor-Key');
    assert.ok(view.authentication.oauth2.scope === 'mcp');
    assert.match(view.authentication.summary, /Authentication/);
  });

  it('advertises the sandbox, quickstart, and docs MCP endpoints', () => {
    assert.equal(view.endpoints.sandbox.url, 'https://www.worldmonitor.app/sandbox/index.json');
    assert.doesNotThrow(
      () => readFileSync(join(ROOT, 'public/sandbox/index.json')),
      'sandbox index advertised but public/sandbox/index.json is missing',
    );
    assert.equal(view.endpoints.docsMcp.url, 'https://www.worldmonitor.app/docs/mcp');
    assert.ok(view.quickstart && typeof view.quickstart === 'object');
    for (const key of ['sandbox', 'rest', 'mcp']) {
      assert.match(view.quickstart[key], /^curl /, `quickstart.${key} must be a runnable curl line`);
    }
    // The sandbox quickstart must reference a fixture that actually ships.
    assert.doesNotThrow(() => readFileSync(join(ROOT, 'public/sandbox/get-resilience-score.json')));
  });

  it('advertises every official SDK ecosystem with an install command', () => {
    const sdks = view.endpoints.sdks;
    assert.deepEqual(
      Object.keys(sdks).filter((k) => !['guide', 'note'].includes(k)).sort(),
      ['go', 'javascript', 'python', 'ruby'],
    );
    assert.equal(sdks.python.install, 'pip install worldmonitor-sdk');
    assert.match(sdks.go.install, /^go get github\.com\/koala73\/worldmonitor\/sdk\/go$/);
    for (const key of ['javascript', 'python', 'ruby', 'go']) {
      assert.match(sdks[key].url, /^https:\/\//, `sdks.${key}.url must be a registry URL`);
    }
    // The SDK sources these advertise must exist in-repo.
    for (const dir of ['sdk/python', 'sdk/ruby', 'sdk/go']) {
      assert.doesNotThrow(() => readFileSync(join(ROOT, dir, 'README.md')), `${dir} must exist`);
    }
  });

  it('the marketing homepage points at the agent view via link rel=alternate', () => {
    // Hand-synced pair: the pro-test source and the committed build artifact
    // must both carry the pointer (the pre-push gate rebuilds and compares).
    const linkTag =
      '<link rel="alternate" type="application/json" href="https://www.worldmonitor.app/?mode=agent"';
    for (const path of ['pro-test/welcome.html', 'public/pro/welcome.html']) {
      assert.ok(
        readFileSync(join(ROOT, path), 'utf-8').includes(linkTag),
        `${path} must advertise the agent-mode view via <link rel="alternate">`,
      );
    }
  });

  it('advertises the schemamap and every section llms.txt', () => {
    assert.equal(view.discovery.schemamap, 'https://www.worldmonitor.app/schemamap.xml');
    assert.doesNotThrow(() => readFileSync(join(ROOT, 'public/schemamap.xml')));
    const sections = view.discovery.sectionLlmsTxt;
    assert.deepEqual(Object.keys(sections).sort(), ['api', 'blog', 'developers', 'docs']);
    const trackedSectionFiles = {
      api: 'public/api/llms.txt',
      developers: 'public/developers/llms.txt',
      blog: 'blog-site/src/pages/llms.txt.ts', // generated at /blog/llms.txt by Astro
    };
    for (const [section, path] of Object.entries(trackedSectionFiles)) {
      assert.doesNotThrow(
        () => readFileSync(join(ROOT, path)),
        `${path} must exist for discovery.sectionLlmsTxt.${section}`,
      );
    }
    // /docs/llms.txt is Mintlify-served; pin the URL so a docs-host move shows up here.
    assert.equal(sections.docs, 'https://www.worldmonitor.app/docs/llms.txt');
  });

  it('stays in parity with the MCP server card and A2A agent card', () => {
    assert.equal(view.endpoints.mcp.url, serverCard.url);
    assert.equal(view.endpoints.mcp.tools, serverCard.tools.length);
    assert.equal(view.endpoints.a2a.url, agentCard.url);
    assert.equal(view.endpoints.nlweb.url, 'https://www.worldmonitor.app/ask');
  });

  it('vercel.json serves it for /?mode=agent ahead of the welcome rewrite', () => {
    const rewrites = vercelConfig.rewrites;
    const agentIdx = rewrites.findIndex(
      (r) =>
        r.source === '/' &&
        Array.isArray(r.has) &&
        r.has.some((h) => h.type === 'query' && h.key === 'mode' && h.value === 'agent') &&
        r.destination === '/agent-view.json',
    );
    const welcomeIdx = rewrites.findIndex(
      (r) => r.source === '/' && r.destination === '/pro/welcome.html',
    );
    assert.ok(agentIdx >= 0, 'missing /?mode=agent rewrite to /agent-view.json');
    assert.ok(welcomeIdx >= 0, 'welcome rewrite missing');
    assert.ok(agentIdx < welcomeIdx, '?mode=agent rewrite must precede the welcome rewrite (first match wins)');
  });

  it('every discovery URL it advertises resolves to a tracked file or a live rewrite', () => {
    // Static, repo-tracked surfaces — a typo here ships a dead link to agents.
    const trackedPaths = {
      'https://worldmonitor.app/.well-known/agent-skills/index.json':
        'public/.well-known/agent-skills/index.json',
      'https://worldmonitor.app/.well-known/api-catalog': 'public/.well-known/api-catalog',
      'https://worldmonitor.app/.well-known/ai-catalog.json': 'public/.well-known/ai-catalog.json',
      'https://worldmonitor.app/llms.txt': 'public/llms.txt',
    };
    for (const [url, path] of Object.entries(trackedPaths)) {
      assert.equal(
        Object.values(view.discovery).includes(url),
        true,
        `discovery must advertise ${url}`,
      );
      assert.doesNotThrow(() => readFileSync(join(ROOT, path)), `${path} must exist for ${url}`);
    }
    // /index.md is rewrite-served (public/home.md) since #4830.
    const mdRewrite = vercelConfig.rewrites.find((r) => r.source === '/index.md');
    assert.ok(mdRewrite, 'markdownHomepage advertised but /index.md rewrite is gone');
  });
});