---
name: citation-sync
description: "研究 repo の引用 3 層 (docs 実引用 → .zenodo.json references → graph.jsonld ExternalReference) を監査し、下層から順に同期する orchestrator。旧層 4 (Wikidata P2860) は 2026-07 の governance revocation により恒久 retire (authorship-strategy ADR-0021) — 同期対象にしない。Use when the user says 「参考文献が少ない/足りない」「引用がずれてる」「citation を同期して」「引用文献を graph に反映して」, when new external papers were cited in ADR/glossary/empirical docs, or before a release of a DOI-registered repo. 単層の実装は release-doi (.zenodo.json) / jsonld-knowledge-graph (graph) に defer し、本 skill は層間の divergence 検出・curation 基準・同期順序だけを持つ。NOT for: 論文 (paper item) 自体の reference list 整備 (paper-deposit が担当)、引用を含まない repo。"
compatibility: Developed and tested on Claude Code; portable to other Agent Skills-compatible agents.
user-invocable: true
origin: shimo4228
---

# Citation Sync

研究 repo が外部文献を引用するとき、その引用は 3 つの層に現れる。層はそれぞれ別の audience に向けて伝播するため、**どれか 1 つに書いて終えると残りの層では引用が存在しないことになる**。本 skill はこの 3 層の divergence を検出し、下層から順に揃える。

| 層 | 担体 | 伝播先 | 実装 skill |
|---|---|---|---|
| 1. docs | ADR / glossary / empirical / README 内の引用 | 人間 + LLM crawler | (執筆時に発生) |
| 2. zenodo | `.zenodo.json` `related_identifiers` (`relation: references`) | DataCite → OpenAIRE / Scholix (次 release 時) | `release-doi` |
| 3. graph | `graph.jsonld` の `ExternalReference` ノード | LLM ingest / HF mirror / knowledge-graph crawler | `jsonld-knowledge-graph` |
| ~~4. wikidata~~ | ~~repo item の P2860 (cites work)~~ | **RETIRED 2026-07** — governance revocation で全 item 削除 (ADR-0021)。監査・同期対象外、`--skip-wikidata` を常用 | (retired) |

**docs 層が source of truth**。上の層は docs に実在する引用だけを carry する (捏造辺の禁止)。逆に docs に引用を足したら、上 3 層への反映はこの skill の同期で行う — 「repo markdown に引用を書くだけでは citation graph に不可視」というのが authorship-strategy の citation-graph federation tactic の出発点。

## Phase 0: Audit (read-only)

```bash
python3 ~/.claude/skills/citation-sync/scripts/citation_audit.py REPO_DIR [REPO_DIR ...]
#   --skip-wikidata   retired 層 (旧層 4) の探索を省略。常に付ける
#   --json OUT.json   機械可読の結果も保存
# exit 0 = 全 repo converged, 1 = divergence あり, 2 = fatal
```

repo ごとに identifier × 層のマトリクスを出す (docs / zenodo / graph の 3 層)。

**先に audit、議論はそれから。** どの層が欠けているかを推測で語らない — 今日の層別カバレッジは repo ごとに本当にバラバラで、直感は外れる (実例: ある repo は zenodo refs が空、別の repo は graph と zenodo が互いに素の集合を指していた)。

## Phase 1: Curate (判断層)

audit が出した docs 層の identifier を、repo の公式引用に昇格させるか判定する。機械抽出は過剰検出を含むので、**この phase だけは人間判断 (または明示基準の適用) が必要**:

- **公開 docs のみ**: `.notes/` (paper 草稿・scratch) は repo の引用ではない。paper 草稿の references は paper item 側の federation が担当する (二重計上しない)
- **引用文脈であること**: 文献として参照している言及だけを採る。例の中の ID、CHANGELOG の作業記録、tool 出力の貼り付けは引用ではない
- **external のみ**: sibling repo の Zenodo DOI は ecosystem cross-link であって external citation ではない (audit が別枠で報告する)
- **識別子と内容の一致を検証する**: 昇格前に arXiv API / Crossref でタイトルを引き、docs の引用文脈と照合する。LLM が書いた引用 link の arXiv ID は hallucination しうる (実例: 「GlassWorm」への引用が無関係な Novel View Synthesis 論文の ID を指していた — 正しい出典は arXiv ではなくベンダーのセキュリティレポートだった)。不一致なら昇格せず、docs 側の引用を正す
- 迷う識別子は出現箇所を `grep -rn` で開いて文脈を見る。昇格させない判断も記録する (次回 audit で同じ識別子を再審査しない)

