name: Qverify-contract description: Verify that an implementation and its tests honor a business-logic contract stored under .qe/contracts/active/. Delegates to the Econtract-judge LLM agent on cache miss; returns cached verdict on cache hit. Use when the user says 'verify contract', 'check contract', '/Qverify-contract', or when called from /Qcode-run-task.
Contract Verification (Qverify-contract)
Role
Execute contract conformance verification. Compute a 3-hash (contract/impl/test) cache key; return cached verdict on hit; otherwise invoke the Econtract-judge agent, parse its JSON verdict, cache it, and report.
Invocation Modes
/Qverify-contract <name> — Verify a Single Contract
Steps:
Validate
<name>viaassertValidContractNamefromhooks/scripts/lib/contract-manifest.mjs. Reject invalid identifiers.Locate contract file via
resolveContractPath(name)fromhooks/scripts/lib/contract-manifest.mjs. Contract must be inactive/; pending contracts are not verified.- If contract not found: report
{verdict: "FAIL", summary: "contract not found: {name}"}and exit.
- If contract not found: report
Read contract file content →
contractText.Use
contract-file-resolver.mjsfunctions:resolveImplPath(name, contractText)→ locate implementation fileresolveTestPath(name, contractText)→ locate test file- Read impl file if exists (else
implText = '') - Read test file if exists (else
testText = '')
Compute 3-part cache key via
contract-hash.mjs → computeContractHash:contract_hash— SHA256 of contract contentimpl_hash— SHA256 of impl content (or empty string)test_hash— SHA256 of test content (or empty string)
Call
isCacheHit(name, {contract_hash, impl_hash, test_hash})fromcontract-verdict-cache.mjs:- Cache HIT →
readVerdict(name), return cached verdict, print report and exit - Cache MISS → proceed to step 7
- Cache HIT →
Cache MISS flow:
- Call
buildJudgePrompt({contractName: name, contractText, implText, testText})fromcontract-judge-prompt.mjsto construct the prompt - Invoke the
Econtract-judgeagent via the Agent tool withsubagent_type: 'Econtract-judge', passing the built prompt as the agent's input - Parse the agent's output by extracting the last ```json code fence (the judge is instructed to emit exactly one; using the last occurrence tolerates accidental earlier example fences without silently accepting a stray first-fence from summary text)
- If NO ```json fence is found, OR the extracted JSON does not parse, OR the parsed object lacks the required keys (
verdict,summary,findings): return{verdict: "FAIL", summary: "judge returned unparseable output", findings: [{ section: "Judge Output", expected: "single valid JSON verdict fence with verdict/summary/findings", actual: "<first 200 chars of agent output>", severity: "critical" }]} - If MORE than one ```json fence is found: proceed with the last fence's JSON but add a minor finding:
{ section: "Judge Output", expected: "exactly one JSON fence", actual: "N fences found (took the last)", severity: "minor" }to the parsed findings array before caching - On successful parse, enrich the JSON verdict with:
contract_hash(from step 5)impl_hash(from step 5)test_hash(from step 5)judged_at: new Date().toISOString()model: "claude-sonnet-4-6"(or whatever model the agent used)
- Call
Call
writeVerdict(name, enriched)fromcontract-verdict-cache.mjsto persist the verdict.Print formatted report (see Report Format below) and return the verdict.
/Qverify-contract --all — Verify All Active Contracts
Steps:
Call
listActive()fromcontract-manifest.mjsto fetch all active contract names.For each contract name, execute the single contract flow (steps 1–9 above).
Aggregate results: count PASS vs FAIL verdicts.
Print table with columns:
Contract Name— identifierVerdict— PASS or FAILSummary— 1-line verdict summaryJudged At— ISO timestamp (or "Cached" if from cache)
Exit with non-zero status code if any contract verdict is FAIL (enables CI integration).
Report Format
Single contract (example):
Contract: sivs-enforcer
Verdict: PASS
Summary: Implementation honors all declared invariants and error modes.
Judged At: 2026-04-22T14:35:00Z
---
Contract: user-service
Verdict: FAIL
Summary: Missing DuplicateEmailError handling.
Findings:
[critical] Error Modes — expected: throw DuplicateEmailError when email exists | actual: returns null
All contracts (example):
Contract Verification Report (--all)
=====================================
sivs-enforcer | PASS | Implementation honors all invariants | Cached
user-service | FAIL | Missing DuplicateEmailError handling | 2026-04-22T14:35:00Z
auth-provider | PASS | Tokens verified correctly | 2026-04-22T14:36:15Z
Summary: 2 PASS, 1 FAIL
Exit code: 1
Dependencies
This skill depends on the following library modules:
hooks/scripts/lib/contract-manifest.mjs— name validation (assertValidContractName), path resolution (resolveContractPath), listing (listActive)hooks/scripts/lib/contract-file-resolver.mjs— implementation and test path resolution (resolveImplPath,resolveTestPath)hooks/scripts/lib/contract-hash.mjs— 3-hash computation (computeContractHash)hooks/scripts/lib/contract-verdict-cache.mjs— cache operations (isCacheHit,readVerdict,writeVerdict)hooks/scripts/lib/contract-judge-prompt.mjs— prompt builder (buildJudgePrompt)agents/Econtract-judge.md— LLM judge agent (invoked via Agent tool withsubagent_type: 'Econtract-judge')
Will
- Return structured verdicts (JSON) with hash metadata
- Cache verdicts on successful judge invocation
- Short-circuit on missing contract or unparseable judge output
- Exit non-zero when
--alldetects FAIL verdicts (for CI pipelines) - Invoke the Econtract-judge agent only on cache miss
Will Not
- Modify contracts, implementations, or tests
- Attempt automatic fixes
- Emit verdicts without invoking judge on cache miss
- Return verdicts from cache without first checking hash equivalence
Examples
/Qverify-contract sivs-enforcer
→ Verifies .qe/contracts/active/sivs-enforcer.md
→ Locates impl + test files via contract-file-resolver
→ Computes 3 hashes, checks cache
→ On miss: invokes Econtract-judge, caches result, prints report
/Qverify-contract --all
→ Lists all active contracts
→ Verifies each one (in sequence or parallel)
→ Prints table of results
→ Exits non-zero if any FAIL found
Handoff
After contract verification completes, use standard handoff format:
Phase 3: Contract Layer — Verification complete
PSE: [x] Plan [x] Spec [x] Execute [>] Verify
Contract: {name} — {verdict}
Next: /Qcode-run-task