Skip to content
Back to skills

Citation Content Verify

ASecurity

Substantive 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 retri...

  • 39 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added August 31, 2026
ai-agentsgobashdatabase

Works with

  • mcp

Security analysis

A100/100

Scanned August 31, 2026

npx -y skills add fedec65/bettercallclaude --skill citation-content-verify --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Citation Content Verify?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Citation Content Verify
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/fedec65-citation-content-verify/badge)](https://www.skillsdirectory.com/skills/fedec65-citation-content-verify)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: citation-content-verify
description: "Substantive 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)."
tools:
  - Read
  - Grep
  - Glob
  - Bash
  - WebSearch
  - WebFetch
  - mcp__plugin_bettercallclaude_legal-citations__extract_citations
  - mcp__plugin_bettercallclaude_legal-citations__parse_citation
  - mcp__plugin_bettercallclaude_legal-citations__validate_citation
  - mcp__plugin_bettercallclaude_legal-citations__review_citations
  - mcp__plugin_bettercallclaude_fedlex-sparql__lookup_statute
  - mcp__plugin_bettercallclaude_fedlex-sparql__get_article
  - mcp__plugin_bettercallclaude_entscheidsuche__search_decisions
  - mcp__plugin_bettercallclaude_entscheidsuche__get_decision_details
  - mcp__plugin_bettercallclaude_onlinekommentar__search_commentaries
  - mcp__plugin_bettercallclaude_onlinekommentar__get_commentary_for_article
  - mcp__plugin_bettercallclaude_swiss-caselaw__cite
  - mcp__plugin_bettercallclaude_swiss-caselaw__get_decision
  - mcp__plugin_bettercallclaude_swiss-caselaw__get_erwaegung
  - mcp__plugin_bettercallclaude_swiss-caselaw__get_regeste
  - mcp__plugin_bettercallclaude_swiss-caselaw__find_relevant_erwaegung
  - mcp__plugin_bettercallclaude_swiss-caselaw__check_claim_support
  - mcp__plugin_bettercallclaude_swiss-caselaw__attest_response
  - mcp__plugin_bettercallclaude_swiss-caselaw__get_doctrine
  - mcp__plugin_bettercallclaude_ollama__ollama_check_status
---

# Citation Content Verify

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):

- **`strict` mode**: privileged content MUST NOT cross to cloud content-checks. Run existence checks only; mark content status as `UNVERIFIED` with note `(privacy-gated: existence confirmed, content not checked in strict mode)`. Optionally offer local-only review via the ollama server.
- **`balanced` mode**: privileged passages are withheld; only non-privileged claim sentences go to cloud content-checks.
- **`cloud` mode**: 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` → fallback `bge-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_erwaegung` or `get_erwaegung` for the verbatim snippet; `confidence=low`/`no_match` on the pinpoint downgrades to at most `PARTIAL`.

**`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:

```json
{
  "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:

1. **Fix** — remove or replace the citation (and re-run this stage on the revised draft).
2. **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)*.
3. **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 `MATCH` without a real tool retrieval behind it — a `MATCH` from 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`/`UNVERIFIED` finding.
- 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_blocked` flag.
- Never modifies the draft itself — modifications happen via the gate options chosen by the user or the pipeline.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.