Superseded by 0016 (2026-08-31)。Phase 1(inline Behavior.stepsの導入)は実装され「Acceptedへ変更する条件」を一度満たしたが、実データでの利用によりbehavior.stepsをConditionの共通粒度とする前提そのものが崩れたため、0016がこのADRを置き換える。
generate.rs::generate_testcasesが生成するTestCase.stepsは、実装上は配列型だが実際には常に[behavior.description]という単一要素にしかならない(testcase-generation-design.md §3.3(現行の見出しは0016後の内容に更新済みだが、当時のtitle = condition.description/steps = behavior.stepsという単純転記方式の記述はそのまま残っている))。behavior.yml(behavior.schema.json)自体にはdescriptionという1つの自由文フィールドしかなく、Test Designerは本来順序立てて書きたい複数の操作手順を1つの文字列に無理に詰め込んでいる。testcase-generation-design.md §7は「Behavior階層を使ったより高度なグルーピング・Axisの多段管理などのモデル拡張」を将来課題として明示していたが、steps自体の複数要素化には言及していなかった。
同時に、複数のBehaviorが同じ操作手順(例: ログイン手順)を繰り返し記述する再利用ニーズが将来生じうる。descriptionを都度コピーすると内容の乖離(あるBehaviorだけ手順が更新され、他が古いまま)を検出できない、という懸念がある。
当初案では、Behaviorの複数要素化・共有Stepレジストリ・UID・ハッシュ整合性検証・acceptコマンドを一度に導入する設計を検討した。しかしレビューにより、この一括導入は過剰であると判断した。共有ニーズは現時点で実データに基づく確認ができておらず(本ADR時点でリポジトリ内にbehavior.ymlの実データは存在しない)、共有Step変更時の影響範囲(全参照Behavior一括更新か個別承認か、原子性、復旧)や、Stepを第6のEntityKindとしてidentity lifecycle基盤に統合する必要性も未検証のまま、hash不一致のfail-closed運用だけを先に確定させることはリスクが大きい。
そのため本ADRは、複数要素化そのもの(Phase 1)だけを決定事項とし、共有レジストリ以降(Phase 2〜4)は実データで需要を確認したうえで改めて設計する方針とする。
behavior.ymlの形式変更に伴う既存データのマイグレーションは行わない。本ADR時点でリポジトリ内(samples/含む)にbehavior.ymlの実データは存在しないため、一括書き換えや移行コマンドは不要である。steps必須フィールド追加はADR 0014が定めるschema_version更新の対象としない。Behavior.stepsを導入するbehavior.ymlにsteps: Vec<String>(必須、順序付き配列)を追加する。各要素はその場に直接書くインライン文字列であり、共有レジストリへの参照は行わない。steps配列の1要素 = 1操作」に統一する。複数操作をまとめて1要素に書くことは許容しない。descriptionは人間向けの1文要約として残すが、テストケース生成には一切使わない。generate.rs::generate_testcasesのsteps = [behavior.description]をsteps = behavior.stepsに置き換える。behavior.descriptionは生成ロジックから完全に除外され、knowledge/上の人間向けドキュメントとしての役割のみを持つ。stepsが空配列である場合、および各要素が空文字列である場合は、Knowledge検証でエラーとする。steps accept等の復旧コマンドは、本Phaseでは導入しない。knowledge add --edit(KnowledgeDraft/BehaviorDraft、src/knowledge_draft.rs)を、新設の必須stepsを入力・検証できるように更新する。具体的には、BehaviorDraftへstepsフィールドを追加し、knowledge add --editが開く空draftテンプレートおよび非対話呼び出し用のテンプレート出力(markharness knowledge add --edit --print-template相当、cli.rs)にもsteps:の記入欄を含める。push_missing_descriptionと同様に、draft側でもstepsが空・全要素空文字列の場合は検証エラーとする。この更新を行わない限り、唯一の作成経路が新しい必須フィールドを満たせず、Behaviorを新規作成できなくなる。# behavior.yml
id: todo-add-task
feature: todo
label: Add Task
axis: [ui]
description: "User adds a task."
steps:
- "タイトル欄をクリックする"
- "何も入力しない"
- "送信ボタンを押す"
generate.rs::generate_testcasesの変更は、steps = [behavior.description]という前提で書かれている既存テストヘルパー・アサーション(例: steps: vec![case.behavior_description.clone()]を組み立てるテストケース構築箇所、tc.stepsが単一要素であることを前提にしたassert_eq!群)を洗い出し、複数要素stepsに対応させる書き換えが必要になる。影響箇所の網羅的な洗い出しは実装着手時のchecklist化(checklist-<task>.md)で行う。behavior.schema.jsonへのsteps必須フィールド追加、serialize_behavior、fixture、schemaテストの更新が必要になる。schema versionはv1のまま変更しない(上記「前提」参照)。knowledge_draft.rsのKnowledgeDraft/BehaviorDraftおよび関連する検証(push_missing_description相当のsteps版)、draftテンプレート文字列、knowledge_apply::apply_draftのBehavior書き出し処理、既存の draft parse/validate テスト(description: null等の欠落パターンを検証しているテスト群)を、steps必須化に合わせて更新する必要がある。schema/behavior.schema.jsonはvalidate.rsから実行時バリデーションとして実際に使われており、descriptionはminLength: 1でschema層に検証を寄せている。一方このリポジトリには配列長を制約するminItemsの前例がなく、axis: []のように空配列を許容してきた既存フィールドしかない。stepsについてminItems/items.minLengthをschema側に追加して宣言的に弾くか、push_missing_description同様にRust側の手続き的チェックに寄せるかは、実装着手時に決め打ちしておく。stepsの性質上、機械的な検証では強制できない(例: 「Aする。Bする。」を1要素に書いてもknowledge validateは通過する)。この規約はTest Designerのレビュー運用に委ねられるものであり、Knowledge検証の対象外であることを実装時に明記しておく。Phase 1導入後、しばらく実データを蓄積した上で次を確認する。
判断基準は定量的な閾値を設けず、定性的に「重複・更新漏れが実際に発生したら」次のPhaseへ進む。実際に発生しなければ、inline Behavior.steps(Phase 1)のみで完了とする。
Phase 2で共有需要が確認できた場合に限り、別ADR(または本ADRの改訂版)として次を設計する。詳細は本ADRでは決定しない。
.markharness/steps/のデータモデルEntityKindにするか、より単純な共有レジストリで足りるかの判断Phase 3で共有レジストリを導入する場合に限り、次を設計する。詳細は本ADRでは決定しない。
knowledge validate/generateのfail-closed動作steps add/steps acceptの挙動(全参照Behaviorを一括更新するか、個別承認するか、Step変更と参照側更新の原子性、失敗時の復旧、変更対象Behavior一覧の表示)Behavior.steps: Vec<String>の追加、schemaテスト・fixture・generate_testcases・関連テストの更新)が完了すること。steps add/steps acceptの挙動)。共有需要が確認された時点で別途ADRを起こす。knowledge add --edit拡張)。なお、Phase 1でknowledge add --editのdraftテンプレートにstepsの記入欄を追加すること自体は上記Phase 1決定事項に含まれ、対象外ではない。