ADR-0019 — path boundary hook (Option Pragmatic: content-marker 検出)

Status: accepted · Date: 2026-05-25 · folio v0.4.2-draft · retrospective (実装 + e2e 検証済)

§1. Context

ADR-0003 §2.1 は PreToolUse hook「path boundary」 を「spec dir 外への作成を block」 と WHAT level で列挙したが、 spec 作成の検出 mechanism (「spec が作られようとしている」 をどう判定するか) は未確定だった。 試作中、 検出方式の選択肢は full HTML/meta DOM parse から path heuristic only まで幅があり、 採用した「Option Pragmatic」 は scenarios/path-boundary.yaml / verification.html §3.6 / specs/README §6.3 で名称参照されるのみで、 正式な決定記録を欠いていた。

本 ADR は「Option Pragmatic」 を正式に定義し、 ADR-0006 (caller marker) との防御責務分担を明文化する (retrospective、 実装 + e2e 検証後)。

§2. Decision

§2.1 Option Pragmatic = content-marker 検出

.claude-plugin/scripts/check-path-boundary.shPreToolUse (Write) hook として実装し、 以下の条件を 全て満たす時に deny する:

  1. tool = Write (Edit は既存 file 修正のため対象外)
  2. file_path が .html
  3. content に folio-doc-type=spec marker を含む (regex、 閉じ quote で word boundary、 属性順 agnostic、 single/double quote 両対応)
  4. file_path が FOLIO_SPEC_PATH (既定 scratch/specs/) 配下でない

§2.2 word boundary による false positive 回避

content marker 検出は閉じ quote で boundary を取り (content="spec" は match、 content="spec-draft" は match しない)、 属性順 (name 先 / content 先) と quote 種別 (single / double) の両方を許容する。

§2.3 caller marker との防御責務分担

path boundary は caller marker (ADR-0006) と直交する 2 gate を構成する:

両者の組合せにより「spec は spec_path にのみ存在し、 architect のみが編集する」 を保証する。 path boundary は marker が set 済でも spec_path 外作成を捕捉する (e2e walk S-B2)。

§3. Consequences

Positive

Negative

Neutral

§4. Alternatives Considered

採用しなかった理由
案 Strict: full meta/DOM parse で folio-doc-type 抽出bash での HTML parse は脆弱 + overhead。 試作段階に過剰
案 Pragmatic (採用): content marker の grep 検出 + spec_path 配下判定純粋 grep・高速・精度十分。 word boundary で false positive 回避
案 Path-only: path heuristic のみ (content check 無し)非 spec の .html (research report / cluster-readme) を false positive で block
案 None: caller marker のみに依存caller marker は spec_path 配下の編集のみ gate。 spec_path への spec 作成を阻止できない (防御の穴)

§5. Trace