fix: harden engine, enrich failure diagnostics, close adoption gaps

- P0: CLI verify now honors  test budget with seeded multi-sample
- P0: Observe sampling enforced via Math.random() gate in hook-validator
- P1: Remove misleading undici-mock-agent isolation option
- P1: Qualify reuses shared discoverRouteDetails() with warnings
- P1: Chaos/scenario config exposed via preset schema
- P1: README/docs limitations updated to current state
- P2: Nested response annotations prefer 2xx deterministically
- P2: --changed documented as heuristic in verify.md

- Add observe sink tests (sampling 0/1, sink failure non-interference)
- Add verify runs regression tests (scale, determinism, variants)
- Add configured-scenario qualify test (independent of OAuth fixture)
- Add coverageBreakdown to qualify artifacts (per-gate route coverage)
- Add production-style observe example with real sink in docs/observe.md
- Add nightly/staging vs PR gating guidance to docs/qualify.md

- Enrich VerifyFailure with formula-aware diagnostics:
  status:201 => 'HTTP 200', body field checks => actual values
- Remove stale observe CLI activation message
- Document outbound mocks as process-global in getting-started.md
- Refresh APOPHIS_ADOPTION_AUDIT.md with current state

903 tests pass, build clean, typecheck clean.
This commit is contained in:
John Dvorak
2026-05-21 20:39:36 -07:00
parent 55b0262799
commit d0523fcc2d
128 changed files with 4004 additions and 3631 deletions
+117 -5
View File
@@ -43,7 +43,7 @@ describe('packaging', () => {
it('--version exits 0 and prints version', () => {
const { stdout, status } = run(['--version']);
assert.strictEqual(status, 0, `Expected exit 0, got ${status}`);
assert.match(stdout, /2\.0\.0/, `Version should include 2.0.0, got: ${stdout}`);
assert.match(stdout, /2\.7\.0/, `Version should include 2.7.0, got: ${stdout}`);
});
it('init --help exits 0 and prints init help', () => {
@@ -103,7 +103,7 @@ describe('packaging', () => {
name: 'test-consumer',
version: '1.0.0',
dependencies: {
'apophis-fastify': `file:${ROOT}`,
'@apophis/fastify': `file:${ROOT}`,
},
};
writeFileSync(join(tmpDir, 'package.json'), JSON.stringify(pkg, null, 2));
@@ -134,6 +134,118 @@ describe('packaging', () => {
assert(files.includes('dist/cli/index.js'), 'Tarball must include dist/cli/index.js');
});
it('npm pack does not contain dist/test files', () => {
const result = spawnSync('npm', ['pack', '--dry-run', '--json'], {
cwd: ROOT, encoding: 'utf8', timeout: 30000,
});
assert.strictEqual(result.status, 0, `npm pack failed: ${result.stderr}`);
const packOutput = JSON.parse(result.stdout);
const files = packOutput[0]?.files?.map((f: { path: string }) => f.path) || [];
const testFiles = files.filter((f: string) => f.includes('dist/test/'));
assert.strictEqual(testFiles.length, 0, `Package must not contain dist/test/ files. Found: ${testFiles.join(', ')}`);
});
it('real consumer can import the package after install', () => {
const tmpDir = join(tmpdir(), `apophis-consumer-${Date.now()}`);
mkdirSync(tmpDir, { recursive: true });
try {
const pkg = {
name: 'test-consumer-import',
version: '1.0.0',
type: 'module',
dependencies: {
'@apophis/fastify': `file:${ROOT}`,
},
};
writeFileSync(join(tmpDir, 'package.json'), JSON.stringify(pkg));
const installResult = spawnSync('npm', ['install', '--silent', '--install-strategy=nested'], {
cwd: tmpDir, encoding: 'utf8', timeout: 120000,
});
assert.strictEqual(installResult.status, 0, `npm install failed: ${installResult.stderr}`);
const importRootResult = spawnSync('node', ['-e', "import('@apophis/fastify').then(m => console.log('OK:', Object.keys(m))).catch(e => { console.error('FAIL:', e.message); process.exit(1) })"], {
cwd: tmpDir, encoding: 'utf8', timeout: 30000,
});
assert.strictEqual(importRootResult.status, 0, `Import root failed: ${importRootResult.stderr}`);
assert.ok(importRootResult.stdout.includes('OK:'), `Import should print OK, got: ${importRootResult.stdout}`);
const importExtResult = spawnSync('node', ['-e', "import('@apophis/fastify/extensions').then(m => console.log('EXT OK:', Object.keys(m))).catch(e => { console.error('EXT FAIL:', e.message); process.exit(1) })"], {
cwd: tmpDir, encoding: 'utf8', timeout: 30000,
});
assert.strictEqual(importExtResult.status, 0, `Import extensions failed: ${importExtResult.stderr}`);
assert.ok(importExtResult.stdout.includes('EXT OK:'), `Extensions import should print OK, got: ${importExtResult.stdout}`);
const binResult = spawnSync('node', [join(tmpDir, 'node_modules/.bin/apophis'), '--version'], {
cwd: tmpDir, encoding: 'utf8', timeout: 30000,
});
assert.strictEqual(binResult.status, 0, `CLI bin failed: ${binResult.stderr}`);
assert.ok(binResult.stdout.includes('2.'), `CLI should print version starting with 2., got: ${binResult.stdout}`);
} finally {
rmSync(tmpDir, { recursive: true, force: true });
}
});
it('TypeScript consumer can import and typecheck', () => {
const tmpDir = join(tmpdir(), `apophis-ts-consumer-${Date.now()}`);
mkdirSync(tmpDir, { recursive: true });
try {
writeFileSync(join(tmpDir, 'package.json'), JSON.stringify({
name: 'ts-test',
version: '1.0.0',
type: 'module',
dependencies: {
'@apophis/fastify': `file:${ROOT}`,
'fastify': '^5.0.0',
'@fastify/swagger': '^9.0.0',
},
}));
const installResult = spawnSync('npm', ['install', '--silent', '--install-strategy=nested'], {
cwd: tmpDir, encoding: 'utf8', timeout: 120000,
});
assert.strictEqual(installResult.status, 0, `npm install failed: ${installResult.stderr}`);
writeFileSync(join(tmpDir, 'consumer.ts'), `
import Fastify from 'fastify'
import apophis, { createAuthExtension } from '@apophis/fastify'
import { jwtExtension } from '@apophis/fastify/extensions'
import { sseExtension } from '@apophis/fastify/extensions/sse'
import { websocketExtension } from '@apophis/fastify/extensions/websocket'
import { createSerializerExtension, createSerializerRegistry } from '@apophis/fastify/extensions/serializers'
import { createHeaderExtension } from '@apophis/fastify/extension/factories'
const app = Fastify()
app.register(apophis, {
extensions: [jwtExtension, sseExtension, websocketExtension],
})
`);
writeFileSync(join(tmpDir, 'tsconfig.json'), JSON.stringify({
compilerOptions: {
target: 'es2020',
module: 'nodenext',
moduleResolution: 'nodenext',
strict: true,
skipLibCheck: true,
},
include: ['consumer.ts'],
}));
const tsc = join(ROOT, 'node_modules/.bin/tsc');
const tscResult = spawnSync(tsc, ['--noEmit', '--project', tmpDir], {
cwd: tmpDir, encoding: 'utf8', timeout: 60000,
});
if (tscResult.status !== 0) {
console.error('TSC errors:', tscResult.stdout + tscResult.stderr);
}
assert.strictEqual(tscResult.status, 0, `TypeScript typecheck must pass cleanly. Got:\n${tscResult.stdout}${tscResult.stderr}`);
} finally {
rmSync(tmpDir, { recursive: true, force: true });
}
});
it('npx apophis --help works in a temp project after npm install', () => {
const tmpDir = join(tmpdir(), `apophis-npx-test-${Date.now()}`);
mkdirSync(tmpDir, { recursive: true });
@@ -142,7 +254,7 @@ describe('packaging', () => {
name: 'npx-test',
version: '1.0.0',
dependencies: {
'apophis-fastify': `file:${ROOT}`,
'@apophis/fastify': `file:${ROOT}`,
},
};
writeFileSync(join(tmpDir, 'package.json'), JSON.stringify(pkg, null, 2));
@@ -173,7 +285,7 @@ describe('packaging', () => {
name: 'npx-test',
version: '1.0.0',
dependencies: {
'apophis-fastify': `file:${ROOT}`,
'@apophis/fastify': `file:${ROOT}`,
},
};
writeFileSync(join(tmpDir, 'package.json'), JSON.stringify(pkg, null, 2));
@@ -199,7 +311,7 @@ describe('packaging', () => {
it('declares supported Node policy and default confidence test path', () => {
const rootPkg = JSON.parse(readFileSync(PACKAGE_JSON, 'utf8'));
assert.strictEqual(rootPkg.engines.node, '^20.0.0 || ^22.0.0');
assert.strictEqual(rootPkg.engines.node, '>=20.18.1 <21 || >=22 <23');
assert.strictEqual(rootPkg.scripts.test, 'npm run build && npm run test:src && npm run test:cli');
});
});