読み順: §1 概念 → §2 scope → §3 EARS 規範 → §4 実装。 着手前は §1 + §3 必読。
「verification」 の canonical 定義章 (他 spec はここへ参照、 P-5)。
検証の 3 state を canonical 定義する (下表)。
| concept | 定義 | 担当 |
|---|---|---|
| sandbox-verified | plugin の機能 (use case) が tests/scenarios/ 配下の YAML scenario で実機検証され、 期待挙動 (exit code + stderr + baseline) と一致した状態 |
folio framework (本 spec) |
| experiment-verified | spec 内の各 claim (HOW level) が個別実機検証された状態 (twill plugin が採用する 4-state lifecycle: proposed / accepted / experiment-verified / archived) | 本 framework scope 外、 将来別 plugin folio-claim-verifier (仮称) で対応 (ADR-0015) |
| unverified | 上記いずれも未実施。 spec 上の規範 (EARS REQ) は存在するが実機 verify がない初期状態 | — |
本 framework は sandbox-verified のみを対象とする MUST。
検証対象と非対象の境界章 (in-scope 3 カテゴリ / out-of-scope 3 種)。
検証対象は plugin behavior・spec 整合性・CI gate (REQ-CI-010〜016) の 3 カテゴリ。
本 framework の検証対象は以下 3 カテゴリ:
scope 外 3 種と、 in-scope な hook unit test の用語整理 (用語衝突)。
.claude-plugin/scripts/ 配下で個別実装)。 ⚠ §4.1 Step 1 の 「hook script unit test」 は script の stdin / exit code / stdout の契約を実機検証する black-box 行動検証であり、 本項 (white-box 内部 test) とは別概念で in-scope (用語衝突の整理、 ADR-0026)規範要件を EARS で集約する章。 図 1 が verification model の全体像。
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#2a4d6e', 'primaryTextColor': '#ffffff'}}}%%
flowchart TB
accTitle: folio verification model
accDescr: scenario YAML を runner が読み、 hook mock payload (kind:hook) または CLI golden (kind:cli-golden) で実行し、 exit_code / file-state / golden-diff のいずれかで assert する流れ。
SC["scenario YAML
tests/scenarios/"]
RUN["runner.sh"]
HK["hook mock
kind: hook"]
CL["CLI golden
kind: cli-golden"]
EX["assert
exit_code"]
FS["assert
file-state (e2e)"]
GD["assert
golden diff"]
SC --> RUN
RUN --> HK
RUN --> CL
HK --> EX
HK --> FS
CL --> GD
classDef src fill:#e6f6f2,stroke:#1e7b65,color:#08131a;
classDef run fill:#2a4d6e,stroke:#08131a,color:#ffffff;
classDef br fill:#fefbea,stroke:#916626,color:#08131a;
classDef as fill:#fdf3f3,stroke:#b22323,color:#08131a;
class SC src;
class RUN run;
class HK,CL br;
class EX,FS,GD as;
runner.sh が scenario YAML を hook mock / CLI golden で実行し、 exit_code / file-state / golden diff で assert する。検証 scenario の format と参照 req_id を定める (REQ-VER-001 / 002)。
tests/scenarios/ 配下の YAML ファイル (構造は §3.2 で定義)。
REQ-VER-001: Each verification scenario file SHALL be a YAML file placed under tests/scenarios/ with the structure defined in §3.2.
req_id を 1 つ参照する (rules §10 / relations §5.3、 または verification 固有の REQ-VER-*)。
REQ-VER-002: Each scenario SHALL reference one canonical req_id from rules.html §10 (REQ-CM-* / REQ-CI-*) or relations.html §5.3 (REQ-REL-*), or be a verification-specific REQ-VER-* defined in this §3.
scenario YAML の 2 種 (hook / cli-golden) の schema を定める。
schema_version: "0.1"
req_id: "REQ-VER-001" # REQ-CM-* / REQ-CI-* / REQ-REL-* / REQ-VER-* のいずれか
ears_pattern: "ubiquitous" # event-driven | state-driven | ubiquitous | unwanted | optional
description: |
本 scenario が検証する規範要件の概要 (EARS 文)。
setup:
env: { ... } # 環境変数
fixtures: [ ... ] # fixture file の配置
scenarios:
- name: "..." # scenario 名
given: # Gherkin Given (前提)
env: { KEY: "value" } # 環境変数 (任意、 例 FOLIO_ARCHITECT_CONTEXT)
file_path: "..." # tool に渡す対象 file path (相対 or 絶対)
content: | # Write tool 時の file 内容 (任意、 marker/JSON-LD 検出に使用)
...
when: # Gherkin When (トリガー)
tool: "Edit|Write|NotebookEdit" # mock payload の tool_name
expect:
exit_code: 0|2|N # § 3.3 (assertion 戦略) 参照
stderr_contains: "..."
stdout_contains: "..."
decision: "allow|deny" # informative、 主 assertion は exit_code
teardown:
cleanup_files: [ ... ]
scenario kind: 上記は hook を mock payload で叩く kind: hook (既定、 省略可) の schema。 CLI subcommand (bin/folio) を golden 比較で検証する kind: cli-golden は次の field を持つ (REQ-VER-011、 hook payload field は無視)。 出力ソース capture (file | stdout) と比較方式 compare (json | text) の 2 軸で 2 種の CLI 出力に対応する:
schema_version: "0.1"
req_id: "REQ-VER-010" # 検証対象 REQ
kind: "cli-golden" # hook (既定) | cli-golden
description: |
CLI subcommand の出力を golden と比較する。
command: ["inventory"] # bin/folio に渡す引数列
capture: "file" # file (既定) = output_file を読む | stdout = command の stdout を捕捉
output_file: "inventory.json" # capture:file 時、 CLI が生成する成果物 (repo root 相対)
compare: "json" # json (既定) = jq -S 正規化 + exclude_paths 除外 | text = plain byte-exact
normalize:
exclude_paths: [".generatedAt"] # compare:json 時、 除外する非決定的 field (jq path)
golden: "baselines/reference/inventory.golden.json" # 期待値 (VCS 管理、 §3.4 REQ-VER-004)
expect:
exit_code: 0
例: inventory-gen.yaml (REQ-VER-010) は capture:file + compare:json (inventory.json を jq 正規化比較)。 prime-digest.yaml (REQ-VER-012) は capture:stdout + compare:text (folio prime の text digest を byte-exact 比較)。
assertion の主軸を exit_code に定める (REQ-VER-003 / REQ-VER-006)。
exit_code とする。
REQ-VER-003: Each scenario expect block SHALL specify exit_code as the primary assertion.
permissionDecision JSON を主軸にすべきでない (upstream bug 既知ゆえ、 §3.3 の exit_code 中心と対)。
REQ-VER-006: Scenario assertion SHOULD NOT rely on permissionDecision JSON output as primary, due to known upstream bugs (Issue #37210 / #33106 / #39344 / #18312、 すべて Closed/not planned 状態 ―― 詳細は research §2.6)。
golden baseline の 2-dir model と accept 規律 (REQ-VER-004)。
reference/ = VCS golden / local/ = 実行生成・gitignore)。 更新は明示的 accept workflow (--accept) を経る。
REQ-VER-004: baseline file SHALL follow the TypeScript compiler 2-dir model: tests/baselines/reference/ (VCS 管理、 golden) vs tests/baselines/local/ (実行生成、 .gitignore)。 baseline 更新は明示的 accept workflow (例: runner.sh --accept) を経る MUST。
各 EARS pattern と Gherkin 構文 (Given / When / Then) の 1:1 対応を下表に示す。
各 EARS pattern と Gherkin 構文の対応:
| EARS pattern | Gherkin 対応 |
|---|---|
| Ubiquitous | Given (初期) + When (任意) + Then |
| Event-Driven | Given (前提) + When (トリガー) + Then |
| State-Driven | Given (状態) + When + Then |
| Unwanted Behavior | Given + When (エラー) + Then (復旧) |
| Optional Feature | Given (機能有効) + When + Then |
変換 reference: conductofcode.io EARS-to-BDD / RequireKit。
試作検証専用の REQ-VER-007〜023 を定義する (各 scenario file が SSoT 実装)。
以下は rules.html §10 / relations.html §5.3 に canonical REQ を持たない、 試作 plugin の検証専用 REQ (§3.1 REQ-VER-002 の verification-specific 条項に従う)。 対応 scenario file (REQ-VER-009 は agent-driven runbook) が SSoT 実装。
spec_path 外への spec (.html) 作成は、 PreToolUse path-boundary hook が deny する (exit 2)。
REQ-VER-007: IF a Write tool creates a .html file carrying <meta name="folio-doc-type" content="spec"> outside the configured spec_path, THEN the PreToolUse path-boundary hook SHALL deny (exit 2)。 scenario: scenarios/path-boundary.yaml (ADR-0003 §2.1 Option Pragmatic、 絶対 path 配下も第 2 branch *"/$2"* で gate)。
README.html index に未掲載の新規 .html 作成は、 PostToolUse README-index hook が notify する (exit 2、 file は作成済の staleness 通知)。
REQ-VER-008: IF a Write tool creates a .html file under a cluster directory that contains a README.html index, and the new file is not listed in that index, THEN the PostToolUse README-index hook SHALL notify (exit 2、 PostToolUse のため file は作成済)。 scenario: scenarios/readme-index.yaml。 これは check 型 staleness 通知で、 ADR-0003 §2.1「README update」の試作 slice。 ADR literal は「自動更新 (mutate)」だが 試作は check 型を採用 (divergence trace = specs/README.html §6.2)。
REQ-VER-009: WHEN the folio plugin is verified as an integrated tool in a live-loaded session (§4.1 Step 2 worktree integration), an agent SHALL walk the e2e runbook scenarios (tests/e2e/runbook.md) by issuing real Edit/Write tool calls so the live hooks fire, and SHALL record per-scenario observations as golden baselines under tests/e2e/baselines/reference/。 primary assertion = file 作成有無 (PreToolUse deny ⇒ file 不在、 PostToolUse notify ⇒ file 存在 + 通知)。 deny は transcript に確実には現れない (research §2.6) ため、 exit code でなく file system state を一次 assertion とする。 実装 = tests/e2e/ (runbook + golden、 sandbox 単体テストの mock payload 検証 (REQ-VER-001〜008) とは別 layer の統合検証)。
folio inventory は relations §4.1 schema 準拠の inventory.json を生成する (§4.4.1 の dir を走査、 cli-golden diff で検証、 非決定的 generatedAt は除外)。
REQ-VER-010: WHEN the folio inventory CLI subcommand runs, it SHALL produce an inventory.json conforming to the relations.html §4.1 schema (required fields $schema / generatedAt / folioVersion / specs[]), scanning the directories defined in relations.html §4.4.1。 conformance は §3.4 golden baseline との kind: cli-golden diff で検証する (非決定的 generatedAt は normalize.exclude_paths で除外)。 scenario: scenarios/inventory-gen.yaml (REQ-VER-011 harness が実行)。
kind: cli-golden の scenario は、 harness が bin/folio を repo root で実行し output と golden を jq 正規化して byte-exact 比較 + exit_code 一致を assert する (CLI 検証の SSoT、 hook 経路と別)。
REQ-VER-011: WHEN a scenario carries kind: cli-golden, the verification harness SHALL (1) run bin/folio with the scenario command at repo root, (2) normalize both the produced output_file and the golden via jq -S with normalize.exclude_paths deleted, and (3) assert byte-exact equality of the normalized JSON plus exit_code match。 golden 更新は明示的 accept workflow (--accept、 §3.4 REQ-VER-004) を経る MUST。 これは hook scenario (kind: hook) の exit-code 中心 assertion (REQ-VER-003) とは 別の assertion 経路を成す (CLI subcommand 検証の SSoT、 ADR-0018 で trace)。
folio prime は Tier 1 inventory digest (per-spec @id/title/summary/doc-type/status) を stdout に出力する (inventory.json stale なら自動再生成、 実 context 注入は SessionStart e2e で検証)。
REQ-VER-012: WHEN the folio prime CLI subcommand runs, it SHALL emit a Tier 1 inventory digest (per-spec @id / title / summary / doc-type / status、 relations.html §4.2 Tier 1) to stdout as agent-readable text, auto-regenerating inventory.json if missing or stale (ADR-0007 §2.4)。 conformance は §3.4 golden baseline との kind: cli-golden (capture: stdout + compare: text) diff で検証する。 scenario: scenarios/prime-digest.yaml。 SessionStart hook による実 context 注入 (ADR-0007 §2.1、 matcher 省略で全 source 発火) は e2e (REQ-VER-009 型) で検証 = SessionStart:startup 注入 PASS (fresh session で Tier 1 digest が context に注入されることを確認)。 PreCompact は ADR-0007 amend (2026-05-25) で除去 (stdout 非注入)。
folio validate は spec 集合を走査し (a) internal link-integrity + (b) jsonld structural の 2 gate を検査する (exit 0=clean / 1=violation / 2=tool error、 --root で検査 root override 可、 prose gate は試作 scope 外)。
REQ-VER-013: WHEN the folio validate CLI subcommand runs, it SHALL scan the spec set (relations.html §4.4.1 と同一 = architecture/{spec,decisions,research} の <head> JSON-LD .html) and check two gates: (a) internal link-integrity — each JSON-LD relation @id resolves to an existing target file, and any #anchor resolves to an existing id in that target (REQ-CI-010 の (b)+(c)); (b) jsonld structural — parse + required @context/@id/@type + @context == object (REQ-CI-016、 ADR-0004 Option B Light)。 exit code は 0 = clean / 1 = violation 検出 / 2 = tool error (jq 不在等、 fail-closed)、 違反は human-readable report を stdout 出力する。 検査 root の override (test isolation) を提供する MUST。 external URL check と prose gate (REQ-CI-011〜015) は 試作 scope 外 (Phase X4+、 ADR-0020 §2.2)。 conformance: clean 集合は scenarios/validate-clean.yaml (cli-golden、 capture:stdout、 exit 0)、 violation 検出 (missing file ref / broken anchor / jsonld 構造違反の 3 種) は実装時に scenarios/validate-violations.yaml + seeded fixtures で 実証する MUST (exit 1 + report)。 ADR-0020 で trace。
folio init は canonical Layer 1 consumer layout (構造のみ) を scaffold する — architecture/{spec,decisions,research}/ + 各 README.html + folio.config.yaml。 既存 file は preserve (idempotent)、 constitution/overview 本文は seed せず lazy-materialize、 生成 skeleton は folio validate clean。
REQ-VER-014: WHEN the folio init [<dir>] CLI subcommand runs, it SHALL scaffold the canonical Layer 1 consumer layout の純粋な構造のみ — architecture/{spec,decisions,research}/、 各 cluster の README.html (P-6 entry point、 index は実在 file のみ dc:hasPart 宣言)、 architecture/spec/{constitution,overview}.html (project starter template、 通常 conforming JSON-LD)、 および folio.config.yaml (rules §2 schema: folio_version / spec_path / caller_marker_env / caller_marker_value / review_model) — そして既存 file は preserve (idempotent、 上書きしない)。 constitution / overview の本文 (実体) は seed しない — folio-architect の greenfield onboarding grilling が引き出した中身を Phase E で lazy-materialize する (§7.1、 ADR-0031 が ADR-0024 の seed 挙動を revise)。 これで空 placeholder が "done" に残る hollow-spec を構造的に排除する。 生成された skeleton は folio validate が clean (exit 0) である MUST (P-6 orphan + link-integrity + jsonld structural を満たす seed)。 exit code は 0 = success / 2 = tool error (fail-closed)。 conformance は scenarios/init-scaffold.yaml (cli-golden) で検証する: init を temp root に実行 → exit 0 + 生成 tree の file 集合 + folio.config.yaml の golden 比較 + folio validate --root <tmp>/architecture clean。 init は tree (複数 file) を生成するため既存 cli-golden harness (単一 output) の拡張が要る可能性があり、 その HOW は実装時に確定する。 scope 決定は ADR-0024 (seed 挙動は ADR-0031 で revise) で trace。
folio fix は各 forward relation に対応する reverse relation を target に materialize する (idempotent、 exit 0)。 併せて folio validate は第 3 gate broken-reverse を持ち、 fix 適用後は 3-gate clean になる (detect↔remediate 対)。
REQ-VER-015: WHEN the folio fix CLI subcommand runs, it SHALL materialize, for each forward relation declared in any spec (relations §5.1 の 6 dual pair), the corresponding reverse relation on the target spec's <head> JSON-LD (REQ-REL-002)、 idempotent に (既存 reverse は重複追加しない)、 exit 0。 併せて folio validate は第 3 gate「broken-reverse」を持ち、 forward に対応する reverse が target に欠ける場合 violation を報告する MUST (REQ-REL-004、 exit 1)。 folio fix 適用後は folio validate (3-gate) が clean になる (detect↔remediate ペア)。 conformance は cli-golden + fixture で検証する: (a) fix が reverse を materialize + exit 0、 (b) fix 後 validate clean、 (c) idempotency (再 fix で no-op)、 (d) broken-reverse を seed した fixture に validate が exit 1。 scenario / golden / harness の HOW は実装時に確定。 scope 決定は ADR-0025 で trace (validate を ADR-0020 の 2→3 gate に拡張)。
folio-architect SKILL の Phase F は review agent (spec-review-{ears,vocabulary,ssot}) を並列 spawn し structured findings を集約する。 検証は structural (agent .md frontmatter + scoped name resolvable) + e2e (seeded violation の flag 観察) の 2 経路。
REQ-VER-016: WHEN the folio-architect SKILL executes Phase F (Quality Review), it SHALL spawn the Phase F review agents in parallel (spec-review-{ears,vocabulary,ssot} = X4-D の 3 軸、 残 3 軸 structure/temporal/stakeholder は X5+) and aggregate their structured findings (severity / location / 違反 rule / 修正提案)。 検証は 2 経路: (a) structural — 各 review agent の agents/<name>.md frontmatter (name / description / model / read-only tools) が妥当で、 scoped name folio:<name> が resolvable (frontmatter name 一致 + folio-architect SKILL が当該 scoped name を参照) であること (決定的、 sandbox 可)。 (b) e2e — 既知 violation (EARS 欠落 / forbidden synonym / domain 越境) を seed した spec に /folio-architect を invoke し、 3 review agent が該当 violation を flag することを観察する (REQ-VER-009 型 agent-driven runbook)。 LLM agent は非決定的ゆえ golden 比較でなく 「検出有無」 を一次 assertion とする。 conformance: (a) は scenarios/agent-structure.yaml (kind: agent-structural、 file 静的検査・決定的・exit 0)、 (b) は tests/e2e/ runbook S-G (live walk は plugin reload を要すため別 fresh session)。 review agent は read-only (Edit は folio-architect が集約後に適用、 caller-marker author 一元性)。 scope 決定は ADR-0027 で trace。
folio validate は object xref の 4 gate を追加検査する: resolve-integrity / uniqueness / tooltip-consistency (universal) + completeness (opt-in、 orphan-mention)。 正しい xref を持つ opt-in fixture は exit 0、 broken-xref / stale-tooltip / orphan-mention は exit 1 + report (rules §9 / ADR-0034 §2.6)。
REQ-VER-017: WHEN the folio validate CLI subcommand runs, it SHALL additionally check four object cross-reference gates (ADR-0034 §2.6): (1) resolve-integrity — each <a class="xref" href> resolves to an existing definition site; (2) uniqueness — each canonical ID is defined at most once as an id-bearing SSoT element; (3) tooltip-consistency — each data-tooltip matches the definition's current essence (§9.2 contract); these three are universal. (4) completeness — orphan-mention detection, applied only to docs that opt in via <meta name="folio-xref-completeness" content="enabled"> (conditional, REQ-XREF-002)。 conformance は scenarios/xref-validate-clean.yaml (cli-golden、 capture:stdout、 exit 0) + scenarios/xref-validate-violations.yaml (broken-xref / stale-tooltip / orphan-mention の 3 種を seed、 exit 1 + report)。 real corpus は xref dogfood 前 (opt-in 0) ゆえ本 gate 追加後も validate-clean.yaml が clean を維持する (additive、 keystone)。
folio fix は opt-in doc の prose 内 canonical token 初出を <a class="xref" href data-tooltip> に wrap する (option F materialize、 href + essence は §9.1/§9.2 contract、 idempotent)。 RED (orphan-mention) → fix → GREEN (completeness clean)。
REQ-VER-018: WHEN the folio fix CLI subcommand runs, it SHALL, for each doc that opts into xref-completeness, wrap the first prose occurrence of each auto-materializable canonical token (P-N / REQ-* / ADR-NNNN) into <a class="xref" href data-tooltip> with the href and data-tooltip derived from the §9.1 registry / §9.2 essence contract, idempotently (re-run = no-op、 既存 xref を持つ token は skip)。 非 opt-in doc では no-op (real corpus 不変、 keystone)。 conformance は scenarios/xref-fix.yaml (kind: cli-fix: pre-fix validate が orphan-mention で RED → fix exit 0 → post-fix validate clean → 再 fix idempotent)。 scope 決定は ADR-0034 §2.5 (option F) で trace。
folio validate は glossary gate を追加検査する: marked term (explicit + auto-mark とも <span class="term" data-term> に統一) の data-term が vocabulary.yaml に解決し (resolve)、 data-tooltip が definition と一致する (consistency)。 marked term は span 統一ゆえ <a class="term"> は anchor-residue として block する (hover-only 不可逆、 rules §9.5)。 生成 glossary.html の term 集合の vocab 一致 (vocabulary-parity) は nav-regen-drift の byte 検査が構造的に含意するため独立 gate を立てず、 対称差を regen-drift の violation message に surface する。 folio fix は marked term の tooltip を definition から materialize する (best-effort、 gap-lint なし、 rules §9.5 / ADR-0034 §2.8)。
WHEN the folio validate CLI subcommand runs and a vocabulary.yaml with definition fields exists, REQ-VER-019: it SHALL check a glossary gate over each marked term (<span class="term" data-term="<canonical>">, whether explicit or auto-marked — 共に span 形に統一): (1) resolve — data-term resolves to a canonical entry in vocabulary.yaml; (2) tooltip-consistency — data-tooltip equals that entry's definition; (3) anchor-residue — enforcing the span-only marking convention of rules §9.5 (which is the normative SSoT) by blocking any <a class="term"> in living spec/research prose ([glossary-anchor-residue]、 vocabulary.yaml 解決に依らず); all block (exit 1) on failure。 generated glossary.html term-set parity with vocabulary.yaml is structurally implied by the nav-regen-drift byte check (no independent parity gate; the symmetric difference is surfaced in the regen-drift violation message, conformance scenarios/glossary-parity-drift.yaml)。 folio fix SHALL materialize each marked term's data-tooltip from the definition, idempotently。 unmarked term mentions SHALL NOT be gap-linted (Class B best-effort)。 vocabulary.yaml 不在 / definition 無しは gate skip (additive、 keystone)。 conformance は scenarios/glossary-validate.yaml (unresolved + stale-tooltip を seed した fixture に validate が exit 1 + report、 resolved+consistent な clean 側は real corpus の glossary dogfood が keystone)。 scope 決定は ADR-0034 §2.8 で trace。
folio validate は dual-audience-structural gate を検査する: data-audience="human" requirement container (verbose section.req + compact details.spec-row の両 form) の machine 対応部存在 (-1) / requirement-id 整合 (-2) / data-audience 値域 (-3) / machine 部 aria-hidden 不在 (-4) / EARS-pattern 整合 (-5) を強制し、 違反は exit 1。 意味的 fidelity は floor 対象外 = ceiling (spec-review-fidelity agent)。
REQ-VER-020: WHEN the folio validate CLI subcommand runs, it SHALL check a dual-audience-structural gate over each data-audience="human" requirement container — both the verbose section.req card and the compact details.spec-row form, keyed by data-audience semantic (container-class 非依存、 ADR-0033 §2.5 / rules §7.2 2-form) — enforcing the five structural safety invariants REQ-DA-STRUCT-1..5: (1) the presence of a data-audience="machine" 子孫 (孤立 human の排除); (2) requirement-id 整合 (container id ↔ badge ↔ machine ears-id); (3) data-audience 値域 (machine | human のみ); (4) machine 部に aria-hidden 不在 (AI / accessibility-tree からの可視性保全); (5) EARS-pattern 整合 (human badge ↔ machine data-ears-pattern)。 違反は report + 非ゼロ exit (block gate)。 意味的 fidelity (essence が machine normative を忠実要約か) は本 floor の対象外であり、 ceiling = Phase F の spec-review-fidelity agent が担う (二層 enforcement、 ADR-0028 / ADR-0033 §2.4)。 本 gate は追加 arm として runtime-CDN script 検出 (rules §8 REQ-DA-JS-2 の vendoring 違反、 ADR-0039 §2.5 = 単一行 heuristic) も担う — conformance は validate-violations.yaml の cdn-script.html seed。 conformance は scenarios/validate-violations.yaml (da-violations.html が -1〜-5 を section.req + details.spec-row の両 form で 1 card 1 違反 = 計 10 違反 seed、 exit 1 + report) + scenarios/validate-clean.yaml (real corpus の dual-audience dogfood が clean 側 keystone)。 scope 決定は ADR-0033 §2.4 で trace (ADR-0020 の validate scope を dual-audience floor に拡張)。
folio validate は render-safety gate を検査する: <pre class="mermaid"> ブロック内の subgraph 多行タイトル (title bracket ["…"] に <br> を含む) を flag する。 mermaid が cluster-label の縦 padding を 1 行分しか確保せず 2 行目が子ノード/枠に overlap する render-後の幾何欠陥を、 DOM を見れない static lint が「既知の overlap パターン」として捕捉する (node label の <br> は対象外)。 違反は exit 1 (block)。 任意 overlap の網羅は browser-render を要する ceiling の領分。
REQ-VER-021: WHEN the folio validate CLI subcommand runs, it SHALL check a render-safety gate over each <pre class="mermaid"> block, flagging any subgraph whose title bracket (["…"]) contains a <br> (multi-line subgraph title) as a [render-safety] violation with non-zero exit, because mermaid reserves only one line of vertical padding for the cluster-label so the second line overlaps child nodes / the box border at render time — a post-render geometric defect the static, browser-less validate cannot observe directly, so the gate pattern-lints the known overlap-prone form (rules §4.5)。 node-label <br> は対象外 (node が自動 sizing するため overlap しない); mermaid を持たない spec は vacuously clean。 conformance は scenarios/render-safety.yaml (多行 subgraph タイトル + 通常 node label <br> を併存させた fixture に validate が [FAIL] render-safety + exit 1 + violation 1 件のみ = subgraph タイトルだけ捕捉し node label を誤検出しない)。 本 static pattern-lint は browser を要さず既知パターンを deterministic に捕捉する floor であり、 任意の render overlap (単行でも長すぎる label の溢れ等) の網羅は browser-render を要する視覚 gate (ceiling、 REQ-VER-022) の領分 (二層)。 scope は ADR-0020 の validate-scope を render-safety floor に拡張。
index.html + architecture 配下) を headless chromium で 3 viewport (375/768/1280) 実 render し、 render 後の DOM 幾何から mermaid 4 class (多行 cluster-label / label-over-node / node-over-node / content-clipped) + chrome 幾何 2 class (意図しない横スクロール horizontal-overflow / nav-over-content) を検出して merge を block する (render-safety の ceiling 層、 floor = REQ-VER-021 / REQ-VER-023)。 render 不足は見逃しでなく fail (fail-closed)、 constitution は advisory、 非 flowchart 図型は vacuous / uncalibrated warning で可視化し、 全 page × viewport の full-page screenshot を CI artifact 保存する (人間 review の補助 — golden 化しない)。 検出力は selftest fixture (kind 完全一致 + scale<1 正規化 + viewport plumbing 対 + 意図された scroll container / closed-details phantom rect の clean ガードを含む 13 case) が回帰固定し、 決定性は vendored mermaid + pinned playwright + pinned font の三重 pin で担保 (deterministic ゆえ blocking 適格)。
REQ-VER-022: WHEN the CI render-gate job runs (push / pull_request), it SHALL render every corpus page (repo-root index.html + architecture/**/*.html) in headless chromium at three viewports (375×667 / 768×1024 / 1280×900) and probe the post-render DOM geometry, flagging six defect classes with non-zero exit (merge block): (1) cluster-label-multiline — subgraph タイトルの縦 overflow (rendered height を svg の viewBox→rendered 縦比 (scaleY) で intrinsic px に正規化し、 useMaxWidth:true の縮小 render でも閾値が scale に引きずられない — mermaid は uniform scale で render するため縦横比は同値); (2) label-over-foreign-node / cluster-label-over-node — text label が自分以外の node 矩形と交差 (面積比、 scale 不変); (3) node-over-node — layout collision; (4) content-clipped — 要素が svg 可視範囲を溢れて clip され読めない (svg overflow は既定 hidden。 判定は rendered px = 視覚上の clip 量で、 (1) の intrinsic 正規化とは意図的に非対称); (5) horizontal-overflow (chrome 幾何 arm、 ADR-0039 §2.8) — 本文が viewport を溢れ document 全体に意図しない横スクロールが発生 (scrollWidth > clientWidth + 2px。 overflow-x:auto の意図された scroll container 内の wide content は document に寄与しないため発火しない。 culprit は clip/scroll 祖先を持たず viewport 右端を越える最外要素を最大 5 件 + 超過は残余 entry で報告し、 特定不能でも document 溢れ自体を報告する = fail-visible); (6) nav-over-content (chrome 幾何 arm) — nav landmark と本文 block の矩形交差 (面積比 > 0.15。 通常 flow の隣接 block は矩形が交差しないため chrome 注入の位置事故・absolute 化の崩れでのみ発火。 closed <details> の中身は Chromium が非 0 の phantom rect を返すため checkVisibility() で非描画要素を除外する)。 render-gate が測る post-render DOM は post-JS の既定表示 — 既定の人間プレゼン化 (ADR-0040 / rules §11.3) 以降、 data-audience を持つ page では chrome script が付与する body.audience-human 状態の幾何を測る (人間が実際に見る view を検査する)。 audience-human が隠す display:none の machine prose も同じ checkVisibility() filter が非描画として除外する (machine 部は幾何検査の対象外 = false positive を生まない)。 mermaid arm (1)〜(4) の検査対象 svg と期待図数は実 <pre class="mermaid"> block 数 (HTML コメント内・prose 内 escaped 言及は数えない — 図は人間層に置き machine 降格しない規律 (rules §11.5) により、 隠れた図の render 不足 false-fail を作らない)、 chrome arm (5)(6) は全 page が対象。 It SHALL fail-closed: render 不足 (rendered svg 数 < 実 block 数) は見逃しでなく failure に倒す。 It SHALL save a full-page screenshot of every page × viewport as a CI artifact (人間 review の補助に充てるのみで golden 比較は行わない — pixel golden は brittle ゆえ幾何 detector + 人間の目の二層で代替、 ADR-0039 §2.8)。 constitution.html (自身の @type が FolioConstitution) は advisory (表示のみ・exit 非影響、 編集禁止資産への blocking は frozen deadlock になるため。 floor の carve-out と同基準)。 coverage の穴は SHALL emit a warning として可視化し silent pass にしない: 幾何対象 (.node/.cluster) を持たない図型 (sequenceDiagram 等) は vacuous-coverage、 .node は出すが図型 (aria-roledescription) が flowchart/graph でない型 (stateDiagram 等 — 構造だけでは flowchart と区別できない) は uncalibrated-coverage (幾何は測るが threshold は flowchart 較正)。 検出力は selftest (fixture 13 case、 violation kind の完全一致判定 (mermaid arm と chrome arm の和集合): detector (1)〜(6) 全 arm の発火 + scale<1 での (1) 正規化発火 (mutation 捕捉を実証済) + clean の誤検出なし + vacuous/uncalibrated 分類。 (2)(3)(4) の単独 arm は mermaid が通常生成しない欠陥ゆえ mermaid と同 class 構造の合成 SVG で、 (5)(6) は合成 page で固定。 同一 fixture を 375/768 で走らせる対が viewport plumbing 自体を、 意図された scroll container (overflow-x:auto) と closed-details phantom rect の clean fixture が chrome arm の誤検出排除を回帰固定する) が mermaid/chromium 版 drift への回帰ガード。 決定性は vendored mermaid + pinned playwright + pinned font (CI が fonts-noto-cjk を install) の三重 pin — deterministic ゆえ blocking 適格 (ADR-0037 §2.3、 ADR-0028 の LLM-ceiling 非決定性根拠は本 gate に適用されない)。 conformance は tests/render-gate/check.py --selftest + .github/workflows/ci.yml の render-gate job (browser 依存ゆえ sandbox scenario でなく CI-only dogfood — consumer の folio validate には入れない、 配布される floor は REQ-VER-021)。 scope/二層化の決定は ADR-0037、 3 viewport 化 + chrome 幾何 arm + screenshot artifact の拡張は ADR-0039 §2.8 で trace。
folio validate は readability-floor gate を検査する (P-14 の floor 層): block 3 系 — viewport meta 欠落 / 孤立 EARS (machine 対応部があるのに essence が空) / 生成 landing hero の空・link ゼロ (dead-end)、 warn 5 系 — essence 句点数 > 4 / 可視 prose 単一段落 > 2000 codepoints / 人間層可視 prose > 12,000 codepoints (上限 box、 ADR-0040) / 章要旨 (p.section-essence) 不在 / 図ゼロ×長文 (> 6,000)。 frozen は warn 除外・essence block は living spec/research のみ・圧縮 3 arm は圧縮対象 (living spec + cluster README) のみ (stuck-RED 回避 + 一次資料層 skip)。
REQ-VER-023: WHEN the folio validate CLI subcommand runs, it SHALL check a readability-floor gate (ADR-0039 §2.7、 P-14 floor) with three blocking arms and five warning arms: block (1) viewport — every scanned doc carries <meta name="viewport"> inside <head> (head-anchored 走査で body / <pre> の raw/escaped 言及に誤反応しない。 rules §4.6 MUST の機械化。 ADR-0039 §2.7 列挙の 3 block への追加 arm = chrome 注入 slice の独立 ceiling 指摘「生成 page のみ viewport を持つ非対称」の是正、 divergence trace は本 REQ); block (2) essence 非空 — data-audience="human" requirement container が machine 対応部を持つのに人間向け要旨 (class="essence" / "req__essence") が無い・空 = 孤立 EARS (REQ-DA-STRUCT-1 の対称拡張。 living spec/research のみ — frozen decisions/ は remediate 不可 = stuck-RED ゆえ除外、 glossary gate と同基準。 container 外の machine 要素検出は ceiling の領分); block (3) landing hero — 生成 index (folio-generated marker、 hand-authored は keystone skip) の folio:landing-hero curated region が非空で <a href> を 1 本以上持つ (空 hero は build の placeholder 再 emit により nav-regen-drift と併発し、 両 violation が同じ remediate = folio build を名指しする); warn (4) essence 句点数 — essence 内の 「。」 が 4 個超 (日本語は語数の決定的計測が不能のため句点近似、 閾値 4 = corpus 較正 2026-06-11 実測 max 4); warn (5) 可視 prose 段落長 — prose_only 可視域 (pre / code / aside.machine-readable / chrome 除外、 class="ears" 完全一致の EARS 全文も除外) の単一 <p> 段落が 2000 codepoints 超 (UTF-8 継続 byte 除去による locale 非依存の決定計測。 閾値 2000 = corpus 較正 2026-06-11: blob 実測 9545 / 次点 1429 (gate 同一計測の codepoints) — blob 再発のみ見張る)。 加えて人間層プレゼン圧縮の warn 3 arm (ADR-0040 §2.5 / rules §11.5、 対象 = 圧縮対象ページ (living spec (subdir=spec、 constitution は scan 対象外) + doc-type=cluster-readme)、 frozen ADR と research の非 README (一次資料層) は skip。 ADR-0040 §2.6 の入口群のうち landing / glossary.html は build 所有の生成物で human-authored 長文 prose を持たないため v1 の機械検査対象外 = cluster README のみ gate し、 残りは ceiling / §11.4 walk に委譲する narrowing): warn (6) 人間層可視 prose 上限 — 既定表示で人間が読む量が約 12,000 codepoints (読了 20 分 box) 超。 計測は data-audience="machine" subtree (降格部、 同名 tag の depth 追跡) と <table> (線形読書しない = 満重みにしない、 v1 は 0 重み) を行 granular に除去 → prose_only → tag 除去 → codepoint 数 (除去は undercount 方向 = warn が鳴りにくい conservative); warn (7) 章要旨不在 — h2 章を持つ living spec ページに p.section-essence が 1 つも無い (v1 は page 単位 presence、 章単位への昇格は migration 後較正で判断); warn (8) 図ゼロ×長文 — 実 mermaid block ゼロかつ人間層可視 prose > 約 6,000 codepoints (目標 box。 block 数は raw grep で HTML コメント内を数えうるが overcount = warn 抑制側で conservative)。 warn 全系は doc-type=adr (frozen) を除外し、 exit code に影響しない (REQ-CI-014 と同じ warn channel)。 block violation は exit 1 + remediate tool/操作の名指し (ADR-0039 §2.9)。 warn 閾値の block 化は ceiling の指摘頻度を見て判断する (ADR-0039 §2.7 — 圧縮 3 arm は migration (folio-bqq) 完了後の corpus 実測で再較正してから昇格判断)。 conformance は scenarios/readability-floor.yaml (block 2 arm + warn 5 arm + hero dead-end + 圧縮 arm の正例 compress-over / 負例 compress-demoted (降格 + table 除去の回帰ガード)、 fix/build 済 fixture で他 gate clean = isolation) + scenarios/readability-floor-hero.yaml (hero 空 + nav-regen-drift 併発の対)。 意味的可読性 (文言の質) は floor の対象外 = ceiling (readability review lens、 ADR-0039 §2.8) の領分 (二層)。
全 REQ の検証被覆を一覧し、 scenario 列が空 = 未検証 gap を可視化する (例 VER-006)。
§3 の各 REQ-VER-* と §3.8 の REQ-NAV-* を derives-from (派生元原則 / ADR) × scenario (検証 file) × verified で一覧する (trace matrix は P-13 ゆえ普遍、 verified/scenario 列は verification mapping を持つ本 spec の opt-in、 ADR-0033 §2.6)。 folio validate は link しか検査しないため、 scenario 列が空 = link は valid だが未検証 = validate が捕らない gap をこの列だけが一目で surface する。
| REQ | EARS | derives-from | scenario (verifies) | verified |
|---|---|---|---|---|
| VER-001 | Ubiq. | ADR-0013 / §3.2 | scenarios/*.yaml | ✓ |
| VER-002 | Ubiq. | rules §10 / relations §5.3 | (全 scenario) | ✓ |
| VER-003 | Ubiq. | ADR-0017 (exit-code 中心) | (全 hook scenario) | ✓ |
| VER-004 | Ubiq. | ADR-0018 / §3.4 | (cli-golden 共通基盤) | ✓ |
| VER-006 | Ubiq. | research §2.6 | — (未検証 gap) | ✗ |
| VER-007 | Unw. | ADR-0019 / P-3 | path-boundary.yaml | ✓ |
| VER-008 | Unw. | ADR-0003 §2.1 | readme-index.yaml | ✓ |
| VER-009 | Event | ADR-0017 | e2e/runbook.md | ✓ |
| VER-010 | Event | relations §4.1 | inventory-gen.yaml | ✓ |
| VER-011 | Event | ADR-0018 | (全 cli-golden) | ✓ |
| VER-012 | Event | ADR-0007 | prime-digest.yaml | ✓ |
| VER-013 | Event | ADR-0020 | validate-clean / -violations.yaml | ✓ |
| VER-014 | Event | ADR-0024 / 0031 | init-scaffold.yaml | ✓ |
| VER-015 | Event | ADR-0025 | fix-bidirectional.yaml | ✓ |
| VER-016 | Event | ADR-0027 / 0029 | agent-structure.yaml (+ e2e S-G) | ✓ |
| VER-017 | Event | ADR-0034 §2.6 | xref-validate-clean / -violations.yaml | ✓ |
| VER-018 | Event | ADR-0034 §2.5 | xref-fix.yaml | ✓ |
| VER-019 | Event | ADR-0034 §2.8 | glossary-validate.yaml | ✓ |
| VER-020 | Event | ADR-0033 §2.4 / rules §7.3 | validate-violations (da-violations) / validate-clean.yaml | ✓ |
| VER-021 | Event | ADR-0020 / rules §4.5 | render-safety.yaml | ✓ |
| VER-022 | Event | ADR-0037 + ADR-0039 §2.8 / VER-021 (二層) | render-gate/check.py --selftest + CI render-gate job (CI-only、 sandbox 被覆外) | ✓ |
| VER-023 | Event | ADR-0039 §2.7 / P-14 | readability-floor / -hero.yaml | ✓ |
| VER-024 | Event | taxonomy §5.2 / ADR-0042 | generator/test-adversarial.sh (A22–A33) | ✓ |
| VER-025 | Event | taxonomy §5.2 gate F / ADR-0037 + ADR-0041 | render-gate-srs.py --selftest + CI render-gate job (CI-only) | ✓ |
| VER-026 | Ubiq. | taxonomy §5.1 / §5.3 / ADR-0041 §2.5 | test-adversarial.sh A22 (floor≠GREEN) + ceiling agents (LLM) | ✓ |
| NAV-001 | Event | ADR-0035 §2.5 | nav-validate-clean / -drift / -keystone.yaml | ✓ |
| NAV-002 | Unw. | ADR-0035 §2.5 | nav-validate-deadlink.yaml | ✓ |
| NAV-003 | Unw. | ADR-0035 §2.5 | nav-validate-reachability.yaml | ✓ |
| NAV-004 | State | ADR-0035 §2.4 / ADR-0039 §2.2 | nav-validate-curated-roundtrip.yaml | ✓ |
| NAV-005 | Unw. | ADR-0035 §2.5 | nav-validate-consumer-deadend.yaml | ✓ |
| NAV-006 | Unw. | ADR-0035 §2.5 (link-rot) | nav-validate-readme-linkrot.yaml | ✓ |
| NAV-007 | State | ADR-0039 §2.3 | chrome-validate-clean / -drift.yaml | ✓ |
walkable nav と chrome の検証要件 REQ-NAV-001〜007 を定義する。
walkable nav (生成 index、 ADR-0035) と全ページ chrome (ADR-0039 §2.3) の検証 REQ。 実装時は scenario file を SSoT とする scenario-first 慣行で運用していたものを、 本節で定義 site (spec-row) に正式化する — 各 scenario の description は実装詳細 (fixture 構成・isolation 根拠) の SSoT として引き続き保持し、 本節は要件 (WHAT) の canonical 定義を担う。
機械 SSoT から生成した SRS プレゼン HTML の完成判定を二層 (floor=決定的 + ceiling=LLM) で定義する (REQ-VER-024〜026、 SRS 部品 taxonomy §5)。 floor 単独で GREEN を宣言しない。
以下は folio 自身の spec 検証 (§3.6 / §3.8) と異なり、 consumer が機械 SSoT から生成する SRS プレゼン HTML の done-condition を定義する (design-system generator .claude-plugin/design-system/generator/ が実装)。 設計 SSoT は SRS 部品 taxonomy §5 (二層判定式 floor + ceiling)、 生成方式は ADR-0042 (ハイブリッド = 構造決定的・prose のみ opus) / ADR-0041。 conformance は generator-local の test-adversarial.sh + render-gate-srs.py --selftest (sandbox scenarios でなく generator-local + CI dogfood — 生成物向けゆえ consumer の folio validate には入れない)。 本節は taxonomy §5 で設計済みの二層モデルを REQ-VER 形式で形式化する (新規 ADR を要さない)。
folio verify-srs <html> <contract> は生成 SRS の決定的 floor (taxonomy §5.2 gate A–E,G,H + visual-first) を検査する。 ★floor 通過は GREEN でなく CEILING=PENDING を返す (exit 0 ≠ GREEN・floor 単独 GREEN 禁止)。 生成と検証を分離した独立検証ゆえ手編集後も再検証可 (manifest 不要)。 render は REQ-VER-025、 ceiling は REQ-VER-026 (gate 詳細は machine 部)。
REQ-VER-024: WHEN the folio verify-srs <generated.html> <contract.yaml> command runs (CLI 引数順 = <html> <contract>、 html=主対象), it SHALL check the deterministic floor of a generated SRS presentation (taxonomy §5.2 gate A–E,G,H + visual-first) over the (contract, html) pair alone (manifest 不要 = 成果物入力ゆえ手編集後も再検証可), flagging with non-zero exit: gate A — 各 MUST 部品 (S5 凍結 required-existence 集合: doc-cover-band / chapter-deck-band / section-lead-callout / scope-summary-panel / actor-stakeholder-table / source-trace-origin / requirement-matrix-table / ears-requirement-row / priority-badge / nfr-hero-metrics / nfr-metrics-table / acceptance-criteria-checklist / rtm-collapse / constraint-callout / glossary-term-table / fidelity-sync-meta / requirement-type-color-tokens) が data-component 属性で各 ≥1 (条件付き MUST = MUST-when-applicable は凍結集合外); gate B — register 整合 (deck-band family ≥1 ∧ dense系 ≥1 ∧ requirement-type-color-tokens 存在 ∧ @media (prefers-color-scheme: dark) 規則の両モード定義 — コメント擬装でなく規則ブロック存在を要求); gate C — RTM 完全性 (孤立要件 (出所なし) = 0 ∧ 未検証要件 (受入なし) = 0、 contract の trace.backward / trace.acceptance から導出); gate D — 要件 ID 健全性 (一意 data-req-id (重複 0) ∧ 全要件行に priority-badge ∧ 検証手法 (T/A/I/D) span ∧ 可視 fid span == 同行 data-req-id で手編集の可視 ID 捏造を検出); gate E — 用語被覆 (plain-language-term-inline の plain 併記が glossary plain_short から正確派生 = verify-fabrication-free --artifact §9 に委譲); gate G — 内容完全性 (no-TBD: MUST 部品の必須スロット非空 ∧ placeholder トークン (TBD/TODO/未定 等・case-insensitive・語境界・日本語含む) = 0); gate H — fidelity meta (fidelity-sync-meta の 機械SSoT / 生成 / 検証状態 の 3 項目が非空白で充填); visual-first — 各章 (footer 除く) に非 prose 部品 ≥1 (字だけの章 = 0)。 It SHALL return CEILING=PENDING on floor PASS — exit 0 は floor PASS であって GREEN ではない (taxonomy §5.1 「floor 単独で GREEN を宣言しない」)。 gate F (render 健全性) は REQ-VER-025、 ceiling (gate I/J) は REQ-VER-026。 conformance は generator の test-adversarial.sh (A22–A33 が各 gate の fail-closed を seed: 空 prose / 中段 TBD / 孤立要件 / sync-meta 欠落・空白化 / MUST 部品欠落 / data-req-id 重複 / 可視 fid 捏造 / dark-media コメント擬装)。 scope は ADR-0042 で trace。
render-gate-srs.py) は生成 SRS を light/dark × 3 viewport で実 render し、 WCAG AA low-contrast / horizontal-overflow / component-overlap を検出する (gradient は停止色 worst-case 評価、 fail-closed)。 重い playwright ゆえ renderer 在環境で実行・不在は honest SKIP (PASS と詐称せず floor 不完全と明示)。 検出器・定数は machine 部。
REQ-VER-025: WHEN gate F (render 健全性、 render-gate-srs.py、 taxonomy §5.2) runs against a generated SRS presentation, it SHALL render the artifact in headless chromium at light / dark の両 prefers-color-scheme × 3 viewport (375 / 768 / 1280) and probe the post-render DOM, flagging with non-zero exit three classes: (1) low-contrast — 各 text 要素の文字色と実効背景の WCAG 2.1 コントラスト比が AA 未満 (通常 4.5:1 / 大 text 18pt=24px or 14pt-bold=18.66px は 3.0:1)。 実効背景は祖先を遡って不透明 background-color を底に半透明 layer を alpha 合成し、 gradient 背景は各レイヤーの停止色を抽出して下から alpha 合成した候補集合の worst-case (最小コントラスト) 停止で判定する (薄い勾配上の白文字を素通りさせない)。 色は 1×1 canvas で任意 CSS 色 (oklch / lab / hsl / hex / rgb 各構文) を sRGB へ解決する; 停止色を抽出できない真の image (url()) のみ skip し件数を disclose する; (2) horizontal-overflow — document.scrollWidth > clientWidth + 2px の意図しない横スクロール (overflow-x:auto の内部 scroll container は document に寄与しないため発火しない); (3) component-overlap — [data-component] が別の可視 block 要素 (素の div/li 等を含む広い集合・包含/inline は除外) と面積比 > 0.15 で矩形交差 (絶対配置・負 margin の崩れ + 非コンポーネント装飾の被さりを捕捉)。 It SHALL fail-closed: 検査対象 text が 1 つも無い (textChecked == 0) = render 破綻として「clean」でなく FAIL に倒す。 重い playwright 検査ゆえ folio verify-srs は renderer 在環境でのみ gate F を実行し、 不在環境では honest SKIP (RESULT を「gate F 未実行・floor 不完全」と明示し PASS と詐称しない); SRS_SKIP_RENDER=1 で bash-only floor に外せる。 幾何定数 (横溢れ許容 2px / overlap 面積比 0.15) は REQ-VER-022 の probe.js (ADR-0037) の値を複製する (drift は test-adversarial.sh A35 が検知)。 conformance は render-gate-srs.py --selftest (fixture 10 本 / case 17: low-contrast/overflow/component-overlap の kind 完全一致発火 + dark-only 崩れ + gradient×dark + url-image skip + viewport plumbing + fail-closed) + CI render-gate job (dogfood SRS を build→gate F、 sandbox 被覆外の CI-only)。 scope は ADR-0037 (検出器・二層) + ADR-0041 (dark-contrast 崩壊型の検出を含む) で trace。
verify-srs が CEILING=PENDING を返し機械担保)。 gate I = 非エンジニア persona walk (北極星)、 gate J = fidelity (捏造/情報落ち/派生ビュー一致を機械 SSoT と突合)。 ceiling は LLM ゆえ非決定的・floor (決定的・blocking) と二層。
REQ-VER-026: A generated SRS presentation SHALL be considered GREEN if and only if both layers pass: (floor) 全 floor gate が PASS (REQ-VER-024 の folio verify-srs 決定的 floor ∧ REQ-VER-025 の gate F (render 健全性)) AND (ceiling) 意味判定の両 lens が合格 (taxonomy §5.3 gate I = persona-walk-srs agent、 gate J = fidelity-srs agent)。 It SHALL NOT declare GREEN on floor pass alone — folio verify-srs が floor 通過時に CEILING=PENDING (exit 0 ≠ GREEN) を返すことで「floor 単独 GREEN 禁止」を機械担保する (taxonomy §5.1 判定式、 ADR-0040 の長さ Goodhart 再発防止)。 gate I (persona walk) = 非エンジニア persona が生成 SRS を index から歩き「何が要件か・なぜ要るか・どう検証されるか」を頑張れば読めるか (専門エンジニアがなんとか読める水準では不合格 = ADR-0041 北極星); gate J (fidelity) = 生成 HTML が機械 SSoT contract の正確な要約か — 情報落ち / 歪み / 捏造 (AI 捏造 RTM 行・SSoT 外の rationale 作文等) が無く、 派生ビュー (plain-language-term-inline) が SSoT 一致、 要件間 consistency (矛盾) も surface。 両 gate は agents/persona-walk-srs.md / agents/fidelity-srs.md として常設し、 spec 用 Phase F の spec-review-* agent と同型の LLM review (read-only・構造化 findings)。 ceiling は LLM ゆえ非決定的 = CI で blocking しない (ADR-0028 の二層 enforcement と同型: floor=機械/blocking + ceiling=LLM/advisory)。 conformance: 二層 invariant (floor PASS ≠ GREEN) は決定的ゆえ test-adversarial.sh A22 (健全 artifact に verify-srs が CEILING=PENDING を返す = GREEN を宣言しない) が固定し、 ceiling agent は fidelity が SSoT 外の捏造 RTM 行を検出する型 (taxonomy §5.3 / ADR-0041 §2.5) を実装する。 scope は taxonomy §5.1 / §5.3 + ADR-0041 §2.5 (persona walk + fidelity = co-equal gate) で trace。
実装 phase 章: 3-Step approach と、 完成形 vs 試作段階の差異を定める。
段階導入の 3-Step approach を定める (REQ-VER-005)。
| Step | 方式 (WHAT) | API call | 適用 Phase |
|---|---|---|---|
| Step 1 | hook script unit test (script の stdin / exit code / stdout を実機で verify) | 不要 | Phase X3 最初 = MUST |
| Step 2 | worktree-based integration test (test project + hook 設定で sandbox 構築) | API key 注入で可 | Phase X3 中盤 = SHOULD |
| Step 3 | container-based isolation + integration test (外部 API allowlist 経由で外部依存制御) | 必須 (Anthropic API のみ allowlist) | Phase X4+ = MAY |
REQ-VER-005: Phase X3 着手時点で Step 1 (hook script unit test) を MUST 実装する。 Step 2 / Step 3 は段階追加 (SHOULD / MAY)。
完成形 (long-term vision) と試作段階を 4 軸で対比 (完成形列は X5-γ で v1.0 実体へ reconcile)。
| 軸 | 完成形 (Phase X5+) | 試作段階 (Phase X3、 現在) |
|---|---|---|
| 検証対象 plugin | §7.2 8 specialist agents 完全実装 | §7.6 minimal (1 skill + 4 hook + 6 script + 1 CLI)、 ADR-0003 |
| scenario カバー範囲 | 全 use case (8 specialist + 全 spec file × CRUD) | 8 use case (caller marker / path boundary / JSON-LD lint / README update / context inject / 双方向 link / inventory regen / EARS coverage、 research §7.5) |
| runner | Inspect AI / Promptfoo 統合候補 | 独自 bash runner (tests/runner.sh、 試作) |
| CI 統合 | 全 scenario PR ごと auto-run + merge gating | scenario 1-3 (caller marker / path boundary / JSON-LD lint) のみ CI gate、 残りは warn のみ |
補足章: 未解決 Gap (§5.1)・起票保留 ADR 候補 (§5.2)・acceptance 済の関連 ADR (§5.3)。
未解決の Gap を優先度付きで一覧する (詳細は research §10.1)。
| Gap | 優先度 | 概要 | resolution 条件 |
|---|---|---|---|
| 1 | MUST | Issue #39344 fix 確認 | もし fix 済なら permissionDecision: deny 信頼可能、 REQ-VER-003 SHOULD NOT を更新 |
| 2 | MUST | runner.sh 具体仕様 (bash + yq vs Python + PyYAML) | Phase X3 Step 1 着手時に最低限の設計選択 |
| 3 | SHOULD | claude plugin validate --strict 全 check 項目 | Phase X3 validate 実行時に網羅 |
| 4 | SHOULD | Issue #18312 URL | research §2.6 Evidence Table 補完 |
| 5 | LOW | fast-check 公式 docs 直接確認 | Phase X4+ TypeScript plugin 実装時 |
詳細は plugin-sandbox-verification-research.html §10.1 Gaps を参照 (重複記述しない)。
起票保留 ADR 候補 (ADR-0017/0018 起票済・ADR-0014/0016 は未起票)。
| ADR ID 候補 | title | resolution 条件 |
|---|---|---|
ADR-0014 | EARS REQ → scenario 導出規範 | 本 §3.5 で実質規範化済、 別 ADR 不要と判断 (本 commit で見送り) |
ADR-0016 | exit code 中心 assertion 規範 | Gap 1 (Issue #39344 fix) 確認後 |
| ADR-0017 | hook unit test vs integration test 境界 | 起票済 2026-05-25 (Track 1/2 後 retrospective、 ADR-0017 / decisions/README §3) |
| ADR-0018 | golden baseline 管理 (2-dir model + accept workflow) | 起票済 2026-05-25 (Track 1 実装後 retrospective、 ADR-0018 / decisions/README §3) |
本 spec 直結の acceptance 済 ADR (ADR-0003 / 0013 / 0015)。
本 spec が依拠する内部・外部参照の一覧。