ADR-0025 — folio fix + validate broken-reverse gate (双方向 link materialize, REQ-REL-002/004)

Status: accepted · Date: 2026-05-26 · folio v0.5.0-draft · forward (X4-B、 user 承認済 (AskUq)、 実装は SPAWN + feature-dev)

§1. Context

relations §5 は双方向 dual の 6 対象関係 (forward/reverse pair) と EARS 要件 (REQ-REL-002 reverse auto-materialize / REQ-REL-004 broken-reverse 検出) を既に規範化済。 ADR-0003fix を CLI subcommand として authorize 済 (HOW は実装時確定)。 X4-B はこの双方向 link の detect (validate) ↔ remediate (fix) ペアを実装する。 fix の core mission は folio の「architecture/ 構造を作成し維持する」 の「維持」 半分 (validate=検出、 fix=修正)。

user 承認 (AskUq): scope = fix + validate broken-reverse gate の両方、 記録 = ADR-0025 起票。 本 ADR は (a) fix の具体 scope と (b) validate を ADR-0020 の 2-gate から 3-gate へ拡張する決定を確定する。

§2. Decision

§2.1 folio fix (REQ-REL-002 = reverse auto-materialize)

folio fix は spec graph 全体を走査し、 §5.1 の 6 dual pair について forward relation A→B が宣言されていれば、 target B の JSON-LD <head> に対応する reverse relation B→A を materialize する:

forwardmaterialize する reverse
dc:replacesdc:isReplacedBy
dc:referencesdc:isReferencedBy
dc:hasPartdc:isPartOf
folio:depends-onfolio:depended-by
folio:extendsfolio:extended-by
folio:implementsfolio:implemented-by

fix は idempotent (既存 reverse は重複追加しない)。 reverse の @id は target B から見た source A への相対 path に正規化する。 exit code は 0 = success (materialize 実行 or 既に完備) / 2 = tool error (fail-closed)。 precedent = log4brains Adr.supersedeBy() (§5.2)。

§2.2 validate broken-reverse gate (REQ-REL-004、 ADR-0020 拡張)

folio validate第 3 gate「broken-reverse」を追加する: forward relation A→B が存在するのに target B に reverse B→A が欠けていれば violation を報告 (exit 1)。 これは ADR-0020 の試作 scope (gate (a) link-integrity + gate (b) jsonld-structural の 2-gate) を 3-gate に拡張する決定である (ADR-0020 §2.2 が broken-reverse を当初 scope 外としていた点を本 ADR が更新)。 detect (validate gate) ↔ remediate (fix) が対をなし、 folio fix 後に folio validate が clean になる。

§2.3 self-host dogfood + frozen ADR の扱い

本 gate を有効化するには folio 自身の spec graph が双方向完備でなければならない。 現状 folio は forward relation を多数持つ (dc:references ~21 file 等) が reverse は 0 件。 よって X4-B 実装時に folio fix を folio 自身の graph に適用し全 reverse を materialize する (self-host dogfood、 fix の実証も兼ねる)。 この materialize は frozen ADR の JSON-LD <head> にも reverse relation を追加する (例: ADR-0003 が他 ADR から参照されていれば dc:isReferencedBy を追加)。 これは ADR 本文 (決定内容) の改訂ではなく link-graph metadata の維持であり、 X4-C で許容された frozen ADR の cross-ref rewrite (P-6 link-integrity 維持) と同性質。 clean な 3-gate validate のため不可避。

§2.4 goldens

reverse materialize で inventory relations が約 2 倍 (forward + reverse) に増えるため、 inventory-gen / prime-digest / validate-clean golden を全再生成する。 validate-violations は broken-reverse fixture を追加する場合に更新。

§2.5 検証 (REQ-VER-015)

verification §3.6 REQ-VER-015 + cli-golden で検証する: (a) folio fix が broken-reverse を materialize し exit 0、 (b) fix 後に folio validate (3-gate) clean、 (c) idempotency (再 fix で no-op)、 (d) broken-reverse を seed した fixture に対し validate が violation を報告 (exit 1)。 scenario / golden / 検証 harness の具体 HOW は SPAWN (feature-dev) が実装時に確定。

§3. Consequences

Positive

Negative

Neutral

§4. Alternatives Considered

採用可否
fix + validate broken-reverse gate 両方 (採用)detect↔remediate の完全ペア、 §5 の REQ-REL-002+004 を共に実現 (AskUq)
fix のみ (gate なし)不採用 — 検出機構がないと reverse 欠落を機械検知できず、 双方向完備を保証できない (AskUq で両方を選択)
broken-reverse を hard violation でなく warning に不採用 — REQ-REL-004 は Phase X3+ で violation (exit 1) と規定。 gate として CI で fail させ完備を強制
frozen ADR を reverse materialize から除外不採用 — 除外すると forward→frozen-ADR の reverse が欠け gate が clean にならない。 link metadata の維持は本文改訂でなく X4-C 同様許容 (§2.3)

§5. Trace