markharness

0036: StrictDocのJSONエクスポートからKnowledge Intentを生成するknowledge intent-from-strictdoc

ステータス

Accepted(2026-09-29決定、実装済み)。

背景

0023はsource: externalのRequirementを定義し、0030は外部側の識別子source_key(StrictDocのMIDを推奨)を追加した。しかし、既存のStrictDocプロジェクトの要求をこれらのRequirementとして登録する手段はCLIに無く、knowledge reconcileのIntentを要求1件ずつ人手で書くしかない(issue #88。実プロジェクトでは358件)。importの入力はnative・junitのみで、knowledgeには書き込まず、常にCanonicalSnapshotを出力する。

strictdoc export --formats=jsonは、プロジェクト全体をout/json/index.jsonの1ファイルに出力する(strictdoc 0.30.1で確認)。DOCUMENTS[]の下にSECTIONと要求がNODESで入れ子になり、要求ノードは_NODE_TYPE: "REQUIREMENT"とMIDを持つ。次の点が設計に効く。

決定

1. knowledge intent-from-strictdocはIntent YAMLをstdoutに出力するだけで、何も書き込まない

markharness knowledge intent-from-strictdoc --input out/json/index.json \
  [--sdoc-root <dir>]... [-d <dir>] | markharness knowledge reconcile -

knowledgeへの書き込みは既存のknowledge reconcileに任せる。これによりatomicな書き込み・--check・id基準の冪等性が再実装なしで得られる。importは「常にCanonicalSnapshotを出力する」性質を保つため、import --source strictdocにはしない。

2. 入力はStrictDocのJSONエクスポートファイルのみ

markharnessはstrictdocを実行せず、要求の本文もパースしない(設計書P5: Coreは外部形式を知らない)。利用者がstrictdoc exportを実行し、出力ファイルを--inputで渡す。

3. 取り込み対象と生成するフィールド

DOCUMENTS[].NODESを再帰的にたどり、_NODE_TYPE == "REQUIREMENT"のノードだけを対象とする(SECTIONは入れ子をたどるだけ。カスタムgrammarの型は対象外)。各要求から次のRequirementを生成する。

フィールド 値
id sd-<MID全体>(MIDは小文字hexで、有効なslug)
source external
source_key MID(0030の推奨どおり)
source_locator §4
source_revision current
axis []

MIDは小文字hexで1桁以上でなければならない(桁数は検証しない)。Intentは文字列整形で組み立てるため、これ以外の値はid(slug)にもYAMLにも到達させない。

4. source_locatorは要求MIDの索引で決める

JSONにソースファイルのパスが無く、Markdown形式にはドキュメントMIDも無いため、要求自身のMIDから所属ファイルを引く。--sdoc-root(複数回指定可。省略時はプロジェクトルート)以下の*.sdoc・*.md・*.markdownを走査し、MIDを宣言する行を索引にする。

要求のMIDに一致する行がちょうど1ファイルにあれば、そのパスをsource_locatorとする。パスはプロジェクトルート基準の相対パスで、区切りは/(knowledge reconcileがgit hash-objectをプロジェクトルートで実行するのと同じ基準)。--sdoc-rootはプロジェクトルート配下でなければならない。

この走査はStrictDocを解釈しない。要求の構文やノード構造は読まず、MIDを宣言する行と、上記のリテラル領域の境界だけを判定する。

5. 不整合は全体を拒否する

次のいずれかがあれば、診断を出力して非0で終了し、Intentは何も出力しない。

6. 利用者が満たすべき前提

不変条件

影響

検討し、採用しなかった選択肢