scripts/skill-eval.mjs runs every case with --max-turns 1, so it measures whether a skill is the model's first tool call. That is the right thing to measure for a skill a user reaches directly, and #2202 tuned every committed case to that shape. It leaves one class of invocation entirely unmeasured: a skill reached from inside another skill.
The gap, measured
testing ends its body with "See /test-servers for picking and building one", and test-servers is model-invocable, so the hand-off is live rather than a dead pointer. It still does not happen:
- Prompt: "Write an integration test that exercises tool listing against a real server."
testing loaded first, 2/2.
- Across the next 9–12 tool calls in each run,
test-servers was never loaded — the model went to Bash/Read/Glob instead.
The suite reports test-servers at 5/5, because all five of its cases ask for it directly. A skill that is only ever reachable through another would score a clean 100% while the hand-off silently never fires.
#2203 improves this particular hand-off two ways — test-servers' description now claims the "a change or a PR needs a real server to exercise it" situation, and testing's pointer moved from its last line into its lede — but neither is measured, and that is the point of this issue rather than a reason to close it.
There is also a task-prompt gap this would cover
"Can you smoke test this PR?" reaches no skill at all (0/3 before #2203's change, 0/3 after). That is arguably correct behavior: the model has to inspect the PR before it can know what fixture the change needs, so firing a skill on the first move would be firing blind. The realistic path for a prompt like that is a second-hop load once the investigation reveals a server is needed — exactly what nothing can currently observe.
What this would take
- A second eval mode with a higher turn budget that asserts an ordered pair — skill A fired, then skill B — rather than a single name.
- A decision about what its number means: a chain hit rate is not comparable to the first-move rate, so it probably wants reporting as its own column rather than folded into
N/M cases at or above 80%.
- Read-only tool restriction has to hold across the extra turns; the current harness leans on
--max-turns 1 for much of that containment.
Acceptance
- The suite can express and score "loading A should lead to loading B", with committed cases for at least the
testing → test-servers hand-off.
- The chained measurement is reported distinctly from the first-move rate.
docs/skill-authoring.md gains a section on when to write a chained case instead of a direct one.
scripts/skill-eval.mjsruns every case with--max-turns 1, so it measures whether a skill is the model's first tool call. That is the right thing to measure for a skill a user reaches directly, and #2202 tuned every committed case to that shape. It leaves one class of invocation entirely unmeasured: a skill reached from inside another skill.The gap, measured
testingends its body with "See/test-serversfor picking and building one", andtest-serversis model-invocable, so the hand-off is live rather than a dead pointer. It still does not happen:testingloaded first, 2/2.test-serverswas never loaded — the model went toBash/Read/Globinstead.The suite reports
test-serversat 5/5, because all five of its cases ask for it directly. A skill that is only ever reachable through another would score a clean 100% while the hand-off silently never fires.#2203improves this particular hand-off two ways —test-servers' description now claims the "a change or a PR needs a real server to exercise it" situation, andtesting's pointer moved from its last line into its lede — but neither is measured, and that is the point of this issue rather than a reason to close it.There is also a task-prompt gap this would cover
"Can you smoke test this PR?" reaches no skill at all (0/3 before #2203's change, 0/3 after). That is arguably correct behavior: the model has to inspect the PR before it can know what fixture the change needs, so firing a skill on the first move would be firing blind. The realistic path for a prompt like that is a second-hop load once the investigation reveals a server is needed — exactly what nothing can currently observe.
What this would take
N/M cases at or above 80%.--max-turns 1for much of that containment.Acceptance
testing→test-servershand-off.docs/skill-authoring.mdgains a section on when to write a chained case instead of a direct one.