Skip to content

Commit fec8453

Browse files
committed
Add post-run validation gate for batch discovery output
Overnight batch runs have shipped bad data straight to the live site: undefined slugs, duplicate entries across domain aliases, mismatched duplicate surfaces, and missing required fields. Add scripts/batch/validate-results.ts to catch these structurally after a run — checked against results-full and the merged catalog export — and wire it into drive.sh as a final gate plus a standalone `bun run validate:batch` script.
1 parent b90c852 commit fec8453

5 files changed

Lines changed: 406 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,27 @@ another port.
99

1010
Check `.claude/launch.json` for available server names before starting
1111
anything — never guess names.
12+
13+
# Batch / catalog generation
14+
15+
After any batch or catalog generation run (`scripts/batch/run-loop.ts`,
16+
`scripts/batch/drive.sh`, `scripts/batch/export-catalog.ts`, or a manual edit
17+
to `scripts/batch/results-full/`, `scripts/batch/results/`, or
18+
`sources/discovered.json`), `bun run validate:batch` must pass before the
19+
results are treated as done or deployed (loaded into KV via
20+
`scripts/batch/load-kv.ts`, or exported into `sources/discovered.json` and
21+
built).
22+
23+
`bun run validate:batch` runs `scripts/batch/validate-results.ts`, which
24+
checks for the failure modes that have shipped to the live site before:
25+
slugs/domains that render as literal `/domain/undefined/`, duplicate
26+
(domain, surface-type, name) entries — within one domain's result, across
27+
domain aliases, and across the static/discovered merge in
28+
`sources/discovered.json` — and surfaces missing the fields their detail page
29+
(`src/pages/[domain]/[surface].astro`) renders unconditionally (name, auth
30+
status, and a locator: url/spec for http+graphql, url for mcp, command or
31+
packages for cli).
32+
33+
`drive.sh` already runs this as its final gate and exits nonzero if it fails.
34+
If you run `run-loop.ts` directly instead of through `drive.sh`, run
35+
`bun run validate:batch` yourself afterward.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"normalize": "bun scripts/normalize.ts",
99
"extract-tools": "bun scripts/extract-tools.ts",
1010
"validate-favicons": "bun scripts/validate-favicons.ts",
11+
"validate:batch": "bun scripts/batch/validate-results.ts",
1112
"dev": "bun run normalize && astro dev",
1213
"build": "ASTRO_TELEMETRY_DISABLED=1 bun run normalize && ASTRO_TELEMETRY_DISABLED=1 astro build",
1314
"preview": "astro preview",

scripts/batch/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,22 @@ Check the output:
4848
bun scripts/batch/check-results.ts --dir scripts/batch/results/
4949
```
5050

51+
`check-results.ts` scores each domain's discovery quality (grounding, checklist).
52+
Before treating a run as done or loading it into KV, also run the structural
53+
gate — it catches problems `check-results.ts` doesn't look for: undefined/empty
54+
slugs that would render as `/domain/undefined/`, duplicate (domain, type, name)
55+
entries (within a result, across domain aliases, and across the
56+
static+discovered merge in `sources/discovered.json`), and surfaces missing
57+
fields the detail page renders unconditionally:
58+
59+
```sh
60+
bun run validate:batch
61+
# or directly:
62+
bun scripts/batch/validate-results.ts --results-dir scripts/batch/results-full
63+
```
64+
65+
`drive.sh` runs this automatically as its final step and exits nonzero if it fails.
66+
5167
If a matching corpus file exists, URL grounding uses the corpus. If not, live-loop output is checked against the result evidence URLs, same registrable domain, and detected machine signals.
5268

5369
Load KV:

scripts/batch/drive.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,17 @@ PY
7171
grep -vE '^dedup:' | tail -3
7272
done
7373
echo "=== all batches complete $(date '+%H:%M') ==="
74+
75+
# Final gate: the checklist above scores individual result quality, but it
76+
# can't see cross-file problems (duplicate/aliased domains, slugs that will
77+
# render as literal "undefined", static+discovered merge collisions). Run the
78+
# structural validator over the full results dir before this run is treated
79+
# as done — a failure here means the data is not safe to load into KV.
80+
echo "=== validating results $(date '+%H:%M') ==="
81+
bun scripts/batch/validate-results.ts --results-dir "$OUT" --no-catalog
82+
VALIDATE_STATUS=$?
83+
if [ "$VALIDATE_STATUS" -ne 0 ]; then
84+
echo "GATE: validate-results failed — fix the offenders above before loading $OUT into KV"
85+
exit 4
86+
fi
87+
echo "=== validation passed $(date '+%H:%M') ==="

0 commit comments

Comments
 (0)