feat(verify-first): cover probes that pass for the wrong reason - #91
Merged
Merged
Conversation
The skill was thorough about false negatives: one negative probe is not proof of absence, never refute a claim you have not tested. It said nothing about the inverse, which is easier to miss because it feels like success. The probe passes, the claim gets marked verified, and the thing you cared about was broken the whole time. The incident that prompted this: a skill whose only job was to hand a reviewer a running app was recorded as fully verified end to end on the strength of an HTTP 200 and a title tag, while the app was in fact broken in the browser because a stale generated module never resolved. A vite dev server returns 200 for the HTML shell even when every module it references fails, so that probe could not have failed for the reason that mattered. A human opening the page found it immediately. Three additions. A liveness-versus-correctness table, since a status code, a bound port, a live process, an exit code and a startup banner all prove that something started and none of them prove it works. A note that detectors fail silent-clean, because "found no problems" and "never ran" are byte-identical output, so a green detector is only evidence after you have watched it go red on a known-bad fixture. And a third lesson alongside the existing two: match the precision of the claim to the precision of the probe, because quietly widening "the server is up" into "the app works" is how an unrun claim gets laundered into a verified one. Step 3 now asks the falsifiability question before a probe runs: if the thing were broken, would this probe look any different? If not, it is the wrong probe. 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.
TL;DR
verify-firstwas thorough about false negatives and silent about their inverse. It now covers probes that pass for the wrong reason: liveness signals mistaken for correctness signals, and detectors that report nothing because they never ran.Why
The skill's founding incident was a false negative (
window.Relayundefined did not mean Relay was gone), and both of its stated lessons point that way. Nothing in it guarded the opposite direction, which is easier to miss precisely because it feels like success: the probe passes, the claim is marked[V], and the thing you cared about was broken all along.The incident that prompted this, 2026-07-30: a skill whose only job was to hand a reviewer a running app was recorded as "fully verified end to end" on the strength of an HTTP 200 plus a
<title>tag. The app was actually broken in the browser,does not provide an export named 'AIAgent', because a stale generated module never resolved. A vite dev server returns 200 for the HTML shell even when every module it references fails, so that probe could not have failed for the reason that mattered. A human opening the page found it in seconds.What changed
[V]Verification
make test(skills-check, flows-check, smoke)make skills-syncrun and committed;skills-checkpasses, and only the threeverify-firstfiles changed, no collateral churnmake determinism SKILL=verify-firstmainfor comparison: both1 passed (100%), 0 failed, 0 errors, both emitting a real Verification Ledger with the pinned[V]/[B]/[R]table against the throwaway fixture, 44s here vs 51s on mainThe gate asserts only the ledger shape, which this change preserves, and running it against both branches confirms the edit is inert to it rather than assuming so.
Worth knowing for anyone reading the gate output: promptfoo prints
Could not find any valid files in the command: bash eval-run.shon both branches. It is a cosmetic warning from globbing the provider string as a path before falling back toexec:, not a failure. The 44s duration and the real ledger in the output are what establish that the skill actually ran, and that distinction is the whole subject of this PR.Note for reviewers
feat/eval-testmode(2 commits ahead, 19 behind, no PR) also modifiesskills/verify-first/SKILL.md. It will conflict here and needs a rebase regardless of this change. Flagging rather than resolving, since it is not my branch.Risk
Low. Additive prose to one skill plus its generated copies. No script, flow, or CLI behaviour changes.
🤖 Generated with Claude Code