mirror of
https://github.com/redwoodjs/local-ci.git
synced 2026-09-19 07:54:29 +08:00
23fca333a2
Update the agent-facing skill surfaces to match the recent pause-on-failure fixes and `--json` event stream: - skills/agent-ci/SKILL.md (published) and packages/cli/SKILL.md: document `--json` / `AGENT_CI_JSON=1`, list the NDJSON event types, and note that pipes/redirects are safe — pause-on-failure exits 77 in non-TTY mode. - .claude/commands/agent-ci-dev.md and .pi/skills/agent-ci-dev/SKILL.md: switch the monitor pattern from grepping plaintext "Step failed" to matching `"event":"(run.paused|run.finish)"`, and call out exit-77 as a pause signal alongside the `run.paused` event. - experiments/skill-evals/variants/v2-run-first.md and v3-no-mangling.md: remove stale "no pipes / no redirects" warnings — those scenarios are now the supported path via the detached launcher. Refs #289, #315. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Skill evals
Measure whether skills/agent-ci/SKILL.md (and variants) cause agents to do the right thing in realistic CI-failure scenarios.
What it is
A matrix: variants × fixtures → scorecard.
- Variants = candidate wordings of the skill text (
variants/*.md). - Fixtures = synthetic mini-repos in a known-failing state (
fixtures/<name>/repo/), plus a rubric (expect.yaml). - Runner = headless
claude -pwith the variant injected asCLAUDE.md. - Scorer = regex checks over the captured transcript, per rubric item in
expect.yaml. - Output =
scorecard.json+ a markdown table you can commit.
v1 scope
- Agents: Claude Code only (
runners/claude-code.mjs). - Ground-truth CI check: the fixture ships a mocked
agent-ci(fake-agent-ci/) that counts violations in source files and emits canned eslint-style output — no Docker, runs in seconds. The agent's edits change the stub's output on the next invocation, closing the fix/retry loop. Swap in a real@redwoodjs/agent-cidependency later if fidelity matters. - Scoring: regex-only. Add an LLM-judge pass later for semantic checks like "did it root-cause vs. suppress."
Run
pnpm install # or: pnpm install --ignore-workspace at the monorepo root
pnpm eval # default N=3 trials per cell
pnpm eval --n 5 # more trials = tighter confidence
pnpm eval --variant v2-run-first # limit variants
pnpm eval --fixture missing-changeset # limit fixtures
Rescore without re-running
Every live trial saves _meta.json, _streams.json, and _events.jsonl into its tmp workdir. When you change a rubric pattern, replay the stored transcripts against the current rubric without spending another Claude call:
pnpm rescore # rescore every saved trial, emit scorecard-replay.md
pnpm rescore --fixture lint-curly-x18 # filter
pnpm rescore --last-n 5 # only the 5 most recent trials per (variant, fixture) cell
Use this when iterating on rubric regexes — both of the false-positive bugs in the first version of no_tail_pipe were caught this way, for free.
Layout
experiments/skill-evals/
├── run.mjs # entry: matrix loop + scorecard emit
├── runners/
│ └── claude-code.mjs # wraps `claude -p … --output-format stream-json`
├── scorers/
│ └── grep.mjs # rubric evaluator (pattern match over transcript)
├── variants/
│ └── v1-current.md # baseline: current SKILL.md text
└── fixtures/
└── lint-curly-x18/
├── task.md # prompt handed to the agent
├── expect.yaml # rubric for this fixture
└── repo/ # scratch repo (copied per eval run)
├── package.json
├── .eslintrc.json
├── src/index.js # 18 curly violations
└── fake-agent-ci/ # mock CLI
└── bin/agent-ci.mjs
Adding a fixture
Each fixture is a past mistake made into a regression test. If a real agent run ever does something wrong, build a fixture that reproduces the trap.
mkdir fixtures/<name>/repo— minimal files to reproduce the failure.- Write
task.md— the exact prompt the agent gets. Keep it generic ("make CI pass"). - Write
expect.yaml— list rubric items (kind: grep,stream: tool_calls|file_edits,must: present|absent). pnpm eval— confirm the baseline variant fails or passes as expected.