Files
hakorune/docs/development/roadmap/phases/phase-17/module-interfaces.md

93 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 17 接続モデル(最小): JSON NDJSON over stdio, exe↔exe
目的: まずは「簡単・見える・壊れない」。単一の接続モデルJSONを1行ずつ、標準入出力でやり取りで、エンジンを別プロセスの小さな実行ファイルとして積み上げる。
## 方針
- 1接続モデルのみ: NDJSON1メッセージ=1行のJSON
- 1トランスポートのみ: 標準入出力(子プロセス起動)。パイプ/ソケットは後回し。
- 1エンジン=1 exe: `nyash-engine-core13`, `nyash-engine-loop`など。役割ごとに小さく分割。
- 可視化容易: すべてのトレースをNDJSONで出力し、そのまま保存・比較・変換jq/簡易スクリプト)。
## メッセージ共通フィールド
- `op`: 操作名(例: "load_module", "call", "trace_sub"
- `id`: リクエストID数値/文字列)。応答に同じ`id`を返す。
- `schema`: プロトコル版(整数, 例: 1
- `ts`: 送信者時刻(オプション, ns/μs/ms表現は自由
応答の共通:
- `ok`: true/false
- `id`: リクエストと同一
- `err`: 失敗時のみ `{code, message, data?}`
## 操作一覧(最小)
1) load_module
- 要求: `{op:"load_module", id:1, schema:1, ir:"core13|loop", format:"json|bin", bytes:"<base64>"}`
- 応答: `{ok:true, id:1, module_id:1, features:["interp","trace"], ir:"core13"}`
2) call
- 要求: `{op:"call", id:2, module_id:1, func:"main", args:[1,2,3], timeout_ms:5000?}`
- 応答: `{ok:true, id:2, value:3, events_dropped:0}`
3) trace_subトレース購読
- 要求: `{op:"trace_sub", id:3, mask:["EnterFunc","ExitFunc","LoopIter","Branch","ExternCall"], flush_ms:50?}`
- 応答: `{ok:true, id:3}`
- イベントストリーム: 別行で `{"event":"EnterFunc", "func":"main", ...}` を逐次出力(応答行とは独立)
4) unload任意
- 要求: `{op:"unload", id:4, module_id:1}`
- 応答: `{ok:true, id:4}`
5) pingヘルスチェック
- 要求: `{op:"ping", id:5}`
- 応答: `{ok:true, id:5, now: 1725600000}`
エラー例:
- 応答: `{ok:false, id:2, err:{code:"E_NO_FUNC", message:"function not found", data:{func:"main"}}}`
## トレースイベントNDJSON
- 例: `{"event":"EnterFunc","func":"main","args":[1],"ts":...}`
- 最小セット: `EnterFunc, ExitFunc, Block, PhiMerge, LoopIter, Branch, ExternCall, Safepoint, Barrier`
- フィールドの原則: `event`必須、その他は柔軟に拡張し未知キーは無視可能。
## エンジンexeの約束
- 起動直後にバナー等を出力しない(標準出力は完全にプロトコル専用)。
- 標準エラーは自由(ログ用)。
- 読み込みは行単位でJSONをパース、応答は必ず1行。
- イベントは応答と独立行で流してよいtrace_sub済みのとき
- 大きなIRバイナリは `bytes` を base64。JSON IRはそのまま文字列可。
## クライアント側nyash-cli
- `nyash run --engine=remote --exe ./nyash-engine-core13 --ir=core13 -- program.ny`
- 実装は単純: 子プロセスspawn → stdin/stdoutにNDJSON → `load_module``call`
- `--trace``trace_sub` を投げてNDJSONログをファイル保存そのまま可視化可能
## 可視化(最小)
- NDJSON→Markdown表: `jq -r` で列抽出, `|`区切りでテーブル化。
- NDJSON→CSV: `jq -r '[.event, .func, .block, .ts] | @csv'`
- 差分: 2つのトレースを event+順序でzip比較。簡易Python/nyashツールは後続で追加可。
## バージョニングと互換
- `schema` は整数で宣言、互換性は「追加のみ」原則。意味変更や削除は `schema+1`
- 不明キーは無視。必須キー欠落は `E_SCHEMA`
## タイムアウト/健全性
- `call.timeout_ms` を受付。内部でキャンセル/中断可能な範囲で対応。
- ハートビート: `ping` を定期送信して固まり検出。
## セキュリティ
- ローカル実行のみを想定(最小)。ネットワーク露出はしない。
- 外部からのファイルアクセス/実行はプロトコルに含めないエンジンはIR実行に限定
## 最小試験手順(手動)
1) エンジンを起動(手動で別ターミナル)。`cat`でNDJSONを流せるならなお良い。
2) `load_module` を送信小さなIR
3) `trace_sub` を送信。
4) `call` を送信 → 応答とイベント列を保存。
5) jqでCSV化して目視。
## 将来拡張(後回し)
- 長期接続(ソケット/名前付きパイプ)
- バイナリMessagePack/bincode実装速度重視
- 圧縮gzip
- ストリーム再同期(途中から読み直し)