Skip to content

Skill eval harness + eval-validated Common Tasks section (issue #207)#251

Open
schpetbot wants to merge 2 commits into
mainfrom
skill-eval-207
Open

Skill eval harness + eval-validated Common Tasks section (issue #207)#251
schpetbot wants to merge 2 commits into
mainfrom
skill-eval-207

Conversation

@schpetbot

Copy link
Copy Markdown
Collaborator

Related to #207.

Builds an eval that empirically measures the issue's claim — that an agent reading the skill skips dedicated CLI subcommands and reaches for raw GraphQL via linear api — then uses it to baseline the current skill and validate a "Common Tasks" recipes section.

Headline result

Metric (36 trials/condition, codex gpt-5.6-sol, low effort) Baseline Post-change
Supported tasks: full success (route + all required flags) 30/30 29/30
Holdout prompts only 15/15 15/15
Controls (GraphQL genuinely required): chose linear api 6/6 6/6

The premise of #207 did not reproduce in this setup. With the skill actually read (verified per-trial via the codex event stream), routing was already perfect before any change. Per the outcome rules declared before the baseline ran (evals/linear-cli-skill/README.md), that is reported as the finding rather than manufacturing harder prompts after the fact. The Common Tasks section is therefore shipped as validated non-regressing — in particular, the new recipes did not overcorrect the controls away from legitimate linear api use — not as a measured improvement.

The one post-change failure was a subject first trying the skill's documented npx alternative (npx --yes @schpet/linear-cli issue create …); the frozen grader counts any npx use as a bypass. It was not a GraphQL fallback, and the trial then completed correctly via linear issue create. There were zero linear api fallbacks on supported tasks in either final condition.

What's in the PR

Commit 1 — eval harness + baseline (evals/linear-cli-skill/)

  • run.ts spawns codex exec per trial in full isolation: fresh CODEX_HOME (copied auth + skill under test only) and a fake HOME — codex also discovers skills in ~/.agents/skills, a real leak we verified — plus recording shims for linear/curl/npx/npm on an explicit PATH, under codex's workspace-write sandbox (network denied to subject commands).
  • The linear shim logs every invocation (+ GraphQL heredoc stdin), passes --help/--version/schema through to the real CLI in-repo, and returns consistency-aware canned successes.
  • cases.ts: 5 recipe families × (development + holdout prompt) + 2 controls where linear api is the right answer (issue history, subscribers). Frozen before baseline.
  • grade.ts: deterministic classifier (no LLM judging) + one-sided Fisher exact; 15 unit tests in test/evals/.
  • Committed results are sanitized (no secrets, no absolute paths); deno task skill-eval to run (costs real tokens; never in CI).

Commit 2 — the skill change + post-change results

  • ## Common Tasks near the top of SKILL.template.md (regenerated into SKILL.md): filtered queries via issue query with the issue listissue mine alias gotcha spelled out, create with --description-file/--no-interactive, update state/assignee/labels (label replacement semantics noted), comment from file, view/URL.
  • results/comparison.md with the full per-case tables.

Methodology notes (honesty section)

  • Two earlier baseline runs were voided during harness development: stateless canned outputs contradicted the subject's own actions (issue view not reflecting a just-made update; ENG-* identifiers returned for OPS-team requests), which baited subjects into GraphQL "investigation" and contaminated the route signal. The shim now reflects same-trial updates and honors query filters. Both voided runs failed in the conservative direction (they understated the baseline).
  • Prompts include "Use the installed linear-cli skill", so the eval measures the effect of the skill's content, not skill auto-triggering. Skill: add a minimal "Common tasks" section to SKILL.md #207's experience may live in configurations this doesn't cover: agents that never read the skill, other models/effort levels, or tasks further from the command vocabulary. The harness makes those follow-up experiments cheap.
  • Cases, grader, and thresholds were frozen before the baseline; nothing was tuned after seeing results.

Reproduce:

deno task skill-eval --condition baseline --skill-dir skills/linear-cli --model gpt-5.6-sol
deno run --allow-read --allow-write evals/linear-cli-skill/grade.ts --compare \
  evals/linear-cli-skill/results/baseline.jsonl evals/linear-cli-skill/results/post-change.jsonl

schpet added 2 commits July 18, 2026 16:02
Issue #207 claims agents reading the skill skip dedicated CLI subcommands
and reach for raw GraphQL via `linear api`. Before changing the skill text,
this adds an eval that can actually measure that: codex exec runs each task
prompt in a fully isolated environment (fresh CODEX_HOME + fake HOME so the
globally installed skill can't leak in, recording shims for linear/curl/
npx/npm, workspace-write sandbox) and a deterministic grader classifies
route choice and flag correctness from the recorded invocations.

Cases: five recipe families with development + holdout prompts, plus two
controls where GraphQL is genuinely the right route. Outcome rules were
declared before the baseline ran (see evals/linear-cli-skill/README.md).

Baseline result, 36 trials at low effort on gpt-5.6-sol: 30/30 supported
tasks full success, 6/6 controls on linear api. The premise of #207 did not
reproduce in this configuration — with the skill actually read, routing is
already perfect. Two earlier baseline runs were voided during harness
development because stateless canned outputs (issue view contradicting the
subject's own update; ENG-prefixed identifiers for OPS-team requests)
baited subjects into GraphQL investigation and contaminated the signal;
the shim is now consistency-aware.

Related to #207
…ated

Adds ~7 copy-pasteable recipes near the top of SKILL.template.md (and the
generated SKILL.md): filtered queries via issue query (with the issue
list/mine alias gotcha spelled out), my-issues, create with
--description-file and --no-interactive, update state/assignee/labels
(noting label replacement semantics), comment from file, view/URL. The
boundary note stays generic so it doesn't teach the eval's control answers.

Post-change eval, same frozen 36-trial protocol as the baseline: 29/30
supported tasks full success, holdout 15/15, controls 6/6 still correctly
choosing linear api — no overcorrection from the new recipes. The single
failure was a subject first trying the skill's documented npx alternative
(npx @schpet/linear-cli issue create ...), which the frozen grader counts
as a bypass; it was not a GraphQL fallback and the task then completed
correctly via the CLI. With the baseline already at 30/30, the eval finds
no measurable routing headroom at this configuration; the change is
validated as non-regressing rather than as an improvement. See
evals/linear-cli-skill/results/comparison.md.

Related to #207
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants