folio verification

v1.0.0 · status: active · sandbox verification framework spec (機能単位 use case verification の SSoT)
Status
active
Doc-Type
spec
Version
1.0.0
Layer
core (Layer 0)
Stakeholders
Developer · AI Agent · External Reviewer
Depends-on
rules · relations

§0. Reader's Guide

読み順: §1 概念 → §2 scope → §3 EARS 規範 → §4 実装。 着手前は §1 + §3 必読。

§1. Verification Contract Definition

「verification」 の canonical 定義章 (他 spec はここへ参照、 P-5)。

§1.1 3 concept

検証の 3 state を canonical 定義する (下表)。

folio verification states (3 concept 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 がない初期状態

§1.2 本 framework の scope

本 framework は sandbox-verified のみを対象とする MUST。

本 verification framework (ADR-0013) は sandbox-verified のみを対象とする MUST。 experiment-verified は ADR-0015 により本 framework scope 外。

§2. Verification Scope

検証対象と非対象の境界章 (in-scope 3 カテゴリ / out-of-scope 3 種)。

§2.1 verification 対象

検証対象は plugin behavior・spec 整合性・CI gate (REQ-CI-010〜016) の 3 カテゴリ。

本 framework の検証対象は以下 3 カテゴリ:

§2.2 scope 外

scope 外 3 種と、 in-scope な hook unit test の用語整理 (用語衝突)。

§3. EARS Requirements (REQ-VER-001〜)

規範要件を 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;
図 1. folio verification model。 runner.sh が scenario YAML を hook mock / CLI golden で実行し、 exit_code / file-state / golden diff で assert する。

§3.1 scenario format (YAML、 1 REQ = 1 scenario)

検証 scenario の format と参照 req_id を定める (REQ-VER-001 / 002)。

REQ-VER-001 Ubiq. 検証 scenario は 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-VER-002 Ubiq. 各 scenario は canonical な 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.

§3.2 YAML schema

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 比較)。

§3.3 assertion 戦略 = exit code 中心

assertion の主軸を exit_code に定める (REQ-VER-003 / REQ-VER-006)。

REQ-VER-003 Ubiq. scenario の assertion 主軸は exit_code とする。

REQ-VER-003: Each scenario expect block SHALL specify exit_code as the primary assertion.

REQ-VER-006 Ubiq. scenario 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)。

§3.4 golden baseline 管理

golden baseline の 2-dir model と accept 規律 (REQ-VER-004)。

REQ-VER-004 Ubiq. golden baseline は TypeScript compiler 流 2-dir model (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。

§3.5 EARS → Gherkin 1:1 mapping

各 EARS pattern と Gherkin 構文 (Given / When / Then) の 1:1 対応を下表に示す。

各 EARS pattern と Gherkin 構文の対応:

EARS patternGherkin 対応
UbiquitousGiven (初期) + When (任意) + Then
Event-DrivenGiven (前提) + When (トリガー) + Then
State-DrivenGiven (状態) + When + Then
Unwanted BehaviorGiven + When (エラー) + Then (復旧)
Optional FeatureGiven (機能有効) + When + Then

変換 reference: conductofcode.io EARS-to-BDD / RequireKit

§3.6 verification-specific scenario REQ (REQ-VER-007〜)

試作検証専用の 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 実装。

REQ-VER-007 Unw. 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)。

REQ-VER-008 Unw. clusterREADME.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 Event live-load した session で plugin を統合検証するとき、 agent が e2e runbook を実 Edit/Write で歩いて live hook を発火させ、 観察を golden baseline に記録する。 一次 assertion = file 作成有無 (deny ⇒ 不在 / notify ⇒ 存在)。

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 の統合検証)。

REQ-VER-010 Event folio inventoryrelations §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 で検証する (非決定的 generatedAtnormalize.exclude_paths で除外)。 scenario: scenarios/inventory-gen.yaml (REQ-VER-011 harness が実行)。

