import { describe, it, beforeEach, afterEach, mock } from 'node:test';
import { strict as assert } from 'node:assert';
import {
  BASE_URL,
  HMAC_SECRET,
  PRO_USER_ID,
  PRO_TOKEN_ID,
  PRO_BEARER,
  makePipelineMock,
  makeProDeps,
  proReq,
  callBody,
} from './helpers/mcp-pro-deps.mjs';

const originalFetch = globalThis.fetch;
const originalEnv = { ...process.env };

const VALID_KEY = 'wm_test_key_123';

function makeReq(method = 'POST', body = null, headers = {}) {
  return new Request(BASE_URL, {
    method,
    headers: {
      'Content-Type': 'application/json',
      'X-WorldMonitor-Key': VALID_KEY,
      ...headers,
    },
    body: body ? JSON.stringify(body) : undefined,
  });
}

function initBody(id = 1) {
  return {
    jsonrpc: '2.0', id,
    method: 'initialize',
    params: { protocolVersion: '2025-03-26', capabilities: {}, clientInfo: { name: 'test', version: '1.0' } },
  };
}

function assertNoStore(res, label) {
  assert.equal(res.headers.get('Cache-Control'), 'no-store', `${label} must include Cache-Control: no-store`);
}

let handler;
let evaluateFreshness;

