You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The main usage of eval-magic so far has been in our companion project, slow-powers, where we're attempting to create useful, publishable data about the value of the skills the plugin ships. This has proven to be very difficult, with a recent run using the lowest tier of model power (codex luna) on an eval case based on a bug encountered in a real-world scenario, ceiling on all cases. I believe this is because we simply cannot effectively simulate the complexity of a real task, done in a real codebase. This update seeks to avoid that weakness by simply providing an actual, real code environment, and supporting prompts that involve an agent executing real tasks against the codebase.
Proposal
We already create isolated environments for eval runs. Instead of populating them with small fixtures, they should be initialized with a full codebase, one custom-designed for the eval run, or a project of a reasonable type and complexity. Instead of doing what slow-powers is currently trying, and giving agents fragmentary "transcripts" of ongoing sessions, with the expectation of essentially testing a single turn, we should expect an eval run to start with a realistic prompt, potentially have a dynamic number of turns, and end with the task fully done.
There are a number of benefits to this approach, beyond just the fact the we're now running a real task.
Robust judging
While some mechanical judging is useful (and cheap), it often fails to capture the essence of what we're really trying to test, with the kind of behavior that's most interesting to test often being the hardest to judge. I'll walk through an explanatory example. A hypothetical skill like create-pr might contain instructions along the lines of: check if there's a PR template to follow, use a default if not, always wait for user approval, etc. Most of these would be easy to write eval cases for, and we could reasonably expect those cases to succeed - an agent without the skill has no reason to wait for final user approval, might not know to check for templates, and so on. This is also the least interesting behavior to test, often bordering on completely deterministic and trustworthy on sight.
Such a skill might also contain an instruction like: write a clear, concise PR description. This is much more interesting to test, and still easy to test reliably - a simulated "create a PR" state that matches the kind of case an agent might encounter in the wild is possible, even without a full codebase and a real PR to create. Running that case a number of times and comparing the with and without skill results should be expected to determine if anything in the "clear and concise description" instructions hold their weight, or if the agent would write the same kind of description without any instruction.
A skill like slow-powers:working-with-tdd also contains instructions that are relatively deterministic and trustable: write the test first, it must fail, and so on. (Pressure scenarios - did the agent follow its clear instructions under difficult or unexpected circumstances - are a different type of eval, not relevant to this discussion). The interesting thing to test, however, is actually: is the code itself better when following TDD, than without (better test coverage, code organization, test clarity, etc)? Under a limited, simulated environment, such a test can't be verified. Even haiku is a powerful coding model, and it's not going to have any trouble working through a toy problem, and producing reasonable code.
A realistic environment gives us the circumstances and output artifacts (that is, the code changes) that a judge needs to answer important performance questions that can't reasonably be simulated.
Multiple judges
With a question like "is the code better?", we'd likely see more value by running the test once, and judging it multiple times. The more "opinionated" a question is, the more useful this reverse grading seems. If 6/10 judges grade no-skill work as "good", and 10/10 judges grade with-skill work as "good", we'd count that as marked improvement (see Reference 1, "pass^k" grading). This should be much cheaper, since judging is far simpler than executing the task, and we have a clear pattern for how to judge success for this type of question.
Interactive judging
This also allows the agent driving eval-magic itself to do heuristic judging, without actual eval cases known ahead of time. For instance, if we have a test case like "implement this feature...", the user can ask the agent to have eval-magic run both the no-skill and with-skill sides of the test, then ask vague questions like "did the skill make the code better?" or "did the skill confuse the agent at any point?". This won't be statistically reliable information, but it can lead to the discovery of worthwhile test cases to run real evals for, and give the user an early sense of how the skill is working.
This generally seems like an interesting way to begin drafting actual eval cases, with two comparable session transcripts, given the exact same starting prompt, providing straightforward insight into the function of the skill under test.
Multiple skills tested at once
This is specifically helpful to slow-powers, but should also be generally useful. With a real test case, we could see the full suite of slow-powers skills working together, with the final code being a useful product by which to judge the plugin as a whole. This feels especially useful combined with interactive judging to come up with eval cases for the most useful aspects of the suite.
This is also likely to be a way to catch places where skills conflict or cause confusion, something that is again unlikely to come up in a toy test case.
Issues and considerations
I can see a few things that need deeper investigation, or seem likely to be a source of issues.
Legacy maintenance
My feeling is this will present a number of breaking changes, and that there's no reason to support legacy modes of evals. If we can architecturally handle all our evals in essentially the same way, we should aim for that goal. The simplicity will be a big benefit in the long run.
Sourcing codebases
I think this should be a simple part of the eval configuration, with the option to use a local directory or an online git repo. This is an opportunity to provide some nice UX. We should provide a default fixture for a simple codebase (maybe just by creating it on github), and suggest using the eval-magic codebase itself as a complex fixture. Instructions for what fixtures should be used should be part of the committed eval files in some way, and recorded as part of any run report.
Guard updates
We may need to consider the details of the what should be guarded, and what should be allowed, during this kind of eval run. I'm not sure the scope of this change, but opportunities to simplify the guard are always good.
Multiple runs
While the "one run, many judges" approach is nice, we still need to support statistically significant eval runs, which will likely require running the actual task multiple times. We don't want to check out a dozen copies of a codebase to run the eval though. We might be able to make use of git for this, but we should keep in mind that git actions can be an expected part of an eval itself.
Multiple turns
As stated, we want to support an unknown, dynamic number of turns. I think there's a convenient happy path for most responses an agent-under-test might expect to receive - Did the agent ask a multiple choice question, with a recommended option? Always choose the recommendation. For more complex questions, we may need some kind of "question answering agent", designed to quickly generate a comprehensible response, always tending towards "choose whatever is recommended/simplest/easiest".
Notes
Although I'm generally referring to mode A style runs, as that's what's being tested in slow-powers, most of this should equally apply to mode B runs.
This obviously presents a large change overall. The first goal should be splitting this into smaller tasks, and answering as many open questions as we can.
Feasibility was assessed against the current tree and the work split into 15 sub-tickets. Verdict: feasible, no blocking unknowns. Most of what this issue needs already exists in some
form — private per-(eval, condition, run) environments, a runner-owned Git repo per env, a working
multi-turn driver with native session resume, deterministic + LLM grading, guard and stray-write
accounting, cross-campaign aggregation. The work is reshaping those, not building new subsystems.
The workspace defaults to cwd/.eval-magic, so eval artifacts land inside the user's skills repo, and the live skill source is reachable from the env by a short relative path.
The write guard is already fully decoupled from the workspace's location.marker_allowed_roots
(src/sandbox/install.rs:75) returns exactly one allowed root — the isolated env — and the rationale
is already documented there: "Scoping to the env — not the parent .eval-magic/ or the host temp
directory — keeps the guard boundary identical to the isolation boundary." Nothing about write
containment depends on the workspace sitting next to a skill, so no ticket should be justified as
"simplifying the guard by relocating the workspace". Guard friction during a run is a separate
problem with a separate cause — BASH_MUTATION_PATTERNS firing on ordinary dev commands — and that
is #259.
Decisions
The runner drives every dispatch.dispatch-task becomes the universal execution path; a new eval-magic dispatch runs a whole iteration with concurrency, timeouts, and resume. (Runner-driven dispatch for every task #256)
Task envs are real Git repos with history, remotes stripped, hooks disabled, marked with an eval-magic/baseline ref. A local-directory source that is not already a repo still gets git inited, so every run is guaranteed a repo without requiring one up front. (Source a real codebase into each task environment #252)
A sourced codebase keeps its own CLAUDE.md/AGENTS.md and config — that realism is the
point. Skills it makes discoverable get a distinct codebase-sourced finding class, plus an
opt-in codebase.exclude_skill_sources that moves them aside symmetrically for the
self-referential case (evaluating slow-powers against the slow-powers repo). (Harness config shipped by a sourced codebase #260)
files/files_root survive as a documented overlay on the codebase — seeding a task-specific
file into a real repo is a live use, not legacy baggage. Only isolation is removed, and it is
already a documented no-op. (Retire the fixture-only eval model #266)
Skills become a sourced, copied input and the eval home moves out of the user's repo. The
justification is input symmetry and provenance, not guard simplification — on raw code
complexity this is close to a wash. Today a report can pin the codebase SHA while the skill side
is "whatever was on disk at the time", which is not a reproducible published claim. (Source skills as copied inputs and relocate the eval home #253)
Cross-cutting requirements
Applied to every sub-ticket rather than tracked separately:
Mode B parity. Acceptance holds for both Mode::NewSkill and Mode::Revision, and the
snapshot/promote path keeps working against codebase-backed iterations.
Provenance reaches the report. Codebase and skill source + resolved SHA land in conditions.json, each run.json, benchmark.json, and the BASELINE.md built by promote.rs:231 — not just in the workspace.
The main usage of eval-magic so far has been in our companion project, slow-powers, where we're attempting to create useful, publishable data about the value of the skills the plugin ships. This has proven to be very difficult, with a recent run using the lowest tier of model power (codex luna) on an eval case based on a bug encountered in a real-world scenario, ceiling on all cases. I believe this is because we simply cannot effectively simulate the complexity of a real task, done in a real codebase. This update seeks to avoid that weakness by simply providing an actual, real code environment, and supporting prompts that involve an agent executing real tasks against the codebase.
Proposal
We already create isolated environments for eval runs. Instead of populating them with small fixtures, they should be initialized with a full codebase, one custom-designed for the eval run, or a project of a reasonable type and complexity. Instead of doing what slow-powers is currently trying, and giving agents fragmentary "transcripts" of ongoing sessions, with the expectation of essentially testing a single turn, we should expect an eval run to start with a realistic prompt, potentially have a dynamic number of turns, and end with the task fully done.
There are a number of benefits to this approach, beyond just the fact the we're now running a real task.
Robust judging
While some mechanical judging is useful (and cheap), it often fails to capture the essence of what we're really trying to test, with the kind of behavior that's most interesting to test often being the hardest to judge. I'll walk through an explanatory example. A hypothetical skill like
create-prmight contain instructions along the lines of: check if there's a PR template to follow, use a default if not, always wait for user approval, etc. Most of these would be easy to write eval cases for, and we could reasonably expect those cases to succeed - an agent without the skill has no reason to wait for final user approval, might not know to check for templates, and so on. This is also the least interesting behavior to test, often bordering on completely deterministic and trustworthy on sight.Such a skill might also contain an instruction like: write a clear, concise PR description. This is much more interesting to test, and still easy to test reliably - a simulated "create a PR" state that matches the kind of case an agent might encounter in the wild is possible, even without a full codebase and a real PR to create. Running that case a number of times and comparing the with and without skill results should be expected to determine if anything in the "clear and concise description" instructions hold their weight, or if the agent would write the same kind of description without any instruction.
A skill like
slow-powers:working-with-tddalso contains instructions that are relatively deterministic and trustable: write the test first, it must fail, and so on. (Pressure scenarios - did the agent follow its clear instructions under difficult or unexpected circumstances - are a different type of eval, not relevant to this discussion). The interesting thing to test, however, is actually: is the code itself better when following TDD, than without (better test coverage, code organization, test clarity, etc)? Under a limited, simulated environment, such a test can't be verified. Even haiku is a powerful coding model, and it's not going to have any trouble working through a toy problem, and producing reasonable code.A realistic environment gives us the circumstances and output artifacts (that is, the code changes) that a judge needs to answer important performance questions that can't reasonably be simulated.
Multiple judges
With a question like "is the code better?", we'd likely see more value by running the test once, and judging it multiple times. The more "opinionated" a question is, the more useful this reverse grading seems. If 6/10 judges grade no-skill work as "good", and 10/10 judges grade with-skill work as "good", we'd count that as marked improvement (see Reference 1, "pass^k" grading). This should be much cheaper, since judging is far simpler than executing the task, and we have a clear pattern for how to judge success for this type of question.
Interactive judging
This also allows the agent driving eval-magic itself to do heuristic judging, without actual eval cases known ahead of time. For instance, if we have a test case like "implement this feature...", the user can ask the agent to have eval-magic run both the no-skill and with-skill sides of the test, then ask vague questions like "did the skill make the code better?" or "did the skill confuse the agent at any point?". This won't be statistically reliable information, but it can lead to the discovery of worthwhile test cases to run real evals for, and give the user an early sense of how the skill is working.
This generally seems like an interesting way to begin drafting actual eval cases, with two comparable session transcripts, given the exact same starting prompt, providing straightforward insight into the function of the skill under test.
Multiple skills tested at once
This is specifically helpful to slow-powers, but should also be generally useful. With a real test case, we could see the full suite of slow-powers skills working together, with the final code being a useful product by which to judge the plugin as a whole. This feels especially useful combined with interactive judging to come up with eval cases for the most useful aspects of the suite.
This is also likely to be a way to catch places where skills conflict or cause confusion, something that is again unlikely to come up in a toy test case.
Issues and considerations
I can see a few things that need deeper investigation, or seem likely to be a source of issues.
Legacy maintenance
My feeling is this will present a number of breaking changes, and that there's no reason to support legacy modes of evals. If we can architecturally handle all our evals in essentially the same way, we should aim for that goal. The simplicity will be a big benefit in the long run.
Sourcing codebases
I think this should be a simple part of the eval configuration, with the option to use a local directory or an online git repo. This is an opportunity to provide some nice UX. We should provide a default fixture for a simple codebase (maybe just by creating it on github), and suggest using the eval-magic codebase itself as a complex fixture. Instructions for what fixtures should be used should be part of the committed eval files in some way, and recorded as part of any run report.
Guard updates
We may need to consider the details of the what should be guarded, and what should be allowed, during this kind of eval run. I'm not sure the scope of this change, but opportunities to simplify the guard are always good.
Multiple runs
While the "one run, many judges" approach is nice, we still need to support statistically significant eval runs, which will likely require running the actual task multiple times. We don't want to check out a dozen copies of a codebase to run the eval though. We might be able to make use of git for this, but we should keep in mind that git actions can be an expected part of an eval itself.
Multiple turns
As stated, we want to support an unknown, dynamic number of turns. I think there's a convenient happy path for most responses an agent-under-test might expect to receive - Did the agent ask a multiple choice question, with a recommended option? Always choose the recommendation. For more complex questions, we may need some kind of "question answering agent", designed to quickly generate a comprehensible response, always tending towards "choose whatever is recommended/simplest/easiest".
Notes
References
Breakdown
Feasibility was assessed against the current tree and the work split into 15 sub-tickets.
Verdict: feasible, no blocking unknowns. Most of what this issue needs already exists in some
form — private per-
(eval, condition, run)environments, a runner-owned Git repo per env, a workingmulti-turn driver with native session resume, deterministic + LLM grading, guard and stray-write
accounting, cross-campaign aggregation. The work is reshaping those, not building new subsystems.
Sub-tickets
Foundation
Execution
Environment fidelity
Judging
compare: paired evidence for interactive judgingBreadth
Onboarding and cleanup
#252, #256, #259, #260, and #265 are independently startable today.
Frictions found during assessment
git inited;verify_task_repositoryrejects any remote and any dirty state. A cloned codebase violates both.src/cli/run/orchestrate/git.rs:166-218src/pipeline/diff_scope.rs:18-21(group, condition, run)via plainfs::copy.--runs 10= 20 checkouts.orchestrate/envs.rs:63,src/core/fs.rs:128RUNBOOK.md.conversation.rs:89-93execute_roundruns to completion.conversation.rs:367-387run.json, including every tool invocation's args and results. Unbounded on a real task.grade/judge_tasks.rs:166-218npm/pip installunless the command text happens to mention an allowed root.src/sandbox/policy.rs:55-96,262-264.claude/,.agents/,AGENTS.md, and checked-in skills into both arms.staging/mod.rs:121-123skill_nameis a single string and conditions are binary — no way to make a skill suite the treatment.schema/evals.schema.json:10,core/types.rs:225cwd/.eval-magic, so eval artifacts land inside the user's skills repo, and the live skill source is reachable from the env by a short relative path.src/core/context.rs:221,detect_stray_writes.rs:180-229What is not a problem
The write guard is already fully decoupled from the workspace's location.
marker_allowed_roots(
src/sandbox/install.rs:75) returns exactly one allowed root — the isolated env — and the rationaleis already documented there: "Scoping to the env — not the parent
.eval-magic/or the host tempdirectory — keeps the guard boundary identical to the isolation boundary." Nothing about write
containment depends on the workspace sitting next to a skill, so no ticket should be justified as
"simplifying the guard by relocating the workspace". Guard friction during a run is a separate
problem with a separate cause —
BASH_MUTATION_PATTERNSfiring on ordinary dev commands — and thatis #259.
Decisions
dispatch-taskbecomes the universal execution path; a neweval-magic dispatchruns a whole iteration with concurrency, timeouts, and resume. (Runner-driven dispatch for every task #256)eval-magic/baselineref. A local-directory source that is not already a repo still getsgit inited, so every run is guaranteed a repo without requiring one up front. (Source a real codebase into each task environment #252)codebaseis declarable at the top level as a default and overridable per eval, mirroring howrunsalready works. (Source a real codebase into each task environment #252)ref. The runner records the resolved SHA and keys thecache on it, so re-running an iteration needs no network. (Source a real codebase into each task environment #252, Provision environments from a per-iteration codebase cache #254)
CLAUDE.md/AGENTS.mdand config — that realism is thepoint. Skills it makes discoverable get a distinct
codebase-sourcedfinding class, plus anopt-in
codebase.exclude_skill_sourcesthat moves them aside symmetrically for theself-referential case (evaluating slow-powers against the slow-powers repo). (Harness config shipped by a sourced codebase #260)
files/files_rootsurvive as a documented overlay on the codebase — seeding a task-specificfile into a real repo is a live use, not legacy baggage. Only
isolationis removed, and it isalready a documented no-op. (Retire the fixture-only eval model #266)
justification is input symmetry and provenance, not guard simplification — on raw code
complexity this is close to a wash. Today a report can pin the codebase SHA while the skill side
is "whatever was on disk at the time", which is not a reproducible published claim. (Source skills as copied inputs and relocate the eval home #253)
Cross-cutting requirements
Applied to every sub-ticket rather than tracked separately:
Mode::NewSkillandMode::Revision, and thesnapshot/promote path keeps working against codebase-backed iterations.
conditions.json, eachrun.json,benchmark.json, and theBASELINE.mdbuilt bypromote.rs:231— not just in the workspace.