folio Phase X3 着手直前で、 plugin 構成 (1 skill + 4 hook + 6 script + 1 CLI、 §7.3) は確定したが、 hooks の実挙動 / PreToolUse permissionDecision deny bug (Issue #37210 / #33106) / lint script の throughput を 自前で確認していない。 「机上設計と現実の乖離」 リスクを潰すため、 plugin の 機能単位 (use case 単位) の sandbox 検証フレーム を設計する必要がある。
| # | サブ質問 | 担当 |
|---|---|---|
| Q1 | Claude Code 公式 plugin development workflow (test/dev/sandbox、 Issue #37210 等の verify) | researcher-1 |
| Q2 | 類似 plugin ecosystem test harness deep dive (VS Code / Neovim / JetBrains / MCP / Chrome / Obsidian / Cursor / Continue / Aider) | researcher-2 |
| Q3 | AI agent behavior evaluation framework (LangChain / OpenAI / Anthropic / AutoGen / CrewAI / LangGraph / Inspect AI / Promptfoo / Helicone) | researcher-3 |
| Q4 | Conformance test suite design pattern (W3C WPT / LSP / TypeScript baseline / IETF RFC / OpenAPI Specmatic) | researcher-4 |
| Q5 | 隔離環境構築 sandbox runtime (Nix / Docker / git worktree / Devbox / mise / Firecracker / Vagrant / WSL2) | researcher-5 |
| Q6 | Property-based / behavioral testing (Hypothesis / fast-check / mutation / Gherkin / EARS→scenario) | researcher-3 統合 |
| Q7 | 観察 instrumentation (transcript / hook stdio / golden file / snapshot / structured logging) | researcher-4 統合 |
| Q8 | folio 用 sandbox verification framework 推奨設計 | controller 統合導出 |
| Q9 | twill experiment-verified との境界明文化 | controller 統合導出 |
| Q10 | ADR 起票候補 | controller 統合導出 |
差分調査モード (DIFFERENTIAL_MODE=true、 既存 memory 前提: hash f621abb6 plugin-architecture / hash 96b16f0c twl Hooks/MCP / hash 322df262 Claude Code v2.1 更新)。 5 researcher を並列 spawn (sonnet model)、 67 fetch 成功 (failure 4)、 87 unique sources を集約。 critic 判定 PASS (WARNING 3 + Gap 5、 詳細は §9-§10)。
--plugin-dir が公式 dev install結論: --dev フラグは 存在しない。 公式の "development install" 相当は claude --plugin-dir ./my-plugin (verified [1])。 セッション限定ロード (install なし) がセキュリティ境界。
| 機能 | command | 備考 |
|---|---|---|
| dev install | claude --plugin-dir ./my-plugin | install なし、 session 限定。 同名 installed plugin より優先 (managed settings 上書き不可) |
| ZIP 対応 (v2.1.128+) | claude --plugin-dir ./my-plugin.zip | CI build artifact テスト用 |
| URL 指定 | claude --plugin-url https://example.com/my-plugin.zip | 説明用ダミー URL [1] |
| 複数同時 | --plugin-dir ./p1 --plugin-dir ./p2 | 複数 plugin 同時テスト可 |
| hot reload | /reload-plugins | plugins / skills / agents / hooks / plugin MCP / plugin LSP をリロード。 monitors は除外 (session restart 必要) |
| デバッグ | claude --debug | plugin load 詳細 / manifest error / skill/agent/hook registration 状況 [2] |
| validate | claude plugin validate [--strict] | plugin.json / frontmatter / hooks.json の syntax/schema check。 marketplace community 審査と同一ツール [1] |
| token cost | claude plugin details <name> | 各 skill の token cost 確認 |
公式は「Test the script manually」 と手動実行を推奨 [2]。 公式に hook の automated test framework は 存在しない。 推奨手順:
chmod +x ./scripts/your-script.sh (実行権限確認)#!/bin/bash)${CLAUDE_PLUGIN_ROOT} 利用確認echo '{...JSON}' | bash ./hooks/script.sh で stdin/exit code/stdout を手動 verifyclaude --debug で hook 起動確認PostToolUse not postToolUse)"matcher": "Write|Edit")hook handler type は 5 種 (command / http / mcp_tool / prompt / agent)。
公式推奨アプローチ [3]:
Evaluation JSON 形式 (公式サンプル):
{
"skills": ["pdf-processing"],
"query": "...",
"files": ["test-files/document.pdf"],
"expected_behavior": ["...", "..."]
}
~/.claude/projects/<encoded-project-path>/ に JSONL 形式で自動保存 [7] (詳細 schema は §5.1)simonw/claude-code-transcripts は「unofficial and undocumented APIs の変更により broken」 [8]LANGCHAIN_TRACING_V2=true 等で送信可能 ― 注記: この主張は researcher-1 の検索結果由来で、 公式 Claude Code docs に LangSmith 連携の専用 page は未確認/plugin Errors タブ (UI) でエラー確認2 つの公式 marketplace [4]:
claude-plugins-official: Anthropic 管理、 申請プロセスなし、 裁量で決定claude-community: 第三者 submission を review 後掲載
claude plugin validate ローカル実行必須claude.ai/settings/plugins/submit or platform.claude.com/plugins/submitclaude plugin validate + automated safety screening (詳細非公開)anthropics/claude-plugins-community/marketplace.json 反映permissionDecision: "deny" Bug 群 (4 件 verified)全 4 件が Closed / not planned:
| Issue | 対象 | 内容 | ステータス |
|---|---|---|---|
| #37210 [5] | Edit tool | well-formed deny が無視される | Closed / not planned |
| #33106 [6] | MCP server tools | deny が無視される (built-in は動作) | Closed / not planned (2026-03-11) |
| #39344 [7] | settings.deny vs hook | hook の "ask" が deny rules を silent bypass | Closed (2026-03-26)、 area:security ラベル |
| #18312 [URL 未確認] | allow list 内ツール | Bash allow list で deny/ask 完全無視 | Closed |
公式設計と実態の乖離:
sandbox.filesystem 設定 + OS レベルの filesystem/network アクセス制限 (Bash tool 限定)autoAllowBashIfSandboxed: true (default) で sandbox 内 Bash は prompt なし--plugin-dir) では sandbox の記述なし (unsandboxed)| 事例 | Runner Architecture | Scenario Format | Observation | CI 統合 |
|---|---|---|---|---|
| VS Code Extension [14][15][16][17] | 別プロセス Extension Host + @vscode/test-electron + Mocha |
.vscode-test.mjs (defineConfig) |
SourceMapStore, Test Explorer UI, exit code | xvfb-run + GitHub Actions |
| @vscode/test-cli [16][17] | CLI 設定駆動、 Mocha | .vscode-test.mjs |
AST / eval 二方式テスト抽出 | vscode-test コマンド |
| Neovim plenary.nvim [19][20][21] | ヘッドレス nvim 別インスタンス per file | *_spec.lua (Busted BDD) |
luassert spy/stub/mock, coroutine async | nvim --headless -c PlenaryBustedDirectory exit 0/1 |
| Neovim busted+shim [22] | XDG 分離 shim + -l フラグ |
*_spec.lua |
message trace table | .busted config |
| JetBrains IntelliJ [23][24][25] | 二プロセス (Starter+Driver) + JMX/RMI、 Light/Heavy 二層 | testdata/ + JUnit 5 |
bundled plugin が例外収集、 error log | Gradle + JUnit 5 |
| MCP Inspector (公式) [28] | React UI + Node.js Proxy + stdio/SSE/HTTP | CLI --cli + JSON output |
JSON-RPC 完全可視化 | CLI mode |
| mcp-recorder [30] | Proxy record/replay/verify | cassette.json (metadata + interactions) + scenarios.yml |
request/response/latency 記録 | pytest plugin @mcp_cassette |
| MCPSpec [31] | YAML declarative + session recording | YAML テストコレクション (10 assertion type) | schema drift detection | mcpspec ci-init 自動生成 |
| Obsidian [36][37] | Node.js hidden API + sandbox vault | なし (非構造化) | なし | 未成熟 |
| Chrome Extension (MV3) [26][27] | Puppeteer/Playwright + Browser context | Jest beforeEach/afterEach |
extensionRealms() / service worker target |
xvfb-run (headed mode 必須) |
| Continue.dev [33] | モノレポ 3 層 (Jest/Vitest/npm) | Jest/Vitest 標準 | PR ごと自動実行 | PR merge ブロッカー |
| Aider [34] | pytest 自己テスト + auto-fix loop | pytest | --test-cmd 任意コマンド |
pytest CI |
| pi-test-harness [35] | 実 runtime + 境界 3 点モック | Playbook DSL (when/calls/says) |
event collection 全ステップ | exit code |
when(trigger, actions=[calls(...), says(...)]) 形式の宣言的シナリオ、 LLM/外部プロセス境界のみ差替、 実 runtime はそのまま。 folio 応用: plugin の動作シナリオを Playbook 形式 YAML/DSL で記述action: verify_plugin_contract 相当のアクション定義、 10 種以上の assertion type、 environment variable injection、 tags、 parallel execution、 ci-init で GitHub Actions スクリプト自動生成。 folio 応用: verification rule を YAML で宣言し folio verify で実行.mjs / .lua) で宣言before_each / after_each で状態リセットgenerate() / chain_of_thought() / self_critique() chain + カスタム Solverexact() / includes() / pattern() / model_graded_qa(grader_models=[...]) で複数 grader majority voting [41]react() built-in + use_tools() + generate_loop() (ツール呼び出し停止までループ)handoff() で会話履歴共有sandbox().read_file() / sandbox().exec() でスコアリング時検査現在 OpenAI が取得済み (MIT ライセンス維持) [42][43]。
| assertion 種別 | 用途 | 特徴 |
|---|---|---|
llm-rubric | rubric pass/fail | 迅速・明確 |
g-eval | CoT 複数次元 | 高精度・高 latency |
factuality | 参照との一貫性 | ground truth あり |
select-best | pairwise 比較 | モデル間優劣 |
context-faithfulness | RAG faithfulness | 検索 context 根拠 |
assert-set の threshold: 0.66 で 3 judge 中 2 合格要求description / env / prompts / providers / defaultTest / scenarios / tests 順、 Nunjucks 変数展開| バイアス | 対策 |
|---|---|
| Position bias (提示順序による好み) | 位置交換 (swap) |
| Verbosity bias (長い回答への過評価) | 内容基準の明示 |
| Self-preference bias (同系統モデルへの過評価) | 異系統 judge 使用 |
| Non-determinism (スコアの不安定性) | temperature=0、 複数回実行平均 |
プラグイン状態遷移の自動検証パターン [50]:
| デコレータ | 機能 |
|---|---|
@initialize | テスト前に exactly once 実行 (プラグイン登録) |
@rule | 基本操作定義 (任意順で呼び出し、 lifecycle 操作) |
@precondition | ルール実行前条件チェック |
@invariant | 各ステップ後に必ず実行する検証 (REQ 維持) |
Bundle | 生成値の名前付きコレクション (target/consumes で再利用) |
folio 適用: hook 状態遷移 (unregistered → registered → active → error) を状態機械でモデル化、 全操作列に対して REQ invariant が保たれることを検証可能。
fc.ModelBasedTesting で commands と model を指定、 Jest/Mocha/Vitest で実行| EARS パターン | 構文 | Gherkin 対応 |
|---|---|---|
| Ubiquitous | The [system] shall [behavior] | Given (初期) + When (任意) + Then |
| Event-Driven | When [trigger], the [system] shall [response] | Given (前提) + When (トリガー) + Then |
| State-Driven | While [state], the [system] shall [behavior] | Given (状態) + When + Then |
| Unwanted Behavior | If [error], then the [system] shall [recovery] | Given + When (エラー) + Then (復旧) |
| Optional Feature | Where [feature enabled], the [system] shall [behavior] | Given (機能有効) + When + Then |
変換キー原則: EARS の 1 要件 = 1 Gherkin シナリオ (conductofcode.io で実証済 [52])。 自動変換ツールは RequireKit が /generate-bdd コマンドで EARS → Given-When-Then 自動生成 [53][54]。
folio REQ-CM-001 (Event-Driven) 変換例:
EARS: "WHEN AI agent attempts to write to spec_path, the system SHALL verify caller marker env var"
↓
Feature: spec edit caller marker enforcement
Scenario: caller marker is set correctly → allow
Given the AI agent has set FOLIO_ARCHITECT_CONTEXT=folio-architect
When the agent attempts to Write to scratch/specs/example.html
Then PreToolUse hook SHALL emit exit code 0 (allow)
Scenario: caller marker missing → deny
Given FOLIO_ARCHITECT_CONTEXT is unset
When the agent attempts to Write to scratch/specs/example.html
Then PreToolUse hook SHALL emit exit code 2 (block) with stderr message
PairwiseStringEvalChain で A/B テスト<link rel="match" href="references/test-ref.html"> で参照リンクrel="mismatch" で「異なること」 確認も可<meta name=fuzzy content="maxDifference=15;totalPixels=300">MANIFEST.json): 自動生成、 wpt manifest で更新.ini ファイル、 tests/ 構造をミラーした metadata/ ディレクトリに file.html.ini 形式で配置
expected: PASS / disabled: true / fuzzy: ...if 式で platform 依存の期待値記述Two-directory model [59][60]:
tests/baselines/reference/ ← VCS 管理 (期待値)
tests/baselines/local/ ← 実行生成 (.gitignore)
.js (コンパイル出力) / .errors.txt / .types / .symbolsreference/ vs local/ の diffjake baseline-accept で reference に昇格jake baseline-accept[soft] は新規のみ (delete なし)API 仕様を "Executable Contract" としてそのまま実行 [61][62]。 Scenario format (*.arazzo_inputs.json):
{
"WorkflowName": {
"DEFAULT": { "productType": "Electronics", "maxPrice": 1000 },
"GetProducts.IsArrayEmpty": { "maxPrice": 0 }
}
}
DEFAULT 基底 + named scenario 差分のみ指定してマージ$failureMessage で期待失敗メッセージ用語整理: Golden file ≈ Snapshot ≈ Golden master ≈ Known-answer testing (本質的に同じ概念)。
| 状況 | 推奨 | ツール例 |
|---|---|---|
| 複雑な出力構造 (DOM, AST) | Snapshot testing | Jest *.snap [65] |
| テキスト/CLI 出力 | Golden file | TypeScript baseline |
| 非決定的な値 | Property matcher で動的値をマスク | Jest expect.any(Date) |
| 小さな focused output | Inline snapshot | insta assert_snapshot!(value, @"...") [66] |
| 大きなコーパス | External .snap/.yml | pytest-regressions [68] |
4 つの diff/regression detection pattern:
reference/ vs local/.snap 直接更新 + VCS 追跡.snap.new → review → .snap 昇格JSONL 形式 (append-only) [70]、 ~/.claude/projects/<encoded-project-path>/:
{"type":"user","uuid":"...","parentUuid":"...","timestamp":"2024-01-01T00:00:00Z","sessionId":"abc","cwd":"/path","gitBranch":"main","version":"1.0","message":{"role":"user","content":"Your prompt"}}
{"type":"assistant","uuid":"...","parentUuid":"...","timestamp":"...","message":{"role":"assistant","content":[{"type":"text","text":"..."},{"type":"tool_use","id":"call_1","name":"Bash","input":{"command":"npm test"}}],"usage":{...}}}
{"type":"user","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"call_1","content":"Test output"}]}}
type / uuid / parentUuid / timestamp / sessionId / cwd / gitBranch / versiontranscript_path が全 hook イベント stdin JSON に含まれる、 SessionStart で transcript_path / session_id / cwd 利用可claude.agent.run → tool.*、 OTLP exportinvoke_agent span (CLIENT) → execute_tool spans (INTERNAL)、 gen_ai.* 属性、 TRACEPARENT/TRACESTATE で distributed trace 統合、 OTEL_LOG_RAW_API_BODIES=1 (v2.1.111+).jsonl)、 UTF-8、 各行 complete JSON object、 \n 区切り。 Top-level: TracesData / MetricsData / LogsData (混在不可)| 特性 | YAML | JSON | Markdown |
|---|---|---|---|
| 人間可読性 | 高 (コメント可) | 中 | 最高 |
| パーサビリティ | 厳密 (注意) | 高速・安定 | 限定的 |
| コメント | 可 | 不可 | 可 (prose) |
| LLM 可読性 | GPT 系強 | フォーマット失敗リスク | トークン効率最良 |
| 主用途 | Config, OpenAPI | API responses, Smithy | ドキュメント |
| 落とし穴 | Norway problem, indent | trailing comma | テーブル解析 |
実際の採用状況: WPT (INI + HTML) / TypeScript (テキスト + //// fourslash) / Specmatic Arazzo (JSON) / pytest-regressions (YAML) / Jest (.snap 独自) / Smithy (YAML/JSON) / h2spec (Go コード埋込) / MCPSpec (YAML)。
folio 推奨 (§7 で詳述): シナリオ定義 = YAML、 期待値出力 = JSON Lines / 独自テキスト、 Narrative = Markdown、 差分表示 = テキスト diff。
| 方式 | Declarative | Hermetic | 起動時間 | folio 適合性 | API access 制御 |
|---|---|---|---|---|---|
| Nix flake [75][76] | 最高 | 最高 (bit-for-bit) | ~0.3 秒 (初回 20 分) | 高 (学習コスト大) | OS level |
| Devbox [77] | 高 (JSON) | 高 (Nix 同等) | ~1.5 秒 (初回 4 分) | 最適 (試作段階) | OS level |
| mise [78] | 中 (TOML) | 中 (ツール版のみ) | ~10ms | ツール版用途 | なし |
| git worktree [8][79] | なし | なし (ファイルのみ) | 即時 | 最軽量 (repo 内完結) | なし |
| Docker / Podman [80][84][85] | 中 (Dockerfile) | 中〜高 (digest) | ms 〜 秒 (初回 8 分) | CI 向け | ネットワーク制御可 |
| devcontainer.json | 中 | 中 (image drift 有) | 数秒 | VS Code 連携 | コンテナ境界 |
| Firecracker microVM [81] | 低 | 最高 (KVM) | ~125ms | 過剰 (hook 検証のみ) | VM 境界 |
| Vagrant / QEMU [82] | 中 (Vagrantfile) | 高 | 数分 | 過剰 | VM 境界 |
| WSL2 [83] | なし | なし | 数秒 | Windows 向け | なし |
api.anthropic.com への外部アクセスは Claude Code 動作に必須。 完全網断は不可ANTHROPIC_API_KEY) は sandbox 起動前に注入必要。 起動後の追加はコンテナ再起動が必要で会話 context を失う~/.claude (ユーザーレベル設定) は sandbox 内で無効。 プロジェクトレベル設定 (.claude/settings.json) のみ有効Docker 公式 sandbox: sbx run claude コマンドが存在 [9]。 認証は環境変数 or OAuth。 Squid proxy で他ドメイン遮断しつつ Anthropic API のみ許可可。
BoxLite sandbox 統合提案 (Issue #15888) は Anthropic により "not planned" として却下 [13]。 公式 plugin isolation sandbox は存在しない。
| Step | 方式 | API call | 適用フェーズ |
|---|---|---|---|
| Step 1 (API 不要) | hook script を echo '{...}' | bash ./hooks/script.sh で直接 unit test | 不要 | Phase X3 最初 = MUST |
| Step 2 (軽量) | git worktree (.claude/worktrees/) に test project 作成、 .claude/settings.json で hook 設定 | API key 注入で可 | Phase X3 中盤 = SHOULD |
| Step 3 (本格) | 統合テストが必要な場合のみ Docker Compose (Squid 付き) で Claude Code 実行 | 必須 (Anthropic API のみ allowlist) | Phase X4+ = MAY |
.claude/worktrees/ 配下、 ファイル隔離のみ。 ポート衝突等の runtime isolation は別途対策必要devbox.json をリポジトリに含め Layer 1 consumer に配布、 Nix の複雑さ隠蔽flake.nix + flake.lock + nix flake check で CI、 学習コスト高internal: true + ドメイン allowlist で外部 API 制御scratch/verification/ 配下に隔離.claude-plugin/ の一部として配布候補。 ただし Phase X3 段階では plugin 本体と分離した試作物 として scratch/verification/ に配置scratch/
├── specs/ (既存)
├── decisions/ (既存)
├── research/ (既存、 本レポートを含む)
├── verification/ ← 新規 (本フレーム)
│ ├── README.html entry point + 全 scenario 一覧
│ ├── scenarios/ use case 別 scenario file
│ │ ├── caller-marker.yaml REQ-CM-001〜003
│ │ ├── path-boundary.yaml check-path-boundary.sh
│ │ ├── jsonld-lint.yaml REQ-CI-010〜015 関連
│ │ ├── readme-update.yaml auto-update on new spec
│ │ ├── context-inject.yaml SessionStart inventory inject
│ │ ├── bidir-link.yaml REQ-REL-002
│ │ ├── inventory-regen.yaml REQ-REL-004
│ │ └── ears-coverage.yaml REQ-CI-014
│ ├── fixtures/ テストデータ
│ │ ├── valid-spec.html REQ-REL-001 通過用
│ │ ├── invalid-jsonld.html JSON-LD lint fail 用
│ │ └── ...
│ ├── baselines/ 期待値 (golden file pattern)
│ │ ├── reference/ VCS 管理
│ │ └── local/ 実行生成 (.gitignore)
│ └── runner.sh 軽量 bash runner (試作)
理由: scratch/ は folio rule に縛られない箱 (CLAUDE.md 明記)。 verification 自体は HOW なので本体 specs/ と分離 (P-11 整合)。
folio scenario file の標準構造 (例: caller-marker.yaml):
# scratch/verification/scenarios/caller-marker.yaml
schema_version: "0.1"
req_id: "REQ-CM-001"
ears_pattern: "event-driven"
description: |
WHEN AI agent attempts to write to spec_path,
the system SHALL verify caller marker env var.
setup:
env:
FOLIO_ARCHITECT_CONTEXT: "folio-architect"
fixtures:
- source: fixtures/valid-spec.html
dest: scratch/specs/test-target.html
scenarios:
- name: "caller marker set correctly → allow"
given:
env: { FOLIO_ARCHITECT_CONTEXT: "folio-architect" }
when:
tool: "Edit"
file_path: "scratch/specs/test-target.html"
tool_input: { ... }
expect:
exit_code: 0
stderr: ""
decision: "allow"
- name: "caller marker missing → deny (exit 2 fallback)"
given:
env: { FOLIO_ARCHITECT_CONTEXT: "" }
when:
tool: "Edit"
file_path: "scratch/specs/test-target.html"
expect:
exit_code: 2 # Issue #37210/#33106 対策の確実な fallback
stderr_contains: "FOLIO_ARCHITECT_CONTEXT"
decision: "deny"
teardown:
cleanup_files:
- scratch/specs/test-target.html
設計判断の根拠:
permissionDecision: deny は信頼できない、 exit 2 + stderr を verify| 選択肢 | 利点 | 欠点 | folio 適合性 |
|---|---|---|---|
独自 bash runner (runner.sh) |
試作早い、 依存ゼロ、 P-11 隔離容易、 hook script との親和性 | scenario 仕様の標準化なし | Phase X3 最初 = 推奨 |
| Promptfoo (YAML + llm-rubric) [42] | LLM judge 統合、 OSS 実績、 YAML 自然 | 重量、 plugin verification 用ではない | Phase X4+ (LLM behavior eval 必要時) |
| MCPSpec (YAML + 10 assertion) [31] | MCP 専用だが汎用 YAML scenario pattern が参考 | MCP 専用名前空間、 folio に直適合せず | 参考のみ |
| Inspect AI (Python Task/Scorer) [38] | 高機能、 sandbox 統合、 multi-agent | Python 依存、 試作段階に重い | Phase X4+ (Anthropic eval methodology 採用時) |
| pytest-regressions + Hypothesis [68][50] | golden file + property test、 Python 標準 | Python 必須、 hook script 中心の folio に過剰 | Step 2-3 で validate_jsonld.py のテストに採用可 |
Phase X3 推奨: 独自 bash runner。 試作駆動哲学に合致。 完成形は Inspect AI / Promptfoo 統合候補だが、 まず動くものを 1 scenario から作る。
plugin-architecture-research.html §7.3 の Phase X3 minimal plugin (1 skill + 4 hook + 6 script + 1 CLI) と整合した 8 use case を REQ から導出:
| # | Use case | scenario file | REQ source | Step | 検証 method |
|---|---|---|---|---|---|
| 1 | caller marker check | caller-marker.yaml |
REQ-CM-001〜003 | Step 2 | echo JSON pipe + exit code |
| 2 | path boundary check | path-boundary.yaml |
(rules.html §10) | Step 2 | echo JSON pipe + exit code |
| 3 | JSON-LD lint | jsonld-lint.yaml |
rules §4.1 + relations §3 | Step 3 | fixture + lint script + golden output |
| 4 | README update | readme-update.yaml |
(relations §4 inventory) | Step 4 | 新 spec 追加 → README diff baseline |
| 5 | context injection (SessionStart) | context-inject.yaml |
(Beads pattern) | Step 5 | session start hook → injected content snapshot |
| 6 | 双方向 link materialize | bidir-link.yaml |
REQ-REL-002 | Step 8 | forward 宣言 → reverse 自動付与 baseline |
| 7 | inventory.json regen | inventory-regen.yaml |
REQ-REL-004 | Step 5 | spec edit → inventory.json diff baseline |
| 8 | EARS coverage report | ears-coverage.yaml |
REQ-CI-014 | Step 7 | EARS markup 完全性 grep + REQ-ID uniqueness |
bash scratch/verification/runner.sh 起動、 exit code 0/1 で merge gating~/.claude/projects/<path>/*.jsonl を session 終了時に scratch/verification/transcripts/ にコピー (§5.5)baselines/local/) に書き出し.jsonl) 直接出力で十分 (§5.6)baselines/reference/ (VCS) vs baselines/local/ (gitignore) の TypeScript 2-dir model + runner.sh --accept で reference 昇格 (§5.2, §5.4)twill は spec 内の「情報ひとつひとつ」 (HOW level) に experiment-verified label を付ける方式 (memory hash a6d6b7c1 / 09550ec2):
proposed / accepted / experiment-verified / archived| 軸 | twill (情報単位) | folio (機能単位) |
|---|---|---|
| 検証対象 | spec 内の各 claim (HOW level) | plugin の use case (機能単位) |
| 検証 marker | experiment-verified label を spec 内 inline | scenario YAML file (spec 本体外、 scratch/verification/) |
| 検証粒度 | 1 claim = 1 EXP | 1 use case = 1 scenario (REQ 単位 with EARS) |
| spec 内容 | 情報単位 verified | WHAT-only (verified label なし) |
| constitution 整合 | (twill 独自) | P-3 + P-11 遵守 |
将来、 folio Layer 0 のオプション plugin として folio-claim-verifier (仮称) を提供する設計余地:
data-claim-id="C-001" 等を付与scratch/claims/C-001.html 等) で claim 単位の verify status を管理scratch/verification/scenarios/*.yaml は WHAT (どの REQ をどう検証するか、 use case 単位) のみ規定scratch/verification/ 配下に隔離architecture/verification/ に移植時、 binding を .claude-plugin/scripts/ に分離| ADR ID 候補 | title | 内容 | 関連 finding | 優先度 |
|---|---|---|---|---|
| ADR-0013 | plugin verification framework (sandbox 設計 + scenario format + runner) | folio Phase X3 用 sandbox verification framework を scratch/verification/ に配置。 YAML scenario + bash runner + 2-dir baseline。 8 use case を REQ から 1:1 派生。 P-3/P-11 整合のため本体 spec とは分離。 |
§7 全般 | MUST (Phase X3 着手前) |
| ADR-0014 | verification scenarios を EARS REQ から導出する規範 | EARS 5 pattern を Gherkin Given/When/Then に 1:1 変換。 RequireKit /generate-bdd 相当のルールを folio 用に定式化。 1 REQ = 1 scenario MUST。 |
§4.6 (EARS→Gherkin)、 §7.3 (scenario format) | MUST |
| ADR-0015 | sandbox verification vs experiment-verified (twill 方式) の境界 | folio は機能単位 sandbox verification を採用、 情報単位 experiment-verified は将来別 plugin で独立。 P-3 (WHAT-only) + P-11 (HOW 禁止) との整合を明文化。 twill 方式採用しない根拠。 | §8 全般 | MUST |
| ADR-0016 | exit code 中心の assertion 規範 (Issue #37210/#33106 対策) | permissionDecision: deny JSON は信頼できない (Closed/not planned バグ群)。 verification scenario の assertion は exit_code: 2 + stderr_contains を確実な fallback とする。 |
§2.6 (Issue verify)、 §7.3 (scenario format) | SHOULD (Issue #39344 fix 状況確認後) |
| ADR-0017 | hook unit test vs integration test の境界 | unit test (echo JSON pipe + exit code) は API call 不要、 Phase X3 で MUST 実装。 integration test (実 Claude session 内 hook 発火) は API call 必要、 Phase X4+ で Docker Compose + Squid 採用候補。 | §6.2, §6.3 | SHOULD |
| ADR-0018 | scenario file の golden baseline 管理 (2-dir model + accept workflow) | TypeScript baseline pattern + insta accept workflow を採用。 baselines/reference/ (VCS) vs baselines/local/ (gitignore)、 runner.sh --accept で昇格。 |
§5.2, §5.4, §7.3 | SHOULD |
起票手順: 各 ADR について (1) user に提示 → (2) user 承認取得 → (3) scratch/decisions/ADR-NNNN-<slug>.html に Accepted status で起票 → (4) 関連 spec section に cross-ref を追加。 CLAUDE.md の制約により自動起票は禁止。
permissionDecision: deny JSON も信頼できる可能性があり、 assertion 戦略が変わる。 推奨検索: site:github.com/anthropics/claude-code/issues/39344 fix resolved commit、 "Claude Code" changelog v2.1 "permissions" "hook" fix release notes。runner.sh の仕様不在runner.sh を Phase X3 の中核として推奨しているが、 runner.sh の具体的なインターフェース仕様 (YAML scenario の parse 方法、 assertion 評価ロジック、 exit code の集計方法) は未記載。 ADR-0013 起票時に runner.sh の最低限の設計決定 (bash + yq か、 Python + PyYAML か等) が必要。 推奨検索: bash YAML parser yq script lightweight test runner exit code assertion、 "yq" YAML parsing bash script test framework minimal 2026。claude plugin validate の全 check 項目"claude plugin validate" checks items list "strict" mode output format、 site:github.com/anthropics/claude-code "plugin.json" schema required fields validation。site:github.com/anthropics/claude-code/issues "18312" Bash allow list deny ignore。(deduced) ラベル (GitHub OSS README 水準)。 fc.ModelBasedTesting API の具体的な使用例が公式 docs (fast-check.dev) から未取得。 folio TypeScript plugin 実装時に直接参照が必要になる可能性 (Phase X4+ 候補)。 推奨検索: fast-check "ModelBasedTesting" "commands" API documentation TypeScript example、 site:fast-check.dev model-based testing stateful。LANGCHAIN_TRACING_V2=true 主張は専用 URL が Evidence Table に未記載。 公式 Claude Code docs に LangSmith 連携の専用 page が確認できなかった。 transcript capture の主方法 (JSONL 自動保存) は公式 verified、 LangSmith は補足情報に留めるべき(deduced) に修正済 (本レポート反映済)。 機能説明自体は正確、 Phase X3 採用なし全 87 sources (公式 docs 多数 + GitHub OSS 多数 + tech blog 多数 + GitHub Issues 4 件)。 確認日 2026-05-23。
/tmp/research-search-59a916c0/