feat(evals): support multi-skill treatments - #291
Merged
Conversation
Stage ordered skill rosters as one treatment while preserving scalar artifact compatibility. Grade invocation per member and carry complete treatment provenance through reports and promotion.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
skill_nameformCloses #264.
Overall strategy
The implementation extends the existing treatment, source, and artifact contracts instead of adding a parallel suite abstraction. A list-authored
skill_nameresolves each member through the same source machinery used for a scalar skill, records the CLI-selected member as the eval owner, and carries the ordered roster throughconditions.json,dispatch.json, eachrun.json,benchmark.json, and promotedBASELINE.mdprovenance.For example, an eval can define a coordinated treatment as follows:
{ "skill_name": ["review-workflow", "review-verification"], "evals": [ { "id": "review-change", "prompt": "Review this change.", "expected_output": "A prioritized review." } ] }The
--skillargument selects the eval owner. It supplies the eval definitions and fixtures and owns the workspace and promotion destination, so it must be a member of the authored list.Staging and comparison modes
with_skilland none inwithout_skill.--no-stageinlines every treatment member from the iteration copy.--stage-namerejects list-authored treatments because one override cannot name an entire roster.Treatment names are validated as safe single directory components. Lists must be non-empty and unique, and the eval owner must be present. Failed set snapshots remove their pending directory instead of leaving a partial baseline.
Cross-harness invocation grading
The condition roster supplies each member's staged slug to grading. Harnesses whose descriptors expose a deterministic invocation signature produce one transcript result per member using indexed response files such as
__skill_invoked__skill-1.json. Harnesses without deterministic evidence receive one LLM fallback task per member.Each multi-skill meta result names its
skill_name, andbenchmark.jsonadds per-skill invocation counts and rates. The suite-levelmeta_summary.skill_invokedvalue uses the agreed any-member rule, so partial invocation satisfies the suite check while remaining distinguishable from complete invocation. Negative evals withskill_should_trigger: falsecontinue to suppress invocation checks.Compatibility and provenance
Scalar
skill_namevalues retain the established single-skill paths, filenames, serialized fields, warnings, and grading behavior. Optional roster fields are absent from scalar artifacts. A one-member list deliberately uses the list-authored artifact and indexed grading forms rather than collapsing back to scalar behavior.Multi-skill provenance records every member's resolved source, revision, and dirty state while retaining the eval owner's flattened source for compatibility. Live-source detection checks every recorded treatment source, and promotion renders every source in
BASELINE.md.Prompt-specific roster rendering, orchestration source records, and promotion-row formatting were extracted into focused modules to keep the shared files from accumulating the entire feature.
Before and after
Before, only a scalar treatment was valid:
{ "skill_name": "review-workflow" }The list form treats the coordinated skills as one experimental treatment:
{ "skill_name": ["review-workflow", "review-verification"] }Scalar input remains supported for existing evals.
Verification
cargo fmt --checkcargo buildcargo test --quiet— 926 library tests, 201 CLI tests, and 199 run tests passedcargo clippy --all-targets -- -D warningsgit diff --checkcargo test --test run multi_skill— 12 focused multi-skill workflows passedReviewer notes