Skip to content

Commit e6f126c

Browse files
authored
fix(ci): guard eval schema generation (#1725)
1 parent d89518e commit e6f126c

6 files changed

Lines changed: 70 additions & 3 deletions

File tree

.agents/verification.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ This file expands [AGENTS.md](../AGENTS.md) for testing, manual UAT, CLI and bro
1212
smallest command that exercises the changed code, such as a package-specific
1313
test, a single test file, `bun run typecheck` for type-facing changes, or
1414
`bun run validate:examples` for eval example changes.
15+
- When changing `packages/core/src/evaluation/validation/eval-file.schema.ts`,
16+
run `bun run validate:eval-schema` from the repo root. The command regenerates
17+
`skills-data/agentv-eval-writer/references/eval.schema.json` from the Zod
18+
source and fails with a schema diff if the generated artifact needs to be
19+
committed. Do not edit the generated JSON schema by hand.
1520

1621
- Do not default to full local workspace validation before every PR. Push/open
1722
the PR so GitHub Actions runs the broad build, typecheck, lint, test,

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ jobs:
166166
- name: Install dependencies
167167
run: bun install --frozen-lockfile
168168

169+
- name: Check generated eval schema sync
170+
run: bun run validate:eval-schema
171+
169172
- name: Run tests
170173
run: bun run test
171174

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
"agentv:buildrun": "bun run build && bun apps/cli/dist/cli.js",
2121
"beads:check": "bun scripts/check-beads-context.ts",
2222
"debug:pi-sdk-tools": "bun scripts/debug-pi-sdk-tools.ts",
23+
"generate:eval-schema": "bun packages/core/scripts/generate-eval-schema.ts",
24+
"validate:eval-schema": "bun scripts/check-eval-schema.ts",
2325
"validate:promptfoo-export": "bun test scripts/export-promptfoo-config.test.ts",
2426
"validate:examples": "EVAL_CRITERIA=placeholder CUSTOM_SYSTEM_PROMPT=placeholder bun scripts/validate-example-evals.ts",
2527
"eval:baseline-check": "bun scripts/check-eval-baselines.ts",

packages/core/scripts/generate-eval-schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import { spawn } from 'node:child_process';
33
/**
44
* Generates AgentV JSON schemas from Zod schemas.
5+
* Run: bun run generate:eval-schema (from repo root)
56
* Run: bun run generate:schema (from packages/core)
6-
* Or: bun packages/core/scripts/generate-eval-schema.ts (from repo root)
77
*/
88
import { writeFile } from 'node:fs/promises';
99
import path from 'node:path';

packages/core/src/evaluation/validation/eval-file.schema.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
* Used to generate eval.schema.json for AI agent reference.
44
*
55
* IMPORTANT: This schema describes the YAML input format, not the parsed runtime types.
6-
* When adding new eval features, update this schema AND run `bun run generate:schema`
7-
* to regenerate eval.schema.json. The sync test will fail if they diverge.
6+
* When adding new eval features, update this schema AND run
7+
* `bun run validate:eval-schema` from the repo root. That command regenerates
8+
* eval.schema.json and fails if the generated artifact needs to be committed.
89
*/
910
import { z } from 'zod/v3';
1011

scripts/check-eval-schema.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env bun
2+
import { readFile } from 'node:fs/promises';
3+
import path from 'node:path';
4+
5+
const repoRoot = path.resolve(import.meta.dirname, '..');
6+
const schemaPath = 'skills-data/agentv-eval-writer/references/eval.schema.json';
7+
const schemaAbsolutePath = path.join(repoRoot, schemaPath);
8+
9+
async function runOrExit(args: string[], options: { readonly cwd: string }): Promise<void> {
10+
const proc = Bun.spawn(args, {
11+
cwd: options.cwd,
12+
stdout: 'inherit',
13+
stderr: 'inherit',
14+
});
15+
const exitCode = await proc.exited;
16+
if (exitCode !== 0) {
17+
process.exit(exitCode);
18+
}
19+
}
20+
21+
async function printSchemaDiff(): Promise<void> {
22+
await runOrExit(['git', 'diff', '--', schemaPath], { cwd: repoRoot });
23+
}
24+
25+
async function readSchema(): Promise<string | null> {
26+
try {
27+
return await readFile(schemaAbsolutePath, 'utf8');
28+
} catch (error) {
29+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
30+
return null;
31+
}
32+
throw error;
33+
}
34+
}
35+
36+
const before = await readSchema();
37+
await runOrExit([process.execPath, 'packages/core/scripts/generate-eval-schema.ts'], {
38+
cwd: repoRoot,
39+
});
40+
const after = await readSchema();
41+
42+
if (before === after) {
43+
console.log(`OK: ${schemaPath} is generated from the Zod source`);
44+
process.exit(0);
45+
}
46+
47+
const message =
48+
'Generated eval schema is out of sync. This command regenerated eval.schema.json from packages/core/src/evaluation/validation/eval-file.schema.ts; review and commit the generated diff instead of editing the JSON manually.';
49+
if (process.env.GITHUB_ACTIONS === 'true') {
50+
console.error(`::error file=${schemaPath}::${message}`);
51+
}
52+
console.error(`[schema] ERROR: ${message}`);
53+
console.error(' Run locally: bun run validate:eval-schema');
54+
console.error(` Generated file: ${schemaPath}`);
55+
await printSchemaDiff();
56+
process.exit(1);

0 commit comments

Comments
 (0)