describe('api/mcp.ts — PRO MCP Server', () => {
  beforeEach(async () => {
    process.env.WORLDMONITOR_VALID_KEYS = VALID_KEY;
    // No UPSTASH vars — rate limiter gracefully skipped, Redis reads return null
    delete process.env.UPSTASH_REDIS_REST_URL;
    delete process.env.UPSTASH_REDIS_REST_TOKEN;
    // Telemetry is default-on in prod; off in tests so the JSON line per
    // tools/call doesn't pollute CI stdout and trip any future stdout-grep
    // assertion. The four `telemetry:`-prefixed tests below re-enable it
    // locally.
    process.env.MCP_TELEMETRY = 'false';

    const mod = await import(`../api/mcp.ts?t=${Date.now()}`);
    handler = mod.default;
    evaluateFreshness = mod.evaluateFreshness;
  });

  afterEach(() => {
    globalThis.fetch = originalFetch;
    Object.keys(process.env).forEach(k => {
      if (!(k in originalEnv)) delete process.env[k];
    });
    Object.assign(process.env, originalEnv);
  });

  // --- Auth ---

  // A DATA/quota method (tools/call) is the auth wall: unauthenticated → 401.
  // Discovery methods (initialize / tools/list) are intentionally public — see
  // the 'public discovery' block below — so they are NOT the probe here.
  const protectedCallBody = (id = 1) => ({
    jsonrpc: '2.0', id, method: 'tools/call',
    params: { name: 'get_market_data', arguments: {} },
  });

  it('returns HTTP 401 + WWW-Authenticate when no credentials provided (protected method)', async () => {
    const req = new Request(BASE_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(protectedCallBody()),
    });
    const res = await handler(req);
    assert.equal(res.status, 401);
    assert.ok(res.headers.get('www-authenticate')?.includes('Bearer realm="worldmonitor"'), 'must include WWW-Authenticate header');
    assert.match(res.headers.get('cache-control') || '', /\bno-store\b/i);
    const body = await res.json();
    assert.equal(body.error?.code, -32001);
  });

  // --- Public discovery (initialize + tools/list + resources/list servable without creds) ---

  it('initialize succeeds WITHOUT credentials (public discovery)', async () => {
    const req = new Request(BASE_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(initBody(1)),
    });
    const res = await handler(req);
    assert.equal(res.status, 200, 'unauthenticated initialize must be public');
    const body = await res.json();
    assert.equal(body.result?.protocolVersion, '2025-03-26');
    assert.equal(body.result?.serverInfo?.name, 'worldmonitor');
    assert.ok(res.headers.get('mcp-session-id'), 'Mcp-Session-Id must be issued on the anonymous handshake');
    assertNoStore(res, 'anonymous initialize');
  });

  it('tools/list succeeds WITHOUT credentials (public discovery) and returns tools', async () => {
    const req = new Request(BASE_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} }),
    });
    const res = await handler(req);
    assert.equal(res.status, 200, 'unauthenticated tools/list must be public');
    const body = await res.json();
    assert.ok(Array.isArray(body.result?.tools) && body.result.tools.length >= 3, 'must expose the tool catalog anonymously');
  });

  it('resources/list succeeds WITHOUT credentials (public discovery) and returns resources', async () => {
    // Mirrors orank's `mcp-resource-listing` check, which drives this
    // anonymously: `initialize` advertises the `resources` capability, so an
    // unauthenticated resources/list MUST enumerate the catalog rather than
    // 401 — otherwise the capability reads as advertised-but-empty.
    const req = new Request(BASE_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ jsonrpc: '2.0', id: 4, method: 'resources/list', params: {} }),
    });
    const res = await handler(req);
    assert.equal(res.status, 200, 'unauthenticated resources/list must be public');
    const body = await res.json();
    assert.ok(Array.isArray(body.result?.resources) && body.result.resources.length >= 1,
      'anonymous resources/list must expose a non-empty resource catalog (advertised `resources` capability)');
  });

  it('resources/templates/list succeeds WITHOUT credentials (public discovery) and returns URI templates', async () => {
    // The data-bearing URI templates (country risk, chokepoint, market quote)
    // moved from resources/list to resources/templates/list — this metadata
    // method is public so agents can still discover them without auth.
    const req = new Request(BASE_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ jsonrpc: '2.0', id: 5, method: 'resources/templates/list', params: {} }),
    });
    const res = await handler(req);
    assert.equal(res.status, 200, 'unauthenticated resources/templates/list must be public');
    const body = await res.json();
    assert.ok(Array.isArray(body.result?.resourceTemplates) && body.result.resourceTemplates.length >= 1,
      'anonymous resources/templates/list must expose the URI-template catalog');
    assert.ok(body.result.resourceTemplates.every((r) => typeof r.uriTemplate === 'string'),
      'each template entry must carry a uriTemplate field');
  });

  it('resources/read of a PUBLIC resource succeeds WITHOUT credentials + never touches quota (orank mcp-resource-quality)', async () => {
    // orank reads every resources/list entry via resources/read anonymously.
    // The concrete PUBLIC resources (freshness/health probes) return
    // metadata-only content, so they read cleanly without auth or quota.
    const req = new Request(BASE_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ jsonrpc: '2.0', id: 6, method: 'resources/read', params: { uri: 'worldmonitor://seed-meta/freshness' } }),
    });
    const res = await handler(req);
    assert.equal(res.status, 200, 'anonymous resources/read of a public resource must be 200');
    const body = await res.json();
    assert.equal(body.error, undefined, `must not error: ${JSON.stringify(body.error)}`);
    const c = body.result?.contents?.[0];
    assert.equal(c?.mimeType, 'application/json');
    assert.ok(typeof c?.text === 'string' && c.text.length > 0, 'content must be non-empty');
    assertNoStore(res, 'anonymous public resources/read');
  });

  it('resources/read of a data-bearing TEMPLATE instantiation still requires credentials (no quota bypass)', async () => {
    const req = new Request(BASE_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ jsonrpc: '2.0', id: 7, method: 'resources/read', params: { uri: 'worldmonitor://countries/de/risk' } }),
    });
    const res = await handler(req);
    assert.equal(res.status, 401, 'resources/read of a data-bearing template is a data/quota method — must stay gated');
    const body = await res.json();
    assert.equal(body.error?.code, -32001);
  });

  it('tools/call still requires credentials even though discovery is public', async () => {
    const req = new Request(BASE_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(protectedCallBody(3)),
    });
    const res = await handler(req);
    assert.equal(res.status, 401, 'tools/call is a data/quota method — must stay gated');
    const body = await res.json();
    assert.equal(body.error?.code, -32001);
  });

  it('returns HTTP 401 + WWW-Authenticate when invalid API key provided', async () => {
    const req = makeReq('POST', initBody(), { 'X-WorldMonitor-Key': 'wrong_key' });
    const res = await handler(req);
    assert.equal(res.status, 401);
    const wwwAuth = res.headers.get('www-authenticate') ?? '';
    assert.ok(wwwAuth.includes('Bearer realm="worldmonitor"'), 'must include WWW-Authenticate Bearer realm');
    assert.ok(wwwAuth.includes('error="invalid_token"'), 'must include error="invalid_token" per RFC 6750');
    const body = await res.json();
    assert.equal(body.error?.code, -32001);
  });

  // --- Protocol ---

  it('OPTIONS returns 204 with CORS headers', async () => {
    const req = new Request(BASE_URL, { method: 'OPTIONS', headers: { origin: 'https://worldmonitor.app' } });
    const res = await handler(req);
    assert.equal(res.status, 204);
    assert.ok(res.headers.get('access-control-allow-methods'));
    assert.match(res.headers.get('cache-control') || '', /\bno-store\b/i);
  });

  it('initialize returns protocol version and Mcp-Session-Id header', async () => {
    const res = await handler(makeReq('POST', initBody(1)));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.equal(body.jsonrpc, '2.0');
    assert.equal(body.id, 1);
    assert.equal(body.result?.protocolVersion, '2025-03-26');
    assert.equal(body.result?.serverInfo?.name, 'worldmonitor');
    assert.ok(res.headers.get('mcp-session-id'), 'Mcp-Session-Id header must be present');
  });

  it('bakes Cache-Control: no-store into JSON-RPC success and SSE-upgraded responses', async () => {
    // getMcpCorsHeaders() threads no-store into every branch; assert the positive
    // 200 paths (the #4497 incident class is a CACHED 200), not just the 401/204
    // negative paths the other two assertions cover.
    const json = await handler(makeReq('POST', initBody(50)));
    assert.equal(json.status, 200);
    assert.match(json.headers.get('cache-control') || '', /\bno-store\b/i, 'JSON-RPC 200 success must be no-store');

    // Accept: text/event-stream upgrades the 200 to SSE; it must keep no-transform
    // (framing) AND carry no-store (payload), and preserve Mcp-Session-Id.
    const sse = await handler(makeReq('POST', initBody(51), { Accept: 'text/event-stream' }));
    assert.equal(sse.status, 200);
    assert.match(sse.headers.get('content-type') || '', /text\/event-stream/, 'must upgrade to an SSE stream');
    assert.equal(sse.headers.get('cache-control'), 'no-store, no-transform', 'SSE success must be no-store + no-transform');
    assert.ok(sse.headers.get('mcp-session-id'), 'Mcp-Session-Id must survive the SSE envelope');
    await sse.body?.cancel();
  });

  it('notifications/initialized returns 202 with no body', async () => {
    const req = makeReq('POST', { jsonrpc: '2.0', method: 'notifications/initialized', params: {} });
    const res = await handler(req);
    assert.equal(res.status, 202);
  });

  it('unknown method returns JSON-RPC -32601', async () => {
    const res = await handler(makeReq('POST', { jsonrpc: '2.0', id: 5, method: 'nonexistent/method', params: {} }));
    const body = await res.json();
    assert.equal(body.error?.code, -32601);
  });

  it('malformed body returns JSON-RPC -32600', async () => {
    const req = new Request(BASE_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'X-WorldMonitor-Key': VALID_KEY },
      body: '{bad json',
    });
    const res = await handler(req);
    const body = await res.json();
    assert.equal(body.error?.code, -32600);
  });

  it('sets Cache-Control: no-store on representative MCP success and error responses', async () => {
    const preflight = await handler(new Request(BASE_URL, {
      method: 'OPTIONS',
      headers: { origin: 'https://claude.ai' },
    }));
    assert.equal(preflight.status, 204);
    assertNoStore(preflight, 'OPTIONS preflight');

    const unauthenticated = await handler(new Request(BASE_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(protectedCallBody()),
    }));
    assert.equal(unauthenticated.status, 401);
    assertNoStore(unauthenticated, 'auth error');

    const initialized = await handler(makeReq('POST', initBody(20)));
    assert.equal(initialized.status, 200);
    assertNoStore(initialized, 'initialize success');
    assert.ok(initialized.headers.get('Mcp-Session-Id'), 'Mcp-Session-Id header must still be present');

    const acknowledged = await handler(makeReq('POST', {
      jsonrpc: '2.0',
      method: 'notifications/initialized',
      params: {},
    }));
    assert.equal(acknowledged.status, 202);
    assertNoStore(acknowledged, 'notification acknowledgement');

    const invalidMethod = await handler(makeReq('POST', {
      jsonrpc: '2.0',
      id: 21,
      method: 'nonexistent/method',
      params: {},
    }));
    assert.equal(invalidMethod.status, 200);
    assertNoStore(invalidMethod, 'JSON-RPC error');
  });

  it('SSE-upgraded success carries no-store, no-transform and preserves the session id', async () => {
    // Accept: text/event-stream makes maybeStreamJsonRpcResponse upgrade the 200
    // initialize reply to an SSE stream. The streamed reply (which carries the
    // tool/resource result data on tools/call) must keep no-transform for framing
    // AND now carry no-store so the payload is not cached, and still expose the
    // Mcp-Session-Id through the SSE envelope.
    const res = await handler(makeReq('POST', initBody(40), { Accept: 'text/event-stream' }));
    assert.equal(res.status, 200);
    assert.match(res.headers.get('Content-Type') ?? '', /text\/event-stream/, 'must upgrade to an SSE stream');
    assert.equal(
      res.headers.get('Cache-Control'),
      'no-store, no-transform',
      'SSE success must be no-store (payload not cached) + no-transform (SSE framing preserved)',
    );
    assert.ok(res.headers.get('mcp-session-id'), 'Mcp-Session-Id must survive the SSE envelope');
    await res.body?.cancel();
  });

  // --- logging/setLevel ---

  it('logging/setLevel with valid level returns success', async () => {
    for (const level of ['debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency']) {
      const res = await handler(makeReq('POST', {
        jsonrpc: '2.0', id: 10, method: 'logging/setLevel',
        params: { level },
      }));
      assert.equal(res.status, 200);
      const body = await res.json();
      assert.deepStrictEqual(body.result, {}, `level "${level}" must return empty success result`);
      assert.equal(body.error, undefined, `level "${level}" must not return an error`);
    }
  });

  it('logging/setLevel with invalid level returns JSON-RPC -32602', async () => {
    for (const bad of ['trace', 'warn', 'CRITICAL', 'Info', '', 42, null, undefined]) {
      const res = await handler(makeReq('POST', {
        jsonrpc: '2.0', id: 11, method: 'logging/setLevel',
        params: { level: bad },
      }));
      const body = await res.json();
      assert.equal(body.error?.code, -32602, `level ${JSON.stringify(bad)} must be rejected with -32602`);
    }
  });

  it('initialize response advertises logging capability', async () => {
    const res = await handler(makeReq('POST', initBody(12)));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.capabilities?.logging, 'capabilities.logging must be present');
    assert.deepStrictEqual(body.result.capabilities.logging, {}, 'capabilities.logging must be an empty object');
  });

  // --- tools/list ---

  it('tools/list returns 39 tools with name, description, inputSchema', async () => {
    const res = await handler(makeReq('POST', { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(Array.isArray(body.result?.tools), 'result.tools must be an array');
    assert.equal(body.result.tools.length, 39, `Expected 39 tools, got ${body.result.tools.length}`);
    for (const tool of body.result.tools) {
      assert.ok(tool.name, 'tool.name must be present');
      assert.ok(tool.description, 'tool.description must be present');
      assert.ok(tool.inputSchema, 'tool.inputSchema must be present');
      assert.ok(!('_cacheKeys' in tool), 'Internal _cacheKeys must not be exposed in tools/list');
      assert.ok(!('_execute' in tool), 'Internal _execute must not be exposed in tools/list');
      assert.ok(!('_coverageKeys' in tool), 'Internal _coverageKeys must not be exposed in tools/list');
      assert.ok(!('_apiPaths' in tool), 'Internal _apiPaths must not be exposed in tools/list (Tier-4 parity)');
      assert.ok(!('_postFilter' in tool), 'Internal _postFilter must not be exposed in tools/list (issue #3677)');
      assert.ok(!('_outputBudgetBytes' in tool), 'Internal _outputBudgetBytes must not be exposed in tools/list (PR-B)');
    }
    const toolNames = body.result.tools.map((t) => t.name);
    assert.ok(toolNames.includes('get_displacement_data'), 'get_displacement_data must be registered (U1 Tier 1 regression)');
    assert.ok(toolNames.includes('get_health_signals'), 'get_health_signals must be registered (U2)');
    assert.ok(toolNames.includes('get_energy_intelligence'), 'get_energy_intelligence must be registered (U3)');
    assert.ok(toolNames.includes('get_consumer_prices'), 'get_consumer_prices must be registered (U4)');
    assert.ok(toolNames.includes('get_tariff_trends'), 'get_tariff_trends must be registered (U5)');
    assert.ok(toolNames.includes('get_chokepoint_status'), 'get_chokepoint_status must be registered (U6)');
    assert.ok(toolNames.includes('describe_tool'), 'describe_tool must be registered (v1.5.0 schema compression)');
  });

  // --- tools/call ---

  it('tools/call with unknown tool returns JSON-RPC -32602', async () => {
    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 3, method: 'tools/call',
      params: { name: 'nonexistent_tool', arguments: {} },
    }));
    const body = await res.json();
    assert.equal(body.error?.code, -32602);
  });

  it('tools/call with known tool returns -32603 when EVERY cache read is null (F6: cache_all_null)', async () => {
    // F6 review pass: degenerate-empty result (Redis transient/stampede)
    // must surface as a tool-execution failure instead of a misleading success.
    // The env_key path doesn't have a quota counter; Pro callers keep the
    // already-reserved slot charged after this post-execution failure.
    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 4, method: 'tools/call',
      params: { name: 'get_market_data', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.equal(body.error?.code, -32603, 'all-null cache reads must surface as -32603');
  });

  it('evaluateFreshness marks bundled data stale when any required source meta is missing', () => {
    const now = Date.UTC(2026, 3, 1, 12, 0, 0);
    const freshness = evaluateFreshness(
      [
        { key: 'seed-meta:climate:anomalies', maxStaleMin: 120 },
        { key: 'seed-meta:climate:co2-monitoring', maxStaleMin: 2880 },
        { key: 'seed-meta:climate:ocean-ice', maxStaleMin: 1440 },
        { key: 'seed-meta:weather:alerts', maxStaleMin: 45 },
      ],
      [
        { fetchedAt: now - 30 * 60_000 },
        { fetchedAt: now - 60 * 60_000 },
        { fetchedAt: now - 24 * 60 * 60_000 },
        null,
      ],
      now,
    );

    assert.equal(freshness.stale, true);
    assert.equal(freshness.cached_at, null);
  });

  it('evaluateFreshness stays fresh only when every required source meta is within its threshold', () => {
    const now = Date.UTC(2026, 3, 1, 12, 0, 0);
    const freshness = evaluateFreshness(
      [
        { key: 'seed-meta:climate:anomalies', maxStaleMin: 120 },
        { key: 'seed-meta:climate:co2-monitoring', maxStaleMin: 2880 },
        { key: 'seed-meta:climate:ocean-ice', maxStaleMin: 1440 },
        { key: 'seed-meta:weather:alerts', maxStaleMin: 45 },
      ],
      [
        { fetchedAt: now - 30 * 60_000 },
        { fetchedAt: now - 24 * 60 * 60_000 },
        { fetchedAt: now - 12 * 60 * 60_000 },
        { fetchedAt: now - 15 * 60_000 },
      ],
      now,
    );

    assert.equal(freshness.stale, false);
    assert.equal(freshness.cached_at, new Date(now - 24 * 60 * 60_000).toISOString());
  });

  it('evaluateFreshness marks below-floor recordCount stale even when fetchedAt is fresh', () => {
    const now = Date.UTC(2026, 5, 11, 12, 0, 0);
    const freshness = evaluateFreshness(
      [
        { key: 'seed-meta:supply_chain:portwatch-ports', maxStaleMin: 2160, minRecordCount: 174 },
      ],
      [
        { fetchedAt: now - 12 * 60 * 60_000, recordCount: 139 },
      ],
      now,
    );

    assert.equal(freshness.stale, true);
    assert.equal(freshness.cached_at, new Date(now - 12 * 60 * 60_000).toISOString());
  });

  it('get_chokepoint_status declares the PortWatch 174-country freshness floor', async () => {
    const { CACHE_TOOLS } = await import(`../api/mcp/registry/cache-tools.ts?t=${Date.now()}`);
    const tool = CACHE_TOOLS.find((candidate) => candidate.name === 'get_chokepoint_status');
    const portwatchFreshness = tool?._freshnessChecks?.find(
      (check) => check.key === 'seed-meta:supply_chain:portwatch-ports',
    );

    assert.equal(portwatchFreshness?.minRecordCount, 174);
  });

  // --- Rate limiting ---

  it('returns JSON-RPC -32029 when rate limited', async () => {
    // Set UPSTASH env and mock fetch to simulate rate limit exhausted
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    // @upstash/ratelimit uses redis EVALSHA pipeline — mock to return [0, 0] (limit: 60, remaining: 0)
    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes('fake.upstash.io')) {
        // Simulate rate limit exceeded: [count, reset_ms] where count > limit
        return new Response(JSON.stringify({ result: [61, Date.now() + 60000] }), {
          status: 200,
          headers: { 'Content-Type': 'application/json' },
        });
      }
      return originalFetch(url);
    };

    // Re-import fresh module with UPSTASH env set
    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', initBody()));
    const body = await res.json();
    // Either succeeds (mock didn't trip the limiter) or gets -32029
    // The exact Upstash Lua response format is internal — just verify the handler doesn't crash
    assert.ok(body.error?.code === -32029 || body.result?.protocolVersion, 'Handler must return valid JSON-RPC (either rate limited or initialized)');
  });

  it('tools/call returns JSON-RPC -32603 when Redis fetch throws (P1 fix)', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    // Simulate Redis being unreachable — fetch throws a network/timeout error
    globalThis.fetch = async () => { throw new TypeError('fetch failed'); };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 6, method: 'tools/call',
      params: { name: 'get_market_data', arguments: {} },
    }));
    assert.equal(res.status, 200, 'Must return HTTP 200, not 500');
    const body = await res.json();
    assert.equal(body.error?.code, -32603, 'Must return JSON-RPC -32603, not throw');
  });

  // --- inputSchema completion + cache-tool _postFilter narrowing (issue #3677) ---

  it('tools/list: cache tools advertise filter properties (issue #3677 — no more empty {})', async () => {
    const res = await handler(makeReq('POST', { jsonrpc: '2.0', id: 700, method: 'tools/list', params: {} }));
    const body = await res.json();
    const byName = Object.fromEntries(body.result.tools.map((t) => [t.name, t]));
    // Representative cache tools across every shape (array payload, object-keyed
    // map, multi-key bundle) must now declare ≥1 filter property.
    for (const name of [
      'get_market_data', 'get_country_macro', 'get_conflict_events',
      'get_economic_data', 'get_chokepoint_status', 'get_eu_housing_cycle',
      'get_sanctions_data', 'get_forecast_predictions',
    ]) {
      const props = byName[name]?.inputSchema?.properties ?? {};
      assert.ok(Object.keys(props).length > 0, `${name} must declare at least one filter property`);
    }
    // The exact params from the issue #3677 worked example.
    assert.ok(byName.get_market_data.inputSchema.properties.symbols, 'get_market_data must declare symbols');
    assert.ok(byName.get_market_data.inputSchema.properties.asset_class, 'get_market_data must declare asset_class');
  });

  // Mock Upstash REST: data keys + seed-meta keys resolve from the supplied
  // maps. Any OTHER single-key GET resolves as "key absent" ({} → null) so the
  // unmocked keys of a multi-key bundle tool don't hit the network. Non-GET
  // traffic (the rate-limiter EVALSHA) falls through and throws —
  // applyPerMinuteLimit swallows that (graceful degradation).
  function mockCacheKeys(keyMap, metaKeys = {}) {
    const all = { ...keyMap, ...metaKeys };
    globalThis.fetch = async (url) => {
      const u = url.toString();
      for (const [k, v] of Object.entries(all)) {
        if (u.includes(`/get/${encodeURIComponent(k)}`)) {
          return new Response(JSON.stringify({ result: JSON.stringify(v) }), {
            status: 200, headers: { 'Content-Type': 'application/json' },
          });
        }
      }
      if (u.includes('/get/')) {
        return new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };
  }

  async function callTool(name, args) {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';
    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const res = await freshMod.default(makeReq('POST', {
      jsonrpc: '2.0', id: 701, method: 'tools/call', params: { name, arguments: args },
    }));
    const body = await res.json();
    assert.ok(body.result?.content, `${name} must return result.content (got ${JSON.stringify(body.error)})`);
    return JSON.parse(body.result.content[0].text);
  }

  it('get_market_data: omitting args returns the full payload (additive guarantee)', async () => {
    const stocks = { quotes: [{ symbol: 'AAPL', price: 100 }, { symbol: 'MSFT', price: 200 }] };
    const crypto = { quotes: [{ symbol: 'BTC', price: 50000 }] };
    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': stocks, 'market:crypto:v1': crypto },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: 3 } },
    );
    const out = await callTool('get_market_data', {});
    assert.equal(out.data['stocks-bootstrap'].quotes.length, 2, 'no args → all stock quotes');
    assert.ok(out.data.crypto, 'no args → crypto slice present');
  });

  // --- Telemetry ---

  it('telemetry: successful tools/call emits one mcp.toolcall line with the documented fields', async () => {
    process.env.MCP_TELEMETRY = 'true';
    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': { quotes: [{ symbol: 'AAPL', price: 100 }] }, 'market:crypto:v1': { quotes: [] } },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: 1 } },
    );
    const captured = [];
    const origLog = console.log;
    console.log = (line) => captured.push(line);
    try {
      await callTool('get_market_data', {});
    } finally {
      console.log = origLog;
    }
    const tc = captured.filter((l) => l && typeof l === 'object' && !Array.isArray(l) && l.tag === 'mcp.toolcall');
    assert.equal(tc.length, 1, `expected exactly one mcp.toolcall line, got ${tc.length}`);
    const ev = tc[0];
    assert.equal(ev.tool, 'get_market_data');
    assert.equal(ev.auth_kind, 'env_key');
    assert.equal(ev.ok, true);
    assert.equal(ev.jmespath_used, false);
    assert.equal(ev.jmespath_failed, null);
    assert.equal(typeof ev.latency_ms, 'number');
    assert.equal(typeof ev.bytes_pre_jmespath, 'number');
    assert.equal(typeof ev.bytes_post_jmespath, 'number');
    assert.ok(ev.bytes_post_jmespath > 0, 'bytes_post_jmespath must be > 0 on a successful response');
    assert.equal(typeof ev.ts, 'string');
    assert.equal(typeof ev.user_id, 'string');
    assert.ok(ev.user_id.length > 0, 'user_id must be a non-empty string');
    assert.notEqual(ev.user_id, VALID_KEY, 'env_key user_id MUST be hashed — never log the raw API key');
  });

  it('telemetry: tool-execution throw emits one mcp.toolcall line with ok:false + error_kind:server_error', async () => {
    process.env.MCP_TELEMETRY = 'true';
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';
    // Force the cache-tool fetch path to throw — dispatchToolsCall's outer
    // catch fires and one mcp.toolcall line with ok:false must land.
    globalThis.fetch = async () => { throw new TypeError('fetch failed'); };

    const captured = [];
    const origLog = console.log;
    const origErr = console.error;
    console.log = (line) => captured.push(line);
    console.error = () => {}; // swallow the captureSilentError stderr noise
    try {
      const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
      const res = await freshMod.default(makeReq('POST', {
        jsonrpc: '2.0', id: 901, method: 'tools/call',
        params: { name: 'get_market_data', arguments: {} },
      }));
      const body = await res.json();
      assert.equal(body.error?.code, -32603, 'must return JSON-RPC -32603 on tool throw');
    } finally {
      console.log = origLog;
      console.error = origErr;
    }
    const tc = captured.filter((l) => l && typeof l === 'object' && !Array.isArray(l) && l.tag === 'mcp.toolcall');
    assert.equal(tc.length, 1, `expected exactly one mcp.toolcall line, got ${tc.length}`);
    const ev = tc[0];
    assert.equal(ev.ok, false);
    assert.equal(ev.error_kind, 'server_error');
    assert.equal(ev.tool, 'get_market_data');
    assert.equal(typeof ev.latency_ms, 'number');
    assert.ok(Number.isFinite(ev.latency_ms), 'latency_ms must be finite on the error path');
    assert.equal(typeof ev.user_id, 'string');
    assert.ok(ev.user_id.length > 0, 'user_id must be present on the error path too');
    assert.notEqual(ev.user_id, VALID_KEY, 'error-path env_key user_id MUST be hashed — the key-never-logged contract holds on the ok:false branch too');
  });

  it('telemetry: invalid jmespath expression emits ok:true with jmespath_failed=invalid_expression', async () => {
    process.env.MCP_TELEMETRY = 'true';
    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': { quotes: [{ symbol: 'AAPL', price: 100 }] }, 'market:crypto:v1': { quotes: [] } },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: 1 } },
    );
    const captured = [];
    const origLog = console.log;
    console.log = (line) => captured.push(line);
    try {
      process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
      process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';
      const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
      const res = await freshMod.default(makeReq('POST', {
        jsonrpc: '2.0', id: 902, method: 'tools/call',
        params: { name: 'get_market_data', arguments: { jmespath: 'a.' } },
      }));
      const body = await res.json();
      // applyJmespath soft-fails — tool dispatch still succeeds.
      assert.ok(body.result?.content, 'soft jmespath failure must still return a successful response');
    } finally {
      console.log = origLog;
    }
    const tc = captured.filter((l) => l && typeof l === 'object' && !Array.isArray(l) && l.tag === 'mcp.toolcall');
    assert.equal(tc.length, 1, `expected exactly one mcp.toolcall line, got ${tc.length}`);
    const ev = tc[0];
    assert.equal(ev.ok, true, 'jmespath failure is a *user* error, not a system error');
    assert.equal(ev.jmespath_used, true);
    assert.equal(ev.jmespath_failed, 'invalid_expression');
  });

  it('telemetry: initialize emits mcp.tools_list_emitted with tools_array_bytes, tool_count, client_user_agent', async () => {
    process.env.MCP_TELEMETRY = 'true';
    const mod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const expectedToolCount = mod.__testing__.TOOL_REGISTRY.length;
    const captured = [];
    const origLog = console.log;
    console.log = (line) => captured.push(line);
    try {
      await mod.default(makeReq('POST', initBody(42), { 'user-agent': 'wm-test/1.0' }));
    } finally {
      console.log = origLog;
    }
    const ev = captured.filter((l) => l && typeof l === 'object' && !Array.isArray(l) && l.tag === 'mcp.tools_list_emitted');
    assert.equal(ev.length, 1, `expected exactly one mcp.tools_list_emitted line, got ${ev.length}`);
    assert.equal(typeof ev[0].tools_array_bytes, 'number');
    assert.ok(ev[0].tools_array_bytes > 0, 'tools_array_bytes must be > 0');
    assert.equal(ev[0].tool_count, expectedToolCount, 'tool_count must equal current registry size');
    assert.equal(ev[0].client_user_agent, 'wm-test/1.0');
    assert.equal(ev[0].auth_kind, 'env_key');
    assert.equal(typeof ev[0].user_id, 'string');
    assert.ok(ev[0].user_id.length > 0, 'user_id must be present on initialize too');
    assert.notEqual(ev[0].user_id, VALID_KEY, 'initialize user_id MUST be hashed for env_key — raw key never logged');
  });

  it('telemetry: 32 KB User-Agent is capped at 256 chars in client_user_agent', async () => {
    process.env.MCP_TELEMETRY = 'true';
    const mod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const captured = [];
    const origLog = console.log;
    console.log = (line) => captured.push(line);
    const hugeUa = 'A'.repeat(32 * 1024);
    try {
      await mod.default(makeReq('POST', initBody(43), { 'user-agent': hugeUa }));
    } finally {
      console.log = origLog;
    }
    const ev = captured.filter((l) => l && typeof l === 'object' && !Array.isArray(l) && l.tag === 'mcp.tools_list_emitted');
    assert.equal(ev[0].client_user_agent.length, 256, 'pathological UA must be sliced to 256 chars');
  });

  it('telemetry: circular _execute result + clean JMESPath projection stays 200 with bytes_pre_jmespath=-1 sentinel', async () => {
    // Regression guard for the round-1 blocker fix at api/mcp.ts:3173-3184.
    // Without the inner try/catch, the telemetry `JSON.stringify(result)`
    // on a circular `result` throws, control jumps to the outer catch, the
    // request becomes a 5xx tool error — even though JMESPath successfully
    // projected a clean subtree. The fix must:
    //   (a) keep the response 200 / ok:true (telemetry must never bubble),
    //   (b) emit `bytes_pre_jmespath: -1` (sentinel: measurement unavailable),
    //   (c) emit `bytes_post_jmespath > 0` (projection succeeded).
    // The sentinel is *the* observable that proves the inner catch fired.
    process.env.MCP_TELEMETRY = 'true';
    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const tool = freshMod.__testing__.TOOL_REGISTRY.find((t) => t.name === 'get_commodity_geo');
    assert.ok(tool && tool._execute, 'get_commodity_geo must exist with an _execute');
    const originalExecute = tool._execute;
    tool._execute = async () => {
      const result = { sites: [{ id: 'X1', mineral: 'Gold' }], total: 1 };
      result.self = result; // cycle — JSON.stringify(result) throws
      return result;
    };
    const captured = [];
    const origLog = console.log;
    console.log = (line) => captured.push(line);
    let resStatus, body;
    try {
      const res = await freshMod.default(makeReq('POST', {
        jsonrpc: '2.0', id: 904, method: 'tools/call',
        params: { name: 'get_commodity_geo', arguments: { jmespath: 'total' } },
      }));
      resStatus = res.status;
      body = await res.json();
    } finally {
      console.log = origLog;
      tool._execute = originalExecute;
    }
    assert.equal(resStatus, 200, 'circular result + clean JMESPath projection must still return HTTP 200');
    assert.ok(body.result?.content, 'must return a successful JSON-RPC result (no -32603)');
    assert.equal(body.result.content[0].text, '1', 'JMESPath `total` must extract the clean subtree');
    const tc = captured.filter((l) => l && typeof l === 'object' && !Array.isArray(l) && l.tag === 'mcp.toolcall');
    assert.equal(tc.length, 1, `expected exactly one mcp.toolcall line, got ${tc.length}`);
    const ev = tc[0];
    assert.equal(ev.ok, true, 'telemetry stringify failure must not flip ok to false');
    assert.equal(ev.tool, 'get_commodity_geo');
    assert.equal(ev.jmespath_used, true);
    assert.equal(ev.jmespath_failed, null);
    assert.equal(ev.bytes_pre_jmespath, -1, 'circular result must surface bytes_pre_jmespath: -1 sentinel');
    assert.ok(ev.bytes_post_jmespath > 0, 'bytes_post_jmespath must reflect the projected size (> 0)');
  });

  // --- Budget (PR-B: outputBudgetBytes) ---

  it('budget: tools/call within budget returns normal response', async () => {
    // Small payload well within the 128 KB cache-tool budget
    const stocks = { quotes: [{ symbol: 'AAPL', price: 100 }] };
    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': stocks, 'market:crypto:v1': { quotes: [] } },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: 1 } },
    );
    const out = await callTool('get_market_data', {});
    assert.ok(out.data, 'normal response must contain data');
    assert.equal(out._budget_exceeded, undefined, 'within-budget response must not contain _budget_exceeded');
  });

  it('budget: tools/call exceeding budget returns _budget_exceeded envelope', async () => {
    // Generate a payload that exceeds the 128 KB cache-tool budget.
    // Each quote entry is ~80 bytes; 3000 entries ≈ 240 KB in the stocks
    // slice alone, comfortably above 128 KB after JSON serialisation.
    // Pass limit: 0 to bypass the DEFAULT_LIST_LIMIT (30) cap.
    const hugeQuotes = Array.from({ length: 3000 }, (_, i) => ({
      symbol: `SYM${String(i).padStart(4, '0')}`,
      price: i + 1,
      change: 0.01 * i,
      volume: 1000000 + i,
    }));
    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': { quotes: hugeQuotes }, 'market:crypto:v1': { quotes: [] } },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: hugeQuotes.length } },
    );
    const out = await callTool('get_market_data', { limit: 0 });
    assert.equal(out._budget_exceeded, true, 'oversized response must return _budget_exceeded envelope');
    assert.equal(typeof out.budget_bytes, 'number', 'envelope must include budget_bytes');
    assert.equal(typeof out.actual_bytes, 'number', 'envelope must include actual_bytes');
    assert.ok(out.actual_bytes > out.budget_bytes, 'actual_bytes must exceed budget_bytes');
    assert.equal(typeof out.hint, 'string', 'envelope must include a hint string');
  });

  it('budget: telemetry includes budget_exceeded field', async () => {
    process.env.MCP_TELEMETRY = 'true';
    const captured = [];
    const origLog = console.log;
    console.log = (line) => captured.push(line);

    // Small payload — within budget
    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': { quotes: [{ symbol: 'AAPL', price: 100 }] }, 'market:crypto:v1': { quotes: [] } },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: 1 } },
    );
    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 800, method: 'tools/call',
      params: { name: 'get_market_data', arguments: {} },
    }));
    console.log = origLog;
    assert.equal(res.status, 200);

    const tc = captured.filter((l) => l && typeof l === 'object' && !Array.isArray(l) && l.tag === 'mcp.toolcall');
    assert.equal(tc.length, 1, `expected exactly one mcp.toolcall line, got ${tc.length}`);
    assert.equal(tc[0].budget_exceeded, false, 'within-budget call must emit budget_exceeded: false');
  });

  it('budget: telemetry emits budget_exceeded=true when budget is exceeded', async () => {
    process.env.MCP_TELEMETRY = 'true';
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';
    const captured = [];
    const origLog = console.log;
    console.log = (line) => captured.push(line);

    // Large payload that exceeds the 128 KB cache-tool budget
    const hugeQuotes = Array.from({ length: 3000 }, (_, i) => ({
      symbol: `SYM${String(i).padStart(4, '0')}`,
      price: i + 1,
      change: 0.01 * i,
      volume: 1000000 + i,
    }));
    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': { quotes: hugeQuotes }, 'market:crypto:v1': { quotes: [] } },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: hugeQuotes.length } },
    );
    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const res = await freshMod.default(makeReq('POST', {
      jsonrpc: '2.0', id: 801, method: 'tools/call',
      params: { name: 'get_market_data', arguments: { limit: 0 } },
    }));
    console.log = origLog;
    assert.equal(res.status, 200);
    const body = await res.json();
    const out = JSON.parse(body.result.content[0].text);
    assert.equal(out._budget_exceeded, true, 'sanity: response is the budget-exceeded envelope');

    const tc = captured.filter((l) => l && typeof l === 'object' && !Array.isArray(l) && l.tag === 'mcp.toolcall');
    assert.equal(tc.length, 1, `expected exactly one mcp.toolcall line, got ${tc.length}`);
    assert.equal(tc[0].budget_exceeded, true, 'over-budget call must emit budget_exceeded: true');
    assert.equal(tc[0].ok, true, 'budget-exceeded is a successful dispatch, not an error');
  });

  it('budget: every TOOL_REGISTRY entry declares a positive integer _outputBudgetBytes', async () => {
    const mod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const registry = mod.__testing__.TOOL_REGISTRY;
    assert.ok(Array.isArray(registry) && registry.length > 0, 'TOOL_REGISTRY must be a non-empty array');
    for (const tool of registry) {
      assert.equal(
        typeof tool._outputBudgetBytes,
        'number',
        `tool "${tool.name}" must declare _outputBudgetBytes as a number`,
      );
      assert.ok(
        Number.isInteger(tool._outputBudgetBytes) && tool._outputBudgetBytes > 0,
        `tool "${tool.name}" must declare a positive integer _outputBudgetBytes (got ${tool._outputBudgetBytes})`,
      );
    }
  });

  it('get_market_data: symbols filter narrows quote arrays across asset slices', async () => {
    const stocks = { quotes: [{ symbol: 'AAPL', price: 100 }, { symbol: 'MSFT', price: 200 }] };
    const crypto = { quotes: [{ symbol: 'BTC', price: 50000 }] };
    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': stocks, 'market:crypto:v1': crypto },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: 3 } },
    );
    const out = await callTool('get_market_data', { symbols: ['AAPL'] });
    assert.equal(out.data['stocks-bootstrap'].quotes.length, 1, 'symbols filter drops MSFT');
    assert.equal(out.data['stocks-bootstrap'].quotes[0].symbol, 'AAPL');
    assert.equal(out.data.crypto.quotes.length, 0, 'BTC absent from symbols → crypto quotes emptied');
  });

  it('get_market_data: asset_class selects only the requested dataset slices', async () => {
    const stocks = { quotes: [{ symbol: 'AAPL' }] };
    const crypto = { quotes: [{ symbol: 'BTC' }] };
    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': stocks, 'market:crypto:v1': crypto },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: 2 } },
    );
    const out = await callTool('get_market_data', { asset_class: ['crypto'] });
    assert.ok(out.data.crypto, 'asset_class crypto → crypto slice kept');
    assert.ok(!('stocks-bootstrap' in out.data), 'asset_class crypto → stocks slice dropped');
  });

  it('get_country_macro: countries filter narrows the ISO2-keyed maps', async () => {
    const macro = { countries: { US: { inflationPct: 3 }, DE: { inflationPct: 2 }, CN: { inflationPct: 1 } }, seededAt: 1 };
    const meta = {
      'seed-meta:economic:imf-macro': { fetchedAt: Date.now() - 60_000, recordCount: 3 },
      'seed-meta:economic:imf-growth': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
      'seed-meta:economic:imf-labor': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
      'seed-meta:economic:imf-external': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
    };
    mockCacheKeys({ 'economic:imf:macro:v2': macro }, meta);
    const filtered = await callTool('get_country_macro', { countries: ['US', 'DE'] });
    assert.deepEqual(
      Object.keys(filtered.data.macro.countries).sort(),
      ['DE', 'US'],
      'only the requested ISO2 keys are kept (case-insensitive)',
    );

    mockCacheKeys({ 'economic:imf:macro:v2': macro }, meta);
    const full = await callTool('get_country_macro', {});
    assert.equal(Object.keys(full.data.macro.countries).length, 3, 'no args → all countries retained');
  });

  it('get_energy_intelligence: country filter matches the gas-storage string[] payload', async () => {
    // Regression: energy:gas-storage:v1:_countries is a string[] of ISO2 codes,
    // NOT an array of {iso2} objects. A filter that reads c.iso2 drops everything.
    mockCacheKeys(
      { 'energy:gas-storage:v1:_countries': ['DE', 'FR', 'NL'] },
      { 'seed-meta:energy:gas-storage-countries': { fetchedAt: Date.now() - 60_000, recordCount: 3 } },
    );
    const out = await callTool('get_energy_intelligence', { dataset: ['gas-storage'], country: 'DE' });
    assert.deepEqual(out.data._countries, ['DE'], 'gas-storage _countries is a string[] — filter must match the string itself');
  });

  it('get_tariff_trends: alpha-2 country filter resolves to alpha-3 national-debt entries', async () => {
    // Regression: national-debt entries are keyed by ISO alpha-3 (iso3:"USA").
    // The country param is alpha-2 (consistent with the rest of the tool), so
    // country:"US" must still match iso3:"USA".
    mockCacheKeys(
      { 'economic:national-debt:v1': { entries: [{ iso3: 'USA', debtUsd: 2 }, { iso3: 'DEU', debtUsd: 1 }], seededAt: 1 } },
      { 'seed-meta:economic:national-debt': { fetchedAt: Date.now() - 60_000, recordCount: 2 } },
    );
    const out = await callTool('get_tariff_trends', { dataset: ['national-debt'], country: 'US' });
    assert.equal(out.data['national-debt'].entries.length, 1, 'alpha-2 "US" must match iso3 "USA"');
    assert.equal(out.data['national-debt'].entries[0].iso3, 'USA');
  });

  it('executeTool: a throwing _postFilter falls back to the PRISTINE unfiltered data', async () => {
    // P1 (Greptile): the helpers narrow `data` in place. executeTool hands the
    // filter a structuredClone, so a mid-filter throw — even one that has
    // already mutated its argument — must leave the returned payload complete.
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';
    mockCacheKeys(
      { 'fake:key:v1': { value: 1 } },
      { 'seed-meta:fake': { fetchedAt: Date.now() - 60_000, recordCount: 1 } },
    );
    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const throwingTool = {
      name: 'fake_throwing_tool',
      description: 'test seam',
      inputSchema: { type: 'object', properties: {}, required: [] },
      _cacheKeys: ['fake:key:v1'],
      _seedMetaKey: 'seed-meta:fake',
      _maxStaleMin: 60,
      _apiPaths: [],
      _postFilter: (data) => {
        data.mutated = true; // mutate the clone, then blow up mid-filter
        throw new Error('boom');
      },
    };
    const result = await freshMod.executeTool(throwingTool, { anything: true });
    assert.deepEqual(result.data, { key: { value: 1 } }, 'throw → full unfiltered payload, no partial narrowing leaked');
    assert.ok(!('mutated' in result.data), '_postFilter mutation must not leak through the structuredClone boundary');
  });

  // --- default-cap + summary mode (issue #3678) ---

  it('tools/list: cache tools advertise the universal `summary` flag (issue #3678)', async () => {
    const res = await handler(makeReq('POST', { jsonrpc: '2.0', id: 800, method: 'tools/list', params: {} }));
    const body = await res.json();
    const byName = Object.fromEntries(body.result.tools.map((t) => [t.name, t]));
    for (const name of ['get_market_data', 'get_conflict_events', 'get_country_macro', 'get_chokepoint_status']) {
      assert.ok(byName[name].inputSchema.properties.summary, `${name} must advertise summary`);
      assert.equal(byName[name].inputSchema.properties.summary.type, 'boolean');
    }
    // RPC tools have bespoke shapes — should NOT carry the generic summary flag.
    assert.ok(!byName.get_world_brief.inputSchema.properties.summary, 'RPC tools should not carry the cache-tool summary flag');
  });

  it('default cap: omitting limit caps each list to DEFAULT_LIST_LIMIT (=30)', async () => {
    // Build a 50-event conflict payload; default cap is 30.
    const ucdp = { events: Array.from({ length: 50 }, (_, i) => ({ id: i, country: 'X', deathsBest: 1 })) };
    mockCacheKeys(
      { 'conflict:ucdp-events:v1': ucdp },
      { 'seed-meta:conflict:ucdp-events': { fetchedAt: Date.now() - 60_000, recordCount: 50 } },
    );
    const out = await callTool('get_conflict_events', {});
    assert.equal(out.data['ucdp-events'].events.length, 30, 'omitting limit must apply the default cap of 30');
    assert.equal(out.data['ucdp-events'].events[0].id, 0, 'cap takes the natural array order (newest-first per seeder)');
  });

  it('default cap: get_market_data caps quote arrays at DEFAULT_LIST_LIMIT (issue #3678 example)', async () => {
    // Regression: the issue specifically named get_market_data as a large unfiltered
    // response. The tool must cap each per-class array (stocks/commodities/crypto/
    // sectors/etf-flows/gulf) like every other list-bearing cache tool.
    const stocks = { quotes: Array.from({ length: 50 }, (_, i) => ({ symbol: `T${i}`, price: i })) };
    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': stocks },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: 50 } },
    );
    const out = await callTool('get_market_data', {});
    assert.equal(out.data['stocks-bootstrap'].quotes.length, 30, 'no-args call must apply the default cap of 30');

    mockCacheKeys(
      { 'market:stocks-bootstrap:v1': stocks },
      { 'seed-meta:market:stocks': { fetchedAt: Date.now() - 60_000, recordCount: 50 } },
    );
    const full = await callTool('get_market_data', { limit: 0 });
    assert.equal(full.data['stocks-bootstrap'].quotes.length, 50, 'limit: 0 must opt out to the full quote list');
  });

  it('default cap: get_energy_intelligence caps crisis-policies + other list slices', async () => {
    // Regression: dataset:['crisis-policies'] with 50 policies must come back as 30.
    const policies = { policies: Array.from({ length: 50 }, (_, i) => ({ id: i, country: 'X' })) };
    mockCacheKeys(
      { 'energy:crisis-policies:v1': policies },
      { 'seed-meta:energy:crisis-policies': { fetchedAt: Date.now() - 60_000, recordCount: 50 } },
    );
    const out = await callTool('get_energy_intelligence', { dataset: ['crisis-policies'] });
    assert.equal(out.data['crisis-policies'].policies.length, 30, 'no-args call must apply the default cap of 30');

    mockCacheKeys(
      { 'energy:crisis-policies:v1': policies },
      { 'seed-meta:energy:crisis-policies': { fetchedAt: Date.now() - 60_000, recordCount: 50 } },
    );
    const full = await callTool('get_energy_intelligence', { dataset: ['crisis-policies'], limit: 0 });
    assert.equal(full.data['crisis-policies'].policies.length, 50, 'limit: 0 must opt out');
  });

  it('default cap: get_military_posture caps the theaters array', async () => {
    const theater_posture = { theaters: Array.from({ length: 40 }, (_, i) => ({ theater: `t${i}`, postureLevel: 'normal' })) };
    mockCacheKeys(
      { 'theater_posture:sebuf:stale:v1': theater_posture },
      { 'seed-meta:intelligence:risk-scores': { fetchedAt: Date.now() - 60_000, recordCount: 40 } },
    );
    const out = await callTool('get_military_posture', {});
    assert.equal(out.data.theater_posture.theaters.length, 30, 'no-args must cap theaters to 30');
  });

  it('default cap: get_chokepoint_status caps the chokepoints array', async () => {
    const baselines = { source: 'x', referenceYear: 2023, updatedAt: '', chokepoints: Array.from({ length: 40 }, (_, i) => ({ id: `c${i}`, relayId: `c${i}_strait`, name: `Chokepoint ${i}` })) };
    mockCacheKeys(
      { 'energy:chokepoint-baselines:v1': baselines },
      { 'seed-meta:energy:chokepoint-baselines': { fetchedAt: Date.now() - 60_000, recordCount: 40 } },
    );
    const out = await callTool('get_chokepoint_status', { dataset: ['chokepoint-baselines'] });
    assert.equal(out.data['chokepoint-baselines'].chokepoints.length, 30, 'no-args must cap chokepoints to 30');
  });

  it('default cap: limit: 0 opts out and returns the full list', async () => {
    const ucdp = { events: Array.from({ length: 50 }, (_, i) => ({ id: i, country: 'X', deathsBest: 1 })) };
    mockCacheKeys(
      { 'conflict:ucdp-events:v1': ucdp },
      { 'seed-meta:conflict:ucdp-events': { fetchedAt: Date.now() - 60_000, recordCount: 50 } },
    );
    const out = await callTool('get_conflict_events', { limit: 0 });
    assert.equal(out.data['ucdp-events'].events.length, 50, 'limit: 0 must opt out of the default cap and return the full list');
  });

  // --- limit on country/EU/displacement tools ---
  //
  // Five tools — get_country_macro, get_eu_housing_cycle,
  // get_eu_quarterly_gov_debt, get_eu_industrial_production,
  // get_displacement_data — return per-country payloads that can exceed the
  // per-tool output budget on default args. The IMF/Eurostat tools cap their
  // keyed-object country maps via `capNestedMap`; displacement caps arrays.
  // `limit: 0` is the customer-facing opt-out and always returns the full
  // payload.

  function makeCountryMap(prefix, n) {
    return Object.fromEntries(Array.from({ length: n }, (_, i) => [`${prefix}${i}`, { value: i }]));
  }

  it('limit: get_country_macro default args → caps every IMF dataset to 30', async () => {
    // Mock all four IMF cache keys with 60 countries each so the test
    // actually verifies the `for (const label of ['macro','growth','labor',
    // 'external'])` capNestedMap loop, not just the macro label.
    const payload = { countries: makeCountryMap('C', 60) };
    const meta = {
      'seed-meta:economic:imf-macro': { fetchedAt: Date.now() - 60_000, recordCount: 60 },
      'seed-meta:economic:imf-growth': { fetchedAt: Date.now() - 60_000, recordCount: 60 },
      'seed-meta:economic:imf-labor': { fetchedAt: Date.now() - 60_000, recordCount: 60 },
      'seed-meta:economic:imf-external': { fetchedAt: Date.now() - 60_000, recordCount: 60 },
    };
    mockCacheKeys({
      'economic:imf:macro:v2': payload,
      'economic:imf:growth:v1': payload,
      'economic:imf:labor:v1': payload,
      'economic:imf:external:v1': payload,
    }, meta);
    const out = await callTool('get_country_macro', {});
    for (const label of ['macro', 'growth', 'labor', 'external']) {
      assert.equal(Object.keys(out.data[label].countries).length, 30,
        `default args → ${label}.countries capped to DEFAULT_LIST_LIMIT (30)`);
    }
  });

  it('limit: get_country_macro countries+limit → countries filter wins, limit ignored', async () => {
    // Design choice pinned: when countries[] is provided, the early-return
    // path takes effect and `limit` is silently a no-op. Schema description
    // says "when no countries filter is supplied" — this regression test
    // pins that contract so a future "should limit further-narrow a
    // countries result" rewrite trips the test instead of breaking callers.
    const payload = { countries: makeCountryMap('C', 60) };
    const meta = {
      'seed-meta:economic:imf-macro': { fetchedAt: Date.now() - 60_000, recordCount: 60 },
      'seed-meta:economic:imf-growth': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
      'seed-meta:economic:imf-labor': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
      'seed-meta:economic:imf-external': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
    };
    mockCacheKeys({ 'economic:imf:macro:v2': payload }, meta);
    const out = await callTool('get_country_macro', { countries: ['C0', 'C1', 'C2', 'C3', 'C4'], limit: 1 });
    assert.equal(Object.keys(out.data.macro.countries).length, 5,
      'countries filter takes precedence; limit is ignored when countries is supplied');
  });

  it('limit: get_country_macro limit:0 → full payload', async () => {
    const macro = { countries: makeCountryMap('C', 60) };
    const meta = {
      'seed-meta:economic:imf-macro': { fetchedAt: Date.now() - 60_000, recordCount: 60 },
      'seed-meta:economic:imf-growth': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
      'seed-meta:economic:imf-labor': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
      'seed-meta:economic:imf-external': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
    };
    mockCacheKeys({ 'economic:imf:macro:v2': macro }, meta);
    const out = await callTool('get_country_macro', { limit: 0 });
    assert.equal(Object.keys(out.data.macro.countries).length, 60,
      'limit: 0 is the customer-facing opt-out and returns the full payload');
  });

  it('limit: get_eu_housing_cycle default args → cap to 30, limit:0 → full', async () => {
    const hp = { countries: makeCountryMap('EU', 40) };
    const meta = { 'seed-meta:economic:eurostat-house-prices': { fetchedAt: Date.now() - 60_000, recordCount: 40 } };

    mockCacheKeys({ 'economic:eurostat:house-prices:v1': hp }, meta);
    const capped = await callTool('get_eu_housing_cycle', {});
    assert.equal(Object.keys(capped.data['house-prices'].countries).length, 30, 'default args → cap to 30');

    mockCacheKeys({ 'economic:eurostat:house-prices:v1': hp }, meta);
    const optOut = await callTool('get_eu_housing_cycle', { limit: 0 });
    assert.equal(Object.keys(optOut.data['house-prices'].countries).length, 40, 'limit: 0 → full payload');
  });

  it('limit: get_eu_quarterly_gov_debt default args → cap to 30, limit:0 → full', async () => {
    const gd = { countries: makeCountryMap('EU', 40) };
    const meta = { 'seed-meta:economic:eurostat-gov-debt-q': { fetchedAt: Date.now() - 60_000, recordCount: 40 } };

    mockCacheKeys({ 'economic:eurostat:gov-debt-q:v1': gd }, meta);
    const capped = await callTool('get_eu_quarterly_gov_debt', {});
    assert.equal(Object.keys(capped.data['gov-debt-q'].countries).length, 30, 'default args → cap to 30');

    mockCacheKeys({ 'economic:eurostat:gov-debt-q:v1': gd }, meta);
    const optOut = await callTool('get_eu_quarterly_gov_debt', { limit: 0 });
    assert.equal(Object.keys(optOut.data['gov-debt-q'].countries).length, 40, 'limit: 0 → full payload');
  });

  it('limit: get_eu_industrial_production default args → cap to 30, limit:0 → full', async () => {
    const ip = { countries: makeCountryMap('EU', 40) };
    const meta = { 'seed-meta:economic:eurostat-industrial-production': { fetchedAt: Date.now() - 60_000, recordCount: 40 } };

    mockCacheKeys({ 'economic:eurostat:industrial-production:v1': ip }, meta);
    const capped = await callTool('get_eu_industrial_production', {});
    assert.equal(Object.keys(capped.data['industrial-production'].countries).length, 30, 'default args → cap to 30');

    mockCacheKeys({ 'economic:eurostat:industrial-production:v1': ip }, meta);
    const optOut = await callTool('get_eu_industrial_production', { limit: 0 });
    assert.equal(Object.keys(optOut.data['industrial-production'].countries).length, 40, 'limit: 0 → full payload');
  });

  it('limit: get_displacement_data default args → ≤30 items, limit:0 → full payload', async () => {
    const currentYear = new Date().getUTCFullYear();
    const summary = {
      countries: Array.from({ length: 60 }, (_, i) => ({ iso3: `C${i}`, refugees: i, idps: i })),
      topFlows: Array.from({ length: 60 }, (_, i) => ({ originCode: `O${i}`, asylumCode: `A${i}`, count: i })),
    };
    const dataKey = `displacement:summary:v1:${currentYear}`;
    const meta = { 'seed-meta:displacement:summary': { fetchedAt: Date.now() - 60_000, recordCount: 60 } };

    mockCacheKeys({ [dataKey]: summary }, meta);
    const def = await callTool('get_displacement_data', {});
    assert.equal(def.data.summary.countries.length, 30, 'default args → countries capped to 30');
    assert.equal(def.data.summary.topFlows.length, 30, 'default args → topFlows capped to 30');

    mockCacheKeys({ [dataKey]: summary }, meta);
    const full = await callTool('get_displacement_data', { limit: 0 });
    assert.equal(full.data.summary.countries.length, 60, 'limit: 0 → full countries array');
    assert.equal(full.data.summary.topFlows.length, 60, 'limit: 0 → full topFlows array');
  });

  it('summary mode: collapses arrays to {count, sample} and large entity maps to {count, sample_keys}', async () => {
    // Mix: an array payload + a 10-country IMF map (well above SUMMARY_MAP_THRESHOLD=5).
    const macro = {
      countries: Object.fromEntries(Array.from({ length: 10 }, (_, i) => [`C${i}`, { inflationPct: i }])),
      seededAt: 12345,
    };
    mockCacheKeys(
      { 'economic:imf:macro:v2': macro },
      {
        'seed-meta:economic:imf-macro': { fetchedAt: Date.now() - 60_000, recordCount: 10 },
        'seed-meta:economic:imf-growth': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
        'seed-meta:economic:imf-labor': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
        'seed-meta:economic:imf-external': { fetchedAt: Date.now() - 60_000, recordCount: 0 },
      },
    );
    const out = await callTool('get_country_macro', { summary: true });
    // data.macro is a typed payload {countries, seededAt}. Its `countries` map has 10 keys → summarized.
    assert.equal(out.data.macro.countries.count, 10, 'large entity map → count');
    assert.equal(out.data.macro.countries.sample_keys.length, 3, 'sample_keys capped at 3');
    assert.equal(out.data.macro.seededAt, 12345, 'scalar fields pass through summarisation');
  });

  it('summary mode: composes with filters — counts reflect post-filter result', async () => {
    const ucdp = {
      events: [
        ...Array.from({ length: 10 }, (_, i) => ({ id: i, country: 'Syria', deathsBest: 5 })),
        ...Array.from({ length: 5 }, (_, i) => ({ id: 100 + i, country: 'Iran', deathsBest: 3 })),
      ],
    };
    mockCacheKeys(
      { 'conflict:ucdp-events:v1': ucdp },
      { 'seed-meta:conflict:ucdp-events': { fetchedAt: Date.now() - 60_000, recordCount: 15 } },
    );
    const out = await callTool('get_conflict_events', { country: 'syria', summary: true, limit: 0 });
    assert.equal(out.data['ucdp-events'].events.count, 10, 'summary count reflects the country filter (only Syria events)');
    assert.equal(out.data['ucdp-events'].events.sample.length, 3, 'summary sample capped at 3');
  });

  // --- get_displacement_data (U1: Tier 1 regression) ---

  it('get_displacement_data returns {cached_at, stale, data.summary} on cache hit', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const currentYear = new Date().getUTCFullYear();
    const expectedDataKey = `displacement:summary:v1:${currentYear}`;
    const summaryPayload = {
      year: currentYear,
      countries: [
        { iso3: 'SYR', refugees: 6_700_000, idps: 6_900_000 },
        { iso3: 'UKR', refugees: 5_900_000, idps: 3_700_000 },
      ],
    };
    const seedFetchedAt = Date.now() - 60 * 60_000; // 1h old — well inside 3600 min budget

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent(expectedDataKey)}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(summaryPayload) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      if (u.includes('/get/seed-meta%3Adisplacement%3Asummary')) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: seedFetchedAt, recordCount: 2 }) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      return originalFetch(url);
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 100, method: 'tools/call',
      params: { name: 'get_displacement_data', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'result.content must be present');
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.stale, false, 'fresh meta within budget must yield stale=false');
    assert.equal(payload.cached_at, new Date(seedFetchedAt).toISOString(), 'cached_at must reflect seed-meta fetchedAt');
    assert.deepEqual(payload.data.summary, summaryPayload, 'label-walk strips year+v1, exposes payload under data.summary');
  });

  it('get_displacement_data returns -32603 when cache is empty (cache_all_null)', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    // Upstash returns {} (no result) for every GET — simulates fresh deploy
    // or evicted cache. executeTool's cache_all_null guard must throw → -32603.
    globalThis.fetch = async () => new Response(JSON.stringify({}), {
      status: 200, headers: { 'Content-Type': 'application/json' },
    });

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 101, method: 'tools/call',
      params: { name: 'get_displacement_data', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.equal(body.error?.code, -32603, 'empty cache must surface as -32603 (cache_all_null)');
  });

  // --- get_health_signals (U2) ---

  it('get_health_signals returns both disease-outbreaks and air-quality slices on cache hit', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const outbreaksPayload = { outbreaks: [{ id: 'who-1', disease: 'Marburg', country: 'TZA' }] };
    const airQualityPayload = { stations: [{ id: 'aqi-1', city: 'Delhi', pm25: 187 }] };
    const outbreaksFetchedAt = Date.now() - 60 * 60_000;   // 1h old; within 2880-min budget
    const airQualityFetchedAt = Date.now() - 30 * 60_000;  // 30m old; within 180-min budget

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent('health:disease-outbreaks:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(outbreaksPayload) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      if (u.includes(`/get/${encodeURIComponent('health:air-quality:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(airQualityPayload) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:health:disease-outbreaks')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: outbreaksFetchedAt, recordCount: 1 }) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:health:air-quality')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: airQualityFetchedAt, recordCount: 1 }) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      return originalFetch(url);
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 200, method: 'tools/call',
      params: { name: 'get_health_signals', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'result.content must be present');
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.stale, false, 'both metas within their per-key budgets must yield stale=false');
    assert.equal(payload.cached_at, new Date(outbreaksFetchedAt).toISOString(), 'cached_at reflects oldest valid fetchedAt across freshness checks');
    assert.deepEqual(payload.data['disease-outbreaks'], outbreaksPayload, 'disease-outbreaks slice labelled from cache-key suffix');
    assert.deepEqual(payload.data['air-quality'], airQualityPayload, 'air-quality slice labelled from cache-key suffix');
  });

  it('get_health_signals marks aggregate stale when disease-outbreaks meta is past budget but air-quality is fresh', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const outbreaksPayload = { outbreaks: [{ id: 'who-1' }] };
    const airQualityPayload = { stations: [{ id: 'aqi-1' }] };
    // disease-outbreaks budget is 2880 min — put it at 4000 min old (clearly stale)
    const outbreaksFetchedAt = Date.now() - 4000 * 60_000;
    // air-quality budget is 180 min — put it at 30 min old (fresh)
    const airQualityFetchedAt = Date.now() - 30 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent('health:disease-outbreaks:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(outbreaksPayload) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      if (u.includes(`/get/${encodeURIComponent('health:air-quality:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(airQualityPayload) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:health:disease-outbreaks')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: outbreaksFetchedAt, recordCount: 1 }) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:health:air-quality')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: airQualityFetchedAt, recordCount: 1 }) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      return originalFetch(url);
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 201, method: 'tools/call',
      params: { name: 'get_health_signals', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.stale, true, 'one over-budget key flips aggregate stale=true');
    assert.equal(payload.cached_at, new Date(outbreaksFetchedAt).toISOString(), 'cached_at is the oldest valid fetchedAt (disease-outbreaks)');
  });

  it('get_health_signals returns mixed shape (one slice null) without throwing when only one key is populated', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const airQualityPayload = { stations: [{ id: 'aqi-1' }] };
    const airQualityFetchedAt = Date.now() - 30 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent('health:disease-outbreaks:v1')}`)) {
        // Upstash returns {} (no `result`) when the key is absent — readJsonFromUpstash → null
        return new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('health:air-quality:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(airQualityPayload) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:health:disease-outbreaks')}`)) {
        return new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:health:air-quality')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: airQualityFetchedAt, recordCount: 1 }) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      return originalFetch(url);
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 202, method: 'tools/call',
      params: { name: 'get_health_signals', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    // Must NOT throw: at least one cache slot is populated, so cache_all_null guard does not fire.
    assert.ok(body.result?.content, 'partial-population must return a result, not -32603');
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.data['disease-outbreaks'], null, 'missing slice surfaces as null');
    assert.deepEqual(payload.data['air-quality'], airQualityPayload, 'populated slice still present');
    assert.equal(payload.stale, true, 'missing meta forces stale=true (hasAllValidMeta=false in evaluateFreshness)');
    assert.equal(payload.cached_at, null, 'mixed-validity meta yields cached_at=null per evaluateFreshness contract');
  });

  // --- get_consumer_prices (U4: hybrid _execute, country_code-parameterised) ---

  it('get_consumer_prices returns 5-slice data on cache hit for country_code: "ae"', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const overviewPayload   = { headlineCpiPct: 3.1, asOf: '2026-05-01' };
    const categoriesPayload = { categories: [{ name: 'Groceries', changePct: 2.4 }] };
    const moversPayload     = { items: [{ sku: 'milk-1L', changePct: 8.2 }] };
    const spreadPayload     = { retailers: [{ slug: 'carrefour_ae', basketUsd: 38.9 }, { slug: 'lulu_ae', basketUsd: 41.2 }] };
    const freshnessPayload  = { retailers: [{ slug: 'carrefour_ae', minsSinceScan: 18 }] };
    // All within the shared 1500-min budget — use 60min old.
    const fetchedAt = Date.now() - 60 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      // Data keys
      if (u.includes(`/get/${encodeURIComponent('consumer-prices:overview:ae')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(overviewPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('consumer-prices:categories:ae:30d')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(categoriesPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('consumer-prices:movers:ae:30d')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(moversPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('consumer-prices:retailer-spread:ae:essentials-ae')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(spreadPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('consumer-prices:freshness:ae')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(freshnessPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      // Freshness/seed-meta keys — note `spread:ae` (NOT `retailer-spread:ae:essentials-ae`)
      // matches the producer's actual key shape (see scripts/seed-consumer-prices.mjs:151).
      if (u.includes(`/get/${encodeURIComponent('seed-meta:consumer-prices:overview:ae')}`)
        || u.includes(`/get/${encodeURIComponent('seed-meta:consumer-prices:categories:ae:30d')}`)
        || u.includes(`/get/${encodeURIComponent('seed-meta:consumer-prices:movers:ae:30d')}`)
        || u.includes(`/get/${encodeURIComponent('seed-meta:consumer-prices:spread:ae')}`)
        || u.includes(`/get/${encodeURIComponent('seed-meta:consumer-prices:freshness:ae')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 300, method: 'tools/call',
      params: { name: 'get_consumer_prices', arguments: { country_code: 'ae' } },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'result.content must be present');
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.country_code, 'ae', 'echoes normalised country_code');
    assert.equal(payload.stale, false, 'all 5 freshness checks within 1500-min budget → stale=false');
    assert.equal(payload.cached_at, new Date(fetchedAt).toISOString(), 'cached_at is the oldest valid fetchedAt');
    assert.deepEqual(payload.data.overview, overviewPayload);
    assert.deepEqual(payload.data.categories, categoriesPayload);
    assert.deepEqual(payload.data.movers, moversPayload);
    assert.deepEqual(payload.data.retailerSpread, spreadPayload);
    assert.deepEqual(payload.data.freshness, freshnessPayload);
  });

  it('get_consumer_prices normalises uppercase "AE" to lowercase and succeeds', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const overviewPayload = { headlineCpiPct: 3.1 };
    const fetchedAt = Date.now() - 60 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent('consumer-prices:overview:ae')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(overviewPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes('/get/consumer-prices') || u.includes('/get/seed-meta%3Aconsumer-prices')) {
        // Default: return populated meta so freshness evaluation is clean
        if (u.includes('seed-meta')) {
          return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
        }
        return new Response(JSON.stringify({ result: JSON.stringify({}) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 301, method: 'tools/call',
      params: { name: 'get_consumer_prices', arguments: { country_code: 'AE' } },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'result.content must be present');
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.country_code, 'ae', 'uppercase AE is lowercased before whitelist check + key build');
    assert.deepEqual(payload.data.overview, overviewPayload);
    // No `error` field — request succeeded
    assert.ok(!('error' in payload), 'success path must not surface an error field');
  });

  it('get_consumer_prices returns result-level error (NOT -32603) for unsupported country_code: "us"', async () => {
    // No fetch mock needed — the whitelist guard rejects before any Redis read.
    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 302, method: 'tools/call',
      params: { name: 'get_consumer_prices', arguments: { country_code: 'us' } },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    // Critical: NOT a JSON-RPC error envelope (-32603). The user-input fault
    // surfaces inside result.content as `{error: "..."}` so callers see a
    // usable message instead of "Internal error: data fetch failed".
    assert.ok(body.result?.content, 'unsupported country must return a result, not -32603');
    assert.equal(body.error, undefined, 'result-level error must not set the JSON-RPC error envelope');
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.error, 'Country not yet supported. Available: ae');
  });

  it('get_consumer_prices returns result-level error when country_code is missing', async () => {
    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 303, method: 'tools/call',
      params: { name: 'get_consumer_prices', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'missing country_code must return a result, not -32603');
    assert.equal(body.error, undefined);
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.error, 'country_code is required');
  });

  it('get_consumer_prices throws cache_all_null (→ -32603) when every 5 cache reads return null', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    // F6 contract parity with the cache-tool path: hybrid _execute mirrors the
    // executeTool cache_all_null guard so degenerate-empty responses surface as
    // -32603 instead of success. Without this guard, every other cache-tool
    // throws on all-null while this one would return a misleading success.
    globalThis.fetch = async () => new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 304, method: 'tools/call',
      params: { name: 'get_consumer_prices', arguments: { country_code: 'ae' } },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.equal(body.error?.code, -32603, 'all-5-null reads must surface as -32603 cache_all_null');
  });

  it('get_consumer_prices rejects oversized/non-alpha country_code (e.g. "aexxx", "AE-DXB") with result-level error', async () => {
    // Without strict /^[a-z]{2}$/ validation, `.slice(0,2)` would silently
    // truncate "aexxx" → "ae" and serve AE data — masking client-side bugs.
    for (const bad of ['aexxx', 'AE-DXB', 'a', 'A1', '1AE', 'ae-']) {
      const res = await handler(makeReq('POST', {
        jsonrpc: '2.0', id: 305, method: 'tools/call',
        params: { name: 'get_consumer_prices', arguments: { country_code: bad } },
      }));
      assert.equal(res.status, 200);
      const body = await res.json();
      assert.ok(body.result?.content, `bad country_code ${JSON.stringify(bad)} must return a result, not -32603`);
      assert.equal(body.error, undefined);
      const payload = JSON.parse(body.result.content[0].text);
      assert.equal(
        payload.error,
        'country_code must be a two-letter ISO code (e.g. "ae")',
        `${JSON.stringify(bad)} must be rejected by the strict-shape guard`,
      );
    }
  });

  // --- get_tariff_trends (U5: trade + economic indicator bundle) ---

  it('get_tariff_trends returns 4-slice data on cache hit when every per-key meta is within budget', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const tariffsPayload = { items: [{ hts: '8501.10.40', ratePct: 25 }] };
    const bigmacPayload = { countries: [{ iso: 'CHE', priceUsd: 7.04 }] };
    const faoPayload = { months: [{ month: '2026-04', index: 119.2 }] };
    const debtPayload = { countries: [{ iso: 'JPN', debtPctGdp: 263.1 }] };

    // tariffs budget=540min — set 60min old (fresh)
    const tariffsFetchedAt = Date.now() - 60 * 60_000;
    // bigmac budget=10080min — set 12h old (fresh)
    const bigmacFetchedAt = Date.now() - 12 * 60 * 60_000;
    // fao budget=86400min — set 7d old (fresh)
    const faoFetchedAt = Date.now() - 7 * 24 * 60 * 60_000;
    // national-debt budget=86400min — set 10d old (fresh; OLDEST → anchors cached_at)
    const debtFetchedAt = Date.now() - 10 * 24 * 60 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent('trade:tariffs:v1:840:all:10')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(tariffsPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('economic:bigmac:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(bigmacPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('economic:fao-ffpi:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(faoPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('economic:national-debt:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(debtPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:trade:tariffs:v1:840:all:10')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: tariffsFetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:economic:bigmac')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: bigmacFetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:economic:fao-ffpi')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: faoFetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:economic:national-debt')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: debtFetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 400, method: 'tools/call',
      params: { name: 'get_tariff_trends', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'result.content must be present');
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.stale, false, 'all 4 metas within their per-key budgets must yield stale=false');
    assert.equal(payload.cached_at, new Date(debtFetchedAt).toISOString(), 'cached_at reflects oldest valid fetchedAt (national-debt)');
    // Label-walk derives slice names from the trailing non-(v\d+|\d+) segment.
    // trade:tariffs:v1:840:all:10 → trailing "10" + "all" are skipped/kept;
    // "10" is bare-numeric → skipped, "all" stays → label="all".
    assert.deepEqual(payload.data['all'], tariffsPayload, 'tariffs slice labelled "all" from cache-key label-walk');
    assert.deepEqual(payload.data['bigmac'], bigmacPayload, 'bigmac slice labelled from cache-key suffix');
    assert.deepEqual(payload.data['fao-ffpi'], faoPayload, 'fao-ffpi slice labelled from cache-key suffix');
    assert.deepEqual(payload.data['national-debt'], debtPayload, 'national-debt slice labelled from cache-key suffix');
  });

  it('get_tariff_trends marks aggregate stale when FAO meta is past its monthly budget while tariffs are fresh', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const tariffsPayload = { items: [{ hts: '8501.10.40' }] };
    const bigmacPayload = { countries: [{ iso: 'CHE' }] };
    const faoPayload = { months: [{ month: '2025-12' }] };
    const debtPayload = { countries: [{ iso: 'JPN' }] };

    // tariffs budget=540min → 60min old (fresh)
    const tariffsFetchedAt = Date.now() - 60 * 60_000;
    // bigmac budget=10080min → 12h old (fresh)
    const bigmacFetchedAt = Date.now() - 12 * 60 * 60_000;
    // FAO budget=86400min (60d) → put 100d old (clearly stale)
    const faoFetchedAt = Date.now() - 100 * 24 * 60 * 60_000;
    // national-debt budget=86400min → 5d old (fresh)
    const debtFetchedAt = Date.now() - 5 * 24 * 60 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent('trade:tariffs:v1:840:all:10')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(tariffsPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('economic:bigmac:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(bigmacPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('economic:fao-ffpi:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(faoPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('economic:national-debt:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(debtPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:trade:tariffs:v1:840:all:10')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: tariffsFetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:economic:bigmac')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: bigmacFetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:economic:fao-ffpi')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: faoFetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:economic:national-debt')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: debtFetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 401, method: 'tools/call',
      params: { name: 'get_tariff_trends', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.stale, true, 'one over-budget key (FAO) flips aggregate stale=true');
    assert.equal(payload.cached_at, new Date(faoFetchedAt).toISOString(), 'cached_at is the oldest valid fetchedAt across all 4 metas (FAO)');
    assert.deepEqual(payload.data['all'], tariffsPayload, 'fresh tariffs slice still surfaces');
    assert.deepEqual(payload.data['fao-ffpi'], faoPayload, 'stale FAO payload still returned alongside stale=true');
  });

  it('get_tariff_trends returns mixed shape (3 slices null, 1 populated) without throwing when only one key is populated', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const tariffsPayload = { items: [{ hts: '8501.10.40' }] };
    const tariffsFetchedAt = Date.now() - 60 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent('trade:tariffs:v1:840:all:10')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(tariffsPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:trade:tariffs:v1:840:all:10')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: tariffsFetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      // Everything else absent → readJsonFromUpstash → null
      return new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 402, method: 'tools/call',
      params: { name: 'get_tariff_trends', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    // Must NOT throw -32603: at least one cache slot is populated → cache_all_null guard doesn't fire.
    assert.ok(body.result?.content, 'partial-population must return a result, not -32603');
    const payload = JSON.parse(body.result.content[0].text);
    assert.deepEqual(payload.data['all'], tariffsPayload, 'populated tariffs slice still present');
    assert.equal(payload.data['bigmac'], null, 'missing bigmac slice surfaces as null');
    assert.equal(payload.data['fao-ffpi'], null, 'missing fao-ffpi slice surfaces as null');
    assert.equal(payload.data['national-debt'], null, 'missing national-debt slice surfaces as null');
    assert.equal(payload.stale, true, 'missing meta forces stale=true (hasAllValidMeta=false)');
    assert.equal(payload.cached_at, null, 'mixed-validity meta yields cached_at=null per evaluateFreshness contract');
  });

  it('get_climate_data still includes air-quality slice (regression — U2 must not touch get_climate_data._cacheKeys)', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const climateAirQualityPayload = { stations: [{ id: 'climate-aqi-1', city: 'Lagos', pm25: 92 }] };
    const climateFetchedAt = Date.now() - 30 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      // Return populated climate:air-quality blob; everything else null (cache_all_null
      // guard does NOT trip because at least one key is populated).
      if (u.includes(`/get/${encodeURIComponent('climate:air-quality:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(climateAirQualityPayload) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      // Health-domain key MUST NOT be queried by get_climate_data — if it is, the
      // climate tool was modified, which violates U2's CRITICAL constraint.
      if (u.includes(`/get/${encodeURIComponent('health:disease-outbreaks:v1')}`)) {
        throw new Error('get_climate_data must not read health-domain keys (U2 regression)');
      }
      // Provide a fresh climate:air-quality meta so the freshness check has at
      // least one valid fetchedAt to anchor cached_at off (rest stale → aggregate stale=true).
      if (u.includes(`/get/${encodeURIComponent('seed-meta:health:air-quality')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: climateFetchedAt, recordCount: 1 }) }), {
          status: 200, headers: { 'Content-Type': 'application/json' },
        });
      }
      return new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 203, method: 'tools/call',
      params: { name: 'get_climate_data', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'get_climate_data must still return a result');
    const payload = JSON.parse(body.result.content[0].text);
    // climate:air-quality:v1 → label-walk strips :v1, exposes under data['air-quality']
    assert.deepEqual(payload.data['air-quality'], climateAirQualityPayload, 'get_climate_data._cacheKeys must still include climate:air-quality:v1');
  });

  // --- get_chokepoint_status (U6: maritime chokepoint bundle, payload-verified) ---

  it('get_chokepoint_status returns 6-slice data on cache hit when every per-key meta is within budget', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const transitSummariesPayload = { chokepoints: { suez: { vesselsPast24h: 87 } } };
    const chokepointTransitsPayload = { transits: [{ chokepoint: 'hormuz', count: 142 }] };
    const portwatchPortsPayload = { countries: { US: { ports: 23 } } };
    const chokepointBaselinesPayload = { suez: { lat: 30.0, lon: 32.5 } };
    const portwatchChokepointsRefPayload = { count: 13, ids: ['suez', 'hormuz', 'malacca'] };
    const chokepointFlowsPayload = { suez: { dailyBarrels: 9_200_000 } };

    // transit-summaries budget=30min → 5min old (fresh)
    const transitSummariesFetchedAt = Date.now() - 5 * 60_000;
    // chokepoint_transits budget=30min → 8min old (fresh)
    const chokepointTransitsFetchedAt = Date.now() - 8 * 60_000;
    // portwatch-ports budget=2160min (36h) → 12h old (fresh)
    const portwatchPortsFetchedAt = Date.now() - 12 * 60 * 60_000;
    // chokepoint-baselines budget=576000min (400d) → 60d old (fresh; SECOND-OLDEST)
    const chokepointBaselinesFetchedAt = Date.now() - 60 * 24 * 60 * 60_000;
    // portwatch:chokepoints-ref budget=20160min (14d) → 7d old (fresh)
    const portwatchChokepointsRefFetchedAt = Date.now() - 7 * 24 * 60 * 60_000;
    // chokepoint-flows budget=720min (12h) → 5h old (fresh)
    const chokepointFlowsFetchedAt = Date.now() - 5 * 60 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent('supply_chain:transit-summaries:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(transitSummariesPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('supply_chain:chokepoint_transits:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(chokepointTransitsPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('supply_chain:portwatch-ports:v1:_countries')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(portwatchPortsPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('energy:chokepoint-baselines:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(chokepointBaselinesPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('portwatch:chokepoints:ref:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(portwatchChokepointsRefPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('energy:chokepoint-flows:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(chokepointFlowsPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:supply_chain:transit-summaries')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: transitSummariesFetchedAt, recordCount: 13 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:supply_chain:chokepoint_transits')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: chokepointTransitsFetchedAt, recordCount: 13 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:supply_chain:portwatch-ports')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: portwatchPortsFetchedAt, recordCount: 200 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:energy:chokepoint-baselines')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: chokepointBaselinesFetchedAt, recordCount: 13 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:portwatch:chokepoints-ref')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: portwatchChokepointsRefFetchedAt, recordCount: 13 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:energy:chokepoint-flows')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: chokepointFlowsFetchedAt, recordCount: 13 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 500, method: 'tools/call',
      params: { name: 'get_chokepoint_status', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'result.content must be present');
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.stale, false, 'all 6 metas within their per-key budgets must yield stale=false');
    // chokepoint-baselines is the oldest valid fetchedAt (60d) → anchors cached_at
    assert.equal(payload.cached_at, new Date(chokepointBaselinesFetchedAt).toISOString(), 'cached_at reflects oldest valid fetchedAt (chokepoint-baselines)');
    // Label-walk: trailing non-(v\d+|\d+|stale|sebuf) segment.
    // supply_chain:transit-summaries:v1 → "transit-summaries"
    // supply_chain:chokepoint_transits:v1 → "chokepoint_transits"
    // supply_chain:portwatch-ports:v1:_countries → "_countries" (NOT in NON_LABEL list)
    // energy:chokepoint-baselines:v1 → "chokepoint-baselines"
    // portwatch:chokepoints:ref:v1 → "ref"
    // energy:chokepoint-flows:v1 → "chokepoint-flows"
    assert.deepEqual(payload.data['transit-summaries'], transitSummariesPayload, 'transit-summaries slice labelled from cache-key suffix');
    assert.deepEqual(payload.data['chokepoint_transits'], chokepointTransitsPayload, 'chokepoint_transits slice labelled from cache-key suffix');
    assert.deepEqual(payload.data['_countries'], portwatchPortsPayload, 'portwatch-ports slice labelled from trailing _countries segment');
    assert.deepEqual(payload.data['chokepoint-baselines'], chokepointBaselinesPayload, 'chokepoint-baselines slice labelled from cache-key suffix');
    assert.deepEqual(payload.data['ref'], portwatchChokepointsRefPayload, 'portwatch:chokepoints:ref slice labelled from trailing ref segment');
    assert.deepEqual(payload.data['chokepoint-flows'], chokepointFlowsPayload, 'chokepoint-flows slice labelled from cache-key suffix');
  });

  it('get_chokepoint_status: fast transit-summaries fresh but slow portwatch-ports past budget flips aggregate stale', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const transitSummariesPayload = { chokepoints: { suez: { vesselsPast24h: 87 } } };
    const portwatchPortsPayload = { countries: {} };

    // transit-summaries budget=30min → 5min old (fresh)
    const transitSummariesFetchedAt = Date.now() - 5 * 60_000;
    // portwatch-ports budget=2160min (36h) → 100h old (clearly STALE)
    const portwatchPortsFetchedAt = Date.now() - 100 * 60 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent('supply_chain:transit-summaries:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(transitSummariesPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('supply_chain:portwatch-ports:v1:_countries')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(portwatchPortsPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:supply_chain:transit-summaries')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: transitSummariesFetchedAt, recordCount: 13 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:supply_chain:portwatch-ports')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: portwatchPortsFetchedAt, recordCount: 200 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      // Everything else absent → mixed shape; at least 2 keys populated so cache_all_null doesn't trip.
      return new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 501, method: 'tools/call',
      params: { name: 'get_chokepoint_status', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    const payload = JSON.parse(body.result.content[0].text);
    // One over-budget key (portwatch-ports 100h vs 36h budget) flips aggregate stale=true
    // even though transit-summaries is fresh.
    assert.equal(payload.stale, true, 'one over-budget key (portwatch-ports) flips aggregate stale=true');
    assert.deepEqual(payload.data['transit-summaries'], transitSummariesPayload, 'fresh transit-summaries slice still surfaces');
    assert.deepEqual(payload.data['_countries'], portwatchPortsPayload, 'stale portwatch-ports payload still returned alongside stale=true');
  });

  it('get_chokepoint_status returns mixed shape without throwing when only one key is populated', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const transitSummariesPayload = { chokepoints: { suez: { vesselsPast24h: 87 } } };
    const transitSummariesFetchedAt = Date.now() - 5 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes(`/get/${encodeURIComponent('supply_chain:transit-summaries:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(transitSummariesPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:supply_chain:transit-summaries')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: transitSummariesFetchedAt, recordCount: 13 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      // Every other key absent → readJsonFromUpstash → null
      return new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 502, method: 'tools/call',
      params: { name: 'get_chokepoint_status', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    // Must NOT throw -32603: at least one cache slot is populated → cache_all_null guard doesn't fire.
    assert.ok(body.result?.content, 'partial-population must return a result, not -32603');
    const payload = JSON.parse(body.result.content[0].text);
    assert.deepEqual(payload.data['transit-summaries'], transitSummariesPayload, 'populated transit-summaries slice still present');
    assert.equal(payload.data['chokepoint_transits'], null, 'missing chokepoint_transits slice surfaces as null');
    assert.equal(payload.data['_countries'], null, 'missing portwatch-ports slice surfaces as null');
    assert.equal(payload.data['chokepoint-baselines'], null, 'missing chokepoint-baselines slice surfaces as null');
    assert.equal(payload.data['ref'], null, 'missing portwatch chokepoints-ref slice surfaces as null');
    assert.equal(payload.data['chokepoint-flows'], null, 'missing chokepoint-flows slice surfaces as null');
    assert.equal(payload.stale, true, 'missing meta forces stale=true (hasAllValidMeta=false)');
    assert.equal(payload.cached_at, null, 'mixed-validity meta yields cached_at=null per evaluateFreshness contract');
  });

  // --- get_energy_intelligence (U3: 9-key energy bundle) ---

  it('get_energy_intelligence returns 9-slice data on cache hit when every per-key meta is within budget', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const eiaPayload = { weeklySeries: [{ week: '2026-W18', stocks: 832.1 }] };
    const electricityPayload = { countries: [{ iso: 'DE', priceEurMwh: 88 }] };
    const emberPayload = { regions: [{ id: 'EU', cleanShare: 0.62 }] };
    const gasStoragePayload = { countries: [{ iso: 'DE', fillPct: 71 }] };
    const fuelShortagesPayload = { countries: [{ iso: 'CU', severity: 'high' }] };
    const disruptionsPayload = { events: [{ id: 'pipe-2026-04-21', region: 'Levant' }] };
    const crisisPolicyPayload = { policies: [{ country: 'DE', kind: 'price-cap' }] };
    const fossilSharePayload = { countries: [{ iso: 'PL', fossilSharePct: 73 }] };
    const renewablePayload = { countries: [{ iso: 'IS', renewablePct: 84 }] };

    // Budgets: eiaPetroleum=4320min, electricity-prices=2880, ember=2880, gas-storage=2880,
    // fuel-shortages=2880, disruptions=20160, crisis-policies=~400d, fossil-share=11520, renewable=10080.
    // All fetchedAts within their per-key budgets; oldest = crisisPolicy (30d old, within 400d budget)
    // anchors cached_at — exercises the wide budget-asymmetry property.
    const eiaFetchedAt           = Date.now() - 60 * 60_000;
    const electricityFetchedAt   = Date.now() - 30 * 60_000;
    const emberFetchedAt         = Date.now() - 24 * 60 * 60_000;
    const gasStorageFetchedAt    = Date.now() - 12 * 60 * 60_000;
    const fuelShortagesFetchedAt = Date.now() - 12 * 60 * 60_000;
    const disruptionsFetchedAt   = Date.now() - 5 * 24 * 60 * 60_000;
    const crisisPolicyFetchedAt  = Date.now() - 30 * 24 * 60 * 60_000;  // OLDEST valid → anchors cached_at (within ~400d budget)
    const fossilShareFetchedAt   = Date.now() - 7 * 24 * 60 * 60_000;
    const renewableFetchedAt     = Date.now() - 6 * 24 * 60 * 60_000;

    const JSON_HDR = { 'Content-Type': 'application/json' };
    const meta = (fetchedAt) => ({ fetchedAt, recordCount: 1 });
    // Single Map of cache-key → payload covers both data + seed-meta lookups.
    // Replaces an 18-branch if-chain that biome flagged as too complex.
    const FIXTURES = new Map([
      ['energy:eia-petroleum:v1', eiaPayload],
      ['energy:electricity:v1:index', electricityPayload],
      ['energy:ember:v1:_all', emberPayload],
      ['energy:gas-storage:v1:_countries', gasStoragePayload],
      ['energy:fuel-shortages:v1', fuelShortagesPayload],
      ['energy:disruptions:v1', disruptionsPayload],
      ['energy:crisis-policies:v1', crisisPolicyPayload],
      ['resilience:fossil-electricity-share:v1', fossilSharePayload],
      ['economic:worldbank-renewable:v1', renewablePayload],
      ['seed-meta:energy:eia-petroleum', meta(eiaFetchedAt)],
      ['seed-meta:energy:electricity-prices', meta(electricityFetchedAt)],
      ['seed-meta:energy:ember', meta(emberFetchedAt)],
      ['seed-meta:energy:gas-storage-countries', meta(gasStorageFetchedAt)],
      ['seed-meta:energy:fuel-shortages', meta(fuelShortagesFetchedAt)],
      ['seed-meta:energy:disruptions', meta(disruptionsFetchedAt)],
      ['seed-meta:energy:crisis-policies', meta(crisisPolicyFetchedAt)],
      ['seed-meta:resilience:fossil-electricity-share', meta(fossilShareFetchedAt)],
      ['seed-meta:economic:worldbank-renewable:v1', meta(renewableFetchedAt)],
    ]);
    globalThis.fetch = async (url) => {
      const u = url.toString();
      for (const [key, payload] of FIXTURES) {
        if (u.includes(`/get/${encodeURIComponent(key)}`)) {
          return new Response(JSON.stringify({ result: JSON.stringify(payload) }), { status: 200, headers: JSON_HDR });
        }
      }
      return new Response(JSON.stringify({}), { status: 200, headers: JSON_HDR });
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 300, method: 'tools/call',
      params: { name: 'get_energy_intelligence', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'result.content must be present');
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.stale, false, 'all 9 metas within their per-key budgets must yield stale=false');
    assert.equal(payload.cached_at, new Date(crisisPolicyFetchedAt).toISOString(), 'cached_at reflects oldest valid fetchedAt (crisis-policies, 30d old, within ~400d budget)');
    // Label-walk slice names per NON_LABEL=/^(v\d+|\d+|stale|sebuf)$/:
    assert.deepEqual(payload.data['eia-petroleum'], eiaPayload);
    assert.deepEqual(payload.data['index'], electricityPayload, 'energy:electricity:v1:index → "index"');
    assert.deepEqual(payload.data['_all'], emberPayload, 'energy:ember:v1:_all → "_all"');
    assert.deepEqual(payload.data['_countries'], gasStoragePayload, 'energy:gas-storage:v1:_countries → "_countries"');
    assert.deepEqual(payload.data['fuel-shortages'], fuelShortagesPayload);
    assert.deepEqual(payload.data['disruptions'], disruptionsPayload);
    assert.deepEqual(payload.data['crisis-policies'], crisisPolicyPayload);
    assert.deepEqual(payload.data['fossil-electricity-share'], fossilSharePayload);
    assert.deepEqual(payload.data['worldbank-renewable'], renewablePayload);
  });

  it('get_energy_intelligence marks aggregate stale when one slow-cadence key is past budget while fast keys are fresh', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    // Per-key budget asymmetry exercise: electricity has 48h budget (fast cron),
    // disruptions has 14d budget (weekly cron × 2). Set disruptions=15d old → past
    // its own budget, but electricity stays fresh. Aggregate stale must flip true.
    const electricityFetchedAt = Date.now() - 30 * 60_000;
    const disruptionsFetchedAt = Date.now() - 15 * 24 * 60 * 60_000; // past 14d budget

    globalThis.fetch = async (url) => {
      const u = url.toString();
      // Provide only electricity + disruptions data; rest absent (null).
      if (u.includes(`/get/${encodeURIComponent('energy:electricity:v1:index')}`)) return new Response(JSON.stringify({ result: JSON.stringify({ countries: [{ iso: 'DE' }] }) }), { status: 200 });
      if (u.includes(`/get/${encodeURIComponent('energy:disruptions:v1')}`)) return new Response(JSON.stringify({ result: JSON.stringify({ events: [{ id: 'old-event' }] }) }), { status: 200 });
      if (u.includes(`/get/${encodeURIComponent('seed-meta:energy:electricity-prices')}`)) return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: electricityFetchedAt, recordCount: 1 }) }), { status: 200 });
      if (u.includes(`/get/${encodeURIComponent('seed-meta:energy:disruptions')}`)) return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: disruptionsFetchedAt, recordCount: 1 }) }), { status: 200 });
      return new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 301, method: 'tools/call',
      params: { name: 'get_energy_intelligence', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'result.content must be present (cache_all_null guard does NOT fire: 2 keys populated)');
    const payload = JSON.parse(body.result.content[0].text);
    assert.equal(payload.stale, true, 'one over-budget key (disruptions @ 15d > 14d budget) flips aggregate stale=true');
    assert.equal(payload.cached_at, null, 'mixed-validity meta yields cached_at=null per evaluateFreshness contract');
  });

  it('get_energy_intelligence throws cache_all_null (→ -32603) when every 9 cache reads return null', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    // F6 contract: degenerate-empty result must surface as -32603. For Pro
    // callers this is a post-execution failure, so the slot remains charged.
    globalThis.fetch = async () => new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 302, method: 'tools/call',
      params: { name: 'get_energy_intelligence', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.equal(body.error?.code, -32603, 'all-9-null reads must surface as -32603 cache_all_null');
  });

  it('get_supply_chain_data still returns its 3 slices unchanged (regression — U6 must not touch get_supply_chain_data._cacheKeys)', async () => {
    process.env.UPSTASH_REDIS_REST_URL = 'https://fake.upstash.io';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'fake_token';

    const shippingStressPayload = { index: 1.42 };
    const customsRevenuePayload = { receipts: [{ country: 'US', revenue: 1.2e9 }] };
    const comtradeFlowsPayload = { pairs: [{ a: 'US', b: 'CN', total: 9.1e11 }] };
    const customsFetchedAt = Date.now() - 6 * 60 * 60_000;

    globalThis.fetch = async (url) => {
      const u = url.toString();
      // U6 chokepoint keys MUST NOT be queried by get_supply_chain_data — if they are,
      // the supply-chain tool was modified, violating the CRITICAL constraint.
      if (
        u.includes(`/get/${encodeURIComponent('supply_chain:transit-summaries:v1')}`) ||
        u.includes(`/get/${encodeURIComponent('supply_chain:chokepoint_transits:v1')}`) ||
        u.includes(`/get/${encodeURIComponent('supply_chain:portwatch-ports:v1:_countries')}`) ||
        u.includes(`/get/${encodeURIComponent('energy:chokepoint-baselines:v1')}`) ||
        u.includes(`/get/${encodeURIComponent('portwatch:chokepoints:ref:v1')}`) ||
        u.includes(`/get/${encodeURIComponent('energy:chokepoint-flows:v1')}`)
      ) {
        throw new Error('get_supply_chain_data must not read chokepoint-bundle keys (U6 regression)');
      }
      if (u.includes(`/get/${encodeURIComponent('supply_chain:shipping_stress:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(shippingStressPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('trade:customs-revenue:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(customsRevenuePayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('comtrade:flows:v1')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify(comtradeFlowsPayload) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes(`/get/${encodeURIComponent('seed-meta:trade:customs-revenue')}`)) {
        return new Response(JSON.stringify({ result: JSON.stringify({ fetchedAt: customsFetchedAt, recordCount: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return new Response(JSON.stringify({}), { status: 200, headers: { 'Content-Type': 'application/json' } });
    };

    const freshMod = await import(`../api/mcp.ts?t=${Date.now()}`);
    const freshHandler = freshMod.default;

    const res = await freshHandler(makeReq('POST', {
      jsonrpc: '2.0', id: 503, method: 'tools/call',
      params: { name: 'get_supply_chain_data', arguments: {} },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'get_supply_chain_data must still return a result');
    const payload = JSON.parse(body.result.content[0].text);
    // Label-walk: supply_chain:shipping_stress:v1 → "shipping_stress",
    //             trade:customs-revenue:v1       → "customs-revenue",
    //             comtrade:flows:v1              → "flows"
    assert.deepEqual(payload.data['shipping_stress'], shippingStressPayload, 'get_supply_chain_data._cacheKeys must still include supply_chain:shipping_stress:v1');
    assert.deepEqual(payload.data['customs-revenue'], customsRevenuePayload, 'get_supply_chain_data._cacheKeys must still include trade:customs-revenue:v1');
    assert.deepEqual(payload.data['flows'], comtradeFlowsPayload, 'get_supply_chain_data._cacheKeys must still include comtrade:flows:v1');
    // Exactly 3 slices — no chokepoint keys leaked in.
    assert.equal(Object.keys(payload.data).length, 3, 'get_supply_chain_data must return exactly 3 slices (U6 must not add to it)');
  });

  // --- get_airspace ---

  it('get_airspace returns counts and flights for valid country code', async () => {
    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes('/api/aviation/v1/track-aircraft')) {
        return new Response(JSON.stringify({
          positions: [
            { callsign: 'UAE123', icao24: 'abc123', lat: 24.5, lon: 54.3, altitude_m: 11000, ground_speed_kts: 480, track_deg: 270, on_ground: false },
          ],
          source: 'opensky',
          updated_at: 1711620000000,
        }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes('/api/military/v1/list-military-flights')) {
        return new Response(JSON.stringify({ flights: [] }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 10, method: 'tools/call',
      params: { name: 'get_airspace', arguments: { country_code: 'AE' } },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'result.content must be present');
    const data = JSON.parse(body.result.content[0].text);
    assert.equal(data.country_code, 'AE');
    assert.equal(data.civilian_count, 1);
    assert.equal(data.military_count, 0);
    assert.ok(Array.isArray(data.civilian_flights), 'civilian_flights must be array');
    assert.ok(Array.isArray(data.military_flights), 'military_flights must be array');
    assert.ok(data.bounding_box?.sw_lat !== undefined, 'bounding_box must be present');
    assert.equal(data.partial, undefined, 'no partial flag when both sources succeed');
  });

  it('get_airspace returns error for unknown country code', async () => {
    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 11, method: 'tools/call',
      params: { name: 'get_airspace', arguments: { country_code: 'XX' } },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    const data = JSON.parse(body.result.content[0].text);
    assert.ok(data.error?.includes('Unknown country code'), 'must return error for unknown code');
  });

  it('get_airspace returns partial:true + warning when military source fails', async () => {
    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes('/api/aviation/v1/track-aircraft')) {
        return new Response(JSON.stringify({ positions: [], source: 'opensky' }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      if (u.includes('/api/military/v1/list-military-flights')) {
        return new Response('Service Unavailable', { status: 503 });
      }
      return originalFetch(url);
    };

    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 12, method: 'tools/call',
      params: { name: 'get_airspace', arguments: { country_code: 'US' } },
    }));
    const body = await res.json();
    const data = JSON.parse(body.result.content[0].text);
    assert.equal(data.partial, true, 'partial must be true when one source fails');
    assert.ok(data.warnings?.some(w => w.includes('military')), 'warnings must mention military');
    assert.equal(data.civilian_count, 0, 'civilian data still returned');
  });

  it('get_airspace returns JSON-RPC -32603 when both sources fail', async () => {
    globalThis.fetch = async () => new Response('Error', { status: 500 });

    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 13, method: 'tools/call',
      params: { name: 'get_airspace', arguments: { country_code: 'GB' } },
    }));
    const body = await res.json();
    assert.equal(body.error?.code, -32603, 'total outage must return -32603');
  });

  it('get_airspace type=civilian skips military fetch', async () => {
    let militaryFetched = false;
    globalThis.fetch = async (url) => {
      const u = url.toString();
      if (u.includes('/api/military/')) militaryFetched = true;
      if (u.includes('/api/aviation/v1/track-aircraft')) {
        return new Response(JSON.stringify({ positions: [], source: 'opensky' }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 14, method: 'tools/call',
      params: { name: 'get_airspace', arguments: { country_code: 'DE', type: 'civilian' } },
    }));
    const body = await res.json();
    const data = JSON.parse(body.result.content[0].text);
    assert.equal(militaryFetched, false, 'military endpoint must not be called for type=civilian');
    assert.equal(data.military_flights, undefined, 'military_flights must be absent for type=civilian');
    assert.ok(Array.isArray(data.civilian_flights), 'civilian_flights must be present');
  });

  // --- get_maritime_activity ---

  it('get_maritime_activity returns zones and disruptions for valid country code', async () => {
    // Fixture mirrors the REAL wire shape of the generated sebuf handler:
    // camelCase keys + nested `location` objects. The original fixture used
    // snake_case (which the wire never produces), so the tool's misread of
    // density_zones/snapshot_at passed the suite while returning total_zones=0
    // in production — WORLDMONITOR-T8. Items outside the AE bbox (+3° pad)
    // must be filtered out tool-side; the inner fetch must carry NO bbox
    // query (the handler 400s any dimension >10°, and 67 COUNTRY_BBOXES
    // exceed that).
    let innerUrl = null;
    globalThis.fetch = async (url) => {
      if (url.toString().includes('/api/maritime/v1/get-vessel-snapshot')) {
        innerUrl = url.toString();
        return new Response(JSON.stringify({
          snapshot: {
            snapshotAt: 1711620000000,
            densityZones: [
              { name: 'Strait of Hormuz', location: { latitude: 26.6, longitude: 56.3 }, intensity: 82, shipsPerDay: 45, deltaPct: 3.2, note: '' },
              { name: 'Zone 50,4 North Sea', location: { latitude: 51, longitude: 5 }, intensity: 1, shipsPerDay: 114240, deltaPct: 0, note: 'High traffic area' },
            ],
            disruptions: [
              { name: 'Gulf AIS Gap', type: 'AIS_DISRUPTION_TYPE_GAP_SPIKE', severity: 'AIS_DISRUPTION_SEVERITY_ELEVATED', location: { latitude: 25.5, longitude: 54.0 }, darkShips: 3, vesselCount: 12, region: 'Persian Gulf', description: 'Elevated dark-ship activity' },
              { name: 'Taiwan Strait', type: 'AIS_DISRUPTION_TYPE_CHOKEPOINT_CONGESTION', severity: 'AIS_DISRUPTION_SEVERITY_LOW', location: { latitude: 24.5, longitude: 119.5 }, darkShips: 0, vesselCount: 17, region: 'Taiwan Strait', description: 'Congestion' },
            ],
          },
        }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 20, method: 'tools/call',
      params: { name: 'get_maritime_activity', arguments: { country_code: 'AE' } },
    }));
    assert.equal(res.status, 200);
    const body = await res.json();
    const data = JSON.parse(body.result.content[0].text);
    assert.equal(data.country_code, 'AE');
    assert.ok(innerUrl !== null, 'inner vessel-snapshot fetch must happen');
    assert.ok(!/sw_lat|ne_lat/.test(innerUrl), 'inner fetch must NOT send a bbox (handler caps at 10°/side)');
    assert.equal(data.total_zones, 1, 'North Sea zone must be filtered out of AE results');
    assert.equal(data.total_disruptions, 1, 'Taiwan Strait must be filtered out of AE results');
    assert.equal(data.density_zones[0].name, 'Strait of Hormuz');
    assert.equal(data.density_zones[0].ships_per_day, 45, 'camelCase wire field must map to snake_case output');
    assert.equal(data.disruptions[0].dark_ships, 3);
    assert.equal(data.snapshot_at, new Date(1711620000000).toISOString(), 'snapshotAt wire field must populate snapshot_at');
    assert.ok(data.bounding_box?.sw_lat !== undefined, 'bounding_box must be present');
  });

  it('get_maritime_activity keeps dateline-adjacent results when the pad crosses ±180 (FJ)', async () => {
    // FJ bbox is [-18.25, 177.34, -16.15, 180]: the +3° pad pushes the east
    // edge to 183, so a point at -179 sits just across the dateline and MUST
    // match (it is 1-4° away), while a genuinely distant Pacific point must
    // not. The original filter only treated sw_lon > ne_lon as wrapped and
    // silently dropped the -179 point.
    globalThis.fetch = async (url) => {
      if (url.toString().includes('/api/maritime/v1/get-vessel-snapshot')) {
        return new Response(JSON.stringify({
          snapshot: {
            snapshotAt: 1711620000000,
            densityZones: [
              { name: 'Across the dateline', location: { latitude: -17.5, longitude: -179 }, intensity: 10, shipsPerDay: 20, deltaPct: 0, note: '' },
              { name: 'West of Fiji in-box', location: { latitude: -17.0, longitude: 178.0 }, intensity: 5, shipsPerDay: 10, deltaPct: 0, note: '' },
              { name: 'Far Pacific', location: { latitude: -17.5, longitude: -150 }, intensity: 3, shipsPerDay: 5, deltaPct: 0, note: '' },
            ],
            disruptions: [],
          },
        }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 23, method: 'tools/call',
      params: { name: 'get_maritime_activity', arguments: { country_code: 'FJ' } },
    }));
    const body = await res.json();
    const data = JSON.parse(body.result.content[0].text);
    const names = data.density_zones.map((z) => z.name).sort();
    assert.deepEqual(names, ['Across the dateline', 'West of Fiji in-box'], 'dateline-adjacent point must match; far-Pacific point must not');
  });

  it('get_maritime_activity matches every longitude for full-span bboxes (AQ stored as -180..180)', async () => {
    globalThis.fetch = async (url) => {
      if (url.toString().includes('/api/maritime/v1/get-vessel-snapshot')) {
        return new Response(JSON.stringify({
          snapshot: {
            snapshotAt: 1711620000000,
            densityZones: [
              { name: 'Drake Passage', location: { latitude: -65, longitude: -62 }, intensity: 4, shipsPerDay: 8, deltaPct: 0, note: '' },
              { name: 'Ross Sea', location: { latitude: -75, longitude: 175 }, intensity: 1, shipsPerDay: 1, deltaPct: 0, note: '' },
            ],
            disruptions: [],
          },
        }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 24, method: 'tools/call',
      params: { name: 'get_maritime_activity', arguments: { country_code: 'AQ' } },
    }));
    const body = await res.json();
    const data = JSON.parse(body.result.content[0].text);
    assert.equal(data.total_zones, 2, 'a full-circle longitude span must not collapse under pad normalization');
  });

  it('get_maritime_activity works for countries whose bbox exceeds the 10° handler cap (e.g. JP)', async () => {
    globalThis.fetch = async (url) => {
      if (url.toString().includes('/api/maritime/v1/get-vessel-snapshot')) {
        return new Response(JSON.stringify({
          snapshot: {
            snapshotAt: 1711620000000,
            densityZones: [
              { name: 'Tokyo Bay', location: { latitude: 35.4, longitude: 139.8 }, intensity: 60, shipsPerDay: 500, deltaPct: 1, note: '' },
            ],
            disruptions: [],
          },
        }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 22, method: 'tools/call',
      params: { name: 'get_maritime_activity', arguments: { country_code: 'JP' } },
    }));
    const body = await res.json();
    assert.equal(body.error, undefined, 'JP (14°×16° bbox) must not error');
    const data = JSON.parse(body.result.content[0].text);
    assert.equal(data.total_zones, 1);
    assert.equal(data.density_zones[0].name, 'Tokyo Bay');
  });

  it('get_maritime_activity returns error for unknown country code', async () => {
    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 21, method: 'tools/call',
      params: { name: 'get_maritime_activity', arguments: { country_code: 'ZZ' } },
    }));
    const body = await res.json();
    const data = JSON.parse(body.result.content[0].text);
    assert.ok(data.error?.includes('Unknown country code'), 'must return error for unknown code');
  });

  it('get_maritime_activity returns JSON-RPC -32603 when vessel API fails', async () => {
    globalThis.fetch = async (url) => {
      if (url.toString().includes('/api/maritime/')) {
        return new Response('Service Unavailable', { status: 503 });
      }
      return originalFetch(url);
    };

    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 22, method: 'tools/call',
      params: { name: 'get_maritime_activity', arguments: { country_code: 'SA' } },
    }));
    const body = await res.json();
    assert.equal(body.error?.code, -32603, 'vessel API failure must return -32603');
  });

  it('get_maritime_activity handles empty snapshot gracefully', async () => {
    globalThis.fetch = async (url) => {
      if (url.toString().includes('/api/maritime/v1/get-vessel-snapshot')) {
        return new Response(JSON.stringify({ snapshot: {} }), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return originalFetch(url);
    };

    const res = await handler(makeReq('POST', {
      jsonrpc: '2.0', id: 23, method: 'tools/call',
      params: { name: 'get_maritime_activity', arguments: { country_code: 'JP' } },
    }));
    const body = await res.json();
    const data = JSON.parse(body.result.content[0].text);
    assert.equal(data.total_zones, 0);
    assert.equal(data.total_disruptions, 0);
    assert.deepEqual(data.density_zones, []);
    assert.deepEqual(data.disruptions, []);
  });
});

// ===========================================================================
// U7 — Pro-path: McpAuthContext, INCR-first daily quota, internal-HMAC tool fetches
// ===========================================================================
// Pro-path fixtures (PRO_USER_ID, makePipelineMock, makeProDeps, proReq,
// callBody) live in tests/helpers/mcp-pro-deps.mjs so the concurrent-quota
// and per-tool contract suites can share them.

describe('api/mcp.ts — U7 Pro-path', () => {
  let mcpHandler;
  beforeEach(async () => {
    process.env.WORLDMONITOR_VALID_KEYS = VALID_KEY;
    delete process.env.UPSTASH_REDIS_REST_URL;
    delete process.env.UPSTASH_REDIS_REST_TOKEN;
    process.env.MCP_INTERNAL_HMAC_SECRET = HMAC_SECRET;
    const mod = await import(`../api/mcp.ts?t=${Date.now()}`);
    mcpHandler = mod.mcpHandler;
  });
  afterEach(() => {
    globalThis.fetch = originalFetch;
    Object.keys(process.env).forEach((k) => {
      if (!(k in originalEnv)) delete process.env[k];
    });
    Object.assign(process.env, originalEnv);
  });

  it('happy: Pro bearer, 0 calls today, tools/call cache tool → counter at 1', async () => {
    const { deps, pipe } = makeProDeps();
    // Stub Upstash GET responses so cache reads return non-null data —
    // F6 review pass throws cache_all_null when every read is null, which
    // the env-disabled stub-by-default would trigger. Provide a single
    // non-null response so this happy-path test exercises the success
    // branch (counter increments and stays incremented).
    process.env.UPSTASH_REDIS_REST_URL = 'https://stub.upstash';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'stub';
    globalThis.fetch = async () => new Response(JSON.stringify({ result: JSON.stringify({ ok: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, 'must return tool result');
    assert.equal(pipe.count, 1, 'counter at 1 after first call');
  });

  it('happy: Pro bearer, 49 calls today → 50th tools/call counter at 50', async () => {
    const { deps, pipe } = makeProDeps({ pipelineOpts: { initialCount: 49 } });
    process.env.UPSTASH_REDIS_REST_URL = 'https://stub.upstash';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'stub';
    globalThis.fetch = async () => new Response(JSON.stringify({ result: JSON.stringify({ ok: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.ok(body.result?.content, '50th call must succeed');
    assert.equal(pipe.count, 50);
  });

  it('happy: Pro bearer, 50 calls today → 51st tools/call rejected with -32029 + 429 + Retry-After, counter back at 50', async () => {
    const { deps, pipe } = makeProDeps({ pipelineOpts: { initialCount: 50 } });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 429);
    assert.ok(res.headers.get('Retry-After'), 'Retry-After header required');
    const body = await res.json();
    assert.equal(body.error?.code, -32029);
    assert.equal(pipe.count, 50, 'DECR rolled back to 50');
  });

  it('edge: initialize and tools/list for Pro user with counter at 50 → no INCR/DECR runs', async () => {
    const { deps, pipe } = makeProDeps({ pipelineOpts: { initialCount: 50 } });
    const r1 = await mcpHandler(proReq('POST', initBody(1)), deps);
    assert.equal(r1.status, 200);
    const r2 = await mcpHandler(proReq('POST', { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} }), deps);
    assert.equal(r2.status, 200);
    assert.equal(pipe.count, 50, 'counter unchanged for non-tools/call methods');
    assert.equal(pipe.ops.length, 0, 'no pipeline ops for initialize/tools/list');
  });

  it('edge: tools/call that throws (upstream non-2xx) for Pro at count=10 → slot stays charged at 11 (GHSA-hcq5, no post-execution refund)', async () => {
    const { deps, pipe } = makeProDeps({ pipelineOpts: { initialCount: 10 } });
    globalThis.fetch = async () => new Response('Service Unavailable', { status: 503 });
    const res = await mcpHandler(proReq('POST', callBody('get_country_risk', { country_code: 'US' })), deps);
    assert.equal(res.status, 200);
    const body = await res.json();
    assert.equal(body.error?.code, -32603);
    assert.equal(pipe.count, 11, 'GHSA-hcq5: the tool executed (incurred upstream cost) before erroring, so the daily slot stays charged — no post-execution refund');
  });

  it('edge: 100 concurrent tools/call from Pro user at count=49 → exactly 1 succeeds, 99 reject, final counter 50', async () => {
    const { deps, pipe } = makeProDeps({ pipelineOpts: { initialCount: 49 } });
    process.env.UPSTASH_REDIS_REST_URL = 'https://stub.upstash';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'stub';
    globalThis.fetch = async () => new Response(JSON.stringify({ result: JSON.stringify({ ok: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
    const reqs = Array.from({ length: 100 }, () => mcpHandler(proReq('POST', callBody('get_market_data')), deps));
    const results = await Promise.all(reqs);
    const ok = results.filter((r) => r.status === 200).length;
    const rejected = results.filter((r) => r.status === 429).length;
    assert.equal(ok, 1, 'exactly 1 must succeed');
    assert.equal(rejected, 99, 'exactly 99 must hit -32029');
    assert.ok(pipe.count <= 50, `counter must be <= 50, got ${pipe.count}`);
  });

  it('edge: best-effort DECR fails on cap-exceeded → counter overshoots, never undershoots', async () => {
    const { deps, pipe } = makeProDeps({ pipelineOpts: { initialCount: 50, decrFails: true } });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 429);
    assert.ok(pipe.count >= 50, 'counter must not undershoot the floor');
  });

  it('error: Pro bearer with revoked mcpProTokens row → -32001 + 401, no INCR runs', async () => {
    const { deps, pipe } = makeProDeps({ validateProMcpToken: async () => null });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 401);
    const body = await res.json();
    assert.equal(body.error?.code, -32001);
    assert.match(body.error.message, /revoked/i);
    assert.equal(pipe.count, 0);
    assert.equal(pipe.ops.length, 0);
  });

  it('error: cross-user binding violation (validate userId !== bearer userId) → 401', async () => {
    const { deps } = makeProDeps({ validateProMcpToken: async () => ({ userId: 'user_someone_else' }) });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 401);
    const body = await res.json();
    assert.equal(body.error?.code, -32001);
  });

  it('error: getEntitlements null → -32001 + 401', async () => {
    const { deps, pipe } = makeProDeps({ getEntitlements: async () => null });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 401);
    const body = await res.json();
    assert.equal(body.error?.code, -32001);
    assert.equal(pipe.count, 0);
  });

  it('error: getEntitlements throws → -32001 + 401 (fail-closed)', async () => {
    const { deps } = makeProDeps({ getEntitlements: async () => { throw new Error('convex down'); } });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 401);
    const body = await res.json();
    assert.equal(body.error?.code, -32001);
  });

  it('error: tier 0 → -32001 + 401', async () => {
    const { deps } = makeProDeps({
      getEntitlements: async () => ({ planKey: 'free', features: { tier: 0, mcpAccess: false }, validUntil: Date.now() + 86_400_000 }),
    });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 401);
    const body = await res.json();
    assert.equal(body.error?.code, -32001);
  });

  it('error: tier 1 but mcpAccess false → -32001 + 401', async () => {
    const { deps } = makeProDeps({
      getEntitlements: async () => ({ planKey: 'pro', features: { tier: 1, mcpAccess: false }, validUntil: Date.now() + 86_400_000 }),
    });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 401);
  });

  it('error: Redis pipeline throws on INCR → -32603 + 503 + Retry-After', async () => {
    const { deps, pipe } = makeProDeps({ pipelineOpts: { throwOnIncr: true } });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 503);
    assert.equal(res.headers.get('Retry-After'), '5');
    const body = await res.json();
    assert.equal(body.error?.code, -32603);
    assert.equal(pipe.count, 0, 'no successful INCR happened');
  });

  it('F12: MCP_INTERNAL_HMAC_SECRET unset on Pro path → 503 Retry-After preflight', async () => {
    delete process.env.MCP_INTERNAL_HMAC_SECRET;
    const { deps, pipe } = makeProDeps();
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 503, 'preflight must surface as 503');
    assert.equal(res.headers.get('Retry-After'), '5');
    const body = await res.json();
    assert.equal(body.error?.code, -32603);
    assert.equal(pipe.count, 0, 'no INCR on preflight rejection');
  });

  it('F4: post-DECR-failure overshoot → next request clamps counter back via DECR sweep', async () => {
    // Models the failure mode: counter is pinned at 100 (50 + 50 leaked
    // overshoot from prior DECR failures). Without F4 the user 429s for
    // the rest of the UTC day. With F4 the next rejection-path probe
    // sees newCount > limit + 1 and DECR-sweeps the overshoot.
    const { deps, pipe } = makeProDeps({ pipelineOpts: { initialCount: 100 } });
    process.env.UPSTASH_REDIS_REST_URL = 'https://stub.upstash';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'stub';
    globalThis.fetch = async () => new Response(JSON.stringify({ result: JSON.stringify({ ok: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 429, 'over-cap request 429s as expected');
    // The clamp logic INCRs+DECRs to probe, then DECR-sweeps. The exact
    // resulting count depends on the probe path; the contract is "post-
    // call counter must not exceed limit + a small probe slack".
    assert.ok(pipe.count <= 51, `F4: counter must clamp back near limit; got ${pipe.count}`);
  });

  it('F6: cache-only tool with all-null reads → slot stays charged (GHSA-hcq5, no post-execution refund)', async () => {
    // Pro path: starting at 5, every cache read returns null → executeTool
    // throws cache_all_null AFTER running. Per GHSA-hcq5 the slot is NOT
    // refunded (the cost is already incurred) → counter stays at 6.
    const { deps, pipe } = makeProDeps({ pipelineOpts: { initialCount: 5 } });
    // Stub Upstash with a result of null (genuine miss).
    process.env.UPSTASH_REDIS_REST_URL = 'https://stub.upstash';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'stub';
    globalThis.fetch = async () => new Response(JSON.stringify({ result: null }), { status: 200, headers: { 'Content-Type': 'application/json' } });
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 200, 'JSON-RPC error returns HTTP 200');
    const body = await res.json();
    assert.equal(body.error?.code, -32603, 'cache_all_null surfaces as -32603');
    assert.equal(pipe.count, 6, 'GHSA-hcq5: cache_all_null throws after execution, so the slot stays charged (no DECR refund)');
  });

  it('happy: Starter+ env_key bearer → unaffected by daily INCR path; only 60/min sliding limit applies', async () => {
    const { deps, pipe } = makeProDeps();
    // F6: stub cache reads so executeTool doesn't throw cache_all_null.
    process.env.UPSTASH_REDIS_REST_URL = 'https://stub.upstash';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'stub';
    globalThis.fetch = async () => new Response(JSON.stringify({ result: JSON.stringify({ ok: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
    const req = makeReq('POST', callBody('get_market_data'));
    const res = await mcpHandler(req, deps);
    assert.equal(res.status, 200);
    assert.equal(pipe.count, 0, 'env_key path must NOT touch daily counter');
    assert.equal(pipe.ops.length, 0);
  });

  it('edge: Pro tool _execute fetch sends X-WM-MCP-Internal + X-WM-MCP-User-Id, no X-WorldMonitor-Key', async () => {
    const { deps } = makeProDeps();
    let captured = null;
    globalThis.fetch = async (url, init) => {
      captured = { url: String(url), headers: new Headers(init?.headers) };
      return new Response(JSON.stringify({ ok: true, country_code: 'US' }), { status: 200, headers: { 'Content-Type': 'application/json' } });
    };
    const res = await mcpHandler(proReq('POST', callBody('get_country_risk', { country_code: 'US' })), deps);
    assert.equal(res.status, 200);
    assert.ok(captured, 'fetch was called');
    assert.ok(captured.headers.get('x-wm-mcp-internal'), 'X-WM-MCP-Internal must be set');
    assert.equal(captured.headers.get('x-wm-mcp-user-id'), PRO_USER_ID);
    assert.equal(captured.headers.get('x-worldmonitor-key'), null, 'X-WorldMonitor-Key must NOT be set for Pro');
    // Signature shape: <ts>.<base64url>
    const sig = captured.headers.get('x-wm-mcp-internal');
    assert.match(sig, /^\d{10}\.[A-Za-z0-9_-]+$/, 'signature must be <ts>.<base64url-sig>');
  });

  it('edge: Pro get_country_brief signs a short URL and sends grounding context in the POST body', async () => {
    const { deps } = makeProDeps();
    const captured = [];
    globalThis.fetch = async (url, init = {}) => {
      const call = {
        url: String(url),
        method: init.method || 'GET',
        headers: new Headers(init.headers),
        body: typeof init.body === 'string' ? init.body : '',
      };
      captured.push(call);
      const { pathname } = new URL(call.url);

      if (pathname === '/api/news/v1/list-feed-digest') {
        const items = Array.from({ length: 15 }, (_, index) => ({
          title: `Iran ${index} ${'%'.repeat(300)}`,
          source: 'Context Wire',
          link: `https://example.com/iran-${index}`,
          publishedAt: '2026-06-07T00:00:00.000Z',
          snippet: 'Long Iran grounding item used to keep the MCP signed URL below proxy limits.',
        }));
        return new Response(JSON.stringify({ categories: { world: { items } } }), {
          status: 200,
          headers: { 'Content-Type': 'application/json' },
        });
      }

      if (pathname === '/api/intelligence/v1/get-country-intel-brief') {
        return new Response(JSON.stringify({ brief: 'Grounded country brief.' }), {
          status: 200,
          headers: { 'Content-Type': 'application/json' },
        });
      }

      throw new Error(`Unexpected fetch URL: ${call.url}`);
    };

    const res = await mcpHandler(proReq('POST', callBody('get_country_brief', {
      country_code: 'IR',
      framework: 'PMESII-PT',
    })), deps);
    assert.equal(res.status, 200);
    const rpc = await res.json();
    assert.ok(rpc.result?.content, 'tool call must return content');

    const countryCall = captured.find((call) => new URL(call.url).pathname === '/api/intelligence/v1/get-country-intel-brief');
    assert.ok(countryCall, 'country brief fetch must run');
    const countryUrl = new URL(countryCall.url);
    assert.equal(countryUrl.searchParams.has('context'), false, 'context must not be signed in the URL query');
    assert.ok(countryCall.url.length < 200, `signed URL should stay short, got ${countryCall.url.length} chars`);

    const body = JSON.parse(countryCall.body);
    assert.equal(body.country_code, 'IR');
    assert.equal(body.framework, 'PMESII-PT');
    assert.match(body.context, /Brief source articles:/);
    assert.match(body.context, /Headlines:/);
    assert.match(body.context, /Iran/);
    assert.ok(body.context.length > 1000, `expected large grounding context, got ${body.context.length} chars`);
    assert.ok(body.context.length <= 4000, `grounding context should be bounded to 4000 chars, got ${body.context.length}`);

    assert.ok(countryCall.headers.get('x-wm-mcp-internal'), 'X-WM-MCP-Internal must be set');
    assert.equal(countryCall.headers.get('x-wm-mcp-user-id'), PRO_USER_ID);
    assert.equal(countryCall.headers.get('x-worldmonitor-key'), null, 'X-WorldMonitor-Key must NOT be set for Pro');

    const { verifyInternalMcpRequest } = await import(`../server/_shared/mcp-internal-hmac.ts?t=${Date.now()}`);
    const signedReq = new Request(countryCall.url, {
      method: 'POST',
      headers: countryCall.headers,
      body: countryCall.body,
    });
    assert.ok(await verifyInternalMcpRequest(signedReq, HMAC_SECRET), 'signature must verify for the short URL plus context body');

    const tamperedUrl = `${countryCall.url}?context=${encodeURIComponent(body.context)}`;
    const tamperedReq = new Request(tamperedUrl, {
      method: 'POST',
      headers: countryCall.headers,
      body: countryCall.body,
    });
    assert.equal(await verifyInternalMcpRequest(tamperedReq, HMAC_SECRET), null, 'same signature must not verify if context is moved back into the URL');
  });

  it('edge: Pro get_country_brief surfaces gateway error detail for Sentry grouping', async () => {
    const scenarios = [
      {
        name: 'structured HMAC 401',
        expectedLog: 'warn',
        makeResponse: () => new Response(
          JSON.stringify({ error: 'invalid_internal_mcp_signature' }),
          { status: 401, headers: { 'Content-Type': 'application/json' } },
        ),
        assertMessage: (message) => {
          assert.equal(message, 'get-country-intel-brief HTTP 401: invalid_internal_mcp_signature');
        },
      },
      {
        name: 'HTML CDN 503',
        expectedLog: 'error',
        makeResponse: () => new Response(
          '<!DOCTYPE html><html><head><title>Bad Gateway</title></head><body>Cloudflare outage</body></html>',
          { status: 503, headers: { 'Content-Type': 'text/html' } },
        ),
        assertMessage: (message) => {
          assert.equal(message, 'get-country-intel-brief HTTP 503: Bad Gateway Cloudflare outage');
          assert.doesNotMatch(message, /<[^>]*>/, 'HTML tags must not leak into the Sentry/log title');
        },
      },
      {
        name: 'unreadable body 503',
        expectedLog: 'error',
        makeResponse: () => ({ ok: false, status: 503, text: async () => { throw new Error('body locked'); } }),
        assertMessage: (message) => {
          assert.equal(message, 'get-country-intel-brief HTTP 503');
        },
      },
    ];

    for (const scenario of scenarios) {
      const { deps } = makeProDeps();
      const warnCalls = [];
      const errorCalls = [];
      const origWarn = console.warn;
      const origError = console.error;
      console.warn = (...args) => { warnCalls.push(args); };
      console.error = (...args) => { errorCalls.push(args); };
      try {
        globalThis.fetch = async (url) => {
          const { pathname } = new URL(String(url));
          if (pathname === '/api/news/v1/list-feed-digest') {
            return new Response(JSON.stringify({
              categories: {
                world: {
                  items: [{
                    title: 'Iran headline for failing country brief',
                    source: 'Context Wire',
                    link: 'https://example.com/iran-failure',
                    publishedAt: '2026-06-07T00:00:00.000Z',
                    snippet: 'Iran context item used before the brief endpoint fails.',
                  }],
                },
              },
            }), { status: 200, headers: { 'Content-Type': 'application/json' } });
          }
          if (pathname === '/api/intelligence/v1/get-country-intel-brief') {
            return scenario.makeResponse();
          }
          return new Response('', { status: 200 });
        };

        const res = await mcpHandler(proReq('POST', callBody('get_country_brief', {
          country_code: 'IR',
          framework: 'PMESII-PT',
        })), deps);
        assert.equal(res.status, 200, `${scenario.name}: JSON-RPC tool errors stay HTTP 200`);
        const rpc = await res.json();
        assert.equal(rpc.error?.code, -32603, `${scenario.name}: tool failure should be a JSON-RPC internal error`);

        const expectedCalls = scenario.expectedLog === 'warn' ? warnCalls : errorCalls;
        const unexpectedCalls = scenario.expectedLog === 'warn' ? errorCalls : warnCalls;
        const mcpLogs = expectedCalls.filter((args) => args[0] === '[mcp] tool execution error:');
        assert.equal(mcpLogs.length, 1, `${scenario.name}: expected one MCP execution log`);
        assert.equal(unexpectedCalls.some((args) => args[0] === '[mcp] tool execution error:'), false, `${scenario.name}: wrong console severity`);
        const loggedError = mcpLogs[0][1];
        scenario.assertMessage(loggedError instanceof Error ? loggedError.message : String(loggedError));
      } finally {
        console.warn = origWarn;
        console.error = origError;
      }
    }
  });

  it('edge: cache-only tool for Pro user goes through INCR/DECR path (counts toward 50/day)', async () => {
    const { deps, pipe } = makeProDeps();
    process.env.UPSTASH_REDIS_REST_URL = 'https://stub.upstash';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'stub';
    globalThis.fetch = async () => new Response(JSON.stringify({ result: JSON.stringify({ ok: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
    // get_market_data is a cache-only tool (no _execute, just executeTool)
    const res = await mcpHandler(proReq('POST', callBody('get_market_data')), deps);
    assert.equal(res.status, 200);
    assert.equal(pipe.count, 1, 'cache-only tool incremented quota');
  });

  it('v1.5.0: describe_tool for Pro user is EXEMPT from the INCR/DECR daily-quota path (metadata-only)', async () => {
    const { deps, pipe } = makeProDeps();
    process.env.UPSTASH_REDIS_REST_URL = 'https://stub.upstash';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'stub';
    globalThis.fetch = async () => new Response(JSON.stringify({ result: JSON.stringify({ ok: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });
    // describe_tool is the v1.5.0 metadata escape hatch. SERVER_INSTRUCTIONS
    // actively encourages calling it while choosing tools, so it must NOT
    // consume daily quota — otherwise a Pro user at the 50/day cap can't
    // even fetch tool definitions. Rate limit (60/min) still applies.
    const res = await mcpHandler(proReq('POST', callBody('describe_tool', { tool_name: 'get_market_data' })), deps);
    assert.equal(res.status, 200);
    assert.equal(pipe.count, 0, 'describe_tool MUST NOT increment the Pro daily quota');
  });

  it('telemetry: Pro-path tools/call AND initialize emit raw user_id === PRO_USER_ID (un-hashed)', async () => {
    // Pro context carries a real Clerk userId — it is an internal ID, not
    // secret material, so the log-safe principal is the raw userId itself
    // (matches the REST gateway's customer_id convention). This locks in
    // the Pro branch of principalIdForLog against future regressions to
    // hashing/redacting/aliasing.
    process.env.MCP_TELEMETRY = 'true';
    process.env.UPSTASH_REDIS_REST_URL = 'https://stub.upstash';
    process.env.UPSTASH_REDIS_REST_TOKEN = 'stub';
    const { deps } = makeProDeps();
    globalThis.fetch = async () => new Response(JSON.stringify({ result: JSON.stringify({ ok: 1 }) }), { status: 200, headers: { 'Content-Type': 'application/json' } });

    const captured = [];
    const origLog = console.log;
    console.log = (line) => captured.push(line);
    try {
      const initRes = await mcpHandler(proReq('POST', initBody(700)), deps);
      assert.equal(initRes.status, 200, 'initialize must succeed for Pro');
      const callRes = await mcpHandler(proReq('POST', callBody('get_market_data', {}, 701)), deps);
      assert.equal(callRes.status, 200, 'tools/call must succeed for Pro');
    } finally {
      console.log = origLog;
    }

    const init = captured.filter((l) => l && typeof l === 'object' && !Array.isArray(l) && l.tag === 'mcp.tools_list_emitted');
    assert.equal(init.length, 1, `expected exactly one mcp.tools_list_emitted line, got ${init.length}`);
    assert.equal(init[0].auth_kind, 'pro');
    assert.equal(init[0].user_id, PRO_USER_ID, 'initialize user_id MUST be the raw Clerk userId on the Pro path');

    const tc = captured.filter((l) => l && typeof l === 'object' && !Array.isArray(l) && l.tag === 'mcp.toolcall');
    assert.equal(tc.length, 1, `expected exactly one mcp.toolcall line, got ${tc.length}`);
    assert.equal(tc[0].auth_kind, 'pro');
    assert.equal(tc[0].user_id, PRO_USER_ID, 'tools/call user_id MUST be the raw Clerk userId on the Pro path');
  });

  it('integration: signed header for /api/news/v1/list-feed-digest cannot be replayed against /api/intelligence/v1/deduct-situation', async () => {
    const { signInternalMcpRequest, hmacSha256Base64Url, canonicalQueryString, sha256Hex, buildHmacPayload } = await import(`../server/_shared/mcp-internal-hmac.ts?t=${Date.now()}`);
    // Sign for digest endpoint.
    const signed = await signInternalMcpRequest({
      method: 'GET',
      url: 'https://worldmonitor.app/api/news/v1/list-feed-digest?lang=en&variant=full',
      body: null,
      userId: PRO_USER_ID,
      secret: HMAC_SECRET,
    });
    // Re-construct the payload that would be expected for the SAME ts on a different path.
    const replayUrl = new URL('https://worldmonitor.app/api/intelligence/v1/deduct-situation');
    const replayPayload = buildHmacPayload({
      ts: signed.ts,
      method: 'POST',
      pathname: replayUrl.pathname,
      queryHash: await sha256Hex(canonicalQueryString(replayUrl)),
      bodyHash: await sha256Hex(JSON.stringify({ query: 'attacker' })),
      userId: PRO_USER_ID,
      nonce: signed.nonce,
    });
    const replayExpected = await hmacSha256Base64Url(HMAC_SECRET, replayPayload);
    const replayActual = signed.signature.split('.')[1];
    assert.notEqual(replayActual, replayExpected, 'captured signature must NOT verify for the replay target — payload binds method+pathname+body');
  });

  it('canonicalQueryString sorts keys lexicographically — ?a=1&b=2 and ?b=2&a=1 produce identical canonical form', async () => {
    const { canonicalQueryString } = await import(`../server/_shared/mcp-internal-hmac.ts?t=${Date.now()}`);
    const a = canonicalQueryString('?a=1&b=2');
    const b = canonicalQueryString('?b=2&a=1');
    assert.equal(a, b, 'reordered query → identical canonical form');
    assert.equal(a, 'a=1&b=2');
  });

  it('canonicalQueryString URL-encodes values', async () => {
    const { canonicalQueryString } = await import(`../server/_shared/mcp-internal-hmac.ts?t=${Date.now()}`);
    const c = canonicalQueryString('?q=hello world&special=a%2Fb');
    // Spaces become %20, existing %2F is decoded then re-encoded the same.
    assert.match(c, /q=hello%20world/);
    assert.match(c, /special=a%2Fb/);
  });

  it('dailyCounterKey is UTC-stable across timezones', async () => {
    const { dailyCounterKey } = await import(`../server/_shared/pro-mcp-token.ts?t=${Date.now()}`);
    const utc = new Date(Date.UTC(2026, 4, 10, 12, 0, 0));
    const k = dailyCounterKey('user_x', utc);
    assert.equal(k, 'mcp:pro-usage:user_x:2026-05-10');
  });

  it('secondsUntilUtcMidnight returns a positive Δ to next 00:00Z', async () => {
    const { secondsUntilUtcMidnight } = await import(`../server/_shared/pro-mcp-token.ts?t=${Date.now()}`);
    const noon = new Date(Date.UTC(2026, 4, 10, 12, 0, 0));
    const s = secondsUntilUtcMidnight(noon);
    assert.equal(s, 12 * 3600);
  });

  it('F10: signInternalMcpRequest with FormData body throws (no silent JSON.stringify catch-all)', async () => {
    const { signInternalMcpRequest } = await import(`../server/_shared/mcp-internal-hmac.ts?t=${Date.now()}`);
    const fd = new FormData();
    fd.append('x', '1');
    await assert.rejects(
      () => signInternalMcpRequest({
        method: 'POST',
        url: 'https://example.com/x',
        body: fd,
        userId: 'u',
        secret: 'k',
      }),
      (err) => err instanceof Error && /unsupported body shape/i.test(err.message),
    );
  });

  it('F10: signInternalMcpRequest with Blob body throws', async () => {
    const { signInternalMcpRequest } = await import(`../server/_shared/mcp-internal-hmac.ts?t=${Date.now()}`);
    const b = new Blob(['hello'], { type: 'application/octet-stream' });
    await assert.rejects(
      () => signInternalMcpRequest({
        method: 'POST',
        url: 'https://example.com/x',
        body: b,
        userId: 'u',
        secret: 'k',
      }),
      (err) => err instanceof Error && /unsupported body shape/i.test(err.message),
    );
  });

  it('F11: parseSignatureHeader rejects ts strings longer than 15 digits', async () => {
    // Indirect probe via verifyInternalMcpRequest: a 16-digit ts must
    // fail the regex and yield 401.
    const { verifyInternalMcpRequest } = await import(`../server/_shared/mcp-internal-hmac.ts?t=${Date.now()}`);
    const tsTooLong = '1'.repeat(16); // 16 digits — pathological
    const req = new Request('https://example.com/x', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-WM-MCP-Internal': `${tsTooLong}.AAAA`,
        'X-WM-MCP-User-Id': 'u',
      },
      body: '{}',
    });
    const r = await verifyInternalMcpRequest(req, 'k');
    assert.equal(r, null, 'F11: 16-digit ts must reject');
  });
});