## Phase 2: Sync `.zenodo.json` (層 2)

curate 済みの引用を `related_identifiers` に追加する。entry 形式・arXiv の DataCite DOI 形 (`10.48550/arXiv.NNNN.NNNNN`)・重複排除は **`release-doi` skill の citation surface 同期 section が正本**。注意: `.zenodo.json` は **次の release 時に** DataCite metadata として propagate する (commit しただけでは外に出ない — それでも commit しておくのが正しい。release 時に自動で乗る)。

## Phase 3: Sync `graph.jsonld` (層 3)

curate 済みの引用を `ExternalReference` ノードとして graph に追加する。ノード形状 (@id = arXiv abs URL / @type / identifier / datePublished) は **`jsonld-knowledge-graph` skill が正本**。description には「なぜこの repo がこれを引くか」を 1-3 文で書く — anchor-densely (vocabulary discipline) の実践であり、LLM ingest 時に引用関係の意味が残る。push 後は HF mirror (`hf-sync`) も同期する。

## Phase 4: Federate to Wikidata (層 4) — RETIRED (2026-07)

**この Phase は実行しない**。Wikidata アカウントの governance revocation（promotion-only 判定、全 item 一括削除）により、self-created な authority-record 辺は authorship-strategy ADR-0021 で恒久 retire。audit は `--skip-wikidata` で回す。graph 内に dead QID sameAs を見つけたら purge する（ADR-0021 の purge 規律）。

## Phase 5: Verify

Phase 0 の audit を再実行し、全 repo `CONVERGED` を確認してから完了報告する。divergence が残る場合は、それが意図的 (例: graph には載せるが zenodo は次 release でまとめる) かを明記する。

## Pitfalls

| Pitfall | 回避 |
|---|---|
| 層が時期差で乖離する (graph は今日足したが zenodo は半年前のまま) | 引用を 1 本でも足したらこの skill を通す。release 前は必ず Phase 0 を回す |
| docs の機械抽出を無批判に昇格させる | Phase 1 の curation 基準を適用。`.notes/` 由来と非引用文脈を落とす |
| paper の references を repo 層に混ぜる (またはその逆) | paper の引用は paper の reference list から、repo の引用は repo docs から。担体が違う (paper 側は `paper-deposit` の担当) |
| sibling DOI を external citation として数える | ecosystem cross-link は別枠。audit script が自動で分離する |
| graph に既存の内部 bibliography 規約があるのに新ノードを追加して重複させる | Phase 3 の前に graph 内を被引用文献の名前でも grep する（例: `ans:ref/sharf-2014` が既にあるのに DOI @id の新ノードを足してしまった）。既存ノードがあれば identifier / url / sameAs を**追記**する方が正しい |
| 複数行 node 形式前提の text-surgery script が 1 行ノード形式の graph で JSONDecodeError | graph への機械的注入 script は pretty-print 前提で書かれがち。1 行ノードの graph は手動 Edit（または Python 文字列置換 + json 検証）で注入する。失敗時にファイル無傷となるよう書き込み前 validation を挟む |
| docs が識別子無しで引用 (名前のみ) → audit が docs 層欠落として DIVERGED を報告 | 識別子ベース比較の既知の限界。引用が docs に実在するなら**意図的残差**として完了報告に明記すれば良い（docs に ID を書き足す義務はない）|
| graph 層が audit で全行空欄 (citation node が `ScholarlyArticle` 単独型) | audit script は `ExternalReference` 型のみを層 3 として検出する。citation node は `["ExternalReference", "ScholarlyArticle"]` の dual-type にする（AKC は v2.3.0 で全 prior-art node を移行済み。@context に `ExternalReference` の定義があるか先に確認）|
| 括弧入り DOI (例: Bainbridge `10.1016/0005-1098(83)90046-8`) が docs/graph 層で truncate され永続 DIVERGED | script の DOI regex は `)` を終端扱いする既知制約。zenodo 層でのみ carry し、当該 graph node は dual-type から**除外**（truncate された偽 ID 行の発生防止）、**意図的残差**として記録して CONVERGED 相当と判定する |

## Related skills

- `release-doi` — 層 2 の正本。release workflow 内の citation surface 同期
- `jsonld-knowledge-graph` — 層 3 の正本。ExternalReference ノード設計
- ~~`wikidata-federation`~~ — **削除済み** (旧層 4。2026-07 governance revocation → ADR-0021 で恒久 retire、skill 本体は harness から削除。経緯は project memory `wikidata-qids` 参照)
- `hf-sync` — 層 3 更新後の mirror 反映
