Repository navigation
Measure which skill an agent reaches for, and record what it found - #267
Merged
Merged
Conversation
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.
A live walk of the published 0.0.59 reported that
add-sourcesdid not fire on its headline prompt. The tempting repair is to reword the description until it does — a guess. This is the instrument that replaces the guess, plus what it found when pointed at the actual question.What it does
packages/ksor/src/evals/skill-triggers.agent.test.ts: N runs per phrase, in a fresh scaffold with all three skills present, graded on which skill the agent actually invoked — read from the whole transcript, not the first tool call, so an agent that reads a file before deciding is not scored a miss. Five phrases, including two controls: one where a different skill must win, one where none should.Gated like the content eval (logged-in
claudelocally,CLAUDE_CODE_OAUTH_TOKENin CI) and announces its own skip. Reported, never gating — a model is stochastic and a threshold over a handful of runs flakes.What it found
The model is a column, because the answer depends on it. Same phrase, same scaffold, same harness:
own-words— "add this to the knowledge base: …"from-memory— nobody wrote it downget-started→ intake-interview (control)stay-silent→ nothing fires (control)file-in-repo— "here issrc/policy.txt, add it underfinance/"That is why the walk (default model, one run) and my first probe (Sonnet, pinned) disagreed. Neither was wrong; neither alone measured the trigger.
The obvious repair does not work. I added a clause naming exactly that shape — "points at a file already in the repo and says where it belongs", shipped as 2.1.0 — and re-measured on the model that missed: 0/3 before, 0/3 after. So the cause is not the wording. An instruction concrete enough to act on gets acted on, and no skill is consulted. The clause is reverted (
add-sourcesstays 2.0.0): it is resident context in every session and bought nothing a measurement can see. The negative result is recorded beside the rows it explains, per the invariant about recording negative results next to the constant they explain.The question this leaves — owner's, not mine
On the one path where the skill does not fire, the record still came out well-formed, because the emitted
AGENTS.mdcarries the same rules and is always resident. The content eval said the same from the other side: both arms passed every behavioural gate. So isadd-sourcesearning its resident cost on that path, or is AGENTS.md already doing the work? AGENTS.md's own rule is that a skill nobody can show winning is deleted. The note in the harness header says how to answer it: a fixture the two arms score differently, or delete the skill — not another reworded description.Also fixed
The CLI can emit raw control characters inside its JSON, which
JSON.parserejects outright — the harness lost the entire transcript to a stray byte. It now falls back to a scrubbed parse. Hit by hand while probing; it would have shown up as a flaky "did not return JSON".Verified
unit 1702, integration 749 passed / 34 skipped, agent tier unarmed 5 passed / 4 skipped (announces its skip), typecheck 0, guard ok, corpus ok, format clean. About $17 of real agent runs, all recorded in
TRIGGER_BASELINE.