| name | verify-before-claim |
| description | Enforce the "no premature done" discipline. Before claiming a task is complete, the model MUST produce real evidence โ a test run with passing output, a real DB query result, a rendered screenshot, a build that compiles, a command's actual stdout. "200 OK" alone, fake fixtures (fake JWT, synthetic audio), or code-inference without execution are NOT evidence. ROUTE BY INTENT, NOT KEYWORDS โ load this whenever the model is about to say "done", "complete", "fixed", "finished", "์๋ฃ", "๊ตฌํ ์๋ฃ", or any completion claim, OR when the user asks "did it work?", "are you sure?", "์ง์ง์ผ?", or expresses doubt about a claim. Also load when a conclusion lacks a quantitative basis (test count, response time, measured value). Returns either evidence (command + output / test result) or an explicit "ํ์ธ ๋ถ๊ฐ" (cannot verify) verdict with the missing evidence named. NOT a code editor โ it produces or demands evidence, never edits code. |
Verify before claim
The reliability doctrine: a completion claim without evidence is a hypothesis, not a verdict. This skill is the gate every "done" must pass.
The single rule
Before any statement of completion, you MUST have run something and shown its output. The evidence must be:
- Real, not synthetic. A real test run (the actual test framework), a real query against real data, a real build, a real HTTP request returning a real response. Fixtures are acceptable for input only, never for the verdict. A fake JWT, a mocked DB, a synthetic audio file, a placeholder screenshot โ none of these verify the real system.
- Shown, not asserted. Paste the command AND its output. "The tests pass" is not evidence; "
pytest -q tests/test_foo.py โ 3 passed in 0.4s" is. "The API returns 200" is not evidence; "curl -s -o /dev/null -w '%{http_code}' ... โ 200" with the response body is.
- Quantitative where possible. "It's fast" โ "p95 42ms (n=100)". "It works" โ "5/5 test cases pass". A number anchors the claim; a vibe does not.
What counts as evidence (by task type)
| Task type | Minimum evidence |
|---|
| Bug fix | The failing test now passes (show the run); the original repro no longer reproduces (show the command + output). |
| New feature | A test covering the new behavior passes; the feature is exercised end-to-end with real input โ real output. |
| Refactor | The existing test suite still passes (test count before/after); behavior is unchanged. |
| Config / infra change | The change is applied (show the diff or git status); the system starts / responds with the new config. |
| UI work | The surface renders at the target route (Playwright navigate + screenshot, or at minimum a computed-style probe). "I wrote the component" is not evidence. |
| DB / data change | A query confirms the new state (e.g. db.collection.countDocuments({field: value}) โ real number). |
| Performance claim | A benchmark with sample size + p50/p95. |
The honest-degrade verdict: "ํ์ธ ๋ถ๊ฐ" (cannot verify)
If you cannot produce evidence โ because the environment is not available, the test doesn't exist yet, the feature requires prod data you can't access, or verification would take longer than the task itself โ the verdict is "ํ์ธ ๋ถ๊ฐ" (cannot verify), not "done". Name the missing evidence explicitly:
์ํ: ํ์ธ ๋ถ๊ฐ โ . <why it's not available now>. <what's needed to verify>.
This is not failure โ it is honesty. A scoped "ํ์ธ ๋ถ๊ฐ" with a named gap is far more useful than a false "์๋ฃ" that sends the user on a goose chase. The worst outcome is a claim the user trusts and acts on, then discovers was never true.
Banned patterns (the false-evidence tells)
- "200 OK" as the verdict. A 200 response to a stub endpoint with a mocked body proves nothing about the real system. Show the actual response body + a real data assertion.
- Code-inference as verdict. "The function returns X because the code says Y" โ unless you ran it and saw X. Reading code is a hypothesis; running it is evidence.
- Synthetic fixtures as the system. A test with
mock_db.return_value = {...} verifies the test's mock, not the DB layer. Integration tests against a real (even if local) DB are evidence; pure mocks are not.
- "Should work" / "would work" / "is expected to." These are predictions, not evidence. Run it.
- Skipping verification because "it's a small change." Small changes break things too. The smallest change still gets the smallest applicable evidence (at least: the test suite runs clean).
- Sycophantic reversal under pushback. If the user questions a claim and you have no new evidence, KEEP the prior verdict or escalate to "ํ์ธ ๋ถ๊ฐ" โ do not flip to "you're right, it's broken" just to agree.
The completion gate
Every task ends with one of exactly three verdicts:
์๋ฃ (done) โ backed by shown evidence (command + output / test result / rendered probe). Name the evidence inline.
ํ์ธ ๋ถ๊ฐ (cannot verify) โ the honest gap verdict. Name the missing evidence + why + what's needed.
๋ถ๋ถ ์๋ฃ (partial) โ some aspects verified, others not. Split clearly: "A is done (evidence: ...). B is ํ์ธ ๋ถ๊ฐ (missing: ...)."
There is no fourth verdict. "I think it's done" is not a verdict โ it's a hypothesis that needs evidence or an explicit "ํ์ธ ๋ถ๊ฐ".
How this composes with bash-guard
The bash-guard hook (this plugin's PreToolUse(Bash) component) surfaces environment footguns โ non-local DB URIs, protected-branch commits, destructive ops โ for user confirmation. It does NOT block (fail-open, permissionDecision: ask). Its job is to prevent the verification step itself from accidentally hitting prod or destroying state. If bash-guard fires during your evidence-gathering, confirm the command is safe before proceeding โ do not just bypass with BASH_GUARD_OFF=1 to save a step.