Accepted(2026-09-13決定、2026-09-13実装完了)。knowledge reconcile本体の機能、crash-recoverableな原子的保存、0028の実行、および関連文書の更新をすべて満たした。
AIやスクリプトからKnowledgeを作成する現在の経路は、KnowledgeDraftをknowledge validate・knowledge applyへ渡した後、identity migrateを実行するという手続き的な操作を呼び出し側へ要求する。新規Requirementとそれを参照するFeatureを同時に作る場合は、Requirement UIDがまだ存在しないため、さらに事前の対話操作または一時的なdisplay ID参照が必要になる。
この経路では、呼び出し側がKnowledgeの保存順序、UID発行時期、display IDとUIDの使い分け、およびapplyとmigrateの順序を理解しなければならない。apply成功後にmigrateを忘れたり、その間に処理が中断したりすると、UIDなしのKnowledgeやdisplay IDを含むrequirement_uidsが正規保存領域へ露出し得る。これは0013の「UIDモードでは新規UIDなしKnowledgeを通常コマンドで導入しない」という不変条件と整合しない。
AI authoringで必要なのは保存手順の指定ではなく、「どのKnowledgeが存在してほしいか」という意図の宣言である。markharnessが、その宣言を現在のリポジトリ状態と照合し、UID発行・参照解決・検証・原子的保存を完結させる必要がある。
knowledge reconcileをAI authoringの標準経路とする次の非対話コマンドを導入する。
markharness knowledge reconcile <intent-file> [--check] [--json] [--dir <path>]
入力をKnowledge Intentと呼ぶ。Knowledge Intentはauthoring専用の宣言であり、.markharness/knowledge/の保存形式ではない。新規要素のUID、保存パス、identity event、および移行手順を呼び出し側へ要求しない。
knowledge reconcileは、一つのKnowledge Intentについて次を一操作として行う。
検証完了前には正規保存領域を変更しない。論理commit前の失敗は旧状態へ収束し、論理commit後の失敗はcommit済みの新状態へ冪等にroll-forwardする。UIDなし、未解決参照、Knowledgeとidentity eventの片側だけが更新された状態を通常コマンドへ公開しない。
同一Intent内の新規要素は、保存されない文書ローカルなkeyで参照する。例えば、FeatureからRequirementへの関係はcontributes_toへRequirementのkeyを記述する。既存RequirementはUIDで参照する。display IDだけによる既存Requirementの選択は行わない。
format: markharness/knowledge-intent/v1
mode: merge
requirements:
- key: req_todo
id: todo
source: native
label: TODO管理
axis: [functional]
features:
- key: feature_todo
id: todo-management
contributes_to: [req_todo]
label: TODO管理
axis: [functional]
behaviors:
- key: behavior_add
id: add-todo
description: TODOを追加する
scenarios:
- id: empty-title
description: 空のタイトルは追加できない
phases:
- steps:
- action: タイトルを空にして追加する
results:
- TODOは追加されない
keyとcontributes_toはauthoring上の表現であり、正規Knowledgeへ保存しない。正規Featureでは、従来どおりrequirement_uidsだけをcontributes-to関連の正本とする。新しい永続的な関連型や汎用グラフは導入しない。
新規要素にはUIDを書かない。markharnessだけがUIDを発行する。
既存要素の内容変更またはdisplay ID変更には、その要素のUIDをKnowledge Intentへ明示する。内容の類似性や同じdisplay IDだけを根拠として既存UIDを推測・継承しない。この規則は0017の改訂と新規作成の区別、および0021の再登場時のidentity規則を維持する。
照合規則は次のとおりとする。
| Intentの指定 | 現在状態 | 結果 |
|---|---|---|
| UIDなし、同じkind・scope・IDが存在しない | 新規 | UIDを発行して作成 |
| UIDなし、同じkind・scope・IDが存在し、正規化後の内容が完全一致する | 既存 | 変更なし |
| UIDなし、同じkind・scope・IDが存在するが内容が異なる | 既存 | ambiguous_identityで停止し、UIDの明示を要求 |
| UIDあり、UIDとkindが一致し、現在のscopeとIntent上のscopeも一致する | 既存 | 内容を比較し、更新または変更なし |
| UIDあり、display IDだけが異なる | 既存 | 明示的なrenameとして処理 |
| Scenario UIDあり、Intent上で別のFeatureまたはBehaviorへ配置される | 既存 | 明示的なreparentとしてUIDを維持して移動 |
| UIDが存在しない、kindが異なる、またはScenario以外でscopeが矛盾する | 不整合 | fail-closedで停止 |
Scenarioの内容変更およびUID付きの明示的なreparentではScenario UIDを維持し、effective contentに応じてCase revisionを再計算する。reparentは、既存Scenario UIDを現在とは異なるFeatureまたはBehavior配下へIntent上で配置した場合に限り成立する。UIDを省略した同名Scenarioから移動を推測しない。Scenarioの分割・統合・コピーで新しく生じるScenarioには新しいUIDを発行し、内容一致から分割・統合を推測しない。
mergeだけを提供する初期版のmodeはmergeのみとする。Intentに記載した要素だけを作成または更新し、記載されていない既存要素は変更しない。省略を削除またはRetireの意思と解釈しない。
望ましい状態との差分から未記載要素をRetireするexactモードは、対象scope、確認・権限、派生するScenario/TestCaseへの影響を別途決定するまで実装しない。--deleteや--allow-retireも本ADRの初期実装範囲外とする。
Axisは登録済みのものだけを参照できる。Knowledge IntentからのAxis作成や削除は、KnowledgeとAxisの所有範囲を混在させるため初期版では行わない。未知のAxisはunknown_axisで停止する。
UIDを指定した既存要素は、Intentに記載したフィールドだけを変更する。省略したscalar、value collectionおよび子Knowledge要素は現在値を維持する。明示したscalarは置換する。必須値をnullまたは空値で消去する入力は、そのフィールドのドメイン規則に従って拒否する。
Collectionは次の二種類に分ける。
axis・contributes_to・procedures・phases・steps・results。明示した場合はcollection全体を置換する。空collectionは空にする明示的な更新であり、省略とは異なる。置換後の値は各フィールドの必須・非空・参照規則を満たさなければならない。Featureのcontributes_toを省略した場合は現在のrequirement_uidsを維持し、指定した場合は文書ローカルkeyまたはRequirement UIDを解決した集合で全置換する。これにより、関連の追加と削除を別コマンドなしで表現する。
既存要素の子Knowledge要素をIntentへ記載したことは、その子だけを作成またはpatchする意味であり、同じ親の未記載の子を削除しない。proceduresとphasesは独立したUIDを持つKnowledge要素ではなく、所有元のBehaviorまたはScenarioの値であるため、この規則ではなくValue collectionの全置換規則に従う。
External Requirementの固定参照を現在の.sdoc blobへ進める場合は、UID付きRequirementへsource_revision: currentを明示する。Reconciliation Moduleはsource_locatorが指す現在のblob OIDを解決して正規Knowledgeへ保存し、native Requirement、存在しないlocator、または解決不能なGit状態ではfail-closedで停止する。currentはIntentだけの命令値であり、正規Knowledgeへ保存しない。
--checkと通常実行は同じmutation planを使う--checkは解析・照合・検証・mutation plan生成までを通常実行と同じ実装で行い、書込みだけを行わない。差分がなければ成功し、変更が必要なら機械判定可能な専用終了コードと計画を返す。
通常実行はコミット直前に現在状態を再確認し、--check後または計画中に入力状態が変化していればstale planとして停止する。--checkの結果を、そのまま後続書込みの許可証として扱わない。
同じリポジトリ状態と同じIntentからは、UIDの具体値を除いて同じmutation planを生成する。新規UIDは計画上の一時トークンで表し、コミットする実行内で割り当てる。同じUIDなしIntentを成功後に再実行した場合、kind・scope・display IDおよび正規化後の内容が完全一致する要素はunchangedとなる。内容差分を伴う更新やrenameには、最初の成功結果または最新の機械可読snapshotから得たUIDをIntentへ明示する。
--jsonの成功結果は、少なくともcreated・updated・unchanged、各要素のkind・UID・display ID、および変更パスを返す。失敗結果は安定したcode、Intent内の位置、message、可能ならremediationを返す。Rustの型名や内部エラー文字列を外部契約にしない。
初期版で必要な診断には、少なくとも次を含める。
invalid_formatduplicate_keyduplicate_uidunknown_local_referenceunknown_axisambiguous_identityunknown_uidconflicting_scopeconflicting_existing_valueinvalid_procedure_referenceinvalid_source_revisionstale_planinvariant_violationidentity migrateをauthoring手順にしないknowledge reconcile成功時点で、作成したすべての正規KnowledgeはUIDを持ち、すべてのUID参照が解決済みでなければならない。後続のidentity migrateを成功条件に含めない。
identity migrateは既存・手動導入データの移行または明示的な修復操作として残す。AI向け文書ではknowledge reconcileを標準経路とし、複数コマンドの手続き的フローを案内しない。
knowledge reconcileと責務が重複する既存のauthoringコマンドは、0028に従い、本ADRのReconciliation Moduleと移行先Interfaceが完成した後に廃止する。旧経路との後方互換は提供しない。
requirement_uidsにはRequirement UIDだけを保存し、display IDやIntentのkeyを保存しない。source: externalのRequirement本文をmarkharnessの正本として取り込まない。docs/knowledge-from-code.ai.mdは実装完了時にknowledge reconcileを標準手順として更新する。0028の削除へ進む前に、次の機能完成ゲートをすべて満たす。本節はADR 0027全体の受け入れ条件ではなく、ADR 0028を開始するための中間ゲートである。
contributes_toの全置換でRequirement関連の追加・削除を表現できる。source_revision: currentが、既存requirement repinと同じblob OID検証を行う。--check、機械可読結果、Intent雛形、およびcrash-recoverableな原子的保存が動作する。本ADRは、次をすべて満たしたときに実装完了とする。
knowledge reconcileが、新規Knowledge一式の作成、既存要素の変更なし判定、UIDを指定した更新・rename、複数要素の一括処理、--check、機械可読結果、Intent雛形、およびcrash-recoverableな原子的保存を提供する。knowledge reconcileだけをauthoringの標準経路として示す状態へ更新する。knowledge apply後にidentity migrateを1回実行する:現行実装との差分は小さいが、display IDをrequirement_uidsへ一時保存し、UIDなしの正規Knowledgeとコマンド順序を呼び出し側へ露出する。knowledge apply内部だけを拡張する:一操作で完結できるが、現在の1チェーン・create-or-reuse中心のDraft契約と、複数要素の望ましい状態を宣言する契約が同じInterfaceに混在する。既存コマンドの意味を暗黙に変えるより、authoring intentのseamを明示し、移行完了後は重複する旧Interfaceを削除する。exact同期と暗黙Retireを提供する:宣言的同期としては完全だが、scopeの誤指定やAIの省略が破壊的変更になる。具体的な削除要求がない初期版には不要である。