Skip to content

feat: add the skill eval runner - #78

Open
AntTheLimey wants to merge 11 commits into
mainfrom
feat/skill-evals
Open

AntTheLimey wants to merge 11 commits into
mainfrom
feat/skill-evals

Conversation

@AntTheLimey

Copy link
Copy Markdown
Member

What changed

Adds evals/, a local runner that measures whether the skills in plugins/pgedge make an agent better at real pgEdge Starfleet Managed tasks. Each task runs in three setups (skills + CLI, CLI only, raw API) on three agent harnesses, and every answer is graded against the live API.

  • Harnesses: Claude Code (Sonnet), Cursor's cursor-agent (Grok 4.7 Medium only), and the Codex CLI (GPT-6.1-Sol and GPT-6-Luna, ChatGPT login only). Any other model is refused.
  • Each run is sandboxed to one tenant with its own HOME, workspace and network allowlist. Negative and positive controls run before any task, and tasks do not start unless every control passes.
  • One process per harness and model lane. A lane stops on SIGINT, keeps its finished runs and deletes its fixtures; --resume, --redo and --redo-arm rerun only what is missing, and --combine merges lanes.
  • --plugin-ref tests the skills from another ref, such as an open skills PR. --release scores the commit a release would tag and writes a scrubbed summary.
  • Ten task prompts in evals/tasks/; tasks 6 to 10 are the release suite.
  • make test-evals runs the offline unit tests, and a new CI job runs it. Nothing in CI starts an agent.

How it was measured

On 2026-10-23: 225 graded runs (5 lanes × 5 tasks × 3 setups × 3 runs), then the skills arm again with the skills from #75. Every fixture database the runner created was deleted. Killing one lane mid-run left the others running, and resuming it ran only its missing runs. One lane in that run, Cursor's Composer 2.5, has since been dropped.

Gates

  • make test: 41 packages ok, coverage 90.6% (gate 90.0%)
  • make lint: 0 issues
  • make lint-docs: 0 errors in 678 files
  • make test-evals: 36 tests ok

For the reviewer

  • The runner needs macOS, signed-in Claude Code, cursor-agent and the ChatGPT app's Codex, and a tenant where creating and deleting databases is safe. See evals/README.md.
  • The scorecard implements the current KR3 (correct at least 90%, zero safety failures, at least 25% fewer tokens per correct answer than the CLI alone). It reports and never gates. A revision that compares against raw API is planned separately.
  • Cursor always allows fetches of cursor.com, whatever its deny rules say; this is listed under Known limits.
  • When Codex refreshes its login during a run, the refreshed login is written back to ~/.codex/auth.json. The runner refuses to start with under three days left on the token.
  • No Go code changes.
  • Reviewed independently before opening; the findings were fixed in the last commit.

Measures whether the agent skills in plugins/pgedge change outcomes
on real pgEdge Starfleet Managed tasks: the same tasks run with the
skills, without them and against the raw API, are graded against
live API data, and produce a scorecard per harness and model
(correct, safe, cheaper, lift).

Runs locally on macOS from a config naming the tester's pgedge
config and profile, harnesses, models, tasks, arms and runs. A
release mode scores the commit a tag would point to and writes a
summary for committing that names no tenant, host or other database.
It reports; it never decides a release.

make test-evals covers grading, scoring and publishing offline.
A failed run's tokens now count against its side, so a cheap wrong
answer no longer makes the CLI without skills look cheaper. CI runs
make test-evals, which needs no agents and no tokens.
codex exec runs under a generated permissions profile with a private
CODEX_HOME per run. The tester's HOME and the login copy are
unreadable, writes are limited to the run's own paths, and network
goes through Codex's proxy and the arm's allowlist. Negative controls
run through codex sandbox, because the model refuses to try a denied
path. Only a ChatGPT login is accepted, Codex runs go one at a time,
and the runner refuses to start with under three days left on the
access token.

Cursor is limited to grok-4.7-medium and composer-2.5, and Claude
defaults to Sonnet.
Codex accepts only gpt-6.1-sol and gpt-6-luna. The self-report prompt
asks for names only, since a sentence on the MCP line failed the
cross-arm check.
A lane can be stopped with SIGINT and resumed alone with --resume; the
others carry on, and --combine merges the lanes' results. Codex runs
take a file lock, so they stay one at a time across processes, and
shared files are written by rename. Cursor's token is unset in the
agent's shell, which a new control checks.
A stopped Codex lane no longer waits on another lane's lock, --budget
is split across lanes, a lane that writes no results still counts as
planned, --combine refuses a repeated run, and --resume refuses rows
from other skills or another binary.
The lock guarded only against two runs refreshing the login at once,
which the three-day expiry guard already makes unlikely, at the cost
of running every Codex lane one run at a time.
The grader failed a run that searched the llms reference for the
rotate-password section as if it had rotated a password.
--plugin-ref loads the skills and plugin manifests from a ref, such as
an open skills PR, and --redo-arm reruns one arm on resume. The skills
check on resume covers only kept rows that loaded skills.
With the skills it deleted unasked in every chance it had, so it is
not a lane we test or recommend.
Resume compares the binary's source, not its bytes, which change with
every build. A lane that reuses the binary still writes its config and
shim, and --lane refuses --release. Rotation is judged per command
segment, so reading the reference is not a rotation and chaining a
read before one does not hide it. --plugin-ref prefers origin's branch,
and lanes get the sha the launcher resolved.
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.

1 participant