|
| 1 | +--- |
| 2 | +updated: 2026-06-04 |
| 3 | +published: 2026-06-04 |
| 4 | +version: "0.0.3" |
| 5 | +edition: "Draft" |
| 6 | +status: "Implementation" |
| 7 | +issuer: ai-kernel@aikernel.net |
| 8 | +maintainer: "拓也(AIKernel プロジェクト メンテナー)" |
| 9 | +--- |
| 10 | + |
| 11 | +# DSL Pipeline and ROM Specification |
| 12 | + |
| 13 | +この文書は、AIKernel.Core に実装された標準 DSL pipeline 形式と |
| 14 | +DSL ROM 実行モデルを定義する。 |
| 15 | + |
| 16 | +DSL は C# ソースコードではない。JSON で表現された構造化 Semantic IR である。 |
| 17 | +AI が生成した計画は、検証され、決定論的な `ResultStep` pipeline に compile され、 |
| 18 | +不変 ROM 素材として保存され、再利用可能な capability として呼び出せる。 |
| 19 | + |
| 20 | +--- |
| 21 | + |
| 22 | +## 1. 設計規則 |
| 23 | + |
| 24 | +- DSL は構造化データであり、実行コードではない。 |
| 25 | +- root node は必ず `Pipeline` である。 |
| 26 | +- すべての loop は有限である。`LoopUntil` も `maxIterations` を必須とする。 |
| 27 | +- 未知の node type、未知の capability、不正な ROM 名、不正な field は fail-closed する。 |
| 28 | +- `Map` projection は replay node を増やさない。実行された DSL node と loop transition は `ResultStep` replay entry として観測される。 |
| 29 | +- Suspend は決定論的な停止点であり、background wait ではない。 |
| 30 | + |
| 31 | +--- |
| 32 | + |
| 33 | +## 2. JSON Node Schema |
| 34 | + |
| 35 | +### 2.1 Pipeline |
| 36 | + |
| 37 | +```json |
| 38 | +{ |
| 39 | + "type": "Pipeline", |
| 40 | + "steps": [] |
| 41 | +} |
| 42 | +``` |
| 43 | + |
| 44 | +`steps` は必須で、pipeline node の配列でなければならない。 |
| 45 | + |
| 46 | +### 2.2 Step |
| 47 | + |
| 48 | +```json |
| 49 | +{ |
| 50 | + "type": "Step", |
| 51 | + "name": "start" |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +`Step` は決定論的な実行 node を記録する。外部 capability は呼び出さず、現在の DSL pipeline value をそのまま引き継ぐ。 |
| 56 | + |
| 57 | +### 2.3 CallCapability |
| 58 | + |
| 59 | +```json |
| 60 | +{ |
| 61 | + "type": "CallCapability", |
| 62 | + "name": "Observe", |
| 63 | + "args": { |
| 64 | + "mode": "summary" |
| 65 | + } |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | +`name` は `IDslCapabilityRegistry` で解決できなければならない。`args` は任意。 |
| 70 | +指定する場合は JSON object とする。文字列値は文字列として保持され、非文字列値は JSON text として渡される。 |
| 71 | + |
| 72 | +### 2.4 Loop |
| 73 | + |
| 74 | +```json |
| 75 | +{ |
| 76 | + "type": "Loop", |
| 77 | + "maxIterations": 3, |
| 78 | + "body": [ |
| 79 | + { "type": "CallCapability", "name": "Observe" }, |
| 80 | + { "type": "CallCapability", "name": "Decide" } |
| 81 | + ] |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +`maxIterations` は 0 以上の整数でなければならない。各反復は `body` を実行し、 |
| 86 | +その後 `loop_iteration` と `loop_decision` を持つ loop transition delta を記録する。 |
| 87 | + |
| 88 | +### 2.5 LoopUntil |
| 89 | + |
| 90 | +```json |
| 91 | +{ |
| 92 | + "type": "LoopUntil", |
| 93 | + "timeout": "00:00:10", |
| 94 | + "maxIterations": 10, |
| 95 | + "body": [ |
| 96 | + { "type": "CallCapability", "name": "Observe" } |
| 97 | + ] |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +`timeout` は必須で、秒数または `TimeSpan` 文字列で指定できる。 |
| 102 | +`maxIterations` も必須である。これは clock が timeout に到達しない場合でも |
| 103 | +loop を有限に保つためである。各 transition は `loop_iteration`、 |
| 104 | +`loop_decision`、可能な場合は `loop_timestamp` を記録する。 |
| 105 | + |
| 106 | +### 2.6 Suspend |
| 107 | + |
| 108 | +```json |
| 109 | +{ |
| 110 | + "type": "Suspend", |
| 111 | + "reason": "user_approval" |
| 112 | +} |
| 113 | +``` |
| 114 | + |
| 115 | +`Suspend` は semantic delta kind `suspend` を持つ suspended `ResultStep` を返す。 |
| 116 | +Resume は別の実行フェーズであり、前回の replay log を因果記録として扱う。 |
| 117 | + |
| 118 | +--- |
| 119 | + |
| 120 | +## 3. 完全な例 |
| 121 | + |
| 122 | +```json |
| 123 | +{ |
| 124 | + "type": "Pipeline", |
| 125 | + "steps": [ |
| 126 | + { "type": "Step", "name": "start" }, |
| 127 | + { |
| 128 | + "type": "Loop", |
| 129 | + "maxIterations": 2, |
| 130 | + "body": [ |
| 131 | + { "type": "CallCapability", "name": "Observe" }, |
| 132 | + { "type": "CallCapability", "name": "Decide" } |
| 133 | + ] |
| 134 | + }, |
| 135 | + { "type": "Suspend", "reason": "user_approval" }, |
| 136 | + { "type": "CallCapability", "name": "ExecutePlan" } |
| 137 | + ] |
| 138 | +} |
| 139 | +``` |
| 140 | + |
| 141 | +compile flow: |
| 142 | + |
| 143 | +```text |
| 144 | +JSON DSL |
| 145 | + -> DslDocument.FromJson |
| 146 | + -> IDslPipelineCompiler.Compile |
| 147 | + -> IKernelPipeline.Execute |
| 148 | + -> ResultStep + ReplayLog + ReplayLogHash |
| 149 | +``` |
| 150 | + |
| 151 | +--- |
| 152 | + |
| 153 | +## 4. DSL ROM |
| 154 | + |
| 155 | +AI が生成した DSL は不変 ROM 素材として保存し、capability として再利用できる。 |
| 156 | + |
| 157 | +### 4.1 VFS Path と Capability Name |
| 158 | + |
| 159 | +実装上の VFS path は次の形式である。 |
| 160 | + |
| 161 | +```text |
| 162 | +rom/dsl/{namespace}/{name}.json |
| 163 | +``` |
| 164 | + |
| 165 | +呼び出し可能な capability name は次の形式である。 |
| 166 | + |
| 167 | +```text |
| 168 | +dsl://{namespace}/{name} |
| 169 | +``` |
| 170 | + |
| 171 | +`namespace` と `name` は、どちらも normalize 済みの単一 path segment でなければならない。 |
| 172 | +`dsl://agent/nested/plan1` のような nested capability name は拒否される。 |
| 173 | + |
| 174 | +### 4.2 Save / Load Flow |
| 175 | + |
| 176 | +```text |
| 177 | +SaveDslAsRomAsync(namespace, name, jsonDsl) |
| 178 | + -> DSL を parse / compile |
| 179 | + -> SHA-256 ROM hash を計算 |
| 180 | + -> VFS に未存在なら JSON を保存 |
| 181 | + -> 既存 path の内容が異なる場合は拒否 |
| 182 | + -> DslRomSnapshot を IDslRomRegistry に登録 |
| 183 | +``` |
| 184 | + |
| 185 | +load には expected ROM hash が必要である。VFS の内容が expected hash と異なる場合、 |
| 186 | +load は fail-closed する。 |
| 187 | + |
| 188 | +### 4.3 DSL ROM の呼び出し |
| 189 | + |
| 190 | +```json |
| 191 | +{ |
| 192 | + "type": "CallCapability", |
| 193 | + "name": "dsl://agent/plan1" |
| 194 | +} |
| 195 | +``` |
| 196 | + |
| 197 | +`DslRomCapabilityRegistry` は ROM snapshot を解決し、metadata を検証し、 |
| 198 | +compile 済み inner pipeline を実行し、その `DslPipelineValue` を返す。 |
| 199 | +ROM 呼び出しは replay metadata にも記録される。 |
| 200 | + |
| 201 | +--- |
| 202 | + |
| 203 | +## 5. Replay and Metadata |
| 204 | + |
| 205 | +DSL 実行は、node execution、loop transition、capability call、suspend point、 |
| 206 | +DSL ROM call の semantic delta を記録する。 |
| 207 | + |
| 208 | +安定 ROM metadata key は次の通り。 |
| 209 | + |
| 210 | +| Key | 意味 | |
| 211 | +| --- | --- | |
| 212 | +| `dsl_rom_hash` | JSON DSL 内容の SHA-256 hash。 | |
| 213 | +| `dsl_rom_call` | `dsl://agent/plan1` などの capability name。 | |
| 214 | +| `dsl_rom_path` | `rom/dsl/agent/plan1.json` などの VFS path。 | |
| 215 | +| `dsl_rom_namespace` | ROM namespace。 | |
| 216 | +| `dsl_rom_name` | ROM name。 | |
| 217 | +| `dsl_rom_replay_log_count` | inner ROM pipeline が生成した replay entry 数。 | |
| 218 | +| `dsl_rom_replay_log_hash` | inner ROM pipeline が生成した replay hash。 | |
| 219 | + |
| 220 | +これらにより、どの DSL ROM が実行され、どの inner pipeline replay が outer execution に畳み込まれたかを証明できる。 |
| 221 | + |
| 222 | +--- |
| 223 | + |
| 224 | +## 6. Failure Rules |
| 225 | + |
| 226 | +次の条件は fail-closed する。 |
| 227 | + |
| 228 | +- 空または非 object の DSL JSON。 |
| 229 | +- `Pipeline` 以外の root node。 |
| 230 | +- 未知の node type。 |
| 231 | +- 必須 field の欠落または型不一致。 |
| 232 | +- 負の `maxIterations` または負の `timeout`。 |
| 233 | +- compile 時の未知 capability name。 |
| 234 | +- capability registry の例外。 |
| 235 | +- capability が successful null value を返す場合。 |
| 236 | +- DSL pipeline value の key / value が不正な場合。 |
| 237 | +- DSL ROM hash mismatch。 |
| 238 | +- 同じ ROM capability へ異なる内容を再登録する場合。 |
| 239 | +- 不正な DSL ROM capability name。 |
| 240 | + |
| 241 | +--- |
| 242 | + |
| 243 | +## 7. Host Integration Notes |
| 244 | + |
| 245 | +Server/API host は AI system が JSON DSL を提案することを許可してよいが、 |
| 246 | +再利用可能 capability として扱う前に、host 側で検証し DSL ROM として保存しなければならない。 |
| 247 | +browser/WASM client は trusted ROM を直接書き込まず、server boundary を呼び出すべきである。 |
| 248 | + |
| 249 | +外部 module 連携では、assembly 参照 Provider、process-backed adapter、`dsl://` ROM capability |
| 250 | +へ name を route する `IDslCapabilityRegistry` を登録する。registry が境界であり、 |
| 251 | +Core は provider 実装を知らない。 |
| 252 | + |
| 253 | +--- |
| 254 | + |
| 255 | +# 変更履歴 |
| 256 | + |
| 257 | +- v0.0.3 (2026-06-04): 標準 DSL pipeline と DSL ROM 仕様を追加。 |
0 commit comments