Files
hakorune/docs/private/roadmap/phases/phase-20-python-integration/planning/milestones.md

12 KiB
Raw Blame History

Python統合マイルストーンM0〜M6

作成: 2025-10-02 ソース: ChatGPT Pro UltraThink Mode ステータス: 計画・Phase 15完了後に実装


📋 概要

Python-Hakorune統合を段階的に進めるためのマイルストーン定義です。 最小から始めて、機能を段階的に追加していきます。


🎯 M0: PyRuntimeBox の最小化

目的

import("math")/call("sqrt") が走る最小実装

成果物

  • PyRuntimeBoxの基本実装
  • PyFunctionBoxの基本実装
  • math.sqrtの実行確認

実装内容

PyRuntimeBox最小版

pub struct PyRuntimeBox {
    py: GILGuard,
    modules: HashMap<String, Py<PyModule>>,
}

impl PyRuntimeBox {
    pub fn init() -> Self {
        pyo3::prepare_freethreaded_python();
        let gil = Python::acquire_gil();
        PyRuntimeBox {
            py: gil,
            modules: HashMap::new(),
        }
    }

    pub fn import(&mut self, name: &str) -> PyModuleBox {
        let py = self.py.python();
        let module = PyModule::import(py, name).unwrap();
        self.modules.insert(name.to_string(), module.into());
        PyModuleBox::new(module)
    }
}

テストケース

using "python"

box Main {
    flow main() {
        let py = PyRuntimeBox();
        let math = py.import("math");
        let sqrt = math.get("sqrt");
        let result = sqrt.exec([2.0]);
        assert(result.to_float() == 1.4142135623730951);
        py.fini();
    }
}

Capability/Contract

  • Capability/Contractはログのみ(観測)
  • HAKO_TRACE_EFFECTS=1 で呼び出しログ記録

DoD完了定義

  • math.sqrt(2.0)が正常実行
  • 結果が正しい値を返す
  • メモリリークなし
  • スモークテスト追加

期間

1週間


🛡️ M1: Capability ゲート

目的

ホワイトリスト運用開始

成果物

  • Capability管理機構
  • hako.toml設定サポート
  • 違反時のエラーハンドリング

実装内容

hako.toml設定

[box.PyRuntimeBox.capabilities]
allow = [
    "py.import:math",
    "py.import:json",
    "py.time:monotonic"
]
deny = [
    "py.subprocess",
    "py.net"
]
enforce = true

Capability検証

impl PyRuntimeBox {
    pub fn import(&mut self, name: &str) -> Result<PyModuleBox> {
        // Capability確認
        if !self.capabilities.allows_import(name) {
            return Err(CapabilityError::ImportDenied(name.to_string()));
        }

        // 通常のimport処理
        // ...
    }
}

テストケース

using "python"

box Main {
    flow main() {
        let py = PyRuntimeBox();

        // OK: 許可されたモジュール
        let math = py.import("math");

        // ERROR: 拒否されたモジュール
        try {
            let subprocess = py.import("subprocess");
        } catch(e) {
            assert(e.type == "CapabilityError");
        }

        py.fini();
    }
}

トグル

# Dev: 違反時fail-fast
HAKO_PLUGIN_CAPS_ENFORCE=1

# Prod: 違反時警告(継続)
HAKO_PLUGIN_CAPS_ENFORCE=0

DoD完了定義

  • allow/denyリスト動作確認
  • 違反時の適切なエラー
  • hako.toml読み込み動作
  • トグル切り替え動作

期間

1-2週間


M2: Contract 検証

目的

pre/post 条件検証の実装

成果物

  • Contract検証機構
  • pre条件検証引数チェック
  • post条件検証返り値チェック

実装内容

Contract定義

[contracts.PyFunctionBox.exec]
pre = [
    "args.len <= 8",
    "bytes_total <= 1_000_000"
]
post = [
    "result.size <= 1_000_000",
    "no_exception",
    "allow_none = true"
]

Contract検証Python側wrapper

