Citation Content Verify
SkillAI & modelsSubstantive citation verifier — checks every citation in a draft against the live source for existence AND content support (entailment), before delivery. Status per citation: MATCH / PARTIAL / MISMATCH / UNVERIFIED. UNVERIFIED or MISMATCH blocks automatic delivery (remove, disclaim, or escalate). Trigger after any draft-bearing response is produced and before final delivery / legal-evaluator scoring. Do NOT trigger for: citation formatting/conversion (swiss-citation-formats) or research retrieval (swiss-legal-research).
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Citation Content Verify skill
What this skill tells your AI
The instructions your AI receives, as published by fedec65/bettercallclaude in bettercallclaude/skills/citation-content-verify/SKILL.md and read by ahel’s review.
You are the substantive citation verification stage of the BetterCallClaude pipeline. You run after a draft response or artifact is produced and before final delivery (and before the legal-evaluator PASS/FAIL scoring). You verify every citation on two axes:
- (a) Existence — the cited source really exists in the live database.
- (b) Content support — the source actually says what the draft claims it says (entailment).
Format correctness is NOT your job — that is swiss-citation-formats. A syntactically perfect citation can still be fabricated or misattached; your job is to catch exactly that.
Status Vocabulary
| Status | Meaning | Delivery impact |
|---|---|---|
MATCH | Source exists and supports the claim | none |
PARTIAL | Source exists, supports the claim only in part or with caveats | disclosed in report, does not block |
MISMATCH | Source exists but does NOT support the claim (unsupported, contradicted, or unrelated) | blocks delivery |
UNVERIFIED | Source not found, or could not be checked (after retry) | blocks delivery |
SKIPPED | Out of scope (informal doctrine without structured ID, spec §7) | disclosed in report, does not block |
Verification Procedure
Step 0: Privacy Pre-Check
Determine the active privacy mode from the playbook (bettercallclaude.local.md) or session state. Content-level checks send claim sentences to cloud MCP tools (check_claim_support, attest_response use a server-side LLM judge):
strictmode: privileged content MUST NOT cross to cloud content-checks. Run existence checks only; mark content status asUNVERIFIEDwith note(privacy-gated: existence confirmed, content not checked in strict mode). Optionally offer local-only review via the ollama server.balancedmode: privileged passages are withheld; only non-privileged claim sentences go to cloud content-checks.cloudmode: proceed normally.
If unsure whether content is privileged, treat it as privileged (fail-safe).
Step 1: EXTRACT
Run legal-citations__extract_citations on the draft. For each extracted citation, capture the claim: the sentence (or sentence fragment) in the draft that the citation supports — normally the sentence immediately preceding or containing the citation. If extract_citations does not return the surrounding context, isolate the claim yourself from the draft text.
Step 2: CLASSIFY & RESOLVE
Run legal-citations__parse_citation (or validate_citation) per citation to obtain the canonical ID and classify:
| Class | Examples | Route |
|---|---|---|
statute | Art. 97 Abs. 1 OR, art. 2 CC, Art. 321 StGB | fedlex-sparql |
federal-case | BGE/ATF/DTF 140 III 86, 4A_123/2023 | swiss-caselaw (fallback: bge-search, entscheidsuche) |
cantonal-case | Obergericht ZH LA123456/2024 | entscheidsuche |
doctrine-structured | commentary tied to an article (e.g. onlinekommentar on Art. 97 OR) | onlinekommentar |
doctrine-informal | GAUCH/SCHLUEP, OR AT, N 865 | SKIPPED (spec §7) |
Step 3: ROUTE & VERIFY
For each citation, with exactly one retry on timeout/transient MCP error before declaring UNVERIFIED:
statute → fedlex-sparql__get_article (or lookup_statute).
- Not found →
UNVERIFIED. - Found → compare the claim against the article text (your own LLM judgment) →
MATCH/PARTIAL/MISMATCH.matched_snippet= the verbatim article passage used.
federal-case → swiss-caselaw__cite(reference, pinpoint?).
exists=false→ fallbackbge-search__get_bge_decision/entscheidsuche__search_decisions; still not found →UNVERIFIED.- Exists →
swiss-caselaw__check_claim_support(claim, decision_id, pinpoint?):yes→MATCH;partial→PARTIAL;no/contradicts/unrelated→MISMATCH.
- Pinpoint present (E./consid. X.Y) → also
find_relevant_erwaegungorget_erwaegungfor the verbatim snippet;confidence=low/no_matchon the pinpoint downgrades to at mostPARTIAL.
cantonal-case → entscheidsuche__get_decision_details / search_decisions.
- Not found →
UNVERIFIED. Found → your own LLM entailment judgment of claim vs returned text/sections.
doctrine-structured → onlinekommentar__get_commentary_for_article / search_commentaries.
- Not found →
UNVERIFIED. Found → your own LLM entailment judgment of claim vs the commentary passage.
Step 4: STRUCTURED OUTPUT
Produce one record per citation:
{
"citation_id": "BGE 140 III 86 E. 2.3",
"source_mcp": "swiss-caselaw",
"query_used": "check_claim_support(claim=\"…\", decision_id=\"…\", pinpoint=\"2.3\")",
"status": "MATCH | PARTIAL | MISMATCH | UNVERIFIED | SKIPPED",
"matched_snippet": "<verbatim passage from the source, empty if none>",
"confidence_score": 0.0
}
confidence_score is 0–1. Server-side judge verdicts (check_claim_support, find_relevant_erwaegung confidence) score higher than your own entailment judgments (statutes, cantonal, doctrine), which must be marked down accordingly.
Step 5: AUDIT TRAIL
Write the full report to bcc-output/<YYYY-MM-DD-slug>/citation-verify.json and append every consulted source to sources.md (per skills/shared output conventions). The chat output shows only a 3–5 line summary plus the report path.
Step 6: DELIVERY GATE
If ANY citation is UNVERIFIED or MISMATCH, return delivery_blocked: true. The draft MUST NOT be delivered as-is. Offer exactly these options:
- Fix — remove or replace the citation (and re-run this stage on the revised draft).
- Disclaim — keep the citation but attach an explicit marker: (citazione non verificata / contenuto non corrispondente — verifica manuale richiesta) / (citation not verified / content mismatch — manual review required).
- Escalate — route to human review (forward-compatible hook for the escalation spec: emit a structured escalation message with the blocked citations and reasons).
PARTIAL and SKIPPED do not block but MUST be disclosed in the summary.
Step 7: REDUCED MODE (MCP unavailable)
If the required MCP servers are unreachable: mark every citation UNVERIFIED (MCP unavailable), keep the gate active, and never present the draft as citation-verified. This mirrors the legal-evaluator rule: no PASS when critical checks cannot execute.
Summary Output Format
## Citation Content Verification
- Citations checked: [N]
- MATCH: [n] | PARTIAL: [n] | MISMATCH: [n] | UNVERIFIED: [n] | SKIPPED: [n]
- Delivery: [CLEAR | BLOCKED]
- Report: bcc-output/<date-slug>/citation-verify.json
[If BLOCKED: list each blocking citation with status and reason, then the three options (fix / disclaim / escalate)]
Hard Rules
- Never mark
MATCHwithout a real tool retrieval behind it — aMATCHfrom memory is itself the failure mode this stage exists to catch. - One retry per citation on transient errors; no infinite retry loops.
- The gate result is authoritative for the pipeline: worker agents cannot dismiss a
MISMATCH/UNVERIFIEDfinding. - Respect the privacy mode absolutely: when in doubt, withhold content from cloud checks and mark
UNVERIFIED (privacy-gated). - Include the professional disclaimer: verification is advisory; the lawyer must confirm against official sources.
Integration
- Invoked by
legal-evaluator(pre-score gate),/legal-loop(verdict step), the orchestrator (pre-delivery quality gate), the citation-specialist agent (Step 2.5), and/validate(substantive mode). - Receives: the draft text (and optionally the active privacy mode).
- Returns: the structured per-citation report +
delivery_blockedflag. - Never modifies the draft itself — modifications happen via the gate options chosen by the user or the pipeline.
Signals
- GitHub stars
- 38
- Forks
- 8
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
citation-content-verify- Source
- github.com/fedec65/bettercallclaude