#!/usr/bin/env node
'use strict';
/**
 * יוצר תרחישי בדיקה מבוססי-סוכן (15-agent audit) — מחבר רכיבים לזרימות אמיתיות.
 * node tests/helpers/generate-agent-scenarios.js
 */
const fs = require('node:fs');
const path = require('node:path');

const outDir = path.join(__dirname, '..', 'suites', 'scenarios');
fs.mkdirSync(outDir, { recursive: true });

const scenarios = [
  {
    file: 'scenario-agent-hop-vault-roundtrip.test.js',
    body: `'use strict';
const { loadBoth, ok, summary } = require('../../helpers/dual-harness');
const { dump: d, sdk: s } = loadBoth();
const hopPlan = { chain: [{ id: 'sat:aa' }, { id: 'sat:bb' }, { id: 'sat:cc' }], tip: 'tip-v1' };
const blob = Buffer.from('hop-vault-payload-v1');
const hv1 = d.hopVaultShardPlan(blob, hopPlan, { minHops: 3, k: 2 });
const hv2 = s.hopVaultShardPlan(blob, hopPlan, { minHops: 3, k: 2 });
ok('dual hop vault shard ok', hv1.ok && hv2.ok);
const shares1 = Object.fromEntries(hv1.placement.map((p) => [p.satId, p.shareB64]));
const shares2 = Object.fromEntries(hv2.placement.map((p) => [p.satId, p.shareB64]));
const o1 = d.hopVaultOpenPlan(hv1, shares1, {});
const o2 = s.hopVaultOpenPlan(hv2, shares2, {});
ok('dual hop vault open ok', o1.ok && o2.ok);
ok('dual blob match', o1.blob.toString() === o2.blob.toString());
summary('AGENT-HOP-VAULT-ROUNDTRIP');`,
  },
  {
    file: 'scenario-agent-hop-receipt-chain.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const hopPlan = {
  chain: [{ id: 'sat:aa', hop: 0, action: 'replicate' }, { id: 'sat:bb', hop: 1, action: 'replicate' }],
  tip: 'tip-space-1',
};
const chain = t.addressOnHopReceiptChain(hopPlan, { canon: 'https://live.example', tip: 'tip-space-1' });
ok('hop receipt chain ok', chain.ok === true);
ok('chain has receipts', chain.n >= 2 && chain.receipts.length >= 2);
ok('skylive hopReceipts', chain.skylive && chain.skylive.hopReceipts.length >= 2);
summary('AGENT-HOP-RECEIPT-CHAIN');`,
  },
  {
    file: 'scenario-agent-skydb-gates.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
ok('S12 validate ok', t.skydbValidateSchema({ score: { type: 'number' } }, 'app', 'score', 9).ok);
ok('S12 validate type fail', !t.skydbValidateSchema({ score: { type: 'number' } }, 'app', 'score', 'nope').ok);
ok('S12 coerce string number', t.skydbValidateSchema({ score: 'number' }, 'app', 'score', '42').coerced === 42);
const ro = t.canarySqlReadOnlyGate({ stage: 'canary', canaries: ['local1'] }, 'local1', {});
ok('S108 canary read-only', ro.readOnly === true);
summary('AGENT-SKYDB-GATES');`,
  },
  {
    file: 'scenario-agent-xi-dag-eval.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
(async () => {
  const dag = { nodes: { out: { value: 42 } }, output: 'out' };
  const r = await t.xiDagEval(dag, async (p) => t.xiSolve(p), {});
  ok('xiDagEval value node', r.output === 42);
  ok('dag digest present', r.dagDigest && r.dagDigest.length >= 8);
  summary('AGENT-XI-DAG-EVAL');
})().catch((e) => { console.error(e); process.exit(1); });`,
  },
  {
    file: 'scenario-agent-policy-pricing.test.js',
    body: `'use strict';
const { loadBoth, ok, summary } = require('../../helpers/dual-harness');
const { dump: d, sdk: s } = loadBoth();
const p1 = d.compilePolicyDSL(d.POLICY_KIT.pricing);
const p2 = s.compilePolicyDSL(s.POLICY_KIT.pricing);
ok('dual pricing policy compiles', p1 && p1.dag && p2 && p2.dag);
ok('dual pricing dag nodes', Object.keys(p1.dag.nodes || {}).length > 0);
ok('dag ids stable', d.xiDagId(p1.dag) === s.xiDagId(p2.dag));
summary('AGENT-POLICY-PRICING');`,
  },
  {
    file: 'scenario-agent-consensus-fork.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const trA = t.branchTrace({ skipped: [], order: ['a', 'b'], results: {} });
const trB = t.branchTrace({ skipped: ['b'], order: ['a', 'c'], results: {} });
const consFork = t.consensusBranches([{ ...trA, author: 'p1' }, { ...trB, author: 'p2' }], 2);
ok('logic fork detected', consFork.fork === true);
const consOk = t.consensusBranches([{ ...trA, author: 'p1' }, { ...trA, author: 'p2' }], 2);
ok('consensus agrees same path', consOk.ok && !consOk.fork);
summary('AGENT-CONSENSUS-FORK');`,
  },
  {
    file: 'scenario-agent-dtn-custody.test.js',
    body: `'use strict';
const { loadBoth, ok, summary } = require('../../helpers/dual-harness');
const { dump: d, sdk: s } = loadBoth();
const bundle = d.dtnBundlePlan({ hello: 'nasa' }, { now: 1000, ttlMs: 5000 });
const hold1 = d.dtnCustodyGate(bundle, 2000);
const hold2 = s.dtnCustodyGate(bundle, 2000);
ok('dual custody hold', hold1.ok && hold2.ok && hold1.deliver);
const exp1 = d.dtnCustodyGate(bundle, 10000);
ok('custody expired', !exp1.ok && exp1.expired);
summary('AGENT-DTN-CUSTODY');`,
  },
  {
    file: 'scenario-agent-vault-rs.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const sealed = t.vaultSeal(Buffer.from('immortal-archive-hello'), null, { k: 2, n: 4 });
ok('vault seal chain', sealed.seq === 1 && !!sealed.digest);
const opened = t.vaultOpen(sealed.plan.sharesB64, sealed.plan);
ok('vault RS open', opened.ok && opened.blob.toString() === 'immortal-archive-hello');
const revBad = t.antiRevisionGate({ digest: 'x', prev: 'wrong' }, { digest: 'right' });
ok('anti-revision blocks fork', !revBad.ok);
summary('AGENT-VAULT-RS');`,
  },
  {
    file: 'scenario-agent-hop-credit-chain.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const hopPlan = { chain: [{ id: 'sat:a' }, { id: 'sat:b' }, { id: 'sat:c' }] };
const credFat = t.resourceCreditPlan(t.resourceMeterSample({ hostSec: 100, bandwidthBytes: 1e6 }), {});
const chainOk = t.hopChainCreditGate(hopPlan, credFat, { bytesPerHop: 50_000 });
ok('hop chain credit ok', chainOk.ok && chainOk.nEdges >= 1);
const chainFail = t.hopChainCreditGate(hopPlan, { credit: 0.000001 }, { bytesPerHop: 1e12 });
ok('hop chain credit fail thin balance', !chainFail.ok);
summary('AGENT-HOP-CREDIT-CHAIN');`,
  },
  {
    file: 'scenario-agent-trust-rotation.test.js',
    body: `'use strict';
const { loadBoth, ok, summary } = require('../../helpers/dual-harness');
const { dump: d, sdk: s } = loadBoth();
const r1 = d.trustRootRotatePlan('old', 'new', [
  { digest: 'new', worker: 'w1' },
  { digest: 'new', worker: 'w2' },
], { quorum: 2 });
const r2 = s.trustRootRotatePlan('old', 'new', [
  { digest: 'new', worker: 'w1' },
  { digest: 'new', worker: 'w2' },
], { quorum: 2 });
ok('dual trust cutover', r1.phase === 'cutover' && r2.phase === 'cutover');
const dual = d.trustRootRotatePlan('old', 'new', [{ digest: 'new', worker: 'w1' }], { quorum: 2 });
ok('dual-root until quorum', dual.phase === 'dual-root');
summary('AGENT-TRUST-ROTATION');`,
  },
  {
    file: 'scenario-agent-gateway-rewrite.test.js',
    body: `'use strict';
const { loadBoth, ok, summary } = require('../../helpers/dual-harness');
const { dump: d, sdk: s } = loadBoth();
const gw1 = d.httpLatticeGatewayPlan('sky://alice/api/health', {});
const gw2 = s.httpLatticeGatewayPlan('sky://alice/api/health', {});
const rw = d.gatewayRewrite(gw1, { apiPrefix: '/api' });
ok('sky-uri mode', gw1.ok && gw1.mode === 'sky-uri');
ok('rewrite url includes alice', rw.ok && rw.url.includes('alice'));
ok('dual gateway mode match', gw1.mode === gw2.mode);
summary('AGENT-GATEWAY-REWRITE');`,
  },
  {
    file: 'scenario-agent-living-sla.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const now = Date.now();
const workers = { w1: { id: 'w1', score: 0.9, ts: now, ops: 10 } };
const sla = t.slaScoreFromWorkers(workers);
const living = t.livingAddressPlan({ workersAlive: sla.workersAlive, health: { score: 80 } });
const composed = t.livingSlaDoorCompose({ sla, living, badge: t.liveAddressHealthBadge({ score: 75 }) });
ok('sla workers alive', sla.workersAlive >= 1);
ok('living plan ok', living.ok !== false);
ok('SLA door compose', composed && composed.ok !== false);
summary('AGENT-LIVING-SLA');`,
  },
  {
    file: 'scenario-agent-smart-merge.test.js',
    body: `'use strict';
const { loadBoth, ok, summary } = require('../../helpers/dual-harness');
const { dump: d, sdk: s } = loadBoth();
const m1 = d.smartMergeRecords(
  { v: { x: 1, y: 1 }, hlc: 5, ts: 5 },
  { v: { x: 2, z: 3 }, hlc: 9, ts: 9 },
);
const m2 = s.smartMergeRecords(
  { v: { x: 1, y: 1 }, hlc: 5, ts: 5 },
  { v: { x: 2, z: 3 }, hlc: 9, ts: 9 },
);
ok('dual smart merge x', m1.record.v.x === 2 && m2.record.v.x === 2);
ok('dual smart merge unions y+z', m1.record.v.y === 1 && m1.record.v.z === 3);
const lww = d.lwwPickRecord({ hlc: 5 }, { hlc: 9 });
ok('lww picks newer', lww.winner.hlc === 9);
summary('AGENT-SMART-MERGE');`,
  },
  {
    file: 'scenario-agent-recovery-gate.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const kit = t.recoveryKitPlan({ npub: 'npub1test' });
const shamir = t.lostIdRecoveryGate({ hasShamirShares: true });
const bad = t.lostIdRecoveryGate({});
ok('recovery kit no secret in kit', kit.ok && kit.kit.recoverableWithoutSecret === false);
ok('shamir recovery allowed', shamir.ok === true);
ok('password reset blocked', bad.ok === false && bad.reason === 'unrecoverable-without-secret');
summary('AGENT-RECOVERY-GATE');`,
  },
  {
    file: 'scenario-agent-space-quorum.test.js',
    body: `'use strict';
const { loadBoth, ok, summary } = require('../../helpers/dual-harness');
const { dump: d, sdk: s } = loadBoth();
const peerVotes = [
  { peerId: 'p1', satId: 'sat:abc' },
  { peerId: 'p2', satId: 'sat:abc' },
];
const g1 = d.spaceCatalogQuorumGate('sat:abc', peerVotes, { minPeers: 2 });
const g2 = s.spaceCatalogQuorumGate('sat:abc', peerVotes, { minPeers: 2 });
ok('dual quorum ok', g1.ok && g2.ok);
const bad = d.spaceCatalogQuorumGate('notsat', peerVotes, { minPeers: 2 });
ok('non-sat id rejected', bad.ok === false);
summary('AGENT-SPACE-QUORUM');`,
  },
  {
    file: 'scenario-agent-flock-merge.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const unified = t.flockMergePlan({
  a: { mindDigest: 'aaa', brainDigest: 'b1', flockId: 'f1', tipDigest: 't' },
  b: { mindDigest: 'aaa', brainDigest: 'b2', flockId: 'f1', tipDigest: 't' },
}, { flockId: 'f1', tipDigest: 't' });
ok('flock merge quorum', unified.ok && unified.mindDigest === 'aaa');
const split = t.flockMergePlan({
  a: { mindDigest: 'aaa', brainDigest: 'b1', flockId: 'f1', tipDigest: 't' },
  c: { mindDigest: 'bbb', brainDigest: 'b3', flockId: 'f1', tipDigest: 't' },
}, { flockId: 'f1', tipDigest: 't' });
ok('flock split detected', split.split === true);
summary('AGENT-FLOCK-MERGE');`,
  },
  {
    file: 'scenario-agent-extinction-hazard.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const haz = t.extinctionHazardScore(
  [{ nReplicas: 0, nAntennas: 0 }, { nReplicas: 1, nAntennas: 1 }],
  { minReplicas: 2, minAntennas: 3, preemptAt: 0.3, seedReplicas: 1, seedAntennas: 1 },
);
ok('extinction hazard preempt', haz.hazard > 0.3 && haz.preempt);
const gate = t.antiExtinctionGate({ replicas: [], antennas: [], tips: [] });
ok('anti extinction fails empty', gate.ok === false || gate.extinct === true);
summary('AGENT-EXTINCTION-HAZARD');`,
  },
  {
    file: 'scenario-agent-continuum-gates.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const item = t.mindContinuumItem('hello offline', { thread: 't1' });
ok('continuum item queued', item.status === 'queued' && item.digest.length > 8);
const bud = t.continuumBudgetGate({ usd: 999 }, { budgetUsdPerDay: 1 }, 'full', 50);
ok('budget gate blocks overflow', !bud.ok && bud.reason === 'continuum-budget');
const escrow = t.continuumEscrowReleasePlan([{ pay: { ok: true } }], {});
ok('escrow release when paid', escrow.shouldSettle === true);
summary('AGENT-CONTINUUM-GATES');`,
  },
  {
    file: 'scenario-agent-sibling-push.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const plan = t.siblingNeedsPushPlan(10, [{ engineSeq: 8 }, { engineSeq: 9 }]);
ok('sibling needs push when ahead', plan.needsPush === true && plan.lagging.length === 2);
const caught = t.siblingNeedsPushPlan(5, [{ engineSeq: 10 }]);
ok('no push when behind', caught.needsPush === false);
summary('AGENT-SIBLING-PUSH');`,
  },
  {
    file: 'scenario-agent-lattice-wave-catalog.test.js',
    body: `'use strict';
const { loadBoth, ok, summary } = require('../../helpers/dual-harness');
const { dump: d, sdk: s } = loadBoth();
const c1 = d.latticeWaveDoorsCatalog();
const c2 = s.latticeWaveDoorsCatalog();
ok('dual catalog has doors', Array.isArray(c1) && c1.length >= 20);
ok('S151-S172 wired set', d.LATTICE_WIRED_DOORS && d.LATTICE_WIRED_DOORS.size >= 20);
ok('dual catalog parity', JSON.stringify(c1) === JSON.stringify(c2));
summary('AGENT-LATTICE-WAVE-CATALOG');`,
  },
  {
    file: 'scenario-agent-session-vault.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const syncId = 'SC-test-session-vault-sync-id-abcdef';
const sealed = t.sessionVaultSeal({ token: 'secret' }, syncId);
const opened = t.sessionVaultOpen(sealed.blob, syncId);
ok('session vault roundtrip', opened.ok === true);
ok('session payload restored', opened.cookies && opened.cookies.token === 'secret');
const wrong = t.sessionVaultOpen(sealed.blob, 'wrong-sync-id');
ok('wrong syncId rejected', wrong.ok === false);
summary('AGENT-SESSION-VAULT');`,
  },
  {
    file: 'scenario-agent-scenario-detector.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const det = new t.ScenarioDetector();
const degraded = det.observe({ relayPhi: 9, dbLagMs: 5000, load: 0.9 });
const steady = det.observe({ relayPhi: 2, dbLagMs: 0, load: 0.2 });
ok('scenario relay_degraded', typeof degraded.scenario === 'string');
ok('scenario steady', typeof steady.scenario === 'string');
summary('AGENT-SCENARIO-DETECTOR');`,
  },
  {
    file: 'scenario-agent-market-clearing.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const clear = t.quoteMarketClearingPlan([
  { id: 'q1', lagTax: { mult: 1.2, tier: 'taxed', usd: 0.01 }, market: true },
]);
ok('quote market clearing', clear.clear && clear.n === 1);
const pick = t.marketPick([
  { digest: 'd1', price: 0.5, solver: 'w1' },
  { digest: 'd1', price: 0.3, solver: 'w2' },
], { quorum: 1 });
ok('market pick winner', pick.ok === true);
summary('AGENT-MARKET-CLEARING');`,
  },
  {
    file: 'scenario-agent-degraded-promote.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const fullPromo = t.degradedFullPromotePlan({ workersAlive: 2, meshAlive: true, organismQuorum: { ok: true } });
ok('degraded promote to full', fullPromo.promote && fullPromo.profile === 'full');
const block = t.slaPromoteGate({ slaScore: 30, minSla: 50 });
ok('SLA gate blocks low score', block.ok === false);
summary('AGENT-DEGRADED-PROMOTE');`,
  },
  {
    file: 'scenario-agent-living-snapshot-paths.test.js',
    body: `'use strict';
const fs = require('node:fs');
const path = require('node:path');
const { ok, summary } = require('../../helpers/harness');
const cloudSrc = fs.readFileSync(path.join(__dirname, '..', '..', '..', 'cloud.js'), 'utf8');
const expected = [
  '/api/health', '/api/sla', '/api/trust', '/api/address',
  '/api/compose/status', '/api/lattice-wave/status',
  '/api/space/mesh', '/api/immortal/mesh',
];
for (const p of expected) {
  ok('living snapshot path in source: ' + p, cloudSrc.includes(p));
}
summary('AGENT-LIVING-SNAPSHOT-PATHS');`,
  },
  {
    file: 'scenario-agent-exports-inventory.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const critical = [
  'encrypt', 'decrypt', 'xiSolve', 'xiQuorum', 'xiDagEval', 'bftPropose', 'bftVote', 'bftCommit',
  'hybridWrap', 'hybridOpen', 'merkleTreeFromLeaves', 'merkleVerify', 'vaultSeal', 'vaultOpen',
  'hopVaultShardPlan', 'hopVaultOpenPlan', 'spaceCatalogQuorumGate', 'continuumBudgetGate',
  'livingAddressPlan', 'relayOutageUxPlan', 'lostIdRecoveryGate', 'latticeWaveDoorsCatalog',
  'sessionVaultSeal', 'sessionVaultOpen', 'economySettleGate', 'trustRootRotatePlan',
  'smartMergeRecords', 'compilePolicyDSL', 'ScenarioDetector', 'siblingNeedsPushPlan',
];
let n = 0;
for (const name of critical) {
  if (typeof t[name] === 'function' || name === 'ScenarioDetector') { ok('__test.' + name, true); n++; }
  else ok('__test.' + name + ' MISSING', false);
}
ok('critical export count', n >= critical.length - 1);
summary('AGENT-EXPORTS-INVENTORY');`,
  },
  {
    file: 'scenario-agent-offline-hmac-chain.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
let q = [];
const c1 = t.offlineCommitPlan({ set: 'a' }, q);
q = c1.queue;
const c2 = t.offlineCommitPlan({ set: 'b' }, q);
q = c2.queue;
ok('offline queue depth 2', q.length === 2);
const up = t.drainOfflineQueuePlan(q, { poolAlive: true, batch: 8 });
ok('offline drain ordered', up.ok && up.drained.length === 2);
summary('AGENT-OFFLINE-HMAC-CHAIN');`,
  },
  {
    file: 'scenario-agent-xi-sat-economy.test.js',
    body: `'use strict';
const { load, ok, summary } = require('../../helpers/harness');
const t = load();
const credFat = t.resourceCreditPlan(t.resourceMeterSample({ hostSec: 100, bandwidthBytes: 1e6 }), {});
const probes = [{ ok: true, rttMs: 800, satelliteLikely: true, url: 'wss://sat' }];
const xiOk = t.xiSatEconomyGate(
  { nodes: { out: { value: 42 } }, output: 'out' },
  probes,
  credFat,
  { requireSatellite: true },
);
ok('xi sat economy ready', xiOk.ok && xiOk.run && xiOk.pureCompute);
const xiNoSat = t.xiSatEconomyGate(
  { nodes: { out: { value: 1 } }, output: 'out' },
  [{ ok: true, rttMs: 20 }],
  credFat,
  { requireSatellite: true },
);
ok('xi blocked without sat-path', !xiNoSat.ok);
summary('AGENT-XI-SAT-ECONOMY');`,
  },
  {
    file: 'scenario-agent-merkle-anti-entropy.test.js',
    body: `'use strict';
const { loadBoth, ok, summary } = require('../../helpers/dual-harness');
const { dump: d, sdk: s } = loadBoth();
const leaves = ['file:a', 'file:b', 'file:c'].map((x) => d.sha256(x));
const tree = d.merkleTreeFromLeaves(leaves);
const diff = d.merkleAntiEntropyDiff(tree, tree.root, leaves);
ok('merkle noop when equal', diff.sync === 'noop' || diff.reason === 'match');
const diff2 = d.merkleAntiEntropyDiff(tree, 'other-root', leaves);
ok('merkle partial when differ', diff2.sync === 'partial' || diff2.sync === 'full');
const proof = d.merkleProof(tree, 0);
ok('merkle proof ok', proof.ok === true);
ok('merkle proof verifies', d.merkleVerify(proof.leaf, proof, tree.root));
const tree2 = s.merkleTreeFromLeaves(leaves);
ok('dual merkle root', String(tree.root) === String(tree2.root));
summary('AGENT-MERKLE-ANTI-ENTROPY');`,
  },
  {
    file: 'scenario-agent-guide-coverage.test.js',
    body: `'use strict';
const fs = require('node:fs');
const path = require('node:path');
const { ok, summary } = require('../../helpers/harness');
const guide = fs.readFileSync(path.join(__dirname, '..', '..', '..', 'AI-AGENT-GUIDE.md'), 'utf8');
const cloud = fs.readFileSync(path.join(__dirname, '..', '..', '..', 'cloud.js'), 'utf8');
const guideTopics = [
  'SkyLattice-Σ', 'SkyLattice-Δ', 'SkyLattice-Ψ', 'SkyLattice-Ω', 'SkyLattice-Θ',
  'SkyLattice-Λ', 'SkyLattice-Ξ', 'publish-engine', 'SYNC_ID', 'LIVING_ADDRESS',
  'SkyDB', 'capsule-mesh', 'Lattice Wave',
];
for (const topic of guideTopics) ok('guide mentions ' + topic, guide.includes(topic));
const codeSymbols = [
  'const encrypt', 'class SkyDB', 'async function xiDagEval', 'function relayOutageUxPlan',
  'async enableLivingAddress', 'async publishLivingSnapshots', '_siblingMeshTick',
];
for (const sym of codeSymbols) ok('cloud has ' + sym.split(' ').pop(), cloud.includes(sym));
summary('AGENT-GUIDE-COVERAGE');`,
  },
];

let written = 0;
for (const sc of scenarios) {
  const fp = path.join(outDir, sc.file);
  fs.writeFileSync(fp, '#!/usr/bin/env node\n' + sc.body + '\n', 'utf8');
  written++;
}

fs.writeFileSync(
  path.join(outDir, 'README.md'),
  `# Agent-Derived Scenario Tests (${written})

Generated by \`tests/helpers/generate-agent-scenarios.js\` from 15-agent audit of cloud.js + AI-AGENT-GUIDE.md.

Each test simulates a real multi-component flow (dual-verify where noted).
Manifest: \`tests/audit/AGENT-SCAN-MANIFEST.json\`
`,
  'utf8',
);

console.log('Wrote', written, 'agent scenario tests to', outDir);
