Repository navigation
test(skills): guard the version literals in skills/, and stop measuring with the buggy release - #123
Merged
Merged
Conversation
…ng with the buggy release
A skill is prose, and prose carries version literals nothing checks: the
`npx -p @opentechevents/<pkg>@<minor>` lines an organizer actually runs, a
pinned embed URL, a `specVersion` in an example an agent will copy. Each one
was right the day it was written. They drifted exactly as you would expect,
because the rule asking for the pins to move lived in SKILL.md and the pins
lived in references/:
- references/website.md pinned export-jsonld@0.4 and embed v0.7.0, two
minors and one widget line behind what this repo ships.
- references/writing.md's canonical "minimum a standalone event needs"
wrote specVersion 0.4.0, so an agent following it mints a document two
minors behind on the day it is written.
- evals/src/assertions.ts measured `fileIsValid` — what the README calls
ground truth — by fetching the validate package on the 0.4 line, which
judges a document against the newest release instead of the version it
declares. That is the bug this kit fixed in 0.6, live in the instrument:
a correct 0.5 or 0.6 document came out broken and a green run meant
nothing.
So the rule is no longer discipline, it is a test. version-pins.test.ts
derives everything at run time — from the workspace's own package.json
versions and from packages/validate's support policy — and fails with the
file, the line and the value to write. It holds: npm pins name a package this
repo ships, on the line it ships; a pinned embed/v<x.y.z> URL matches
apps/embed AND has a committed snapshot behind it; a specVersion in anything
skills/ote-event/ tells an organizer to write is the latest published
version; and no .md names a bare spec minor in prose, because "what v0.4
documents" is read as current by whoever reads it.
The failure nobody would have seen without it: an eval fixture pinned to a
spec version changes meaning when the support window moves.
corunajug-feed.json was stamped 0.3.0 to be the "older but supported — a
notice, never a defect" case, and the day 0.5.0 and 0.6.0 shipped together
the window slid past it. The fixture still parsed and the case still ran,
having quietly become a migration case that asserted the opposite. Fixtures
now declare a role (latest / older-supported / none) resolved against the
live policy, so a window move names the file to re-stamp. Re-stamped to
0.4.0, and its watch_for rewritten: it described the pre-0.6 CLI behaviour as
"live today".
fileIsValid now imports validateDocument from the workspace instead of
pinning a published release. An instrument must be the code under review, not
a copy of it from npm — and an unpinned import cannot drift. The agent-facing
pins stay literal on purpose: they say which release the instructions were
tested with.
No per-line ignore mechanism, deliberately: a marker that silences this scan
would be reached for on the day the scan is right. A comment that needs to
discuss an old pin spells it in words ("the 0.4 line"), which reads better
anyway — the guard caught its own comments on first run and that is how it
was fixed.
Verified by simulation rather than by reading: bumping validate to 0.7.0 and
embed to 0.9.0 and re-stamping the fixture makes it report each stale pin with
its file and line, and inserting a bare `v0.5` into prose trips the prose rule.
What this does not fix: ote-validate still reports a healthy kit fork's
events/*.json as `0/3 valid` with exit 3 (#117), and the skill's Gate 2 still
sends the agent at them first (#119).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
skills/carries version literals that nothing checked: thenpx -p @opentechevents/<pkg>@<minor>lines an organizer actually runs, a pinned embed URL, aspecVersionin an example an agent will copy. They had drifted, because the rule asking for the pins to move lives inSKILL.mdand the pins live inreferences/.This replaces that rule with a test.
What was wrong
references/website.mdexport-jsonld@0.4×2references/website.mdembed/v0.7.0×2references/writing.mdspecVersion: 0.4.0references/website.mdapplication/ote+json— what v0.4 documents"evals/test/assertions.test.ts@0.4And the one that mattered most:
fileIsValidmeasured ground truth with the release whose version bug this kit exists to have fixed. It fetched the validate package on the 0.4 line, which judges a document against the newest release instead of the version it declares — so a correct 0.5 or 0.6 document came out broken, and a green run meant nothing. The eval README warns about exactly this ("an uncalibrated instrument turns a real regression into a green run") one screen above the pin that did it.The guard
skills/evals/test/version-pins.test.ts— a plain unit test, no agent, no API key, runs in CI with everything else. It lists nothing: every expectation is derived at run time from the workspace's ownpackage.jsonversions and frompackages/validate's support policy, and failures name the file, the line and the value to write.embed/v<x.y.z>URL matchesapps/embedand has a committedversions/v<x.y.z>/snapshot behind it — the skill tells organizers to put that URL in a live<script>tag.specVersionin anythingskills/ote-event/tells an organizer to write is the latest published version..mdnames a bare spec minor in prose: "what v0.4 documents" is read as current by whoever reads it.No per-line ignore mechanism, deliberately — a marker that silences this scan would be reached for on the day the scan is right. A comment that needs to discuss an old pin spells it in words ("the 0.4 line"). The guard caught its own comments on the first run, and that is how they were fixed.
The failure nobody would have seen
An eval fixture pinned to a spec version changes meaning when the support window moves.
corunajug-feed.jsonwas stamped0.3.0to be the "older but supported — a notice, never a defect" case. The day 0.5.0 and 0.6.0 shipped together, the window slid past it. The fixture still parsed, the case still ran, and it had quietly become a migration case still asserting the opposite — today it exits 3.Fixtures now declare a role (
latest/older-supported/none) that the test resolves against the live policy, so a window move names the file to re-stamp instead of silently rewriting what a case tests. Re-stamped to0.4.0(✓ valid against OTE 0.4.0, with the notice), and itswatch_forrewritten — it described the pre-0.6 CLI behaviour as "live today".fileIsValidnow importsvalidateDocumentfrom the workspace rather than pinning a published release. An instrument must be the code under review, not a copy of it from npm, and an unpinned import cannot drift. The agent-facing pins stay literal on purpose: they say which release the instructions were tested with.Verification
By simulation, not by reading. Bumping
validateto 0.7.0 andembedto 0.9.0 and re-stamping the fixture:Inserting a bare
v0.5into prose trips the prose rule with its file and line. Both reverted.pnpm lint,pnpm build,pnpm typecheck,pnpm testgreen (31 tests inskill-evals).CLAUDE.mdgets the procedure: the command, the five rules, and the fixture-role rule that matters on a release day — re-stamp the fixture, never move the bar.What this does not fix
Found while investigating, filed rather than fixed here:
ote-validatereports a healthy kit fork'sevents/*.jsonas0/3 valid, exit 3.ote-build-feed --check.🤖 Generated with Claude Code