フィールドトライアル方法論 — 目的・フェーズ・終着点
本ドキュメントは、フィールドトライアル(FT)ループがなぜ存在するか、目的が どう変化したか、何をもって「完了」とするかを説明する。手順(診断/ペンテスト の周期・レポートテンプレート・DX レビューのペルソナ)は CLAUDE.md §12 と docs/templates/field-trial-report.md を参照。
なぜ FT ループが存在するのか
各 FT は 独立サンドボックス(/home/xi/docker/nene2-python-FT/ftNNN-*/)上で nene2-python を使って実際のワークロードを実装し、全チェックを通し、実装者が実際に 詰まった摩擦点を記録する。狙いは、推測ではなく観察からドキュメントと設計を育てること:
- フレームワーク API が多様なドメインで 安定・快適 に使えることを実証する
- 摩擦点(
F-1,F-2, …)を具体的で修正可能な観察として表面化する - セキュリティ診断・クラッカーペンテストを通じ セキュリティ知見 を蓄積する
- 決定を記録し続けることで AI 可読性 を保つ
各 FT の恒久的な成果物は docs/field-trials/ のレポートであり、サンドボックス 自体は使い捨て(.venv は uv sync で再生でき、古いサンドボックスは ft-status.sh --clean-sandbox で定期的に整理する)。
フェーズ(目的は時間とともに変化した)
FT ループは単一の活動ではなく、目的が段階的に変化してきた。#540 はまさにその変化が 明文化されていなかったために存在する。
フェーズ0 — フレームワークのフィードバックループ(FT1〜FT6)
実サンプルアプリ(lunchlog / bookshelf / tasklist / wallet / weather …)で フレームワーク機能を検証した: 認証(Bearer/ApiKey)・ミドルウェアスタック・ MCP サーバー/クライアント・トランザクション・AsyncUseCaseProtocol。目的は フレームワーク自身の API を堅牢化することで、発見は nene2.* に直接反映された。
フェーズ1 — 標準ライブラリの体系的検証(FT7〜約FT202)
コア API が安定した後、ループは 1 FT につき標準ライブラリ 1 モジュールを薄い nene2 HTTP 層でラップする方向に転換した。各 FT が問うのは「フレームワークの parse → use-case → response の形が このドメイン で快適か、このモジュール の 安全な使い方の落とし穴は何か」。このフェーズが FT INDEX と how-to 群の大半を生んだ。
フェーズ2 — セキュリティ深掘り(FT203〜)
約 FT203 以降、ループは セキュリティプリミティブ と「危険プリミティブ回避」 シリーズに重心を移した: secrets/hashlib/hmac(暗号)、 pickle/marshal/ast.literal_eval/eval(デシリアライズ)、subprocess (コマンドインジェクション)、urllib.parse/ipaddress(SSRF)、re(ReDoS)、 zipfile/tarfile/zlib/gzip/lzma(slip・解凍爆弾)、 string.Formatter/string.Template(format string / SSTI)。これらは 監査チェックリストとしても機能するため、恒久的価値が最も高い。
周期
- セキュリティ診断(🔒):
FT % 3 == 0の FT で実施 - クラッカーペンテスト(🔍):
FT % 4 == 0の FT で実施 - 6 ペルソナ DX レビュー: 全 FT で実施
終着点 — 「完了」の定義
標準ライブラリの網羅スイープは永久に回す前提ではなかった。フェーズ2 までで セキュリティ関連の標準ライブラリ表面は網羅済みである(シリアライズ・圧縮/ アーカイブ・パース/マークアップ・暗号/認証・サブプロセス・ファイルパス・ ネットワーク入力・正規表現・数値入力の堅牢化)。純粋に計算系のモジュール (colorsys・cmath・calendar・math …)を追加でラップしても、当初の目的に 対する限界効用は逓減する。
したがって FT ループは 網羅スイープとしては完了と見なし、保守 + オンデマンド モードへ移行する。新規 FT が正当化されるのは、以下のいずれかのトリガーが発火した ときに限る:
- 新しいフレームワーク機能の検証が必要なとき(フェーズ0 型のフィードバックに戻る)
- 新しい依存(標準/サードパーティ)を フレームワークまたは example に採用 する とき — 依存する前に検証する
- 未カバーのセキュリティカテゴリが見つかったとき(新種のインジェクション等)
- メンテナからの明示的な依頼
保守モードでの定常的な義務は、月次の uv lock --upgrade → pip-audit → テスト → PR サイクル(CLAUDE.md §5)であり、新規 FT ではない。
続けるか止めるかの判断
- 候補 FT が上記 4 トリガーのいずれにも該当しないなら、回さないことを優先する。 ループを閉じ、その分のサイクルをオープン Issue やフレームワーク機能に充てる。
- 「完了」は番号ではなく記録された決定である。ループを停止するときは
docs/todo/current.mdに決定を記録し、 FT INDEX のフッターも更新する。
摩擦点と決定の分類
オンデマンドで FT を走らせる際は、各摩擦点(F-1, F-2, …)に kind(種別) と decision(決定) を付けて記録する。自由記述のままにせず、トライアル横断で 一貫・分析可能にするため。
Friction kinds(摩擦の種別)
| Kind | 意味 |
|---|---|
docs-gap | フレームワークの挙動は正しいが、ドキュメント/例から発見できなかった。 |
feature-gap | 実装者が期待した機能が実際に欠けている。 |
design-trade-off | 意図した設計判断の受容可能な帰結としての摩擦。 |
process-gap | API ではなくツール/ワークフロー(CI・チェック・足場)の摩擦。 |
python-idiomatic-trade-off | Python 固有の摩擦(Pydantic v2 の型強制・async/await・uv lock・mypy strict)で唯一解が無いもの。 |
最後の種別は、NeNe の renovation 固有 legacy-preserved の置換である(新規構築の Python フレームワークには当てはまらないため)。
Decision kinds(決定の種別) — 各摩擦は必ずひとつに収束する:
| Decision | 対応 |
|---|---|
fix-in-framework | 同 FT の PR 内でフレームワーク/例のコードを修正。 |
document | 挙動は正しい。ドキュメント/CLAUDE.md を追記・明確化。 |
keep | そのまま受容し、理由を記録。 |
defer | 理由を明記して follow-up Issue で追跡 — Issue が FT PR より長生きする唯一のケース(CLAUDE.md §12)。 |
このタクソノミーは姉妹リポジトリのガバナンス提案(#545)から抽出した。提案の残り (bootstrap script・専用 ADR・独立した FT README)は、既に CLAUDE.md §12・既存の レポートテンプレート・本ドキュメントで カバー済みか、FT ループが終着点に達したことで価値が低くなっている。
まとめ
| フェーズ | 範囲 | 目的 | 状態 |
|---|---|---|---|
| 0 — フレームワーク FB | FT1〜FT6 | nene2 API の堅牢化 | ✅ 完了 |
| 1 — 標準ライブラリ検証 | FT7〜約FT202 | 快適性の確認 + ドキュメント拡充 | ✅ スイープ済 |
| 2 — セキュリティ深掘り | FT203〜 | セキュリティプリミティブ=監査チェックリスト | ✅ 表面網羅 |
| 保守 + オンデマンド | — | 4 トリガー時のみ FT・月次依存更新 | 🔄 現在 |