# hakorune_contract.py
def verify_contract(func, pre_conditions, post_conditions):
    def wrapper(*args, **kwargs):
        # Pre条件検証
        if len(args) > 8:
            raise ContractViolation("args.len > 8")

        total_bytes = sum(sys.getsizeof(a) for a in args)
        if total_bytes > 1_000_000:
            raise ContractViolation("bytes_total > 1_000_000")

        # 実行
        result = func(*args, **kwargs)

        # Post条件検証
        if sys.getsizeof(result) > 1_000_000:
            raise ContractViolation("result.size > 1_000_000")

        return result

    return wrapper

テストケース

using "python"

box Main {
    flow main() {
        let py = PyRuntimeBox();

        // OK: Contract満たす
        let math = py.import("math");
        let sqrt = math.get("sqrt");
        let r1 = sqrt.exec([2.0]);

        // ERROR: 引数多すぎ
        try {
            let r2 = sqrt.exec([1,2,3,4,5,6,7,8,9]);
        } catch(e) {
            assert(e.type == "ContractViolation");
        }

        py.fini();
    }
}

DoD完了定義

  • pre条件違反検出
  • post条件違反検出
  • ErrorBox化
  • トグル切り替えstrict/warn

期間

2週間


🎲 M3: Deterministic

目的

random/time/os.urandom に shims を適用

成果物

  • Deterministic shims実装
  • random固定化
  • time論理クロック化
  • スモーク再現性確認

実装内容

Deterministic Random

# hakorune_deterministic.py
class DeterministicRandom:
    def __init__(self, seed=42):
        self._rng = random.Random(seed)

    def random(self):
        return self._rng.random()

    def randint(self, a, b):
        return self._rng.randint(a, b)

# モンキーパッチ
if os.getenv('HAKO_DETERMINISTIC') == '1':
    random.random = DeterministicRandom().random

Logical Clock

class LogicalClock:
    def __init__(self):
        self._tick = 0

    def monotonic(self):
        self._tick += 1
        return float(self._tick)

    def time(self):
        return self.monotonic()

# モンキーパッチ
if os.getenv('HAKO_DETERMINISTIC') == '1':
    time.monotonic = LogicalClock().monotonic

テストケース

using "python"

box Main {
    flow main() {
        let py = PyRuntimeBox();

        // Deterministic mode
        let random = py.import("random");

        // 同じseedなら同じ結果
        let r1 = random.get("random").exec([]);
        let r2 = random.get("random").exec([]);
        assert(r1 == r2);  // Deterministic!

        py.fini();
    }
}

トグル

# Deterministic モード有効化
HAKO_DETERMINISTIC=1
HAKO_TRACE_EFFECTS=1  # 効果ログ収集

DoD完了定義

  • random固定化動作
  • time論理クロック動作
  • スモーク再現性100%
  • トレースログ記録

期間

1-2週間


🏗️ M4: Type/Instance 反射

目的

クラス→PyTypeBox、インスタンス→PyInstanceBox

成果物

  • PyTypeBox実装
  • PyInstanceBox実装
  • get/setField統一
  • call_method統一

実装内容

PyTypeBox

pub struct PyTypeBox {
    py_type: Py<PyType>,
}

impl PyTypeBox {
    pub fn get_name(&self) -> String {
        // クラス名取得
    }

    pub fn get_bases(&self) -> Vec<PyTypeBox> {
        // 基底クラスリスト
    }

    pub fn new_instance(&self, args: Vec<Value>) -> PyInstanceBox {
        // インスタンス化
    }
}

PyInstanceBox

pub struct PyInstanceBox {
    py_obj: Py<PyAny>,
}

impl PyInstanceBox {
    pub fn get_field(&self, name: &str) -> Value {
        // フィールド取得
    }

    pub fn set_field(&self, name: &str, value: Value) {
        // フィールド設定
    }

    pub fn call_method(&self, name: &str, args: Vec<Value>) -> Value {
        // メソッド呼び出し
    }
}

テストケース

using "python"

