Accepted(2026-09-16決定)。
markharness v2は、Change ImpactとRelease Coverageのビューやダッシュボードを別リポジトリmarkharness-view(仮)に委ねる方針である。この方針を実現するため、docs/ja/design/cli-read-model-design.md(Draft)がCLIの外部向け読み取り契約(リードモデル)を、新設のrecord_kind/schema_versionエンベロープとCommandOutcomeへの新variant追加を前提に提案した。
grillingセッションで実装(src/)を調べたところ、この前提は誤りだった。実際には次の2つの独立した出力系統が既に存在する。
CommandOutcome/Presenter系統(src/presentation.rs): canonical_imported・generated・changes_computed(markharness changes computeが.markharness/changes/へ書き込む処理結果)の3つの書込み系コマンドの結果を表す。JsonPresenterは{"schema_version": 1, "outcome": "<tag>", ...フィールド}というフラットな形式で、v0.6.1から出力している。src/impact.rs・src/coverage.rs): impact・coverageという読み取り系コマンドは、CommandOutcome/Presenterを一切経由しない。各モジュールが自前の構造体(ChangeImpact・ReleaseCoverage)を持ち、schema_version・record_kind(値はそれぞれ"change_impact"・"release_coverage")フィールドを既に備え、cli.rsからserde_json::to_string_prettyで直接シリアライズしている。--formatは現状Jsonしか値がなく、人間可読出力は未実装である。つまり、ドラフトが提案しようとした「record_kind/schema_versionを持つリードモデルを、Application層で生成してJSON Presenterへ渡す」という設計は、impact/coverageについて既に実装済みである。またrecord_kindという名前自体も、0025とmarkharness-v2-design.md§9.1が.markharness/配下の永続レコード向けに確立し、impact/coverageのCLI出力もそれを踏襲している既存の命名規約であり、ドラフトが暗黙に想定していた新規の入れ子構造やフィールド名でもない。
新規に必要なのは、この既存パターンに従うtraceabilityコマンド(現状は未実装)を1つ追加することだけである。
さらに、src/traceability.rsというファイル自体は既に存在しており、TraceabilityIndex/build_index/serialize_indexを実装している。これはgenerateが生成時に組み立て、.markharness/generated/traceability-index.jsonへ書き込む生成アーティファクト(application.rs)であり、verifyが再生成の決定性を確認するために使う(verify.rs)。TestCase単位のフラットな一覧(case_id・requirement_ids・feature・behavior・scenario・axis)で、record_kind/schema_versionを持たず、markharness-viewが読む対象でもない。新設するTraceabilityReadModel(Requirement/Feature/Behavior/Scenario/TestCaseの各Node配列とRelationを持つ、--at指定時にオンデマンドで計算されCLI標準出力へ返す読み取り専用モデル)とは、生成物か問い合わせ結果かという点も含め責務が異なる。同じファイル名を異なる責務のために使い回すと、どちらのモジュールを指しているか読み手が混乱するため、本ADRで名前の衝突を解消する。
traceabilityはimpact/coverageと同じ出力パターンに従う新設するtraceabilityコマンドは、CommandOutcome/Presenterを経由しない。impact.rs・coverage.rsと同様、専用モジュールにTraceabilityReadModel構造体を定義し、schema_version: u32・record_kind: &'static str(値は"traceability")を持たせ、cli.rsからserde_jsonで直接シリアライズする。
CommandOutcomeへの新variant追加(ImpactComputed・CoverageComputed・TraceabilityComputed)は行わない。impact・coverageは元からCommandOutcomeを使っておらず、traceabilityもそれに合わせる。
src/traceability.rsはsrc/traceability_index.rsへリネームし、src/traceability.rsを新設CLIコマンド用にするTraceabilityIndex/build_index/serialize_index(generateの生成アーティファクト用)は、名前をsrc/traceability_index.rsへ変更する。呼び出し元(application.rs・verify.rs)のuseと参照パスを更新する。型名・関数名・.markharness/generated/traceability-index.jsonというファイル名自体は変更しない(生成アーティファクトのファイル名はモジュール名と独立した既存の外部仕様であり、変更する理由がない)。
空いたsrc/traceability.rsを、新設CLIコマンドtraceability(TraceabilityReadModel)専用のモジュールとする。これにより、impact.rs↔impactコマンド、coverage.rs↔coverageコマンドと同じ「モジュール名がコマンド名と一致する」命名パターンをtraceabilityでも維持できる。
このリネームは、markharness::traceability::TraceabilityIndexという公開Rust APIパス(src/lib.rsはpub mod traceability;を含め全モジュールをpubにしている)をmarkharness::traceability_index::TraceabilityIndexへ破壊的に変更する。本クレートのpub mod群はtests/配下の統合テストからクレート内部へアクセスするためのものであり、外部のライブラリ利用者への安定APIとして提供・保証しているものではない(Cargo.tomlのdescriptionは”Git-native test knowledge management CLI”であり、ライブラリとしての利用は想定外)。したがって、再エクスポート(pub use)による旧パスの互換維持は行わない。CLAUDE.mdの「後方互換のための設計を持ち込まない」方針をRust公開APIにも適用する。
impact・coverageの出力契約は変更しないChangeImpact・ReleaseCoverageは、record_kind/schema_versionを含め、既に外部契約として妥当な形になっている。ドラフトが提案していたChangeImpactReadModel・ReleaseCoverageReadModelは、既存のChangeImpact・ReleaseCoverageを指すものとして読み替える。既存フィールドの破壊的変更は、本ADRの範囲では行わない。
CommandOutcome/Presenter系統(outcomeフィールド)はリードモデルの対象外とするcanonical_imported・generated・changes_computedは書込み系コマンドの実行結果であり、markharness-viewが読み取り対象とするtraceability/impact/coverageとは無関係である。これらのoutcomeフィールドをrecord_kindへ統一する変更は、具体的な必要性がないため本ADRのスコープに含めない(YAGNI)。将来、書込み系コマンドの出力を外部契約として整理する具体的な必要が生じた場合は、別のADRで扱う。
traceabilityを既存の読み取り系パターンに合わせて追加する」という決定のみとするTraceabilityReadModelの詳細なフィールド構成(Node種別ごとの配列、Relationの表現等)は、本ADRでは決定事項として扱わず、docs/ja/design/cli-read-model-design.md(設計doc)の責務として残す。
src/traceability.rsのリネームと新規実装、cli.rsへのtraceabilityコマンド追加は、本ADRの範囲に含めない。別タスク(実装フェーズ)として、TDD(Red-Green-Refactor)で行う。
src/traceability.rs(TraceabilityIndex/build_index/serialize_index)をsrc/traceability_index.rsへリネーム。型名・関数名・出力ファイル名.markharness/generated/traceability-index.jsonは変更しないsrc/application.rs・src/verify.rs: 上記リネームに伴うuse crate::traceability::...の参照パス更新src/lib.rs: pub mod traceability;をpub mod traceability_index;へ変更し、新設のtraceabilityコマンド用モジュールをpub mod traceability;として追加する。公開Rustモジュールパスの破壊的変更であり、再エクスポートによる互換維持は行わない(決定2参照)src/traceability.rs(新規): 新設CLIコマンドtraceability用のTraceabilityReadModel構造体、生成ロジックsrc/cli.rs: traceabilityコマンドの追加(impact/coverageと同じ、直接serde_jsonでシリアライズする配線)docs/ja/design/cli-read-model-design.md・docs/en/design/cli-read-model-design.md: 既存のimpact/coverageの実装状況、CommandOutcomeとは無関係であること、src/traceability.rsのリネームの明記。この2ファイルのみ、本ADRの一部として既に更新済み(いずれもまだgit未追跡の新規ファイル)。未着手(実装フェーズで行う): 以下の既存の追跡済みドキュメントは、本ADRの時点ではsrc/traceability.rsへの言及を意図的にそのままにしてある。理由は、決定2のリネームがまだコードに反映されておらず(src/traceability.rsは現時点でもTraceabilityIndexのままである)、今ここでsrc/traceability_index.rsと書き換えると、まだ存在しないファイルを指す誤った記述になるためである。実際のRustリネーム(決定6)が実装された時点で、同じコミット内でこれらも更新する。
docs/ja/design/markharness-v2-design.md・docs/en/design/markharness-v2-design.md(§5.1・実装状況表)docs/ja/design/testcase-generation-design.md・docs/en/design/testcase-generation-design.md(冒頭のStatus行、§3.4)docs/ja/cli-manual.md・docs/en/cli-manual.md(§3 動作確認・テスト、cargo test対象モジュール一覧。新設traceabilityコマンドの説明追加も同時に行う)src/presentation.rs(CommandOutcome・Presenter)、src/impact.rs・src/coverage.rsの出力構造体、.markharness/generated/traceability-index.jsonのファイル形式・内容schema/配下(schema/traceability-read-model.schema.json等。impact/coverageが既に使っているrecord_kind命名に従う)CommandOutcomeにImpactComputed/CoverageComputed/TraceabilityComputedを追加する: 当初のドラフトの前提。実装を確認した結果、impact/coverageはそもそもCommandOutcomeを使っておらず、この前提自体が誤りだった。既に動いている独立した出力系統をわざわざCommandOutcomeへ統合する具体的な理由もない。canonical_imported/generated/changes_computedのoutcomeフィールドもrecord_kindへリネームする: 全コマンドの命名を統一する案として一度検討した。しかしこれらはmarkharness-viewが読む対象ではなく、リネームの具体的な動機がない(YAGNI)。書込み系コマンドの出力契約を将来整理する必要が生じた場合、別ADRで扱う。record_kind/schema_versionを新しい入れ子構造にする: impact/coverageが既に採用しているフラットな構造と異なる形式を新設する理由がない。TraceabilityReadModelを既存のsrc/traceability.rs(TraceabilityIndex)と同じファイルに共存させる: ファイル数は増えないが、「generateが書き込む生成アーティファクト」と「markharness-view向けにオンデマンドで計算する読み取り専用モデル」という異なる責務・異なるライフサイクルが1ファイルに混在し、どちらを指しているか読み手が混乱する。traceability_read_model.rs)にし、既存のTraceabilityIndex側の名前src/traceability.rsを維持する: impact.rs↔impactコマンド、coverage.rs↔coverageコマンドという既存の命名対称性がtraceabilityだけ崩れる。既存のTraceabilityIndexはgenerate内部の一部品であり、traceabilityというコマンド名を代表するものではないため、代表権は新設コマンド側に譲るのが自然。