source_key)を追加するAccepted(2026-09-15決定)。0023が定めたexternal Requirement(source_locator/source_revision)を拡張し、StrictDoc側のUID文字列を保持する第三の固定フィールドsource_keyを追加する。
StrictDoc側のUID(.sdoc内の要件識別子)は自由記述であり、大文字小文字を含む任意の文字列を取り得る。実際にStrictDoc側のUIDをmarkharness側へ保持しようとしたところ、次の事故が発生した。
markharnessのid(表示ID)はis_valid_slug(src/knowledge.rs)によって小文字ASCII英数字とハイフンのみに制限されている。これはRequirement固有の制約ではなく、idがファイルシステム上のパス構成要素(knowledge/requirements/<id>/requirement.yml等)として使い回されるための、markharness全体で共通の安全側の制約である。StrictDoc側の大文字を含むUID(例: REQ-Login-01)をそのままidへ書き込もうとした結果、この制約に弾かれ、やむなく小文字化して保存することになった。この時点でStrictDoc側の原表記とmarkharness側の保存値が乖離し、原表記のままの一致検索・目視照合ができなくなり、トレーサビリティを大きく損ねた。
markharness-v2-design.md §9.2.1は、将来のStrictDoc Adapter(M3)のための前方互換契約として「external Requirementは、外部key、同一Git内のlocator、固定revisionを区別する」とあらかじめ定めていたが、この「外部key」自体は未実装だった。本ADRはこの契約を先取りして実装し、StrictDoc UIDをmarkharnessのファイル名安全制約に従わせず、原表記のまま保持できるようにする。
Requirementにsource_keyを追加するsource_key: Option<String>をRequirement(src/knowledge.rs)に追加する。source_locator/source_revisionと同じ扱いとし、source: externalでは必須、source: nativeでは禁止する。両方を持つ、あるいはどちらも欠くrequirement.ymlはvalidateで拒否する(0023§4と同じ排他ルール)。
現設計上source: externalは常にStrictDoc(.sdoc)を指すモードであり、StrictDocを使わない場合はsource: nativeを使う。したがってsource_keyをexternalの必須項目にしても、StrictDoc以外の外部仕様書を想定した拡張性を損なわない。
source_keyにはStrictDoc側の識別子をそのまま保存する。大文字・小文字を含め、markharness側での自動変換・強制正規化は行わない。文字集合の制限も設けない(idのis_valid_slug制約は適用しない)。原表記を保持することが、StrictDoc側との目視照合・grep等の手動一致確認を可能にする前提だからである。
保存する値として推奨するのはStrictDocのMID(Model ID)であり、事故の原因になった自由記述のUID:フィールドではない。 MIDはStrictDocが各ノードに自動生成する、常に小文字16進文字列の機械生成識別子であり(ENABLE_MID: True、または個々の要件への明示的なMID:行で.sdocに書き出される)、人手による表記ゆれが構造的に発生しない。source_keyフィールド自体はどのStrictDoc識別子を保存するかを型として強制しない(汎用の生値保持フィールドのまま)が、運用上はMIDの利用を推奨する。
同じsource_key(大文字正規化して比較した場合に一致する)を持つ複数のRequirementが存在しても、validateはこれを検出・拒否しない。markharness側にsource_keyによる検索・lookupコマンドも追加しない。将来この種の比較が必要になった場合は、大文字正規化して比較する方針だけを本ADRで定め、実装は需要が具体的に確認された時点で別ADRとして追加する。
source_keyはRequirementの同一性に一切関与しない本ADRは0013が定めるRequirementのuid運用に一切影響しない。source_keyは表示・照合用の付随情報であり、同一性の判定・rename耐性のロジック(0021)には一切使わない。新規フィールドは既存のRequirement entityへの追加であり、新しいEntityKindは導入しない。
schema_versionは変更しないmarkharness-v2-design.md §9.2.2の既存方針(0018と同じ考え方)により、フィールド追加のみを理由にschema_versionを進めない。プロトタイプ期であり、実際に比較・互換性ゲートを実装する必要が生じるまで値は1のまま固定する。
src/knowledge.rsのRequirement構造体・YAMLシリアライズ、src/validate.rsのcheck_requirement_source_mode、src/knowledge_reconcile/(Intentスキーマ・plan構築・blank文字列チェック)、schema/requirement.schema.jsonにsource_keyを追加する。requirement.yml(現状このリポジトリにはsource: externalの実体は存在しない)には影響しない。id(表示ID)をStrictDoc UIDとして流用する: 実際にこの事故の直接の原因になった案。idはRequirement固有の値ではなく、markharness全体でファイル名など他の用途にも安全に使い回される前提の値であり、この制約(is_valid_slug)を緩めることはidを使う他のentity・他の用途すべての安全性を損なう。したがってidとは別の、StrictDoc UID専用のフィールドを設けた。UID:フィールドを推奨値のままにする: 当初の事故対応としては「原表記のまま保持できればよい」で十分だったが、UID:フィールドは依然として人手で書かれる自由記述であり、将来同じ表記ゆれが再発する可能性を残す。MIDは機械生成のため表記ゆれが構造的に発生せず、より安全側に倒せる選択肢が判明したため、推奨値をMIDへ変更した。次のいずれかが成立した時点で、比較(重複検出・検索)を実装しない本決定の範囲を再検討する。