REQ-VER-011 Event 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)。

REQ-VER-012 Event 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 / statusrelations.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 非注入)。

REQ-VER-013 Event 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-016ADR-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。

REQ-VER-014 Event 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.1ADR-0031ADR-0024 の seed 挙動を revise)。 これで空 placeholder が "done" に残る hollow-spec を構造的に排除する。 生成された skeleton は folio validateclean (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。

REQ-VER-015 Event 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 に拡張)。

REQ-VER-016 Event 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。

REQ-VER-017 Event 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)。

REQ-VER-018 Event 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。

REQ-VER-019 Event folio validate は glossary gate を追加検査する: marked term (explicit + auto-mark とも <span class="term" data-term> に統一) の data-termvocabulary.yaml に解決し (resolve)、 data-tooltipdefinition と一致する (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) resolvedata-term resolves to a canonical entry in vocabulary.yaml; (2) tooltip-consistencydata-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。

REQ-VER-020 Event 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.yamlcdn-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 に拡張)。

REQ-VER-021 Event 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 に拡張。

REQ-VER-022 Event CI の render-gate job は、 corpus 全 page (repo-root 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 + 2pxoverflow-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 (自身の @typeFolioConstitution) は 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.ymlrender-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。

REQ-VER-023 Event 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) の領分 (二層)。

§3.7 Coverage RTM (requirement traceability)

全 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 する。

