import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { ROOT, tmp, cli } from './helpers.ts';
import { HELP_FLAGS } from './guide-flags.ts';
const guide = readFileSync(join(ROOT, 'docs/GUIDE.md'), 'utf8');
const prose = guide.replace(/```[\s\S]*?```/g, ' ');
const words = prose.replace(/[#*|`_-]/g, ' ').split(/\s+/).filter((w) => /[A-Za-z0-9]/.test(w));
test('G1 the guide covers what an agent is, install, what stays sovereign and what Kognai helps with', () => {
for (const h of ['What a Zimakri agent is', 'Install the template', 'What stays sovereign', 'What Kognai helps with']) assert.ok(guide.includes(`## ${h}`), h);
for (const s of ['**Keys.**', '**Memory.**', '**Earnings.**']) assert.ok(guide.includes(s), s);
for (const k of ['Encrypted memory backup', 'Key and DID recovery', 'The Cerberus passport', 'Template updates']) assert.ok(guide.includes(`**${k}.**`), k);
});
test('G2 accurate against the template: every file, folder, flag and wake step it names is what init really does', () => {
const d = tmp();
const r = cli(['init', '--dir', d, '--name', 'Guide Check']);
assert.equal(r.code, 0);
const cfg = JSON.parse(readFileSync(join(d, 'zimakri.config.json'), 'utf8'));
for (const f of ['.zimakri/identity/agent.key', '.zimakri/identity/did.json', 'zimakri.config.json', 'SOUL.md', 'WAKE.md', 'wake.json', 'lax-offer.json', 'memory/earnings/ledger.jsonl']) {
assert.ok(guide.includes('`' + f + '`'), `guide names ${f}`);
assert.ok(readFileSync(join(d, f)) !== undefined);
}
for (const m of cfg.memory.dirs) assert.ok(guide.includes('`' + m.split('/')[1] + '`'), `guide names ${m}`);
for (const step of cfg.wake.steps) assert.match(guide, new RegExp(`\\*\\*${step}\\*\\*:`), `wake step ${step}`);
assert.equal(cfg.wake.steps.length, 7); assert.match(guide, /runs seven steps/);
for (const flag of guide.match(/`--[a-z]+`/g) ?? []) assert.ok(HELP_FLAGS.includes(flag.slice(1, -1)), `${flag} is a real option`);
assert.equal(cfg.mandates.max_spend_usdc_per_day, '0'); assert.match(guide, /starts at 0 per day/);
assert.match(guide, /mode 600/);
assert.ok(r.out.includes(cfg.did) && guide.includes('prints the new DID'));
});
test('G3 readable by a non expert: at most 1,500 words, short sentences, plain text rules', () => {
assert.ok(words.length <= 1500, `${words.length} words`);
const sentences = prose.split(/[.!?]\s/).map((s) => s.split(/\s+/).filter(Boolean).length).filter((n) => n > 2);
const avg = sentences.reduce((a, b) => a + b, 0) / sentences.length;
assert.ok(avg <= 18, `average sentence ${avg.toFixed(1)} words`);
assert.doesNotMatch(guide, /[\u2013\u2014]/, 'no long dashes');
assert.doesNotMatch(guide, /[\u0660-\u0669\u06F0-\u06F9]/, 'Latin digits only');
assert.doesNotMatch(guide, /\b(seed phrase|mnemonic)\b/i);
});
agentgate-source: code mirror on Cloudflare Pages. All repos