Commit 3700a92
authored
v0.18.11.0 feat: Track 2B (audit cutover) + Track 4C (skill prose corpus) — suite 113s→13s (#63)
* chore: gitignore node_modules
* feat(test): Track 4C — LLM-as-judge for skill prose (v0.18.10.0)
`tests/helpers/llm-judge.ts` exposes `callJudge<T>(prompt, validator)` —
an Anthropic SDK wrapper hardened against the failure modes the eng-review
surfaced: maxRetries:0 (no compounding retries), one explicit 1× 429 retry,
stop_reason check before regex extract, baked-in validator, strict
isJudgeScore predicate (rejects NaN/Infinity/decimals/0/6/null/wrong-types/
empty-reasoning), pinned Sonnet model + temperature:0 + max_tokens:1024.
`tests/llm-judge.test.ts` runs 13 mocked-Anthropic-client unit tests
covering every helper branch: happy path, stop_reason mismatch, no-JSON,
JSON.parse failure, validator rejection, 429 retry success, non-429
no-retry, plus 6 isJudgeScore cases.
`tests/skill-llm-eval.test.ts` is the paid evaluation, gated on
`process.env.EVALS === '1'` (exact match) plus a strict ANTHROPIC_API_KEY
check that throws if EVALS=1 without a key. Sequential test.each over
4 fixtures in `tests/fixtures/skill-prose-corpus/` (3 positive: roadmap-
reassessment, test-plan-extraction, pair-review-test-list; plus 1 shallow
negative-control). Each fixture is markdown with YAML frontmatter carrying
provenance (source skill commit, repo commit, input prompt, model, UTC
timestamp, worktree state). Positive fixtures must score ≥3 on every axis;
negative-control must score ≤2 on at least one axis (catches the failure
mode where the judge rewards plausible-sounding prose over substance).
60s per-test timeout. Cost ~\$0.05–0.15 per EVALS=1 run.
Touchfiles map gains `tests/skill-llm-eval.test.ts → tests/fixtures/
skill-prose-corpus/**` so fixture edits select only the eval test.
CLAUDE.md ## Testing documents the EVALS=1 contract. PROGRESS row +
CHANGELOG entry capture the locked decisions and codex catches.
@anthropic-ai/sdk added as devDependency; bun.lock committed.
Source: /plan-eng-review session in workspace valletta (kbitz/llm-judge-
skill-prose, 2026-05-03), 14 decisions resolved, 10 codex catches batch-
applied. Tool-use migration + judge-floor tightening 3→4 deferred to
ROADMAP Future. The 4-fixture corpus is initial-synthesized (each
fixture's provenance documents this); replace with real captures as the
skills produce them.
* feat: Track 2B — cut bin/roadmap-audit over to TS implementation
Track 2A (v0.18.6.0) shipped the TS port at src/audit/** as "dark code"
with full byte-parity verified by tests/audit-shadow.test.ts. The binary
at bin/roadmap-audit was never wired up, so the snapshot suite kept paying
the bash cost — and tests/audit-shadow.test.ts paid it a second time per
fixture for parity verification.
Cutover: bin/roadmap-audit becomes a 7-line POSIX-sh shim
exec bun "$(dirname "$0")/../src/audit/cli.ts" "$@"
tests/audit-shadow.test.ts deleted — parity check is obsolete when the
runner IS the oracle. The 3,868-line bash binary is preserved in git
history at e4f883b (PR #58, the original "dark code" commit).
Manual touchfile entries for tests/{audit-snapshots,audit-cli-contract}
.test.ts gain src/audit/** so audit code edits retrigger the snapshot
suite under diff selection (the static import graph doesn't connect them
because the tests spawn the binary rather than importing).
Measured impact on a 2-core MacBook:
tests/audit-snapshots.test.ts 111s → 7.3s (~15×)
full suite (bun run test:full) 113s → 32s (~3.5×)
test count: 828 → 805 (delta = the 23 deleted shadow parity tests)
Phase 1's stated end-state ("bin/roadmap-audit is a compiled bun binary")
is now met — shim form rather than `bun build --compile` artifact, but
equivalent semantics with simpler deploy (no per-platform binary, source
grep-able at src/audit/**, instant dev iteration without rebuilds).
ROADMAP.md gains "Track 2B: Cut bin/roadmap-audit over to TS implementation
✓ Complete" under Group 2.
* refactor: drop SDK eval path, replace with in-session routing rule
The Track 4C eng-review locked an SDK-driven judge path: tests/helpers/
llm-judge.ts (Anthropic SDK wrapper), tests/llm-judge.test.ts (mocked
units), tests/skill-llm-eval.test.ts (paid eval gated on EVALS=1 +
ANTHROPIC_API_KEY). The plan was implemented and reviewed during /ship,
then reconsidered:
- The eval test only runs on machines that already have `claude`
authenticated. It never runs in CI.
- Requiring a separate ANTHROPIC_API_KEY plus a separate Anthropic SDK
dependency adds setup friction with no ecological payoff — the user
is the only person running it, on a machine that's already paying for
Claude via Claude Code.
- The corpus + rubric retain their value as calibration material; the
test infrastructure around them does not.
Dropping:
- tests/helpers/llm-judge.ts (callJudge helper, 173 LOC)
- tests/llm-judge.test.ts (13 mocked unit tests, 135 LOC)
- tests/skill-llm-eval.test.ts (paid eval test, 165 LOC)
- @anthropic-ai/sdk devDependency
- bun.lock (no deps remaining)
- tests/skill-llm-eval.test.ts touchfiles entry
Keeping:
- tests/fixtures/skill-prose-corpus/ (4 reference fixtures, full
YAML-frontmatter provenance preserved)
- The three-axis rubric (clarity / completeness / actionability,
1–5 each, ≥3 on positives, ≤2 on at least one axis for the control)
Adding (CLAUDE.md ## Testing):
Routing rule — when skills/*.md is edited in a session, Claude
proactively recommends judging the changed prose against the corpus
and rubric in-session. No new code, no new dep, no new env var, no
separate billing — uses the existing Claude Code session with prompt
caching across fixtures.
Stale Future entries removed:
- "Migrate callJudge to tool-use forced JSON" (no callJudge to migrate)
- "Raise judge floor 3 → 4 after 5–10 EVALS runs" (no scheduled run
to retune)
ROADMAP Track 4C entry rewritten to reflect the actual shipped shape
and marked ✓ Complete. CHANGELOG and PROGRESS rows rewritten.
Suite runtime: 32s → 13.6s (the SDK was apparently loading 18s of
transitive deps just to skip the test).
Total impact across the PR (Track 2B + Track 4C combined): full bun
test:full was 113s before the cutover, now 13.6s on the same hardware
with one less dep.1 parent ae63c46 commit 3700a92
14 files changed
Lines changed: 486 additions & 4016 deletions
File tree
- bin
- docs
- tests
- fixtures/skill-prose-corpus
- helpers
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
5 | 73 | | |
6 | 74 | | |
7 | 75 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
| 40 | + | |
39 | 41 | | |
40 | 42 | | |
41 | 43 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
0 commit comments