verification-framework requirement coverage matrix (§3 の REQ-VER-* + §3.8 の REQ-NAV-*。 VER-005 は §4 のため除外)
REQEARSderives-fromscenario (verifies)verified
VER-001Ubiq.ADR-0013 / §3.2scenarios/*.yaml
VER-002Ubiq.rules §10 / relations §5.3(全 scenario)
VER-003Ubiq.ADR-0017 (exit-code 中心)(全 hook scenario)
VER-004Ubiq.ADR-0018 / §3.4(cli-golden 共通基盤)
VER-006Ubiq.research §2.6— (未検証 gap)
VER-007Unw.ADR-0019 / P-3path-boundary.yaml
VER-008Unw.ADR-0003 §2.1readme-index.yaml
VER-009EventADR-0017e2e/runbook.md
VER-010Eventrelations §4.1inventory-gen.yaml
VER-011EventADR-0018(全 cli-golden)
VER-012EventADR-0007prime-digest.yaml
VER-013EventADR-0020validate-clean / -violations.yaml
VER-014EventADR-0024 / 0031init-scaffold.yaml
VER-015EventADR-0025fix-bidirectional.yaml
VER-016EventADR-0027 / 0029agent-structure.yaml (+ e2e S-G)
VER-017EventADR-0034 §2.6xref-validate-clean / -violations.yaml
VER-018EventADR-0034 §2.5xref-fix.yaml
VER-019EventADR-0034 §2.8glossary-validate.yaml
VER-020EventADR-0033 §2.4 / rules §7.3validate-violations (da-violations) / validate-clean.yaml
VER-021EventADR-0020 / rules §4.5render-safety.yaml
VER-022EventADR-0037 + ADR-0039 §2.8 / VER-021 (二層)render-gate/check.py --selftest + CI render-gate job (CI-only、 sandbox 被覆外)
VER-023EventADR-0039 §2.7 / P-14readability-floor / -hero.yaml
VER-024Eventtaxonomy §5.2 / ADR-0042generator/test-adversarial.sh (A22–A33)
VER-025Eventtaxonomy §5.2 gate F / ADR-0037 + ADR-0041render-gate-srs.py --selftest + CI render-gate job (CI-only)
VER-026Ubiq.taxonomy §5.1 / §5.3 / ADR-0041 §2.5test-adversarial.sh A22 (floor≠GREEN) + ceiling agents (LLM)
NAV-001EventADR-0035 §2.5nav-validate-clean / -drift / -keystone.yaml
NAV-002Unw.ADR-0035 §2.5nav-validate-deadlink.yaml
NAV-003Unw.ADR-0035 §2.5nav-validate-reachability.yaml
NAV-004StateADR-0035 §2.4 / ADR-0039 §2.2nav-validate-curated-roundtrip.yaml
NAV-005Unw.ADR-0035 §2.5nav-validate-consumer-deadend.yaml
NAV-006Unw.ADR-0035 §2.5 (link-rot)nav-validate-readme-linkrot.yaml
NAV-007StateADR-0039 §2.3chrome-validate-clean / -drift.yaml

§3.8 walkable-nav / chrome scenario REQ (REQ-NAV-001〜007)

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 定義を担う。

REQ-NAV-001 Event folio validatefolio-generated marker (head-anchored) を持つ生成 index.htmlfolio build の emit と byte 比較し drift を block する。 marker 無し (hand-authored) index は keystone skip — body の escaped 言及には反応しない。

REQ-NAV-001: WHEN the folio validate CLI subcommand runs and a top-level index.html carrying <meta name="folio-generated" content="folio-build"> in its <head> exists, it SHALL byte-compare that index against the deterministic folio build emit and report any difference as a [nav-regen-drift] violation (exit 1、 remediate = folio build)。 marker を持たない index は検査対象外 (keystone) であり、 marker 判定は <head> の実 <meta> に anchor し body の escaped/prose 言及に誤反応しない SHALL。 conformance: scenarios/nav-validate-clean.yaml (clean) / nav-validate-drift.yaml (drift 検出) / nav-validate-keystone.yaml (escaped-mention 誤発火なし)。

REQ-NAV-002 Unw. 生成 index 内の <a href> が実在 file / anchor に解決しない場合、 [nav-dead-link] で block する (curated region の手書き link rot も被覆)。

REQ-NAV-002: IF the generated index.html contains an <a href> whose relative target file does not exist or whose #anchor does not resolve to an id in the target, THEN folio validate SHALL report a [nav-dead-link] violation (exit 1)。 external scheme / pure-anchor / stylesheet href は対象外。 regen-drift が curated region を往復保全するため、 curated 内の手書き link rot は本 gate だけが捕捉する。 conformance: scenarios/nav-validate-deadlink.yaml

REQ-NAV-003 Unw. cluster dir / README の graph scan (生成 index の有無に依存しない) が dead-end README・empty cluster・index-backlink 欠落 (兄弟 cluster へは抜けるが ../index.html への戻りが無い = index 孤島) を検出する。 self-root (FolioConstitution 保持) = block / consumer = warn。

REQ-NAV-003: IF an architecture cluster directory exists whose README.html has no outbound cross-cluster <a href> (dead-end), or which contains no scannable doc (empty cluster), or whose README.html has outbound links but none resolving to ../index.html (親 dir 自体を指す .. / ../ も index 到達可能形として受理) (index-backlink 欠落 — 兄弟 cluster へは抜けるが index へ戻れない「index 孤島」、 ADR-0035 §1 が名指した形。 dead-end 検出済みの README には重ねない = 1 README 1 主因で remediate を迷わせない。 remediate は folio build の breadcrumb 再生成 = detect↔remediate parity)、 THEN folio validate SHALL report it via the [cluster-reachability] gate — as a blocking violation when the root is folio-self (spec/ に @type FolioConstitution)、 as a warning (exit 0) when the root is a consumer corpus。 本 gate は dir/README scan 由来であり生成 index の有無に gate しない (post-init / pre-build window でも検査される)。 conformance: scenarios/nav-validate-reachability.yaml (self-root block、 index-backlink 欠落 arm を含む)。

REQ-NAV-004 State folio build の curated region 往復保全は first-open / last-close 抽出で行い、 region 内の raw marker 言及 (<pre> 解説等) を内側として保全する — editorial の silent 切り捨てを構造的に防ぐ。

REQ-NAV-004: WHILE a curated region (folio:nav-curated / folio:landing-hero) contains raw marker mentions inside its editorial content, folio build SHALL extract the region by first-open / last-close boundary (単純 state-machine の最初の close 終端ではなく) and round-trip the full editorial verbatim、 so that regeneration never silently drops content after a raw close-marker mention (#110/#116/#119 系譜の raw-mention 誤動作の回帰 guard)。 conformance: scenarios/nav-validate-curated-roundtrip.yaml (sentinel 保全を regen-drift [OK] で実証)。

REQ-NAV-005 Unw. consumer corpus (FolioConstitution 無し) の reachability findings は block でなく warn (exit 0) — validate-clean を壊さず authoring を nudge する。 生成 index 不在でも検査される。

REQ-NAV-005: IF the validate root is a consumer corpus (no FolioConstitution in spec/) and the [cluster-reachability] gate finds dead-end / empty-cluster / index-backlink 欠落 / link-rot findings, THEN folio validate SHALL emit them on the warning channel (exit code 非影響) instead of blocking — consumer の post-init / pre-build window で validate-clean 契約 (REQ-VER-014) を保ちながら気付きを与える。 conformance: scenarios/nav-validate-consumer-deadend.yaml (dead-end + dangling home link の 2 warn、 nav 系 gate は index 不在で [SKIP] のまま)。 index-backlink 欠落の warn 振り分けは gate の共有 dispatch (self block / consumer warn) に従い REQ-NAV-003 の self-root scenario と同経路 — 専用の consumer scenario は持たない (finding 種別ごとでなく gate 単位で振り分ける実装のため)。

REQ-NAV-006 Unw. cluster README body の static cross-nav link が解決しない (link rot) 場合、 [cluster-reachability] の link-rot 検査が捕捉する — link-integrity (JSON-LD のみ) と nav-dead-link (生成 index のみ) の未被覆領域を埋める。

REQ-NAV-006: IF a cluster README.html body contains an <a href> whose realpath-normalized relative target does not exist, THEN folio validate SHALL report it via the [cluster-reachability] gate の link-rot 検査 (self-root = block / consumer = warn、 REQ-NAV-003/005 の振り分けと同一)。 JSON-LD relation しか見ない link-integrity と生成 index しか見ない nav-dead-link の両方が README body href を未被覆のため、 link rot は本検査だけが捕捉する。 conformance: scenarios/nav-validate-readme-linkrot.yaml (self-root block 側、 consumer warn 側は REQ-NAV-005 scenario が併せて固定)。

REQ-NAV-007 State chrome marker (folio:chrome-top/toc/bottom) を持つ page の chrome 領域は render 再計算と byte 一致を保つ — drift は [chrome-drift] (nav-regen-drift gate 内包) で block、 marker 無し page は keystone skip。 remediate は folio build

REQ-NAV-007: WHILE a scanned page carries chrome marker regions (folio:chrome-top / chrome-toc / chrome-bottom、 ADR-0039 §2.3 の build 所有領域), folio validate SHALL verify that the page byte-equals its deterministic chrome re-render (folio_chrome_render_doc = strip → 再計算 → 挿入の純関数) and report any mismatch as a [chrome-drift] violation on the nav-regen-drift gate (exit 1、 remediate = folio build — §2.9 分業: 表示層 regen は build 所有)。 marker を持たない page は検査対象外 (keystone) SHALL。 生成規則 (既存 id のみ 2 段 fallback 目次 / prev-next 順序 SSoT / BASE_URL 二段構え breadcrumb) は ADR-0039 §2.3 を SSoT とし、 committed fixture bytes が意味論を pin する。 conformance: scenarios/chrome-validate-clean.yaml (clean + 生成規則 pin) / chrome-validate-drift.yaml (改竄検出)。

§3.9 生成 SRS プレゼンの done-condition gate (REQ-VER-024〜)

機械 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 を要さない)。

REQ-VER-024 Event 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。

REQ-VER-025 Event gate F (render 健全性、 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.pytaxonomy §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-overflowdocument.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-022probe.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。

REQ-VER-026 Ubiq. 生成 SRS が GREEN ⟺ (floor 全通過: REQ-VER-024 + 025) AND (ceiling 合格: persona-walk-srs gate I + fidelity-srs gate J)。 floor 単独で GREEN 禁止 (verify-srsCEILING=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-024folio 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-srsCEILING=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。

§4. Implementation Phase

実装 phase 章: 3-Step approach と、 完成形 vs 試作段階の差異を定める。

§4.1 3-Step approach

段階導入の 3-Step approach を定める (REQ-VER-005)。

verification 段階導入 (sandbox-verification-research §6.3 を normative 化、 WHAT のみ規定)
Step方式 (WHAT)API call適用 Phase
Step 1hook script unit test (script の stdin / exit code / stdout を実機で verify)不要Phase X3 最初 = MUST
Step 2worktree-based integration test (test project + hook 設定で sandbox 構築)API key 注入で可Phase X3 中盤 = SHOULD
Step 3container-based isolation + integration test (外部 API allowlist 経由で外部依存制御)必須 (Anthropic API のみ allowlist)Phase X4+ = MAY
REQ-VER-005 Ubiq. Phase X3 着手時に Step 1 (hook script unit test) を実装する (Step 2/3 は SHOULD/MAY で段階追加)。

REQ-VER-005: Phase X3 着手時点で Step 1 (hook script unit test) を MUST 実装する。 Step 2 / Step 3 は段階追加 (SHOULD / MAY)。

§4.2 完成形 verification vs 試作段階 verification

完成形 (long-term vision) と試作段階を 4 軸で対比 (完成形列は X5-γ で v1.0 実体へ reconcile)。

verification flow の段階別差異
完成形 (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 のみ

§5. Open Questions / ADR Cross-references

補足章: 未解決 Gap (§5.1)・起票保留 ADR 候補 (§5.2)・acceptance 済の関連 ADR (§5.3)。

§5.1 Open Questions (Gap、 sandbox-verification-research §10.1 参照)

未解決の Gap を優先度付きで一覧する (詳細は research §10.1)。

Gap優先度概要resolution 条件
1MUSTIssue #39344 fix 確認もし fix 済なら permissionDecision: deny 信頼可能、 REQ-VER-003 SHOULD NOT を更新
2MUSTrunner.sh 具体仕様 (bash + yq vs Python + PyYAML)Phase X3 Step 1 着手時に最低限の設計選択
3SHOULDclaude plugin validate --strict 全 check 項目Phase X3 validate 実行時に網羅
4SHOULDIssue #18312 URLresearch §2.6 Evidence Table 補完
5LOWfast-check 公式 docs 直接確認Phase X4+ TypeScript plugin 実装時

詳細は plugin-sandbox-verification-research.html §10.1 Gaps を参照 (重複記述しない)。

§5.2 起票保留 ADR (SHOULD ランク)

起票保留 ADR 候補 (ADR-0017/0018 起票済・ADR-0014/0016 は未起票)。

ADR ID 候補titleresolution 条件
ADR-0014EARS REQ → scenario 導出規範本 §3.5 で実質規範化済、 別 ADR 不要と判断 (本 commit で見送り)
ADR-0016exit code 中心 assertion 規範Gap 1 (Issue #39344 fix) 確認後
ADR-0017hook unit test vs integration test 境界起票済 2026-05-25 (Track 1/2 後 retrospective、 ADR-0017 / decisions/README §3)
ADR-0018golden baseline 管理 (2-dir model + accept workflow)起票済 2026-05-25 (Track 1 実装後 retrospective、 ADR-0018 / decisions/README §3)

本 spec 直結の acceptance 済 ADR (ADR-0003 / 0013 / 0015)。

§6. References

本 spec が依拠する内部・外部参照の一覧。