// Domain: protocol. Covers SKILL.md frontmatter, the router dispatch table, the shipped
// skill inventory, and every documented wrapper example run against the real gates.
const test = require('node:test');
const { describe } = test;
const assert = require('node:assert/strict');
const cp = require('node:child_process');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');

const repo = path.join(__dirname, '..', '..');

describe('SKILL.md structure and shipped inventory', () => { // #55
  const skills = path.join(repo, 'skills');
  const inventory = ['okf', 'okf-read', 'okf-write', 'okf-lifecycle', 'okf-review', 'okf-setup'];
  const reachClause = /\bwhen another skill must invoke it\b/i;
  // `okf` and `okf-setup` are the two directly-invoked skills: `okf` is the router a user
  // selects an operation through, and `okf-setup` accepts no delegation brief (#134). Every
  // other inventory member is delegate-only and carries the generic reach clause instead.
  const directInvocationSkills = new Set(['okf', 'okf-setup']);
  const routerTable = '| Operations | Owner |';
  const routerRoutes = [
    ['read', 'okf-read'], ['write', 'okf-write'], ['lifecycle', 'okf-lifecycle'], ['review', 'okf-review'],
    ['init', 'okf-setup'], ['inspect', 'okf-setup'], ['repair', 'okf-setup'],
    ['plan', 'okf-setup'], ['aggregate', 'okf-setup'], ['report', 'okf-setup'],
    ['discover', 'okf-setup'], ['migration-plan', 'okf-setup'], ['partition', 'okf-setup'],
    ['assemble', 'okf-setup'], ['migration-validate', 'okf-setup'], ['publish', 'okf-setup'],
  ];

  function writeSkill(t, name, source, files = {}) {
    const root = fs.mkdtempSync(path.join(os.tmpdir(), 'okf-55-'));
    const directory = path.join(root, name);
    fs.mkdirSync(directory, { recursive: true });
    fs.writeFileSync(path.join(directory, 'SKILL.md'), source);
    for (const [file, content] of Object.entries(files)) {
      const target = path.join(directory, file);
      fs.mkdirSync(path.dirname(target), { recursive: true });
      fs.writeFileSync(target, content);
    }
    t.after(() => fs.rmSync(root, { recursive: true, force: true }));
    return directory;
  }

  function frontmatter(source) {
    const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
    return match ? { text: match[1], body: source.slice(match[0].length) } : null;
  }

  function field(frontmatterText, name) {
    const match = frontmatterText.match(new RegExp(`^${name}:([^\\r\\n]*)$`, 'm'));
    if (!match) return null;
    const value = match[1].trim();
    if (value === '|' || value === '>') {
      const block = frontmatterText.slice(match.index + match[0].length).match(/^\r?\n(?:[ \t]+.+(?:\r?\n|$))*/);
      return block ? block[0].trim() : '';
    }
    if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
      return value.slice(1, -1).trim();
    }
    return value.replace(/\s+#.*$/, '').trim();
  }

  function withoutFencedCode(markdown) {
    let fenced = false;
    return markdown.split(/(?<=\n)/).map((line) => {
      if (/^\s*(```|~~~)/.test(line)) {
        fenced = !fenced;
        return '';
      }
      return fenced ? '' : line;
    }).join('');
  }

  function withoutInlineCode(markdown) {
    let result = '';
    for (let index = 0; index < markdown.length;) {
      if (markdown[index] !== '`') {
        result += markdown[index++];
        continue;
      }
      let end = index;
      while (markdown[end] === '`') end += 1;
      const delimiter = markdown.slice(index, end);
      const close = markdown.indexOf(delimiter, end);
      if (close === -1) {
        result += delimiter;
        index = end;
      } else {
        index = close + delimiter.length;
      }
    }
    return result;
  }

  function markdownDestinations(markdown) {
    const destinations = [];
    const pattern = /!?\[[^\]\n]*\]\(\s*(?:<([^>\n]*)>|([^\s)]+))(?:\s+(?:"[^"]*"|'[^']*'))?\s*\)/g;
    for (const match of withoutInlineCode(withoutFencedCode(markdown)).matchAll(pattern)) {
      destinations.push(match[1] === undefined ? match[2] : match[1]);
    }
    return destinations;
  }

  function scriptReferences(markdown) {
    const visible = withoutFencedCode(markdown).replace(
      /!?\[[^\]\n]*\]\(\s*(?:<([^>\n]*)>|([^\s)]+))(?:\s+(?:"[^"]*"|'[^']*'))?\s*\)/g,
      (link, enclosed, plain) => isExternal(enclosed ?? plain) ? '' : link,
    );
    return [...visible.matchAll(/\bscripts\/(?:[A-Za-z0-9][A-Za-z0-9._-]*\/)*[A-Za-z0-9][A-Za-z0-9._-]*/g)]
      .map((match) => match[0]);
  }

  function repeatedNormativeStatements(markdown) {
    const seen = new Set();
    const repeated = [];
    for (const statement of withoutFencedCode(markdown).matchAll(/[^\n]*\b(?:MUST|MUST NOT|SHALL|SHALL NOT)\b[^\n]*/g)) {
      const normalized = statement[0].replace(/\s+/g, ' ').trim().toLowerCase();
      if (seen.has(normalized)) repeated.push(normalized);
      seen.add(normalized);
    }
    return repeated;
  }

  function routerOwners(markdown) {
    const table = markdown.indexOf(routerTable);
    if (table === -1) return [];
    return [...markdown.slice(table + routerTable.length).matchAll(/^\|\s*`([^`\r\n]+)`\s*\|\s*`([^`\r\n]+)`\s*\|\s*$/gm)]
      .map((match) => [match[1], match[2]]);
  }

  function validateInventory(directory) {
    const shipped = fs.readdirSync(directory, { withFileTypes: true })
      .filter((entry) => entry.isDirectory())
      .map((entry) => entry.name)
      .sort();
    return [
      ...inventory.filter((name) => !shipped.includes(name)).map((name) => `SKILL_REQUIRED:${name}`),
      ...shipped.filter((name) => !inventory.includes(name)).map((name) => `SKILL_UNEXPECTED:${name}`),
    ];
  }

  function isExternal(destination) {
    return /^([a-z][a-z0-9+.-]*:|\/\/)/i.test(destination);
  }

  function existsAt(directory, destination) {
    const file = destination.split(/[?#]/, 1)[0];
    if (!file || isExternal(file)) return true;
    try {
      return fs.existsSync(path.resolve(directory, decodeURIComponent(file)));
    } catch {
      return false;
    }
  }

  // This validator is intentionally local: skill directories are its only seam.
  function validateSkill(directory) {
    const file = path.join(directory, 'SKILL.md');
    if (!fs.existsSync(file)) return ['SKILL_FILE_REQUIRED'];

    const source = fs.readFileSync(file, 'utf8');
    const parsed = frontmatter(source);
    if (!parsed) return ['FRONTMATTER_REQUIRED'];

    const errors = [];
    const name = field(parsed.text, 'name');
    const description = field(parsed.text, 'description');
    const directoryName = path.basename(directory);
    if (!name) errors.push('FRONTMATTER_NAME_REQUIRED');
    else if (name !== directoryName) errors.push('FRONTMATTER_NAME_MISMATCH');
    if (!description) errors.push('FRONTMATTER_DESCRIPTION_REQUIRED');

    if (description) {
      const firstWord = description.match(/^\s*([A-Za-z]+)\b/)?.[1];
      if (!firstWord || !/s$/i.test(firstWord)) errors.push('DESCRIPTION_NOT_THIRD_PERSON');
      if ((description.match(/\bwhen\b/gi) || []).length !== 1) errors.push('DESCRIPTION_TRIGGER_BRANCH_COUNT');
      if (reachClause.test(description)) {
        if (!inventory.includes(directoryName) || directInvocationSkills.has(directoryName)) errors.push('REACH_CLAUSE_FORBIDDEN');
      } else if (inventory.includes(directoryName) && !directInvocationSkills.has(directoryName)) {
        errors.push('REACH_CLAUSE_REQUIRED');
      }
    }

    if (directoryName === 'okf') {
      const routes = routerOwners(parsed.body);
      for (const [operation, owner] of routerRoutes) {
        if (!routes.some(([actualOperation, actualOwner]) => actualOperation === operation && actualOwner === owner)) {
          errors.push(`ROUTER_ROUTE_REQUIRED:${owner}`);
        }
      }
    }

    for (const destination of markdownDestinations(parsed.body)) {
      if (!existsAt(directory, destination)) errors.push(`LINK_NOT_FOUND:${destination}`);
    }
    for (const script of scriptReferences(parsed.body)) {
      if (!existsAt(directory, script)) errors.push(`SCRIPT_NOT_FOUND:${script}`);
    }
    for (const statement of repeatedNormativeStatements(parsed.body)) {
      errors.push(`NORMATIVE_MEANING_REPEATED:${statement}`);
    }
    return errors;
  }

  function validSkill(name = 'okf-read') {
    const descriptions = {
      okf: 'Routes OKF requests when a user selects an operation.',
      'okf-read': 'Reads admitted OKF bundles when another skill must invoke it.',
      'okf-write': 'Writes bounded OKF updates when another skill must invoke it.',
      'okf-lifecycle': 'Maintains OKF lifecycle work when another skill must invoke it.',
      'okf-review': 'Reviews OKF evidence when another skill must invoke it.',
      'okf-setup': 'Bootstraps an OKF bundle when a user explicitly invokes setup.',
    };
    const dispatch = name === 'okf'
      ? `\n## Dispatch\n\n${routerTable}\n| --- | --- |\n| \`read\` | \`okf-read\` |\n| \`write\` | \`okf-write\` |\n| \`lifecycle\` | \`okf-lifecycle\` |\n| \`review\` | \`okf-review\` |\n| \`init\` | \`okf-setup\` |\n| \`inspect\` | \`okf-setup\` |\n| \`repair\` | \`okf-setup\` |\n| \`plan\` | \`okf-setup\` |\n| \`aggregate\` | \`okf-setup\` |\n| \`report\` | \`okf-setup\` |\n| \`discover\` | \`okf-setup\` |\n| \`migration-plan\` | \`okf-setup\` |\n| \`partition\` | \`okf-setup\` |\n| \`assemble\` | \`okf-setup\` |\n| \`migration-validate\` | \`okf-setup\` |\n| \`publish\` | \`okf-setup\` |\n`
      : '';
    return `---\nname: ${name}\ndescription: ${descriptions[name] || 'Reads bounded material when a task requires it.'}\n---\n# Skill\n${dispatch}`;
  }

  test('rejects absent and empty required frontmatter fields', (t) => {
    const cases = [
      ['absent name', '---\ndescription: Reads material when a task requires it.\n---\n', 'FRONTMATTER_NAME_REQUIRED'],
      ['empty name', '---\nname: ""\ndescription: Reads material when a task requires it.\n---\n', 'FRONTMATTER_NAME_REQUIRED'],
      ['absent description', '---\nname: okf-read\n---\n', 'FRONTMATTER_DESCRIPTION_REQUIRED'],
      ['empty description', '---\nname: okf-read\ndescription: ""\n---\n', 'FRONTMATTER_DESCRIPTION_REQUIRED'],
    ];
    for (const [label, source, error] of cases) {
      assert.ok(validateSkill(writeSkill(t, 'okf-read', source)).includes(error), label);
    }
  });

  test('rejects a frontmatter name that does not match its skill directory', (t) => {
    assert.ok(validateSkill(writeSkill(t, 'okf-read', validSkill().replace('name: okf-read', 'name: okf-write')))
      .includes('FRONTMATTER_NAME_MISMATCH'));
  });

  test('rejects each static description violation', (t) => {
    const cases = [
      ['third-person wording', validSkill().replace('Reads admitted', 'Read admitted'), 'DESCRIPTION_NOT_THIRD_PERSON'],
      ['multiple trigger branches', validSkill().replace('when another skill must invoke it', 'when a user requests inspection and when another skill must invoke it'), 'DESCRIPTION_TRIGGER_BRANCH_COUNT'],
    ];
    for (const [label, source, error] of cases) assert.ok(validateSkill(writeSkill(t, 'okf-read', source)).includes(error), label);
  });

  test('requires reach clauses only for the delegate-only leaf skills', (t) => {
    assert.ok(validateSkill(writeSkill(t, 'okf-read', validSkill().replace('when another skill must invoke it', 'when a task requires it')))
      .includes('REACH_CLAUSE_REQUIRED'));
    assert.ok(validateSkill(writeSkill(t, 'okf', validSkill('okf').replace('when a user selects an operation', 'when another skill must invoke it')))
      .includes('REACH_CLAUSE_FORBIDDEN'));
    assert.ok(validateSkill(writeSkill(t, 'okf-setup', validSkill('okf-setup').replace('when a user explicitly invokes setup', 'when another skill must invoke it')))
      .includes('REACH_CLAUSE_FORBIDDEN'));
  });

  test('requires each documented dispatch-table operation and owner pair', (t) => {
    assert.deepEqual(validateSkill(writeSkill(t, 'okf', validSkill('okf'))), []);
    assert.ok(validateSkill(writeSkill(t, 'okf', validSkill('okf').replace('| `review` | `okf-review` |', '| `review` | `okf-read` |')))
      .includes('ROUTER_ROUTE_REQUIRED:okf-review'));
    assert.ok(validateSkill(writeSkill(t, 'okf', validSkill('okf')
      .replace('| `read` | `okf-read` |', '| `read` | `okf-write` |')
      .replace('| `write` | `okf-write` |', '| `write` | `okf-read` |')))
      .includes('ROUTER_ROUTE_REQUIRED:okf-read'));
  });

  test('rejects a broken Markdown relative link but ignores external URLs and anchors', (t) => {
    const source = `${validSkill()}\n[broken](references/missing.md)\n[site](https://okf.md/)\n[section](#skill)\n\`\`[example](ignored.md)\`\`\n\`\`\`md\n[fenced](also-ignored.md)\n\`\`\`\n`;
    assert.deepEqual(validateSkill(writeSkill(t, 'okf-read', source)), ['LINK_NOT_FOUND:references/missing.md']);
  });

  test('rejects a missing explicit script reference but ignores fenced examples and external links', (t) => {
    assert.deepEqual(validateSkill(writeSkill(t, 'okf-read', `${validSkill()}\nRun \`scripts/check.js\`.\n[external](https://example.test/scripts/ignored.js)\n\n\`\`\`sh\nnode scripts/example.js\n\`\`\`\n`)), [
      'SCRIPT_NOT_FOUND:scripts/check.js',
    ]);
  });

  test('resolves Markdown links and explicit script references from the skill directory', (t) => {
    const source = `${validSkill()}\n[reference](references/rule.md)\nRun \`scripts/check.js\`.\n`;
    assert.deepEqual(validateSkill(writeSkill(t, 'okf-read', source, {
      'references/rule.md': '# Rule\n',
      'scripts/check.js': 'process.exitCode = 0;\n',
    })), []);
  });

  test('rejects a repeated normative statement', (t) => {
    const statement = 'Agents MUST record the observed evidence.';
    assert.ok(validateSkill(writeSkill(t, 'okf-read', `${validSkill()}\n${statement}\n${statement}\n`))
      .includes(`NORMATIVE_MEANING_REPEATED:${statement.toLowerCase()}`));
  });

  test('defines the required skill inventory with fixtures', (t) => {
    const root = fs.mkdtempSync(path.join(os.tmpdir(), 'okf-55-inventory-'));
    t.after(() => fs.rmSync(root, { recursive: true, force: true }));
    for (const name of inventory) {
      const directory = path.join(root, name);
      fs.mkdirSync(directory);
      fs.writeFileSync(path.join(directory, 'SKILL.md'), validSkill(name));
    }
    assert.deepEqual(validateInventory(root), []);
    fs.rmSync(path.join(root, 'okf-review'), { recursive: true });
    assert.deepEqual(validateInventory(root), ['SKILL_REQUIRED:okf-review']);
    fs.mkdirSync(path.join(root, 'extra'));
    assert.deepEqual(validateInventory(root), ['SKILL_REQUIRED:okf-review', 'SKILL_UNEXPECTED:extra']);
  });

  test('validates the exact shipped inventory before each skill', () => {
    assert.deepEqual(validateInventory(skills), [], 'skills inventory');
    for (const name of inventory) {
      const directory = path.join(skills, name);
      assert.deepEqual(validateSkill(directory), [], path.relative(repo, directory));
    }
  });
});

describe('documented request examples run against the real gates', () => { // #120
  const protocol = require('../../scripts/lib/protocol');
  const runtime = require('../../scripts/lib/runtime');

  const skillsRoot = path.join(repo, 'skills');
  const skills = fs.readdirSync(skillsRoot, { withFileTypes: true })
    .filter((entry) => entry.isDirectory())
    .map((entry) => entry.name);

  // Per-operation payload fields come from protocol.js instead of being duplicated here.
  // The third top-level field, `invocation`, has no code here: parseRequest refuses a
  // `sync` that omits it before the runtime runs, so runWrapper's exit-0 assertion catches it.
  const TOP_LEVEL_FIELD_CODES = new Set(['TASK_KIND_NOT_WRITE_ELIGIBLE', 'INVALID_SCOPE']);
  const FIXTURE_KEYS = new Set(['cwd', 'bundle', 'concept', 'target']);

  function skillDoc(name) {
    return fs.readFileSync(path.join(skillsRoot, name, 'SKILL.md'), 'utf8');
  }

  // Every fenced `json` block in a SKILL.md that parses as an okf-wrapper/1 request.
  function wrapperExamples(markdown) {
    const examples = [];
    for (const match of markdown.matchAll(/```json\n([\s\S]*?)```/g)) {
      let value;
      try {
        value = JSON.parse(match[1]);
      } catch {
        continue;
      }
      if (value && value.protocol === 'okf-wrapper/1') examples.push(value);
    }
    return examples;
  }

  function isPlaceholder(value) {
    return typeof value === 'string' && /^<.*>$/.test(value);
  }

  // `today` is documented as optional (skills/okf-review/SKILL.md), and so are
  // `project_mode`, `manifest`, `workspace_id`, `mappings`, `answers`,
  // `package_root` (skills/okf-setup/SKILL.md, #146), `split_requested`
  // (skills/okf-setup/SKILL.md, #200/#201 task 1), and `split_sections`
  // (skills/okf-setup/SKILL.md, #200/#201 task 2), and `split_proposals`
  // (skills/okf-setup/SKILL.md, #200/#201 task 3), and `split_review`
  // (skills/okf-setup/SKILL.md, #200/#201 task 5), and `group_packages` and
  // `root_package` (skills/okf-setup/SKILL.md, #202/#203); any other placeholder
  // this fixture can't fill is a doc/runtime mismatch, not something to hide.
  const OPTIONAL_PLACEHOLDER_KEYS = new Set([
    'today', 'project_mode', 'manifest', 'workspace_id', 'mappings', 'answers', 'package_root',
    'split_requested', 'semantic_boundary_sources', 'split_sections', 'split_proposals', 'split_review',
    'group_packages', 'root_package',
  ]);

  function fixtureRequest(example, fixture) {
    const payload = {};
    for (const [key, value] of Object.entries(example.payload || {})) {
      if (FIXTURE_KEYS.has(key)) {
        payload[key] = fixture[key];
      } else if (isPlaceholder(value)) {
        assert.ok(OPTIONAL_PLACEHOLDER_KEYS.has(key), `${example.operation}'s example payload.${key} is a placeholder ("${value}") this fixture cannot fill`);
      } else {
        payload[key] = value;
      }
    }
    const request = { ...example, payload };
    if (request.scope && Array.isArray(request.scope.concepts)) {
      request.scope = { ...request.scope, concepts: request.scope.concepts.map((value) => (isPlaceholder(value) ? fixture.concept : value)) };
    }
    return request;
  }

  function bundle(t) {
    const root = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'okf-120-')));
    t.after(() => fs.rmSync(root, { recursive: true, force: true }));
    fs.mkdirSync(path.join(root, '.git'));
    fs.writeFileSync(path.join(root, '.okf-workspace.json'), JSON.stringify({
      schema_version: 1,
      workspace_id: '3f8c1b2e-4a5d-4e6f-8a9b-0c1d2e3f4a5b',
      repositories: [{ name: 'repo', path: '.', local: true }],
      bundles: [{ alias: 'repo', owner: 'repo', root: '.', okf_version: '0.2', project_mode: 'knowledge-only' }],
    }));
    fs.writeFileSync(path.join(root, 'index.md'), '---\nokf_version: "0.2"\nproject_mode: "knowledge-only"\n---\n# Bundle\n');
    fs.writeFileSync(path.join(root, 'evidence.md'), 'observed evidence\n');
    fs.writeFileSync(path.join(root, 'note.md'), '---\ntype: Note\ntitle: Before\n---\n# Note\n');
    return root;
  }

  function fixtureFor(root) {
    return { cwd: root, bundle: root, concept: 'note.md', target: 'note.md' };
  }

  function runWrapper(skill, request) {
    const wrapper = path.join(repo, 'scripts', `${skill}.js`);
    const result = cp.spawnSync(process.execPath, [wrapper], { input: JSON.stringify(request), encoding: 'utf8' });
    assert.equal(result.status, 0, `${skill} rejected the request as invalid wrapper input: ${result.stderr}`);
    assert.equal(result.stderr, '');
    return JSON.parse(result.stdout);
  }

  test('every skill doc is accounted for: which carry a request example and which do not', () => {
    const withExample = new Set();
    const withoutExample = [];
    for (const name of skills) {
      if (wrapperExamples(skillDoc(name)).length > 0) withExample.add(name);
      else withoutExample.push(name);
    }
    // Every skill runtime.routerOwners names as an owner performs an operation directly
    // and must carry an example; a skill that owns nothing (the `okf` router) is not held
    // to that bar, so gaining or losing an example never flips this assertion by accident.
    const leafSkills = new Set(runtime.routerOwners.values());
    const missingExample = [...leafSkills].filter((name) => !withExample.has(name)).sort();
    assert.deepEqual(missingExample, [], `a leaf skill with no request example is a gap, not a silently accepted state (currently without one: ${withoutExample.join(', ') || 'none'})`);
  });

  // Most skills document exactly one operation with one example. `okf-setup` owns
  // five (#138: `init`, `inspect`, `repair`; #135: `plan`, `aggregate`), each with its
  // own example, so this runs once per documented example rather than assuming one
  // example per skill.
  for (const name of skills) {
    const examples = wrapperExamples(skillDoc(name));
    const operations = examples.map((example) => example.operation);
    assert.deepEqual(operations, [...new Set(operations)], `${name}/SKILL.md documents more than one okf-wrapper/1 example for the same operation`);

    for (const example of examples) {
      test(`${name}'s documented request example for ${example.operation} is not blocked by a gate it could have satisfied`, (t) => {
        const root = bundle(t);
        const request = fixtureRequest(example, fixtureFor(root));

        const required = protocol.requiredPayload.get(example.operation) || [];
        for (const key of required) {
          assert.ok(typeof request.payload[key] === 'string' && request.payload[key] !== '', `${name}'s example for ${example.operation} omits payload.${key} after fixture substitution, required per scripts/lib/protocol.js`);
        }

        const response = runWrapper(example.skill, request);
        const code = response.data && response.data.code;
        if (response.result === 'blocked' && TOP_LEVEL_FIELD_CODES.has(code)) {
          const finding = response.findings.find((item) => item.code === code);
          assert.fail(`${name} (${example.operation}): blocked by ${code} (gate: ${finding && finding.detail && finding.detail.gate}) — the documented example could have named this top-level field itself`);
        }
      });
    }
  }

  // enumerate and validate are the only okf-read operations whose SKILL.md bullet
  // documents a `payload.bundle` this fixture can resolve directly, with no workspace
  // manifest and no `payload.candidates` the doc never mentions. resolve, read, and
  // search need one of those to admit anything, and checking them here would mean
  // inventing candidate data the doc does not document, so they are left unchecked.
  const SELF_LOCATING_OPERATIONS = {
    enumerate(response) {
      const gap = response.findings.find((item) => item.code === 'unreadable' && item.detail && item.detail.reason === 'no_admitted_bundle');
      assert.equal(gap, undefined, 'found no admitted bundle');
    },
    validate(response) {
      assert.equal(response.result, 'ok', `got result "${response.result}" instead of "ok" — no admitted bundle for the documented payload`);
    },
  };

  function documentedOperationBullets(markdown) {
    const bullets = new Map();
    for (const match of markdown.matchAll(/^- `(\w+)` — (.+)$/gm)) bullets.set(match[1], match[2]);
    return bullets;
  }

  test("okf-read's self-locating entries name a key that makes the result usable", (t) => {
    const bullets = documentedOperationBullets(skillDoc('okf-read'));
    const root = bundle(t);
    const fixture = fixtureFor(root);

    for (const [operation, checkAdmitted] of Object.entries(SELF_LOCATING_OPERATIONS)) {
      const text = bullets.get(operation);
      assert.ok(text, `okf-read/SKILL.md must document the ${operation} operation`);
      const payload = {};
      for (const match of text.matchAll(/`payload\.(\w+)`/g)) {
        if (Object.hasOwn(fixture, match[1])) payload[match[1]] = fixture[match[1]];
      }

      const response = runWrapper('okf-read', { protocol: 'okf-wrapper/1', skill: 'okf-read', operation, payload });
      checkAdmitted(response);
    }
  });
});
