Status: Implemented(markharness verify trace / markharness verify pending)
関連ドキュメント: テスト知識管理のGit-nativeモデル_統合版.md(以下「統合版」)、gap-analysis-mh-sample-test-case.md
対象読者:markharness(またはその後継ツール)の実装者
位置づけ:本資料は統合版第3.5節・図4が構想する「ChangeEventを起点とした影響TestCase特定→再確認」のうち、実行結果側との連動を具体化するための追加仕様である。統合版はChangeEventの自動生成とimpacted_testcasesの特定までを核心的貢献としており、「その後、実際に再実行されたか」を自動判定する仕組みは第7章(Future Work)相当の未確定領域だった。本資料はこの領域を仕様化する。
現状(MMフォルダの実装)で自動的に答えられない、しかし運用上は必ず聞かれる2つの問いを解決する。
現行実装では、executions/<milestone>/results.ymlがcase_id / result / executor / executed_atのみを保持し、changes/<from>-<to>.yamlのimpacted_testcasesとの突き合わせは人間が目視で行っている。この突合を自動化する。
統合版のER図(第3.1節)におけるTESTEXECUTIONに、以下を追加する。
# executions/<milestone>/results.yml の1レコード
case_id: tc-edit-existing-todo-001
result: pass
executor: soreiyu52
executed_at: 2026-08-08T16:38:52Z
verified_feature_tree_shas: # 追加フィールド
todo-edit: 4f2c9a1e8b3d5670012ab34cd56ef7890a1b2c3
verified_feature_tree_shas:そのTestCaseのgenerated_from(第2.2節参照)に列挙されるFeatureそれぞれについて、実行時点のマイルストーンでのFeatureディレクトリ全体のtree SHA(feature.yml自身だけでなく、配下のBehavior/Condition/ExpectedResultを含むディレクトリ全体のGitツリーオブジェクトSHA)を記録する。feature.yml単体のblob SHAではない点に注意(第7章参照:単体blobだとCondition/ExpectedResultの変更を検知できない)。id_indexキャッシュ(統合版第3.3節)から、対象マイルストーンにおける該当FeatureディレクトリのtreeオブジェクトSHAを引いて機械的に埋める。人間が手入力する項目ではない。generated_fromは既存のまま利用generated/testcases/*.ymlのgenerated_from.feature(例:todo-edit)は既にFeature idを保持しているため、verified_feature_tree_shasのキーとして流用できる。スキーマ変更は不要。
resolved状態は持たせないChangeEvent(changes/*.yaml)自体に「再確認済みフラグ」を持たせる設計は採らない。理由:
--historical既定 / --current-tree)changes computeが書き出すChangeEvent.impacted_testcasesは、2026-08時点で2つのモードを持つ。
to_milestoneタグが指すknowledge/ツリーからTestCaseを生成する。同じfrom_milestone..to_milestone区間を後日再計算しても、常に同じimpacted_testcasesが得られる。--current-tree(従来動作、後方互換のためのオプトイン):現在の作業ツリーのknowledge/からTestCaseを生成する。作業ツリーが変化し続ける限り、同じ区間を再計算するたびに結果が変わりうる。本節2.1のverified_feature_tree_shasとの突合(第3.2節Q2)は、changes/*.yamlに書き出されたimpacted_testcasesの集合をそのままImpactedとして使うため、--current-treeで計算したchanges/*.yamlを後から--historical(既定)で再計算し直すと、Impacted集合自体が変わりうる点に注意する。再現性が必要な運用(本節が前提とするpending/stale判定)では既定のhistoricalモードを使うこと。
入力:case_id, milestone(対象TestExecutionレコード)
results.ymlから対象レコードのverified_feature_tree_shasを取得する。changes/配下の全ChangeEventレコードをto_tree_sha == verified_feature_tree_shas[feature_id]で検索する。event_id・from_milestone・to_milestoneを「この結果が反映している変更」として返す。derived_from鎖を遡り「最後に変更があったマイルストーン」を返す。出力例:
$ markharness verify trace tc-edit-existing-todo-001 --milestone test2
case_id: tc-edit-existing-todo-001
feature: todo-edit
executed_at: 2026-08-08T16:38:52Z
reflects_change: todo-edit--test1--test2
from_milestone: test1
to_milestone: test2
change_type: (未記録、markharness changes annotate で事後入力すれば表示される)
入力:from_milestone, to_milestone(比較したいマイルストーン区間。省略時は直近の隣接ペア)
changes/<from>-<to>.yamlから対象区間の全ChangeEventを読み、impacted_testcasesを統合した集合 Impacted を作る。to_milestone以降(to_milestone自身を含む、以降の全マイルストーン)のresults.ymlを走査し、各case_idについてverified_feature_tree_shas[feature_id] == changes[event].to_tree_shaを満たすレコードが1件でもあれば「再検証済み」とする。Impacted - 再検証済み集合 を「未再実行」として出力する。to_milestoneより後に、対象Featureがさらに変更されている場合(=to_tree_shaがすでに古くなっている場合)は、「未再実行」ではなく「対象自体が陳腐化(stale)」の区分で別掲する(3.3節)。出力例:
$ markharness verify pending --from test1 --to test2
pending (再実行なし):
- tc-edit-existing-todo-001 (todo-edit の変更 test1→test2 の影響、未実行)
stale (影響範囲がさらに変更済み):
(なし)
Q2をマイルストーン跨ぎで運用すると、「再実行される前に対象Featureがさらに変わってしまった」ケースが必ず発生する。これを一律「未実行」として扱うと、テスターは「どの版に対して確認すればよいか」を見失う。そこで2区分に分ける。
判定:対象Feature idについて、Impacted集合の生成元ChangeEventのto_tree_shaが、現在の(問い合わせ時点の)tree SHAと一致するかをid_indexキャッシュで確認する。一致すれば pending、不一致なら stale。
markharness本体のCLIサブコマンドとして以下2コマンドを実装する。
| コマンド | 用途 | 対応する問い |
|---|---|---|
markharness verify trace <case_id> --milestone <m> |
指定した実行結果がどのChangeEventを反映しているかを表示 | Q1 |
markharness verify pending [--from <m1> --to <m2>] |
未再実行/陳腐化したTestCase一覧を表示 | Q2 |
verified_feature_tree_shas・changes/*.yaml・.markharness-cache/(id_index)のみを入力とする。verify pendingをマイルストーンのリリースゲートで実行し、pendingが1件でもあれば非ゼロ終了コードを返すオプション(--fail-on-pending)を用意する。これにより「変更影響テストの再確認漏れ」をCIで機械的にブロックできる。現行のchanges/test2.yaml・executions/test2/results.ymlを本仕様に沿って再構成すると、以下のようになる(verified_feature_tree_shasは本仕様導入後に新規実行分から付与される想定であり、既存レコードには遡及適用しない。第6章参照。to_tree_shaはFeatureディレクトリ全体のtree SHAであり、changes computeの再実行によって値が変わる。以下は例示用の値)。
# changes/test2.yaml(例示。tree SHA化により実際の値は変わる)
- event_id: todo-edit--test1--test2
feature_id: todo-edit
from_milestone: test1
to_milestone: test2
from_tree_sha: null
to_tree_sha: 4f2c9a1e8b3d5670012ab34cd56ef7890a1b2c3
impacted_testcases:
- tc-edit-existing-todo-001
# executions/test2/results.yml(本仕様導入後の形)
- case_id: tc-edit-existing-todo-001
result: pass
executor: soreiyu52
executed_at: 2026-08-08T16:38:52Z
verified_feature_tree_shas:
todo-edit: 4f2c9a1e8b3d5670012ab34cd56ef7890a1b2c3
この2つを突き合わせると、to_tree_shaとverified_feature_tree_shas.todo-editが一致するため、markharness verify pending --from test1 --to test2はtc-edit-existing-todo-001を pending 扱いにせず、正しく「再検証済み」と判定する。
results.yml(test1〜test3)はverified_feature_tree_shasを持たないため、本仕様導入前の実行記録はQ1/Q2の判定対象外(「不明」扱い)とする。統合版第4章のバックフィル方針と同様、id_indexキャッシュから当時のtree SHAを機械的に補完することは理論上可能だが、当面はスコープ外とし、Future Workとする。change_typeとの関係:ChangeEvent.change_type(統合版第3.5節)はmarkharness changes annotateにより事後入力できるようになった。本仕様のQ1/Q2判定自体はtree SHA比較のみで完結し、change_typeの有無には依存しない。verify pendingの出力に変更種別(仕様変更/バグ修正等)でのフィルタ・グルーピングを追加することは未実装で、引き続き将来課題である。schema/execution_result.schema.json(markharness initが既定一式の一部として配置し、markharness validateがexecutions/*/results.ymlを検証対象に含める)を実装済み。case_id/result/executor/executed_atを必須、note/verified_feature_tree_shasを任意フィールドとして定義しているため、本仕様導入前(verified_feature_tree_shasを持たない)の既存レコードも構造検証は通過し、上記「遡及適用はしない」方針とは矛盾しない(cli-manual.md 1.17節)。verified_feature_tree_shasはTestCase生成元のFeature単位で記録するため、Condition・ExpectedResultレベルの変更は自動的に捕捉される:ConditionはFeature配下のツリーの一部であり、Conditionが変わればFeatureディレクトリ全体のtree SHAも変わる。この捕捉はid_cache::resolve_feature_versionsがFeatureディレクトリ全体のtree SHA(git ls-tree -r -tでディレクトリのtreeオブジェクトSHAを取得)を比較することで実現しており、feature.yml単体のblob SHAだけを比較する実装では成立しない(実装初期はfeature.yml単体のblobを比較しており、Condition/ExpectedResultの追加・変更を見逃す既知の不具合があった。この節の記述はその修正を前提にしている)。ただしFeature自体は変わらずAxisレジストリ(axes/*.yml)側だけが変わるケースは本仕様の追跡対象外であり、別途検討が必要。verified_feature_tree_shasが複数キーを持つため、「一部のFeatureだけ再検証され、他は未検証」という部分再検証状態が発生しうる。3.2節のアルゴリズムはこの場合、いずれか1つでも不一致があれば pending として扱う(保守的判定)。