DSL Pipeline and ROM Specification
この文書は、AIKernel.Core に実装された標準 DSL pipeline 形式、 DSL ROM 実行モデル、HistoryROM 保存モデルを定義する。
DSL は C# ソースコードではない。JSON で表現された構造化 Semantic IR である。 AI が生成した計画は、検証され、決定論的な ResultStep pipeline に compile され、 不変 ROM 素材として保存され、再利用可能な capability として呼び出せる。
1. 設計規則
- DSL は構造化データであり、実行コードではない。
- root node は必ず
Pipelineである。 - すべての loop は有限である。
LoopUntilもmaxIterationsを必須とする。 - 未知の node type、未知の capability、不正な ROM 名、不正な field は fail-closed する。
Mapprojection は replay node を増やさない。実行された DSL node と loop transition はResultStepreplay entry として観測される。- Suspend は決定論的な停止点であり、background wait ではない。
2. JSON Node Schema
package-public DTO vocabulary は DslNodeTypes の canonical node type name を使用する。 論文や例との互換性のため、parser は CapabilityCall を CallCapability の alias、 SuspendForApproval を Suspend の alias として受け付けてよい。ただし正規化済み DSL document は canonical name を出力する。
2.1 Pipeline
{\n "type": "Pipeline",\n "steps": []\n}
steps は必須で、pipeline node の配列でなければならない。
2.2 Step
{\n "type": "Step",\n "name": "start"\n}
Step は決定論的な実行 node を記録する。外部 capability は呼び出さず、現在の DSL pipeline value をそのまま引き継ぐ。
2.3 CallCapability
{\n "type": "CallCapability",\n "name": "Observe",\n "args": {\n "mode": "summary"\n }\n}
name は IDslCapabilityRegistry で解決できなければならない。args は任意。 指定する場合は JSON object とする。文字列値は文字列として保持され、非文字列値は JSON text として渡される。
2.4 Loop
{\n "type": "Loop",\n "maxIterations": 3,\n "body": [\n { "type": "CallCapability", "name": "Observe" },\n { "type": "CallCapability", "name": "Decide" }\n ]\n}
maxIterations は 0 以上の整数でなければならない。各反復は body を実行し、 その後 loop_iteration と loop_decision を持つ loop transition delta を記録する。
2.5 LoopUntil
{\n "type": "LoopUntil",\n "timeout": "00:00:10",\n "maxIterations": 10,\n "body": [\n { "type": "CallCapability", "name": "Observe" }\n ]\n}
timeout は必須で、秒数または TimeSpan 文字列で指定できる。 maxIterations も必須である。これは clock が timeout に到達しない場合でも loop を有限に保つためである。各 transition は loop_iteration、 loop_decision、可能な場合は loop_timestamp を記録する。
2.6 Suspend
{\n "type": "Suspend",\n "reason": "user_approval"\n}
Suspend は semantic delta kind suspend を持つ suspended ResultStep を返す。 Resume は別の実行フェーズであり、前回の replay log を因果記録として扱う。
3. 完全な例
{\n "type": "Pipeline",\n "steps": [\n { "type": "Step", "name": "start" },\n {\n "type": "Loop",\n "maxIterations": 2,\n "body": [\n { "type": "CallCapability", "name": "Observe" },\n { "type": "CallCapability", "name": "Decide" }\n ]\n },\n { "type": "Suspend", "reason": "user_approval" },\n { "type": "CallCapability", "name": "ExecutePlan" }\n ]\n}
compile flow:
JSON DSL\n -> DslDocument.FromJson\n -> IDslPipelineCompiler.Compile\n -> IKernelPipeline.Execute\n -> ResultStep + ReplayLog + ReplayLogHash
4. DSL ROM
AI が生成した DSL は不変 ROM 素材として保存し、capability として再利用できる。
4.1 VFS Path と Capability Name
実装上の VFS path は次の形式である。
rom/dsl/{namespace}/{name}.json
呼び出し可能な capability name は次の形式である。
dsl://{namespace}/{name}
namespace と name は、どちらも normalize 済みの単一 path segment でなければならない。 dsl://agent/nested/plan1 のような nested capability name は拒否される。
4.2 Save / Load Flow
SaveDslAsRomAsync(namespace, name, jsonDsl)\n -> DSL を parse / compile\n -> SHA-256 ROM hash を計算\n -> VFS に未存在なら JSON を保存\n -> 既存 path の内容が異なる場合は拒否\n -> DslRomSnapshot を IDslRomRegistry に登録
load には expected ROM hash が必要である。VFS の内容が expected hash と異なる場合、 load は fail-closed する。
4.3 DSL ROM の呼び出し
{\n "type": "CallCapability",\n "name": "dsl://agent/plan1"\n}
DslRomCapabilityRegistry は ROM snapshot を解決し、metadata を検証し、 compile 済み inner pipeline を実行し、その DslPipelineValue を返す。 ROM 呼び出しは replay metadata にも記録される。
5. Replay and Metadata
DSL 実行は、node execution、loop transition、capability call、suspend point、 DSL ROM call の semantic delta を記録する。
安定 ROM metadata key は次の通り。
| Key | 意味 |
|---|---|
dsl_rom_hash |
JSON DSL 内容の SHA-256 hash。 |
dsl_rom_call |
dsl://agent/plan1 などの capability name。 |
dsl_rom_path |
rom/dsl/agent/plan1.json などの VFS path。 |
dsl_rom_namespace |
ROM namespace。 |
dsl_rom_name |
ROM name。 |
dsl_rom_replay_log_count |
inner ROM pipeline が生成した replay entry 数。 |
dsl_rom_replay_log_hash |
inner ROM pipeline が生成した replay hash。 |
これらにより、どの DSL ROM が実行され、どの inner pipeline replay が outer execution に畳み込まれたかを証明できる。
6. HistoryROM
チャット履歴は、不変な署名付き ROM 素材として保存できる。 DSL ROM と異なり、HistoryROM は実行可能 capability ではない。 これは履歴素材であり、Core の他の ROM asset と同じ VFS / ROM 署名検証経路で読み込まれる。
6.1 VFS Path と ROM Id
実装上の VFS path は次の形式である。
rom/history/{namespace}/{name}.md
登録される ROM id は次の形式である。
history://{namespace}/{name}
namespace と name は、どちらも normalize 済みの単一 path segment でなければならない。 history://agent/nested/demo のような nested ROM id は拒否される。
6.2 Save / Load Flow
SaveHistoryAsRomAsync(namespace, name, records)\n -> 順序付き chat record を正規化\n -> 署名付き Markdown ROM を生成\n -> VFS に未存在なら Markdown を保存\n -> 既存 path の内容が異なる場合は拒否\n -> RomLoader で読み込み、署名を検証\n -> HistoryRomSnapshot を IHistoryRomRegistry に登録
host がすでに署名付き Markdown HistoryROM を持っている場合は SaveMarkdownAsRomAsync を利用できる。LoadHistoryRomAsync は expected ROM hash を任意で受け取り、 VFS 内容が一致しない場合は fail-closed する。
6.3 安定 Metadata Key
| Key | 意味 |
|---|---|
history_rom_hash |
検証済み SHA-256 ROM hash。 |
history_rom_id |
history://agent/demo などの ROM id。 |
history_rom_path |
rom/history/agent/demo.md などの VFS path。 |
history_rom_namespace |
History ROM namespace。 |
history_rom_name |
History ROM name。 |
7. Failure Rules
次の条件は fail-closed する。
- 空または非 object の DSL JSON。
Pipeline以外の root node。- 未知の node type。
- 必須 field の欠落または型不一致。
- 負の
maxIterationsまたは負のtimeout。 - compile 時の未知 capability name。
- capability registry の例外。
- capability が successful null value を返す場合。
- DSL pipeline value の key / value が不正な場合。
- DSL ROM hash mismatch。
- 同じ ROM capability へ異なる内容を再登録する場合。
- 不正な DSL ROM capability name。
- HistoryROM signature mismatch。
- HistoryROM expected hash mismatch。
- 同じ HistoryROM id へ異なる内容を再登録する場合。
- 不正な HistoryROM id。
8. Host Integration Notes
Server/API host は AI system が JSON DSL を提案することを許可してよいが、 再利用可能 capability として扱う前に、host 側で検証し DSL ROM として保存しなければならない。 browser/WASM client は trusted ROM を直接書き込まず、server boundary を呼び出すべきである。
チャット履歴 exporter / scraper は、ROM 生成経路の内部で現在時刻を取得せず、 決定論的な timestamp を IHistoryRomStore / HistoryRomStore に渡すべきである。 これにより HistoryROM は再現可能になり、検証済み hash も replay 間で安定する。
外部 module 連携では、assembly 参照 Provider、process-backed adapter、dsl:// ROM capability へ name を route する IDslCapabilityRegistry を登録する。registry が境界であり、 Core は provider 実装を知らない。
v0.0.4 以降、このモデルの公開 contract surface は AIKernel.Abstractions.Dsl、AIKernel.Abstractions.History、 AIKernel.Abstractions.Time、AIKernel.Dtos.Dsl、AIKernel.Dtos.History、 AIKernel.Dtos.Time に配置される。Core は内部で Result ベース実装を維持してよいが、 公開 adapter はこれらの contract package を対象にする。
変更履歴
- v0.0.4 (2026-06-04): 標準 DSL pipeline、DSL ROM、HistoryROM 仕様と公開 contract package mapping を追加。
architecture/18.DSL_PIPELINE_AND_ROM_SPEC-jp.md