box Main {
    flow main() {
        let py = PyRuntimeBox();

        // クラス取得
        let code = "
class Player:
    def __init__(self, name):
        self.name = name
        self.health = 100

    def heal(self, amount):
        self.health += amount
";
        py.exec(code);
        let PlayerClass = py.get("Player");  // PyTypeBox

        // インスタンス化
        let player = PlayerClass.new_instance(["Alice"]);  // PyInstanceBox

        // フィールドアクセス
        let name = player.get_field("name");
        assert(name == "Alice");

        // メソッド呼び出し
        player.call_method("heal", [20]);
        let health = player.get_field("health");
        assert(health == 120);

        py.fini();
    }
}

DoD完了定義

  • PyTypeBox動作確認
  • PyInstanceBox動作確認
  • get/setField統一動作
  • call_method統一動作

期間

2-3週間


🔄 M5: ABI 昇格

目的

C ABI→Hakorune ABIvtableへPoC

成果物

  • Hakorune ABI実装
  • vtable生成
  • C ABI互換レイヤー
  • 段階切り替え確認

実装内容

Hakorune ABIvtable

#[repr(C)]
pub struct HakoruneABI {
    vtable: *const VTable,
    data: *mut c_void,
}

#[repr(C)]
pub struct VTable {
    init: extern "C" fn(*mut c_void),
    fini: extern "C" fn(*mut c_void),
    invoke: extern "C" fn(*mut c_void, method_id: u32, args: *const TLV) -> TLV,
}

トグル切り替え

# C ABI使用
HAKO_ABI_VTABLE=0

# Hakorune ABI使用
HAKO_ABI_VTABLE=1
HAKO_ABI_STRICT=1  # フォールバック禁止

テストケース

using "python"

box Main {
    flow main() {
        // どちらのABIでも同じコードが動く
        let py = PyRuntimeBox();
        let math = py.import("math");
        let sqrt = math.get("sqrt");
        let result = sqrt.exec([2.0]);
        assert(result.to_float() == 1.4142135623730951);
        py.fini();
    }
}

DoD完了定義

  • Hakorune ABI動作確認
  • C ABI互換性維持
  • トグル切り替え動作
  • パフォーマンス劣化なし

期間

3-4週間


📦 M6: AOT/EXE の包み込み10.5b連動)

目的

Python依存をスタティック or 埋め込み方針で詰め、hako EXE生成ラインに統合

成果物

  • スタティックリンク対応
  • 埋め込みPython対応
  • EXE生成パイプライン統合
  • クロスプラットフォーム確認

実装内容

スタティックリンク

# Cargo.toml
[dependencies]
pyo3 = { version = "0.20", features = ["auto-initialize", "extension-module"] }

[build-dependencies]
pyo3-build-config = "0.20"

埋め込みPython

// Python標準ライブラリを埋め込み
#[cfg(feature = "embed-python")]
const PYTHON_STDLIB: &[u8] = include_bytes!("python3.11.zip");

EXE生成

# AOTコンパイル
hakorune --backend llvm --embed-python script.hkr -o app

# 生成されたEXE
./app  # Python依存なしで実行可能

プラットフォーム対応

Platform Python 方式
Linux 3.8+ 動的/静的両対応
macOS 3.8+ 動的優先
Windows 3.8+ 埋め込み推奨

DoD完了定義

  • Linux EXE生成
  • macOS EXE生成
  • Windows EXE生成
  • Python依存最小化
  • サイズ最適化

期間

4-6週間


📊 全体スケジュール

マイルストーン 期間 開始条件
M0: PyRuntimeBox最小化 1週間 Phase 15完了
M1: Capabilityゲート 1-2週間 M0完了
M2: Contract検証 2週間 M1完了
M3: Deterministic 1-2週間 M2完了
M4: Type/Instance反射 2-3週間 M3完了
M5: ABI昇格 3-4週間 M4完了
M6: AOT/EXE統合 4-6週間 M5完了

合計: 約3-5ヶ月


🔗 関連ドキュメント


最終更新: 2025-10-02 作成者: ChatGPT Pro (UltraThink Mode) ステータス: 計画・Phase 15完了後に実装