From 603354f89a61fd50e3325be4a336f0e88b2b3677 Mon Sep 17 00:00:00 2001 From: Takeshi Date: Mon, 12 Oct 2026 07:50:07 +0900 Subject: [PATCH] Preserve unadopted integer window codec candidate and static review checkpoint --- .../integer-window-codec-r285-r02/README.md | 15 + .../performance_budget.candidate.gd | 287 +++ .../build-preexecution-review-r286.json | 260 ++ .../evidence/static-review-r285-r02.json | 130 + .../static-root-verification-r285-r02.json | 87 + .../history-r285/static-review.json | 120 + .../history-r285/tree_numeric_core.cpp | 923 +++++++ .../manifest.json | 119 + .../parent-r274/tree_core.hpp | 75 + .../parent-r274/tree_numeric_core.cpp | 823 +++++++ .../preparation/build-preview-r286.json | 61 + .../preparation/build-r286.py | 181 ++ .../preparation/prepare-r285-r02.py | 124 + .../preparation/prepare-r285.py | 121 + .../reference/marshalls.cpp | 2155 +++++++++++++++++ .../reference/source.json | 11 + .../source/input.json | 75 + .../source/tree_core.hpp | 75 + .../source/tree_numeric_core.cpp | 926 +++++++ 19 files changed, 6568 insertions(+) create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/README.md create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/dependencies/performance_budget.candidate.gd create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/build-preexecution-review-r286.json create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/static-review-r285-r02.json create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/static-root-verification-r285-r02.json create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/history-r285/static-review.json create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/history-r285/tree_numeric_core.cpp create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/manifest.json create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/parent-r274/tree_core.hpp create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/parent-r274/tree_numeric_core.cpp create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/build-preview-r286.json create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/build-r286.py create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/prepare-r285-r02.py create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/prepare-r285.py create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/reference/marshalls.cpp create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/reference/source.json create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/source/input.json create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/source/tree_core.hpp create mode 100644 docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/source/tree_numeric_core.cpp diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/README.md b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/README.md new file mode 100644 index 0000000..a7cc0f2 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/README.md @@ -0,0 +1,15 @@ +# P23-02 整数サンプル符号化候補 r285-r02 開発チェックポイント + +2026-10-12時点の作業をGitで保持するためのスナップショット。制作本体に未採用の候補であり、P23-02の正式完了ではない。台帳の基準はコミット `21d89b988d360269321d79a23f011858777e2fbf`(r282)。30パッケージ/88成果単位、正式9/着手19/予定60、部分点なしを維持する。 + +整数Arrayの従来の符号化を、元エンジン形式と照合する処理と追記・単一先頭削除の変換に置き換える実験候補。形式不一致時の従来処理を残す。`source/`は候補、`parent-r274/`は比較元、`history-r285/`は静的レビューで拒否された初版。初版の一時ベクトル確保失敗への対処不足を、r285-r02で二段階の読み取りと確保結果確認へ修正した。 + +- r285-r02は独立静的レビュー受理済み。ビルド・ロード・エンジンとの実バイト同値・性能は未検証。 +- r286のビルド事前レビューは受理済み。bridge compile1+link1だけが対象で、ビルド自体は未実行。実行前の証拠再照合とroot verificationが必要。 +- 次はr286を必要な事前確認後に実行し、実ビルドの独立レビューを行う。その後、既存のBudget局所比較を再利用してエンジンcodecとの同値・入力と所有関係・通知と記録の維持を検証する。 +- 最新の局所・原S6影響・whole647受理済み候補はr274/library275。r285-r02へその受入や性能値を転用しない。 +- 原17条件C01–C09/X1–X8はすべて未受入。Windows実機を要するC08/X8だけブロック。人のCtrl保持wheel/左保持dragは延期・未達・免除なし。50ms、P95/D10、同一最終版の必須全回帰、通常OS操作と同一Windows配布版実機等が残る。 + +`manifest.json`はコピー元パスとサイズ・SHA256を保存する。コピーした証拠とinput内の絶対パスは、当時のローカル環境に対する原記録として変更していない。`preparation/`は当時の準備スクリプトで、ローカルの既存artifact、SDK133、所有プロセス用helper等に依存する。このディレクトリだけでビルド・受入を再現できるという認定はない。SDK、バイナリ、代表セーブ、巨大ログ、生成stageはこのコミットの対象外。 + +`reference/marshalls.cpp`はGodotのリビジョン `ed1daf0bf` にある `core/io/marshalls.cpp` の原文。配布元URLとハッシュは `reference/source.json` に記録し、ファイル冒頭のMITライセンスと著作権表示を保持する。 diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/dependencies/performance_budget.candidate.gd b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/dependencies/performance_budget.candidate.gd new file mode 100644 index 0000000..45a69dc --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/dependencies/performance_budget.candidate.gd @@ -0,0 +1,287 @@ +class_name SimulationPerformanceBudget +extends RefCounted + +## Lightweight runtime profiler with explicit integer-microsecond samples. +## It is diagnostic state only and deliberately stays outside Save snapshots. + +signal budget_exceeded(metric_id: StringName, report: Dictionary) + +enum Aggregation { + AVERAGE, + P95, + MAXIMUM, +} + +const DEFAULT_SAMPLE_CAPACITY := 512 + +const DEFAULT_BUDGETS := { + &"simulation_x1": {&"aggregation": Aggregation.AVERAGE, &"limit_us": 4_000}, + &"simulation_x3": {&"aggregation": Aggregation.P95, &"limit_us": 12_000}, + &"path_query": {&"aggregation": Aggregation.P95, &"limit_us": 2_000}, + &"main_thread_stall": {&"aggregation": Aggregation.MAXIMUM, &"limit_us": 50_000}, + &"save": {&"aggregation": Aggregation.MAXIMUM, &"limit_us": 5_000_000}, + &"load": {&"aggregation": Aggregation.MAXIMUM, &"limit_us": 8_000_000}, +} + +var sample_capacity := DEFAULT_SAMPLE_CAPACITY +var _p23r257_native_core: RefCounted = null +var _budgets: Dictionary = {} +var _samples: Dictionary = {} +# Derived diagnostic index; never part of game Save snapshots. +var _ordered_samples: Dictionary = {} +var _ordered_sample_bytes: Dictionary = {} +# Complete raw bytes proved integer by this builtin; diagnostic-only derived state. +var _integer_window_bytes: Dictionary = {} +var _totals: Dictionary = {} +var _sample_counts: Dictionary = {} + + +func _init(capacity := DEFAULT_SAMPLE_CAPACITY) -> void: + sample_capacity = maxi(int(capacity), 1) + for raw_metric_id: Variant in DEFAULT_BUDGETS: + _budgets[StringName(raw_metric_id)] = ( + DEFAULT_BUDGETS[raw_metric_id] as Dictionary + ).duplicate(true) + + +func set_budget( + metric_id: StringName, + limit_us: int, + aggregation: Aggregation = Aggregation.P95 +) -> bool: + if metric_id.is_empty() or limit_us <= 0 \ + or aggregation < Aggregation.AVERAGE or aggregation > Aggregation.MAXIMUM: + return false + _budgets[metric_id] = { + &"aggregation": aggregation, + &"limit_us": limit_us, + } + return true + + +func record_sample(metric_id: StringName, duration_us: int) -> Dictionary: + if metric_id.is_empty() or duration_us < 0: + return {&"ok": false, &"error": "Metric ID and non-negative duration are required."} + if get_script().resource_path == "res://scripts/core/performance_budget.gd": + if _p23r257_native_core == null and ClassDB.class_exists(&"TheTreeNumericCore"): + _p23r257_native_core = ClassDB.instantiate(&"TheTreeNumericCore") + if _p23r257_native_core != null and _p23r257_native_core.get_class() == &"TheTreeNumericCore" and _p23r257_native_core.get_script() == null and _p23r257_native_core.has_method(&"performance_record_sample"): + var native_result: Dictionary = _p23r257_native_core.call(&"performance_record_sample", self, metric_id, duration_us) + if bool(native_result.get(&"supported", false)): + var native_report: Dictionary = native_result[&"report"] + if bool(native_report.get(&"budget_exceeded", false)): + budget_exceeded.emit(metric_id, native_report.duplicate(true)) + return {&"ok": true, &"report": native_report} + if not _samples.has(metric_id): + _samples[metric_id] = [] + var values: Array = _samples[metric_id] + var use_index: bool = get_script().resource_path == "res://scripts/core/performance_budget.gd" and _known_integer_window(metric_id, values) + var ordered: Array[int] = [] + if use_index: ordered = _validated_sample_order(metric_id, values) + values.append(duration_us) + if use_index: ordered.insert(ordered.bsearch(duration_us), duration_us) + if values.size() > sample_capacity: + var removed: Variant = values.pop_front() + if use_index: ordered.remove_at(ordered.bsearch(int(removed))) + if use_index: + _ordered_sample_bytes[metric_id] = var_to_bytes(values) + _integer_window_bytes[metric_id] = _ordered_sample_bytes[metric_id] + else: + _ordered_samples.erase(metric_id) + _ordered_sample_bytes.erase(metric_id) + _integer_window_bytes.erase(metric_id) + _totals[metric_id] = int(_totals.get(metric_id, 0)) + duration_us + _sample_counts[metric_id] = int(_sample_counts.get(metric_id, 0)) + 1 + var report: Dictionary = _indexed_report(metric_id, values, ordered) if use_index else get_report(metric_id) + if bool(report.get(&"budget_exceeded", false)): + budget_exceeded.emit(metric_id, report.duplicate(true)) + return {&"ok": true, &"report": report} + + +func record_simulation_tick(duration_us: int, speed: int) -> Dictionary: + var metric_id := &"simulation_x3" if speed == 3 else &"simulation_x1" + return record_sample(metric_id, duration_us) + + +## Records the full main-thread cost of one rendered/process frame, including +## all game-minute ticks consumed at accelerated speed. This keeps x3 from +## accidentally reporting four individually-fast ticks while the frame stalls. +func record_simulation_frame(duration_us: int, speed: int, ticks_run: int) -> Dictionary: + if ticks_run <= 0: + return {&"ok": false, &"error": "At least one completed tick is required."} + var simulation_result := record_simulation_tick(duration_us, speed) + var stall_result := record_sample(&"main_thread_stall", duration_us) + return { + &"ok": bool(simulation_result[&"ok"]) and bool(stall_result[&"ok"]), + &"ticks_run": ticks_run, + &"simulation": simulation_result, + &"main_thread": stall_result, + } + + +func get_report(metric_id: StringName) -> Dictionary: + var raw: Array = _samples.get(metric_id, []) + if get_script().resource_path != "res://scripts/core/performance_budget.gd" or not _known_integer_window(metric_id, raw): + return SimulationPerformanceBudget._legacy_report(self, metric_id) + var ordered: Array[int] = [] + return _indexed_report(metric_id, raw, ordered, true) + + +func _indexed_report(metric_id: StringName, values: Array, ordered: Array[int], validate_order: bool = false) -> Dictionary: + var count := values.size() + var lifetime_count := int(_sample_counts.get(metric_id, 0)) + var lifetime_total := int(_totals.get(metric_id, 0)) + var average_us := lifetime_total / lifetime_count if lifetime_count > 0 else 0 + if validate_order: ordered = _validated_sample_order(metric_id, values) + var maximum_us := maxi(0, ordered[-1]) if not ordered.is_empty() else 0 + var p95_us := 0 + if not ordered.is_empty(): + var rank_numerator := 95 * ordered.size() + var index := maxi((rank_numerator + 99) / 100 - 1, 0) + p95_us = ordered[mini(index, ordered.size() - 1)] + var budget: Dictionary = _budgets.get(metric_id, {}) + var aggregation := int(budget.get(&"aggregation", Aggregation.P95)) + var measured_us := _aggregated_value(aggregation, average_us, p95_us, maximum_us) + var limit_us := int(budget.get(&"limit_us", 0)) + return { + &"metric_id": metric_id, + &"window_sample_count": count, + &"lifetime_sample_count": lifetime_count, + &"average_us": average_us, + &"p95_us": p95_us, + &"maximum_us": maximum_us, + &"aggregation": aggregation, + &"measured_us": measured_us, + &"limit_us": limit_us, + &"budget_exceeded": limit_us > 0 and measured_us > limit_us, + } + + +func get_all_reports() -> Array[Dictionary]: + var metric_ids: Array[StringName] = [] + for raw_metric_id: Variant in _budgets: + metric_ids.append(StringName(raw_metric_id)) + for raw_metric_id: Variant in _samples: + var metric_id := StringName(raw_metric_id) + if not metric_ids.has(metric_id): + metric_ids.append(metric_id) + metric_ids.sort_custom(func(a: StringName, b: StringName) -> bool: + return String(a) < String(b) + ) + var reports: Array[Dictionary] = [] + for metric_id: StringName in metric_ids: + reports.append(get_report(metric_id)) + return reports + + +func clear(metric_id: StringName = &"") -> void: + if metric_id.is_empty(): + _samples.clear() + _ordered_samples.clear() + _ordered_sample_bytes.clear() + _integer_window_bytes.clear() + _totals.clear() + _sample_counts.clear() + return + _samples.erase(metric_id) + _ordered_samples.erase(metric_id) + _ordered_sample_bytes.erase(metric_id) + _integer_window_bytes.erase(metric_id) + _totals.erase(metric_id) + _sample_counts.erase(metric_id) + + +func _aggregated_value( + aggregation: int, + average_us: int, + p95_us: int, + maximum_us: int +) -> int: + match aggregation: + Aggregation.AVERAGE: + return average_us + Aggregation.MAXIMUM: + return maximum_us + _: + return p95_us + + +func _percentile(raw_values: Array, percentile: int) -> int: + if raw_values.is_empty(): + return 0 + var values: Array[int] = [] + for raw_value: Variant in raw_values: + values.append(int(raw_value)) + values.sort() + var rank_numerator := clampi(percentile, 0, 100) * values.size() + var index := maxi((rank_numerator + 99) / 100 - 1, 0) + return values[mini(index, values.size() - 1)] + + +static func _integer_window(values: Array) -> bool: + for raw_value: Variant in values: + if typeof(raw_value) != TYPE_INT: return false + return true + + +func _known_integer_window(metric_id: StringName, values: Array) -> bool: + # Never retain unknown metrics. Exact bytes detect typed/untyped replacement, + # same-size in-place edits and non-integer values before any cache reuse. + if not _samples.has(metric_id): + _integer_window_bytes.erase(metric_id) + return _integer_window(values) + var current_bytes := var_to_bytes(values) + if _integer_window_bytes.has(metric_id) and _integer_window_bytes[metric_id] == current_bytes: + return true + if not _integer_window(values): + _integer_window_bytes.erase(metric_id) + return false + _integer_window_bytes[metric_id] = current_bytes + return true + + +func _validated_sample_order(metric_id: StringName, values: Array) -> Array[int]: + # No retained state for unknown metrics; raw dictionary removal also drops its index. + if not _samples.has(metric_id): + _ordered_samples.erase(metric_id) + _ordered_sample_bytes.erase(metric_id) + _integer_window_bytes.erase(metric_id) + return [] + # Complete immutable raw bytes detect in-place/replaced windows, not just length. + var current_bytes := var_to_bytes(values) + if not _ordered_samples.has(metric_id) or _ordered_sample_bytes.get(metric_id, PackedByteArray()) != current_bytes: + var ordered: Array[int] = [] + for raw_value: Variant in values: ordered.append(int(raw_value)) + ordered.sort() + _ordered_samples[metric_id] = ordered + _ordered_sample_bytes[metric_id] = current_bytes + return _ordered_samples[metric_id] + + +static func _legacy_report(owner: SimulationPerformanceBudget, metric_id: StringName) -> Dictionary: + var values: Array = owner._samples.get(metric_id, []) + var count := values.size() + var lifetime_count := int(owner._sample_counts.get(metric_id, 0)) + var lifetime_total := int(owner._totals.get(metric_id, 0)) + var average_us := lifetime_total / lifetime_count if lifetime_count > 0 else 0 + var maximum_us := 0 + for raw_value: Variant in values: + maximum_us = maxi(maximum_us, int(raw_value)) + var p95_us := owner._percentile(values, 95) + var budget: Dictionary = owner._budgets.get(metric_id, {}) + var aggregation := int(budget.get(&"aggregation", Aggregation.P95)) + var measured_us := owner._aggregated_value(aggregation, average_us, p95_us, maximum_us) + var limit_us := int(budget.get(&"limit_us", 0)) + return { + &"metric_id": metric_id, + &"window_sample_count": count, + &"lifetime_sample_count": lifetime_count, + &"average_us": average_us, + &"p95_us": p95_us, + &"maximum_us": maximum_us, + &"aggregation": aggregation, + &"measured_us": measured_us, + &"limit_us": limit_us, + &"budget_exceeded": limit_us > 0 and measured_us > limit_us, + } + diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/build-preexecution-review-r286.json b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/build-preexecution-review-r286.json new file mode 100644 index 0000000..dbc881f --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/build-preexecution-review-r286.json @@ -0,0 +1,260 @@ +{ + "review_id": "P23-02-native-integer-window-codec-build-preexecution-independent-review-r286", + "reviewed_at": "2026-10-11T22:46:27.030725+00:00", + "execution_allowed": true, + "blockers": [], + "evidence_sha256": { + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-build-r275.py": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-build-r275.py", + "bytes": 16495, + "sha256": "3f3c7118f9ad880a9f8ea0ed7f98940bd8a18a2edacf354fb9028ffba03f16de" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-build-preview-r275.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-build-preview-r275.json", + "bytes": 3379, + "sha256": "43d7ddf26df4b28e48699bae16de16442946890c3e302cd15e94a9e3cd84b8e8" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-bridge-build-r76/input.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-bridge-build-r76/input.json", + "bytes": 900666, + "sha256": "d2381f455e44d8355f54de0c52ed08d6ffbadbd68836848a87e96073c41e80e9" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-bridge-build-r76/sdk/bin/libgodot-cpp.macos.template_debug.arm64.a": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-bridge-build-r76/sdk/bin/libgodot-cpp.macos.template_debug.arm64.a", + "bytes": 2251696, + "sha256": "f429c29496622a7bfd460ebf249bb3930a515ca4fedd7efc6d347acab8015c35" + }, + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++": { + "path": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++", + "bytes": 141373024, + "sha256": "7def90dd8829726686213a747fc5bff1583df933dae5edc55d755479e0bfe00a" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-bridge-build-r76/compile_commands.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-bridge-build-r76/compile_commands.json", + "bytes": 46759, + "sha256": "43cbba9c13c03bc8539efac1eaaf4da9b5d3d6a9af3875d8cc3a3994e1a59745" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-sdk-lifetime-build-actual-independent-review-r133.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-sdk-lifetime-build-actual-independent-review-r133.json", + "bytes": 199445, + "sha256": "c3cbeb45c1353dfea5f8181d10cc60f8a9b81db55d766ac5db902ac28c159a61" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-sdk-lifetime-build-r133/input.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-sdk-lifetime-build-r133/input.json", + "bytes": 838584, + "sha256": "bf6dafe0a55c9ffb0310ef5ede6471aac93f9dee4f4fe6ad84e20e998202514e" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-sdk-lifetime-build-r133/libgodot-cpp.macos.template_debug.arm64.a": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-sdk-lifetime-build-r133/libgodot-cpp.macos.template_debug.arm64.a", + "bytes": 2284912, + "sha256": "4d54f0980c3f445f3013cddb859135b619f28a91205fc8b9fbc9d10bc76c52c3" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-bridge-build-r76.py": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-bridge-build-r76.py", + "bytes": 14637, + "sha256": "e8cfbc4cea630e0cb245d825ac5daf9730e309c4895bcbc949a744f41a2d760a" + }, + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/SDKSettings.json": { + "path": "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/SDKSettings.json", + "bytes": 7774, + "sha256": "f8d005f09381389167f9e0aeaa169bc9e7dff162ef22ca2fd8e98df7ff1acafe" + }, + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/SDKSettings.plist": { + "path": "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/SDKSettings.plist", + "bytes": 5388, + "sha256": "e5c7c40b8c5dc1a9f99f8b9fa51870f8fe180421225b8201d0c4c826aad11bdc" + }, + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/cstddef": { + "path": "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/cstddef", + "bytes": 1607, + "sha256": "53c4fc868f6439e48e52bbc9445a48eab1e597bbfad037ab7480216cb0c6832f" + }, + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libc++.tbd": { + "path": "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libc++.tbd", + "bytes": 155867, + "sha256": "5539059b5e609a9518358e42234cc9a439ae0f54e5e8ca136686a8c9ebc35c1a" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-build-preexecution-independent-review-r275.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-build-preexecution-independent-review-r275.json", + "bytes": 21406, + "sha256": "38639f46a7dedb6926351ba5ded85cb0740ff4988e7ecff0360817696257b76a" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-build-actual-independent-review-r275.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-build-actual-independent-review-r275.json", + "bytes": 21552, + "sha256": "54576596f82b8aceca440c1a5514ce811125e977c64c210675feecbb3901929f" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-build-r286.py": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-build-r286.py", + "bytes": 16592, + "sha256": "14bdaa2dcfab62f594fcb95a9ead5bc6defbc35e727fbb0de46a7494af780e3a" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-build-preview-r286.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-build-preview-r286.json", + "bytes": 3402, + "sha256": "cba922a40684eaf3206c17ac8eaa588b04015a9f09d0dbc5f79a16bf7f4159b2" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-independent-review-r285-r02.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-independent-review-r285-r02.json", + "bytes": 10950, + "sha256": "bffbdcb491ba0aa68eeac764228c04418d2ef3834624cb1fcb98db773e8369fd" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-root-verification-r285-r02.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-root-verification-r285-r02.json", + "bytes": 4849, + "sha256": "27b0b957737d79a3047f2b2a8fa936ac0ec368414d61bb6f097a524a3fd27ead" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_numeric_core.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_numeric_core.cpp", + "bytes": 54002, + "sha256": "ce20a90adb8a410dc1b6cbf607b7bfa8bf21eaef158c5c6bfc7a9bbcc703d2b2" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_core.hpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_core.hpp", + "bytes": 3299, + "sha256": "be46852fe55aeee4e18996b4d87222662b031fd1b946977c81092f4d0707e480" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_numeric_core.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_numeric_core.cpp", + "bytes": 59396, + "sha256": "75bc2f659f62889fccac5990461f5b51e8b87f30ca0791e4a4c542d37a7c5236" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_core.hpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_core.hpp", + "bytes": 3299, + "sha256": "be46852fe55aeee4e18996b4d87222662b031fd1b946977c81092f4d0707e480" + }, + "/private/tmp/thetree-prepare-integer-window-codec-r285-r02.py": { + "path": "/private/tmp/thetree-prepare-integer-window-codec-r285-r02.py", + "bytes": 8607, + "sha256": "7316b5b10bc65f7e286b66940767175f1f6b07182b84c8c2b326907bc668f9b5" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/marshalls.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/marshalls.cpp", + "bytes": 55439, + "sha256": "183c43e46d3e4b73c0fb1fc8018da37faeb88c7414dd928b1fb6ff4f4a91a374" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/source.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/source.json", + "bytes": 585, + "sha256": "cbdfe256f152bc8f0c44b849848a94e3eec1e84d6a55f5da69188a6430a148a9" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-budget-record-candidate-r257-r04/performance_budget.candidate.gd": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-budget-record-candidate-r257-r04/performance_budget.candidate.gd", + "bytes": 11250, + "sha256": "1010129d3124c3aec037c840a5766a7cdabe60c654999dfb6f23b224140a73f8" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-actual-independent-review-r282.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-actual-independent-review-r282.json", + "bytes": 14529, + "sha256": "40b90fe5086d1bb468f14418657b946fac11615b46cdf66de5f0ccac832a8457" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/input.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/input.json", + "bytes": 4325, + "sha256": "38fb6adc0ec74c0f37631da3f1ddecf185879be9655574a920f1c12566beaa8f" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-independent-review-r285.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-independent-review-r285.json", + "bytes": 9547, + "sha256": "c3f3525ee6b172bcbbc79838d49beac137d2dbd86deb61cdbefc1a921e743f06" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/source/tree_numeric_core.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/source/tree_numeric_core.cpp", + "bytes": 59281, + "sha256": "2edd9d6d782cd4072272f0c24b50ce74691899c5a4bbc9ccc946a991217d814a" + } + }, + "canonical_doc4_context_pins": { + "IMPLEMENTATION_PLAN.md": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md", + "bytes": 492762, + "sha256": "c2f4824ac3f47231395820ef792d88884a6d7c578f9f6c7b1379619c25fe7a01" + }, + "PROGRESS_INTEGRATION.md": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md", + "bytes": 410826, + "sha256": "9eaf70befb9b94d0b890caef1d8afd8f6348a3b6621fd03d5fd469f9638806c0" + }, + "work_packages.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json", + "bytes": 1180547, + "sha256": "f6538388b31fecba52276fe90dca327afc00a54ea530a8b4ecddfc87fd32ae7e" + }, + "progress_snapshot.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json", + "bytes": 529159, + "sha256": "9a03b385c8e53570012a0e3b977a8c78a3cec11ea8d5f585841f5abff3c19517" + } + }, + "archival_before_pins": { + "accepted275_context271": { + "IMPLEMENTATION_PLAN.md": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-candidate-r276/before/IMPLEMENTATION_PLAN.md", + "bytes": 511898, + "sha256": "de1f65be5107f297b6737749b89f93c066beb39f223689a27be3698611fdb9bc" + }, + "PROGRESS_INTEGRATION.md": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-candidate-r276/before/PROGRESS_INTEGRATION.md", + "bytes": 429962, + "sha256": "b259f86fe8d9709cf8f943b90aabae4e2ea2457dfce82eaa51a7edf23160b66b" + }, + "work_packages.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-candidate-r276/before/work_packages.json", + "bytes": 1247101, + "sha256": "d058f5d00a98bc162ffefa362c9dce2602adf7ce4cfac0317d5d9de580e96977" + }, + "progress_snapshot.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-candidate-r276/before/progress_snapshot.json", + "bytes": 524354, + "sha256": "99e45a9ae230926987de481123e977a9b0d49fdcc21f1e450d74fc1e2467ccc5" + } + } + }, + "allowed_scope": { + "bridge_compile": 1, + "compile_row": 62, + "link": 1, + "SDK_compile": 0, + "SDK133_archive_reuse": true, + "old_bridge_object_reuse": false, + "Godot_load": 0, + "stage_clone": 0, + "watchdog_seconds_each": 90 + }, + "findings": [ + "Read-only full diff against authenticated275 driver: candidate/review/root/preview/output labels; candidate_cpp/header lookup for input schema; pre-root reviewSHA binding; strict stdout-empty strengthening. Ownedcompiler/run_build_phase/final cleanup/source-default-doc/candidate/SDK protections unchanged.", + "Preview full2argv inverse candidate/outputpaths equals old275 exactly. Compiler flags retain exceptions, Wall/Wextra/Werror, arm64 and authenticatedmacOSSDK; only bridge row062 plus link with unchanged133archive.", + "Static285r02/root and current282 pins fresh; source/header/primaryencoder/original285reject authenticated. Accepted275 oldcurrent271 maps C276/before, not live282.", + "Capacity528MiB admission satisfied at read time, floor512 and growth16 maintained with runtimechecks. Planned2–30seconds is estimate only. Source/default freshly match latest authenticated preintegration evidence.", + "Buildpreflight authorizes only prepared1compile/1link; no ABI/load/runtimecodec/localwhole/performance/adoption/unit acceptance. No fabricated preparation-author pin: provideddriver/preview are the reviewed artifacts." + ], + "capacity_observation": { + "free_bytes": 1318674432, + "floor_bytes": 536870912, + "growth_limit_bytes": 16777216, + "admission_bytes": 553648128, + "runtime_recheck_required": true + }, + "remaining_unaccepted": [ + "Actualhostbuild and ABI/load", + "Enginecodec typed/untyped32/64 empty/bounds/append-pop/externalalias/readonly/report/signal finite local", + "S6/whole647/currentcandidate stableperformance/50ms/P95D10/final172/OSWindows/adoption/unit" + ], + "reviewer_execution": { + "compiler": 0, + "link": 0, + "engine": 0, + "tests": 0, + "validator": 0, + "author": 0, + "SDK": 0, + "new_agents": 0, + "existing_edits": 0 + }, + "pin_counts": { + "direct": 32, + "current": 4, + "archive": 4 + } +} diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/static-review-r285-r02.json b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/static-review-r285-r02.json new file mode 100644 index 0000000..bc69ab1 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/static-review-r285-r02.json @@ -0,0 +1,130 @@ +{ + "review_id": "P23-02-native-integer-window-codec-static-independent-review-r285-r02", + "reviewed_at": "2026-10-11T22:44:32.400565+00:00", + "implementation_supported": true, + "static_accepted": true, + "build_allowed": false, + "execution_allowed": false, + "blockers": [], + "evidence_sha256": { + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_numeric_core.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_numeric_core.cpp", + "bytes": 54002, + "sha256": "ce20a90adb8a410dc1b6cbf607b7bfa8bf21eaef158c5c6bfc7a9bbcc703d2b2" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_core.hpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_core.hpp", + "bytes": 3299, + "sha256": "be46852fe55aeee4e18996b4d87222662b031fd1b946977c81092f4d0707e480" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_numeric_core.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_numeric_core.cpp", + "bytes": 59396, + "sha256": "75bc2f659f62889fccac5990461f5b51e8b87f30ca0791e4a4c542d37a7c5236" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_core.hpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_core.hpp", + "bytes": 3299, + "sha256": "be46852fe55aeee4e18996b4d87222662b031fd1b946977c81092f4d0707e480" + }, + "/private/tmp/thetree-prepare-integer-window-codec-r285-r02.py": { + "path": "/private/tmp/thetree-prepare-integer-window-codec-r285-r02.py", + "bytes": 8607, + "sha256": "7316b5b10bc65f7e286b66940767175f1f6b07182b84c8c2b326907bc668f9b5" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/marshalls.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/marshalls.cpp", + "bytes": 55439, + "sha256": "183c43e46d3e4b73c0fb1fc8018da37faeb88c7414dd928b1fb6ff4f4a91a374" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/source.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/source.json", + "bytes": 585, + "sha256": "cbdfe256f152bc8f0c44b849848a94e3eec1e84d6a55f5da69188a6430a148a9" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-budget-record-candidate-r257-r04/performance_budget.candidate.gd": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-budget-record-candidate-r257-r04/performance_budget.candidate.gd", + "bytes": 11250, + "sha256": "1010129d3124c3aec037c840a5766a7cdabe60c654999dfb6f23b224140a73f8" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-actual-independent-review-r282.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-actual-independent-review-r282.json", + "bytes": 14529, + "sha256": "40b90fe5086d1bb468f14418657b946fac11615b46cdf66de5f0ccac832a8457" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/input.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/input.json", + "bytes": 4325, + "sha256": "38fb6adc0ec74c0f37631da3f1ddecf185879be9655574a920f1c12566beaa8f" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-independent-review-r285.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-independent-review-r285.json", + "bytes": 9547, + "sha256": "c3f3525ee6b172bcbbc79838d49beac137d2dbd86deb61cdbefc1a921e743f06" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/source/tree_numeric_core.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/source/tree_numeric_core.cpp", + "bytes": 59281, + "sha256": "2edd9d6d782cd4072272f0c24b50ce74691899c5a4bbc9ccc946a991217d814a" + } + }, + "canonical_doc4_context_pins": { + "IMPLEMENTATION_PLAN.md": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md", + "bytes": 492762, + "sha256": "c2f4824ac3f47231395820ef792d88884a6d7c578f9f6c7b1379619c25fe7a01" + }, + "PROGRESS_INTEGRATION.md": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md", + "bytes": 410826, + "sha256": "9eaf70befb9b94d0b890caef1d8afd8f6348a3b6621fd03d5fd469f9638806c0" + }, + "work_packages.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json", + "bytes": 1180547, + "sha256": "f6538388b31fecba52276fe90dca327afc00a54ea530a8b4ecddfc87fd32ae7e" + }, + "progress_snapshot.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json", + "bytes": 529159, + "sha256": "9a03b385c8e53570012a0e3b977a8c78a3cec11ea8d5f585841f5abff3c19517" + } + }, + "repair_findings": [ + "Only original B1 repair: new temporary vector reserve/push_back removed. First pass validates each INT and computes bounded signed-int byte length; checked engine PackedByteArray.resize precedes second direct write pass. No new throwing temporary vector allocation in codec path.", + "Repair inverse reconstructs exact frozen285 CPP; prior frozen285 complete inverse274 and unchanged primary source/header/Budget authentication remain applicable. All new direct/current282 pins freshly matched.", + "Second pass reads same caller-owned Array in synchronous integer-only domain; index/type reads and integer conversion have no callback, and new output array is independent. No cross-call sample cache introduced. Arbitrary concurrent mutation is not supported.", + "Per-object4 empty/boundary typed/untyped format comparisons, little endian typed/untyped32/64 layouts, append/pop update, external fullbytes mutation detection, oldencoder fallback and raw/order aliases unchanged. Existing parent report/Time/signal/GD ownership flow unchanged.", + "This support concerns removal of the new allocation hazard, not a blanket OOM guarantee for all unchanged preexisting native/Godot allocations." + ], + "prior_supported_static_findings": [ + "All declared direct and current282 doc4 pins freshly matched; CPP complete mechanical inverse equals exact parent274, header byteexact and BudgetGD unchanged. No stage generated.", + "Local actual primary marshalls.cpp ed1daf0bf SHA183c43… confirms little-endian INT type header plus flag1<<16 outside signed32 range, unsigned two-complement payload4/8, Array header8 untyped or12 builtin typedINT, typed marker1<<16 and length32. No web rendering offsets used.", + "Nine integer boundaries and empty typed/untyped arrays calibrate only per-object format boolean; mismatch preserves old UtilityFunctions encoder. No cached sample values or global objects added.", + "For locally produced exact bytes, update keeps typed prefix and order, changes length and appends exact duration; popFront removes one original element, including zero/negative capacity and empty append-then-pop. Signed total/count/P95/report calculations unchanged from parent.", + "Complete current raw bytes still computed before existing fullbyte cache comparison, so external same-size/value/type mutation is not hidden. Original raw/reusedordered aliases and readonly/custom/malformed guards retained; after-allocation failure path invokes original encoder. No signal/Time/helper/publicreport sequencing changes in CPP inverse; GD original signaldeepdup/return unaffected." + ], + "required_next_gates": [ + "Separate authenticated bridge compile/link preexecution review; SDK methods/header/format runtime not compile-tested by static review.", + "Load and exact engine-codec helper comparisons: empty/typed/untyped, 32/64 allsigned bounds, append/pop0/-1/1/window600, mixed/read-only/custom/rawexternedit/alias/report/signal/reentry finite scopes.", + "Same candidate original S6 impact and whole647 full-save equality, finite exploratory timing only. No stable gain/performancecause/P95/D10/50ms/final172/OS/Windows/adoption/unit acceptance." + ], + "inference_domain": "Exact synchronous integer Array values and fixed authenticated engine encoder layout; calibration mismatch uses original encoder. No arbitrary concurrency or allocator-failure runtime proof.", + "candidate_preserved": true, + "performance_cause_or_gain_claimed": false, + "reviewer_execution": { + "engine": 0, + "compiler": 0, + "tests": 0, + "validator": 0, + "SDK": 0, + "author": 0, + "codec": 0, + "new_agents": 0, + "existing_file_edits": 0 + }, + "pin_counts": { + "direct": 12, + "current": 4 + } +} diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/static-root-verification-r285-r02.json b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/static-root-verification-r285-r02.json new file mode 100644 index 0000000..399ed50 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/evidence/static-root-verification-r285-r02.json @@ -0,0 +1,87 @@ +{ + "passed": true, + "review_sha256": "bffbdcb491ba0aa68eeac764228c04418d2ef3834624cb1fcb98db773e8369fd", + "verified_entries": [ + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_numeric_core.cpp", + "bytes": 54002, + "sha256": "ce20a90adb8a410dc1b6cbf607b7bfa8bf21eaef158c5c6bfc7a9bbcc703d2b2" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_core.hpp", + "bytes": 3299, + "sha256": "be46852fe55aeee4e18996b4d87222662b031fd1b946977c81092f4d0707e480" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_numeric_core.cpp", + "bytes": 59396, + "sha256": "75bc2f659f62889fccac5990461f5b51e8b87f30ca0791e4a4c542d37a7c5236" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_core.hpp", + "bytes": 3299, + "sha256": "be46852fe55aeee4e18996b4d87222662b031fd1b946977c81092f4d0707e480" + }, + { + "path": "/private/tmp/thetree-prepare-integer-window-codec-r285-r02.py", + "bytes": 8607, + "sha256": "7316b5b10bc65f7e286b66940767175f1f6b07182b84c8c2b326907bc668f9b5" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/marshalls.cpp", + "bytes": 55439, + "sha256": "183c43e46d3e4b73c0fb1fc8018da37faeb88c7414dd928b1fb6ff4f4a91a374" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/source.json", + "bytes": 585, + "sha256": "cbdfe256f152bc8f0c44b849848a94e3eec1e84d6a55f5da69188a6430a148a9" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-budget-record-candidate-r257-r04/performance_budget.candidate.gd", + "bytes": 11250, + "sha256": "1010129d3124c3aec037c840a5766a7cdabe60c654999dfb6f23b224140a73f8" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-actual-independent-review-r282.json", + "bytes": 14529, + "sha256": "40b90fe5086d1bb468f14418657b946fac11615b46cdf66de5f0ccac832a8457" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/input.json", + "bytes": 4325, + "sha256": "38fb6adc0ec74c0f37631da3f1ddecf185879be9655574a920f1c12566beaa8f" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-independent-review-r285.json", + "bytes": 9547, + "sha256": "c3f3525ee6b172bcbbc79838d49beac137d2dbd86deb61cdbefc1a921e743f06" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/source/tree_numeric_core.cpp", + "bytes": 59281, + "sha256": "2edd9d6d782cd4072272f0c24b50ce74691899c5a4bbc9ccc946a991217d814a" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md", + "bytes": 492762, + "sha256": "c2f4824ac3f47231395820ef792d88884a6d7c578f9f6c7b1379619c25fe7a01" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md", + "bytes": 410826, + "sha256": "9eaf70befb9b94d0b890caef1d8afd8f6348a3b6621fd03d5fd469f9638806c0" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json", + "bytes": 1180547, + "sha256": "f6538388b31fecba52276fe90dca327afc00a54ea530a8b4ecddfc87fd32ae7e" + }, + { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json", + "bytes": 529159, + "sha256": "9a03b385c8e53570012a0e3b977a8c78a3cec11ea8d5f585841f5abff3c19517" + } + ], + "unit_accepted": false +} \ No newline at end of file diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/history-r285/static-review.json b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/history-r285/static-review.json new file mode 100644 index 0000000..f87c4c7 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/history-r285/static-review.json @@ -0,0 +1,120 @@ +{ + "review_id": "P23-02-native-integer-window-codec-static-independent-review-r285", + "reviewed_at": "2026-10-11T22:43:51.086271+00:00", + "implementation_supported": false, + "static_accepted": false, + "build_allowed": false, + "execution_allowed": false, + "blockers": [ + { + "id": "B1-unhandled-temporary-allocation", + "function": "integer_wire_encode", + "detail": "std::vector integers.reserve(count) and push_back introduce a new unchecked C++ allocation, before complete element-type validation. PackedByteArray.resize error handling does not cover this allocation. bad_alloc/length_error escapes if exceptions are enabled; an exception-disabled configuration can terminate. Therefore the stated failed-allocation false/fallback contract is not established, including large unsupported arrays that originally return on first noninteger element.", + "required_repair": "Remove the temporary vector with two read-only passes: first validate types/compute bounded length, then after checked PackedByteArray.resize write each unchanged integer directly. Alternatively provide an authenticated allocation-failure path compatible with actual build exception policy; do not merely weaken accepted domain or ignore failure." + } + ], + "evidence_sha256": { + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_numeric_core.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_numeric_core.cpp", + "bytes": 54002, + "sha256": "ce20a90adb8a410dc1b6cbf607b7bfa8bf21eaef158c5c6bfc7a9bbcc703d2b2" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_core.hpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_core.hpp", + "bytes": 3299, + "sha256": "be46852fe55aeee4e18996b4d87222662b031fd1b946977c81092f4d0707e480" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/source/tree_numeric_core.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/source/tree_numeric_core.cpp", + "bytes": 59281, + "sha256": "2edd9d6d782cd4072272f0c24b50ce74691899c5a4bbc9ccc946a991217d814a" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/source/tree_core.hpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/source/tree_core.hpp", + "bytes": 3299, + "sha256": "be46852fe55aeee4e18996b4d87222662b031fd1b946977c81092f4d0707e480" + }, + "/private/tmp/thetree-prepare-integer-window-codec-r285.py": { + "path": "/private/tmp/thetree-prepare-integer-window-codec-r285.py", + "bytes": 8488, + "sha256": "ef011afc1f7a8d590330ab9f24bbd973b5bdda6e1923675f55c4f4c83ed9d93b" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/marshalls.cpp": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/marshalls.cpp", + "bytes": 55439, + "sha256": "183c43e46d3e4b73c0fb1fc8018da37faeb88c7414dd928b1fb6ff4f4a91a374" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/source.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/source.json", + "bytes": 585, + "sha256": "cbdfe256f152bc8f0c44b849848a94e3eec1e84d6a55f5da69188a6430a148a9" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-budget-record-candidate-r257-r04/performance_budget.candidate.gd": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-budget-record-candidate-r257-r04/performance_budget.candidate.gd", + "bytes": 11250, + "sha256": "1010129d3124c3aec037c840a5766a7cdabe60c654999dfb6f23b224140a73f8" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-actual-independent-review-r282.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-progress-integration-actual-independent-review-r282.json", + "bytes": 14529, + "sha256": "40b90fe5086d1bb468f14418657b946fac11615b46cdf66de5f0ccac832a8457" + }, + "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/input.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/input.json", + "bytes": 4313, + "sha256": "58dd63b112841a6908e8356741a4f7ca949d29f917c50ecba24be5859b1d1a6c" + } + }, + "canonical_doc4_context_pins": { + "IMPLEMENTATION_PLAN.md": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/IMPLEMENTATION_PLAN.md", + "bytes": 492762, + "sha256": "c2f4824ac3f47231395820ef792d88884a6d7c578f9f6c7b1379619c25fe7a01" + }, + "PROGRESS_INTEGRATION.md": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/PROGRESS_INTEGRATION.md", + "bytes": 410826, + "sha256": "9eaf70befb9b94d0b890caef1d8afd8f6348a3b6621fd03d5fd469f9638806c0" + }, + "work_packages.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/work_packages.json", + "bytes": 1180547, + "sha256": "f6538388b31fecba52276fe90dca327afc00a54ea530a8b4ecddfc87fd32ae7e" + }, + "progress_snapshot.json": { + "path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/docs/plans/original-completion-2026-10-02/progress_snapshot.json", + "bytes": 529159, + "sha256": "9a03b385c8e53570012a0e3b977a8c78a3cec11ea8d5f585841f5abff3c19517" + } + }, + "supported_static_findings": [ + "All declared direct and current282 doc4 pins freshly matched; CPP complete mechanical inverse equals exact parent274, header byteexact and BudgetGD unchanged. No stage generated.", + "Local actual primary marshalls.cpp ed1daf0bf SHA183c43… confirms little-endian INT type header plus flag1<<16 outside signed32 range, unsigned two-complement payload4/8, Array header8 untyped or12 builtin typedINT, typed marker1<<16 and length32. No web rendering offsets used.", + "Nine integer boundaries and empty typed/untyped arrays calibrate only per-object format boolean; mismatch preserves old UtilityFunctions encoder. No cached sample values or global objects added.", + "For locally produced exact bytes, update keeps typed prefix and order, changes length and appends exact duration; popFront removes one original element, including zero/negative capacity and empty append-then-pop. Signed total/count/P95/report calculations unchanged from parent.", + "Complete current raw bytes still computed before existing fullbyte cache comparison, so external same-size/value/type mutation is not hidden. Original raw/reusedordered aliases and readonly/custom/malformed guards retained; after-allocation failure path invokes original encoder. No signal/Time/helper/publicreport sequencing changes in CPP inverse; GD original signaldeepdup/return unaffected." + ], + "remaining_required": [ + "Static allocation repair before build preflight; compile/link new methods/API not yet verified.", + "Local original engine var_to_bytes comparison across typed/untyped empty and signed32/64 edges, append/pop/capacity0/-1/1/window600, raw external edits, readonly/mixed/custom/alias and original report/signal/reentry ownership scopes.", + "Same current candidate original S6 impact and whole647 full-save equality plus finite observation before any performance conclusion.", + "General arbitrary ownership/invalidinput/reentry/OOM-runtime behavior, stable gain/P95/D10/50ms/final172/OS/Windows/adoption/unit acceptance remain unproved." + ], + "reviewer_execution": { + "engine": 0, + "compiler": 0, + "tests": 0, + "validator": 0, + "SDK": 0, + "author": 0, + "codec": 0, + "new_agents": 0, + "existing_file_edits": 0 + }, + "pin_counts": { + "direct": 10, + "current": 4 + }, + "candidate_preserved": true, + "performance_cause_or_gain_claimed": false +} diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/history-r285/tree_numeric_core.cpp b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/history-r285/tree_numeric_core.cpp new file mode 100644 index 0000000..cb89fa9 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/history-r285/tree_numeric_core.cpp @@ -0,0 +1,923 @@ +// Isolated, uncompiled bridge prototype. No production registration or integration yet. +#include "tree_core.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace godot; +using the_tree_native::I; +using the_tree_native::Edge; + +class TheTreeNumericCore : public RefCounted { + GDCLASS(TheTreeNumericCore, RefCounted) +protected: + static void _bind_methods() { + ClassDB::bind_method(D_METHOD("performance_record_sample", "owner", "metric_id", "duration_us"), &TheTreeNumericCore::performance_record_sample); + ClassDB::bind_method(D_METHOD("encode_integer_window", "values"), &TheTreeNumericCore::encode_integer_window); + ClassDB::bind_method(D_METHOD("guest_tree_edge_rows", "path", "current", "layers", "access"), &TheTreeNumericCore::guest_tree_edge_rows); + ClassDB::bind_method(D_METHOD("search", "cells", "indices", "start_index", "goals", "edge_provider"), &TheTreeNumericCore::search); + ClassDB::bind_method(D_METHOD("search_cached", "cells", "indices", "start_index", "goals", "edge_provider"), &TheTreeNumericCore::search_cached); + ClassDB::bind_method(D_METHOD("clear_edge_cache"), &TheTreeNumericCore::clear_edge_cache); + ClassDB::bind_method(D_METHOD("nearest_guest_access", "path", "start", "goals", "fallback_target", "layers", "access", "ticks"), &TheTreeNumericCore::nearest_guest_access); + ClassDB::bind_method(D_METHOD("project_guest_candidates", "runtime", "guest_id", "open_state", "degraded_state", "movement_scale", "stair_credit", "orthogonal_cost", "ticks"), &TheTreeNumericCore::project_guest_candidates); + } +private: + // Cache belongs to this instance and one caller-owned graph workspace. + // No reuse after cells, indices, filters or edge values change: the caller + // must clear it or release this core. The original search never uses it. + std::map> cached_edges; + // Godot ed1daf0bf's integer Array wire layout; checked against this engine + // once per core, never sample values. Every caller-owned Array stays intact. + bool integer_wire_checked=false; + bool integer_wire_compatible=false; + static void wire32(uint8_t *p,uint32_t value) { + for (unsigned i=0;i<4;++i) p[i]=uint8_t(value>>(8*i)); + } + static void wire64(uint8_t *p,uint64_t value) { + for (unsigned i=0;i<8;++i) p[i]=uint8_t(value>>(8*i)); + } + static int64_t integer_wire_width(int64_t value) { + return valueint64_t(INT32_MAX) ? 12 : 8; + } + static void wire_integer(uint8_t *p,int64_t value) { + const bool wide=integer_wire_width(value)==12; + wire32(p,uint32_t(Variant::INT) | (wide ? uint32_t(1)<<16 : 0)); + if (wide) wire64(p+4,uint64_t(value)); else wire32(p+4,uint32_t(value)); + } + static bool integer_wire_encode(const Array &values,PackedByteArray &out) { + const bool typed=values.is_typed(); + if (typed && (values.get_typed_builtin()!=Variant::INT || + !values.get_typed_class_name().is_empty() || values.get_typed_script().get_type()!=Variant::NIL)) return false; + const int64_t count=values.size(),header=typed ? 12 : 8; + // The engine encoder uses a signed-int byte length. Preserve fallback + // for oversized inputs and failed allocations, before owner mutation. + if (count<0 || count>(int64_t(INT32_MAX)-header)/12) return false; + std::vector integers; + integers.reserve(size_t(count)); + int64_t size=header; + for (int64_t i=0;i typed_empty,typed_probe; + const int64_t boundaries[]={INT64_MIN,int64_t(INT32_MIN)-1,INT32_MIN,-1,0,1,INT32_MAX,int64_t(INT32_MAX)+1,INT64_MAX}; + for (const int64_t value: boundaries) {probe.append(value);typed_probe.append(value);} + bool matches=true; + for (const Array &value: {empty,probe,Array(typed_empty),Array(typed_probe)}) { + PackedByteArray encoded; + matches=integer_wire_encode(value,encoded) && encoded==UtilityFunctions::var_to_bytes(value) && matches; + } + integer_wire_compatible=matches;integer_wire_checked=true; + return matches; + } + static bool integer_wire_update(const PackedByteArray &before,bool typed,int64_t old_count, + int64_t appended,bool pop_front,PackedByteArray &after) { + const int64_t header=typed ? 12 : 8; + if (before.size()
0) { + if (before.size()INT32_MAX || after.resize(size)!=OK) return false; + uint8_t *p=after.ptrw();const uint8_t *q=before.ptr(); + std::memcpy(p,q,size_t(header)); + wire32(p+header-4,uint32_t(old_count+1-(pop_front ? 1 : 0))); + const int64_t kept=before.size()-header-skipped; + if (kept>0) std::memcpy(p+header,q+header+skipped,size_t(kept)); + if (added>0) wire_integer(p+header+kept,appended); + return true; + } + + // Per-public-call immutable names. No static/global lifetime, cached + // object values, script dispatch result or profile; recursive calls own + // separate scopes. Destruction precedes leaving the engine call. + struct ProjectionNames { + const StringName k_ACCESS_LAYER_DENIED{"ACCESS_LAYER_DENIED",false}; + const StringName k_CONNECTOR{"CONNECTOR",false}; + const StringName k_GOAL_NOT_PASSABLE{"GOAL_NOT_PASSABLE",false}; + const StringName k_GOAL_TEMPORARILY_BLOCKED{"GOAL_TEMPORARILY_BLOCKED",false}; + const StringName k_GOAL_UNREACHABLE{"GOAL_UNREACHABLE",false}; + const StringName k_OK{"OK",false}; + const StringName k_START_NOT_PASSABLE{"START_NOT_PASSABLE",false}; + const StringName k_START_TEMPORARILY_BLOCKED{"START_TEMPORARILY_BLOCKED",false}; + const StringName k__build_guest_query_tree_compact{"_build_guest_query_tree_compact",false}; + const StringName k__cache_key{"_cache_key",false}; + const StringName k__cell_traffic{"_cell_traffic",false}; + const StringName k__copy_path{"_copy_path",false}; + const StringName k__diagnose_no_route_reason{"_diagnose_no_route_reason",false}; + const StringName k__find_facility_access_path{"_find_facility_access_path",false}; + const StringName k__find_path_internal{"_find_path_internal",false}; + const StringName k__guest_access_batch_can_select{"_guest_access_batch_can_select",false}; + const StringName k__guest_batch_has_permitted_layer_crossing{"_guest_batch_has_permitted_layer_crossing",false}; + const StringName k__guest_has_checked_in{"_guest_has_checked_in",false}; + const StringName k__guest_step_connector_memo{"_guest_step_connector_memo",false}; + const StringName k__guest_tree_arithmetic_wrapped{"_guest_tree_arithmetic_wrapped",false}; + const StringName k__guest_tree_reconstruct_path{"_guest_tree_reconstruct_path",false}; + const StringName k__need_relief_for_facility_tags{"_need_relief_for_facility_tags",false}; + const StringName k__passable_cells{"_passable_cells",false}; + const StringName k__path_cache{"_path_cache",false}; + const StringName k__query_batch{"_query_batch",false}; + const StringName k__route_failure{"_route_failure",false}; + const StringName k__service_category_for_tags{"_service_category_for_tags",false}; + const StringName k__sorted_name_keys{"_sorted_name_keys",false}; + const StringName k_arithmetic_wrapped{"arithmetic_wrapped",false}; + const StringName k_available_quantity{"available_quantity",false}; + const StringName k_base_quality{"base_quality",false}; + const StringName k_base_service_minutes{"base_service_minutes",false}; + const StringName k_begin_guest_path_query_batch{"begin_guest_path_query_batch",false}; + const StringName k_cache_misses{"cache_misses",false}; + const StringName k_calculate_guest_batch_path_cost{"calculate_guest_batch_path_cost",false}; + const StringName k_candidates{"candidates",false}; + const StringName k_capacity{"capacity",false}; + const StringName k_compact{"compact",false}; + const StringName k_cost{"cost",false}; + const StringName k_cost_values{"cost_values",false}; + const StringName k_costs{"costs",false}; + const StringName k_current_cell{"current_cell",false}; + const StringName k_definition_id{"definition_id",false}; + const StringName k_definition_registry{"definition_registry",false}; + const StringName k_elevators{"elevators",false}; + const StringName k_end_guest_path_query_batch{"end_guest_path_query_batch",false}; + const StringName k_entrance{"entrance",false}; + const StringName k_estimated_total_gold{"estimated_total_gold",false}; + const StringName k_expected_quality{"expected_quality",false}; + const StringName k_expected_wait{"expected_wait",false}; + const StringName k_facility_id{"facility_id",false}; + const StringName k_facility_service{"facility_service",false}; + const StringName k_facility_tags{"facility_tags",false}; + const StringName k_get_connector{"get_connector",false}; + const StringName k_get_facility{"get_facility",false}; + const StringName k_get_facility_business_price{"get_facility_business_price",false}; + const StringName k_get_guest{"get_guest",false}; + const StringName k_get_instances{"get_instances",false}; + const StringName k_get_step_connector{"get_step_connector",false}; + const StringName k_graph_revision{"graph_revision",false}; + const StringName k_group_fit{"group_fit",false}; + const StringName k_guest_service{"guest_service",false}; + const StringName k_illegal_level{"illegal_level",false}; + const StringName k_indices{"indices",false}; + const StringName k_inputs_available{"inputs_available",false}; + const StringName k_instance_id{"instance_id",false}; + const StringName k_inventory_inputs{"inventory_inputs",false}; + const StringName k_inventory_service{"inventory_service",false}; + const StringName k_is_open{"is_open",false}; + const StringName k_last_error{"last_error",false}; + const StringName k_last_no_route_reason{"last_no_route_reason",false}; + const StringName k_last_path_cost{"last_path_cost",false}; + const StringName k_local_inventory_id{"local_inventory_id",false}; + const StringName k_movement_type{"movement_type",false}; + const StringName k_need_relief{"need_relief",false}; + const StringName k_occupied_cells{"occupied_cells",false}; + const StringName k_origin{"origin",false}; + const StringName k_owns_connector{"owns_connector",false}; + const StringName k_path{"path",false}; + const StringName k_path_handle{"path_handle",false}; + const StringName k_path_query_measured{"path_query_measured",false}; + const StringName k_path_service{"path_service",false}; + const StringName k_queue_entries{"queue_entries",false}; + const StringName k_reachable{"reachable",false}; + const StringName k_ready{"ready",false}; + const StringName k_resource_path{"resource_path",false}; + const StringName k_risk_level{"risk_level",false}; + const StringName k_service_category{"service_category",false}; + const StringName k_settled{"settled",false}; + const StringName k_staff_only{"staff_only",false}; + const StringName k_start{"start",false}; + const StringName k_state{"state",false}; + const StringName k_supported{"supported",false}; + const StringName k_tags{"tags",false}; + const StringName k_tagproj_hunger{"hunger",false}; + const StringName k_tagproj_sleep{"sleep",false}; + const StringName k_tagproj_hygiene{"hygiene",false}; + const StringName k_tagproj_medical{"medical",false}; + const StringName k_tagproj_leisure{"leisure",false}; + const StringName k_tagproj_intimacy{"intimacy",false}; + const StringName k_tagproj_dining{"dining",false}; + const StringName k_tagproj_lodging{"lodging",false}; + const StringName k_tagproj_social{"social",false}; + const StringName k_tagproj_bath{"bath",false}; + const StringName k_tagproj_wellness{"wellness",false}; + const StringName k_tagproj_adult_only{"adult_only",false}; + const StringName k_tagproj_restricted_service{"restricted_service",false}; + const StringName k_tagproj_food{"food",false}; + const StringName k_tagproj_service{"service",false}; + const StringName k_target_cell{"target_cell",false}; + const StringName k_targets{"targets",false}; + const StringName k_temporary_block{"temporary_block",false}; + const StringName k_travel_minutes{"travel_minutes",false}; + const StringName k_tree{"tree",false}; + const StringName k_usable{"usable",false}; + }; +public: + Dictionary encode_integer_window(const Array &values) { + Dictionary result;const StringName supported("supported",false),bytes("bytes",false); + result[supported]=false;PackedByteArray encoded; + if (!integer_wire_ready() || !integer_wire_encode(values,encoded)) return result; + result[supported]=true;result[bytes]=encoded;return result; + } + // Whole builtin integer record operation. No retained sample values or time + // suppression. Unsupported data returns before any caller-owned mutation. + Dictionary performance_record_sample(Object *owner, const StringName &metric, int64_t duration) { + const StringName supported("supported",false), report_key("report",false); + Dictionary unsupported; unsupported[supported]=false; + Object *script=owner ? owner->get_script() : nullptr; + if (!script || String(script->get(StringName("resource_path",false))) != "res://scripts/core/performance_budget.gd" || metric==StringName() || duration<0) return unsupported; + const StringName samples_key("_samples",false), ordered_key("_ordered_samples",false), bytes_key("_ordered_sample_bytes",false), integer_key("_integer_window_bytes",false), totals_key("_totals",false), counts_key("_sample_counts",false), budgets_key("_budgets",false); + const Variant sv=owner->get(samples_key), ov=owner->get(ordered_key), bv=owner->get(bytes_key), iv=owner->get(integer_key), tv=owner->get(totals_key), cv=owner->get(counts_key), uv=owner->get(budgets_key), capacityv=owner->get(StringName("sample_capacity",false)); + if (sv.get_type()!=Variant::DICTIONARY || ov.get_type()!=Variant::DICTIONARY || bv.get_type()!=Variant::DICTIONARY || iv.get_type()!=Variant::DICTIONARY || tv.get_type()!=Variant::DICTIONARY || cv.get_type()!=Variant::DICTIONARY || uv.get_type()!=Variant::DICTIONARY || capacityv.get_type()!=Variant::INT) return unsupported; + Dictionary samples=sv, orders=ov, rawbytes=bv, integers=iv, totals=tv, counts=cv, budgets=uv; + if (samples.is_read_only() || orders.is_read_only() || rawbytes.is_read_only() || integers.is_read_only() || totals.is_read_only() || counts.is_read_only()) return unsupported; + const std::vector maps{samples,orders,rawbytes,integers,totals,counts,budgets}; + for (size_t i=0;i ordered; + Variant savedbytes=rawbytes.get(metric,PackedByteArray()); + bool reuse=existing && orders.has(metric) && savedbytes.get_type()==Variant::PACKED_BYTE_ARRAY && PackedByteArray(savedbytes)==before; + if (reuse) { + Variant orderv=orders[metric]; + if (orderv.get_type()!=Variant::ARRAY) return unsupported; + Array prior=orderv; + if (prior.is_read_only() || !prior.is_typed() || prior.get_typed_builtin()!=Variant::INT || prior.size()!=values.size()) return unsupported; + ordered=prior; + } else { + for (int64_t i=0;iint64_t(capacityv)) { + Variant removed=values.pop_front(); + ordered.remove_at(ordered.bsearch(removed)); + } + PackedByteArray after; + const bool popped=old_count+1>int64_t(capacityv); + if (!fast_wire || !integer_wire_update(before,values.is_typed(),old_count,duration,popped,after)) + after=UtilityFunctions::var_to_bytes(values); + rawbytes[metric]=after; integers[metric]=after; + const int64_t lifetime_total=the_tree_native::signed_add(int64_t(totalv),duration); + const int64_t lifetime_count=the_tree_native::signed_add(int64_t(countv),1); + totals[metric]=lifetime_total; counts[metric]=lifetime_count; + const int64_t average=lifetime_count>0 ? lifetime_total/lifetime_count : 0; + const int64_t maximum=ordered.is_empty() ? 0 : std::max(0,int64_t(ordered[ordered.size()-1])); + int64_t p95=0; + if (!ordered.is_empty()) { + const int64_t index=std::max(the_tree_native::signed_add(the_tree_native::signed_add(signed_product(95,ordered.size()),99)/100,-1),0); + p95=ordered[std::min(index,ordered.size()-1)]; + } + const int64_t aggregation=aggregationv, limit=limitv; + // Original default match is P95, including unknown aggregation values. + const int64_t measured=aggregation==0 ? average : (aggregation==2 ? maximum : p95); + Dictionary report; + report[StringName("metric_id",false)]=metric; + report[StringName("window_sample_count",false)]=values.size(); + report[StringName("lifetime_sample_count",false)]=lifetime_count; + report[StringName("average_us",false)]=average; + report[StringName("p95_us",false)]=p95; + report[StringName("maximum_us",false)]=maximum; + report[aggregation_key]=aggregation; + report[StringName("measured_us",false)]=measured; + report[limit_key]=limit; + report[StringName("budget_exceeded",false)]=limit>0 && measured>limit; + Dictionary result; result[supported]=true; result[report_key]=report; return result; + } + void clear_edge_cache() { cached_edges.clear(); } + Dictionary search(const Array &cells, const Dictionary &indices, I start_index, + const Dictionary &goals, const Callable &edge_provider) { + return search_impl(cells, indices, start_index, goals, edge_provider, false); + } + Dictionary search_cached(const Array &cells, const Dictionary &indices, I start_index, + const Dictionary &goals, const Callable &edge_provider) { + return search_impl(cells, indices, start_index, goals, edge_provider, true); + } + // One ordered projection, with no new persistent ownership/cache. Only + // builtin pure getters and the already guarded sole budget observer qualify. + Dictionary project_guest_candidates(Object *runtime, const StringName &guest_id, + int64_t open_state, int64_t degraded_state, int64_t movement_scale, + int64_t stair_credit, int64_t orthogonal_cost, const Callable &ticks) { + const ProjectionNames n; + Dictionary unsupported; + unsupported[n.k_supported] = false; + if (!builtin(n,runtime, "res://autoload/simulation_runtime.gd") || !ticks.is_valid()) return unsupported; + Object *path = runtime->get(n.k_path_service); + Object *elevators = runtime->get(n.k_elevators); + Object *facilities = runtime->get(n.k_facility_service); + Object *definitions = runtime->get(n.k_definition_registry); + Object *inventory = runtime->get(n.k_inventory_service); + Object *guests = runtime->get(n.k_guest_service); + if (!builtin(n,path,"res://scripts/world/path_service.gd") || + !builtin(n,elevators,"res://scripts/transport/elevator_service.gd") || + !builtin(n,facilities,"res://scripts/facility/facility_service.gd") || + !builtin(n,definitions,"res://scripts/core/definition_registry.gd") || + !builtin(n,inventory,"res://scripts/inventory/inventory_service.gd") || + !builtin(n,guests,"res://scripts/guest/guest_service.gd") || + !static_cast(runtime->call(n.k__guest_access_batch_can_select))) return unsupported; + Object *guest = guests->call(n.k_get_guest,guest_id); + Array candidates; + if (!guest) { + Dictionary result; result[n.k_supported] = true; + result[n.k_candidates] = candidates; return result; + } + if (!builtin(n,guest,"res://scripts/guest/guest_runtime.gd")) return unsupported; + const Array initial = facilities->call(n.k_get_instances); + // Preflight is read-only: default registry/get_instances have no public + // error/counter effects. Custom resources retain the original whole loop. + for (int64_t i=0;icall(n.k_get_facility,facility->get(n.k_definition_id)); + if (definition && !builtin(n,definition,"res://scripts/data/facility_definition.gd")) return unsupported; + } + Array goals; + for (int64_t i=0;iget(n.k_current_cell); + path->call(n.k_begin_guest_path_query_batch,start,goals); + const Array ordered = facilities->call(n.k_get_instances); + TypedArray layers; layers.push_back(0); layers.push_back(1); + TypedArray access_ids; + for (int64_t i=0;icall(n.k_get_facility,facility->get(n.k_definition_id)); + if (!definition) continue; + const Array tags = definition->get(n.k_tags); + if (tags.has(n.k_staff_only)) continue; + if (tags.has(n.k_entrance) && static_cast(runtime->call(n.k__guest_has_checked_in,guest))) continue; + bool has_inputs = true; + const Dictionary inputs = definition->get(n.k_inventory_inputs); + const Array items = runtime->call(n.k__sorted_name_keys,inputs); + for (int64_t j=0;jcall(n.k_available_quantity,facility->get(n.k_local_inventory_id),items[j]); + if (quantity < static_cast(inputs[items[j]])) {has_inputs=false;break;} + } + if (!has_inputs) { + Dictionary row;row[n.k_facility_id]=facility->get(n.k_instance_id); + row[n.k_inputs_available]=false;candidates.push_back(row);continue; + } + const Array destinations = facility_access_cells(n,path,facility); + Dictionary route = nearest_guest_access_impl(n,path,start,destinations,facility->get(n.k_origin),layers,access_ids,ticks); + if (static_cast(route.get(n.k_supported,false))) route.erase(n.k_supported); + else route = Dictionary(runtime->call(n.k__find_facility_access_path,start,facility)); + const Array walk = route.get(n.k_path,Array()); + const bool plain_tag_relief = builtin(n,runtime,"res://autoload/simulation_runtime.gd") && + tags.is_typed() && tags.get_typed_builtin()==Variant::STRING_NAME; + const Dictionary relief = plain_tag_relief ? builtin_tag_relief(n,tags) : + Dictionary(runtime->call(n.k__need_relief_for_facility_tags,tags)); + Dictionary row; + row[n.k_facility_id]=facility->get(n.k_instance_id); + row[n.k_facility_tags]=tags.duplicate(); + const int64_t state = facility->get(n.k_state); + row[n.k_is_open]=(state==open_state || state==degraded_state); + row[n.k_reachable]=route.get(n.k_reachable,false); + row[n.k_travel_minutes]=guest_path_minutes(n,path,elevators,walk,movement_scale,stair_credit,orthogonal_cost); + const Array queue = facility->get(n.k_queue_entries); + const int64_t capacity = facility->get(n.k_capacity); + row[n.k_expected_wait]=signed_product(queue.size(),facility->get(n.k_base_service_minutes))/std::max(capacity,1); + row[n.k_estimated_total_gold]=runtime->call(n.k_get_facility_business_price,facility); + const int64_t quality = facility->get(n.k_base_quality); + row[n.k_expected_quality]=std::max(0,std::min(quality,100)); + row[n.k_need_relief]=relief; + row[n.k_risk_level]=int64_t(0);row[n.k_illegal_level]=int64_t(0); + row[n.k_group_fit]=signed_product(std::min(capacity,4),5); + // Recheck at the original call position: preceding price/observer + // callbacks must retain a replaced/custom runtime's original call. + const bool plain_tag_category = builtin(n,runtime,"res://autoload/simulation_runtime.gd") && + tags.is_typed() && tags.get_typed_builtin()==Variant::STRING_NAME; + row[n.k_service_category]=plain_tag_category ? Variant(builtin_tag_category(n,tags)) : + runtime->call(n.k__service_category_for_tags,tags); + Dictionary handle;handle[n.k_target_cell]=route.get(n.k_target_cell,guest->get(n.k_current_cell)); + handle[n.k_graph_revision]=path->get(n.k_graph_revision); + row[n.k_path_handle]=handle;candidates.push_back(row); + } + path->call(n.k_end_guest_path_query_batch); + Dictionary result;result[n.k_supported]=true;result[n.k_candidates]=candidates;return result; + } +private: + // Direct translation of the two pure builtin tag methods. Fresh result, + // original insertion/branch order, no retained definition/tag memo. + static Dictionary builtin_tag_relief(const ProjectionNames &n,const Array &tags) { + Dictionary relief; + relief[n.k_tagproj_hunger]=int64_t(0);relief[n.k_tagproj_sleep]=int64_t(0); + relief[n.k_tagproj_hygiene]=int64_t(0);relief[n.k_tagproj_medical]=int64_t(0); + relief[n.k_tagproj_leisure]=int64_t(0);relief[n.k_tagproj_intimacy]=int64_t(0); + if(tags.has(n.k_tagproj_dining)) {relief[n.k_tagproj_hunger]=int64_t(80);relief[n.k_tagproj_leisure]=int64_t(10);} + if(tags.has(n.k_tagproj_lodging)) {relief[n.k_tagproj_sleep]=int64_t(90);relief[n.k_tagproj_hygiene]=std::max(int64_t(relief[n.k_tagproj_hygiene]),10);} + if(tags.has(n.k_tagproj_social)||tags.has(n.k_tagproj_leisure)) relief[n.k_tagproj_leisure]=std::max(int64_t(relief[n.k_tagproj_leisure]),40); + if(tags.has(n.k_tagproj_hygiene)||tags.has(n.k_tagproj_bath)) relief[n.k_tagproj_hygiene]=std::max(int64_t(relief[n.k_tagproj_hygiene]),80); + if(tags.has(n.k_tagproj_medical)) relief[n.k_tagproj_medical]=int64_t(90); + else if(tags.has(n.k_tagproj_wellness)) relief[n.k_tagproj_medical]=std::max(int64_t(relief[n.k_tagproj_medical]),20); + if(tags.has(n.k_tagproj_adult_only)||tags.has(n.k_tagproj_restricted_service)) relief[n.k_tagproj_intimacy]=int64_t(80); + return relief; + } + static StringName builtin_tag_category(const ProjectionNames &n,const Array &tags) { + if(tags.has(n.k_tagproj_dining))return n.k_tagproj_food; + if(tags.has(n.k_tagproj_lodging))return n.k_tagproj_lodging; + if(tags.has(n.k_tagproj_social))return n.k_tagproj_leisure; + return n.k_tagproj_service; + } + static bool builtin(const ProjectionNames &n,Object *object,const char *resource) { + if (!object) return false;Object *script=object->get_script(); + return script && String(script->get(n.k_resource_path))==resource; + } + // Exact builtin cache-key spelling. No normalized/reordered profile and no + // persistent cache; String lengths count Unicode codepoints as GDScript does. + static String cache_key_suffix(const ProjectionNames &n,Object *path, const TypedArray &layers, + const TypedArray &access) { + String layer_text, access_text; + for (int64_t i=0; i(layers[i])); + } + for (int64_t i=0; i(access[i])); + access_text += String::num_int64(value.length()) + ":" + value; + } + return String("|L:") + layer_text + "|A:" + access_text + "|R:" + + String::num_int64(static_cast(path->get(n.k_graph_revision))); + } + static String cache_key_with_suffix(const Vector3i &start, const Vector3i &goal, + const String &suffix) { + return String::num_int64(start.x) + "," + String::num_int64(start.y) + "," + + String::num_int64(start.z) + ">" + String::num_int64(goal.x) + "," + + String::num_int64(goal.y) + "," + String::num_int64(goal.z) + suffix; + } + static int64_t signed_product(int64_t a,int64_t b) { + const uint64_t product=static_cast(a)*static_cast(b); + if (product<=static_cast(std::numeric_limits::max())) return static_cast(product); + return std::numeric_limits::min()+static_cast(product-(uint64_t(1)<<63)); + } + static Array facility_access_cells(const ProjectionNames &n,Object *path,Object *facility) { + const Dictionary passable=path->get(n.k__passable_cells); + Array occupied=Array(facility->get(n.k_occupied_cells)).duplicate(); + if (occupied.is_empty()) occupied.push_back(facility->get(n.k_origin)); + Dictionary unique; + for (int64_t i=0;iget(n.k_origin);if(passable.has(origin)) unique[origin]=true; + const Array keys=unique.keys();std::vector sorted;sorted.reserve(keys.size()); + for (int64_t i=0;iget(n.k__guest_step_connector_memo); + // Route-local only. Reuse an ownership result only after an actual + // BOOL return and a typed cached step; no script callback occurs on a + // repeated typed memo hit. A miss/conversion/custom script keeps calls. + const bool builtin_pair = builtin(n,path,"res://scripts/world/path_service.gd") && + builtin(n,elevators,"res://scripts/transport/elevator_service.gd"); + bool ownership_valid = false; + bool ownership_value = false; + StringName ownership_connector; + for(int64_t i=1;i access;connector=path->call(n.k_get_step_connector,from,to,access);} + bool special; + if (builtin_pair && typed_memo_hit && ownership_valid && connector == ownership_connector) { + special = ownership_value; + } else { + const Variant owned = elevators->call(n.k_owns_connector,connector); + special = static_cast(owned); + ownership_valid = builtin_pair && typed_memo_hit && owned.get_type() == Variant::BOOL; + ownership_value = special; + ownership_connector = connector; + } + if(!special && String(connector).begins_with("infra.connector:") && from.x==to.x && from.z==to.z && + std::abs(int64_t(from.y)-int64_t(to.y))==1) { + const Dictionary detail=path->call(n.k_get_connector,connector); + special=detail.get(n.k_movement_type,StringName())==Variant(n.k_CONNECTOR) && + static_cast(detail.get(n.k_cost,int64_t(0)))==150 && stair_credit>movement_scale; + } + if(special) { + const int64_t cost=path->call(n.k_calculate_guest_batch_path_cost,route[0],route[route.size()-1],route); + return static_cast(std::ceil(static_cast(cost)/static_cast(orthogonal_cost))); + } + } + return std::max(route.size()-1,0); + } +public: + + // Stateless translation of the builtin nearest access query. The caller + // supplies the existing typed default profile and the real Time callable. + // Public cache publication, failure diagnostics and fallback stay ordered. + Dictionary nearest_guest_access(Object *path, const Vector3i &start, + const Array &goals, const Vector3i &fallback_target, + const TypedArray &layers, const TypedArray &access, + const Callable &ticks) { + const ProjectionNames n; + return nearest_guest_access_impl(n,path,start,goals,fallback_target,layers,access,ticks); + } +private: + Dictionary nearest_guest_access_impl(const ProjectionNames &n,Object *path, const Vector3i &start, + const Array &goals, const Vector3i &fallback_target, + const TypedArray &layers, const TypedArray &access, + const Callable &ticks) { + Dictionary unsupported; + unsupported[n.k_supported] = false; + if (!path || !ticks.is_valid() || goals.is_empty()) return unsupported; + Object *script = path->get_script(); + if (!script || String(script->get(n.k_resource_path)) != "res://scripts/world/path_service.gd") return unsupported; + Dictionary batch = path->get(n.k__query_batch); + if (batch.is_empty() || start != static_cast(batch[n.k_start])) return unsupported; + const Dictionary passable = path->get(n.k__passable_cells); + if (!passable.has(start) || blocked(n,path, start) || !layers.has(start.z)) return unsupported; + const Dictionary targets = batch[n.k_targets]; + Dictionary cache = path->get(n.k__path_cache); + // Exact builtin validation loop has no callback before ticks.call(). + // Build the unchanged profile/revision suffix lazily at the first key. + String key_suffix; + bool key_suffix_ready = false; + for (int64_t j = 0; j < goals.size(); ++j) { + if (goals[j].get_type() != Variant::VECTOR3I) return unsupported; + const Vector3i cell = goals[j]; + if (!targets.has(cell)) { + const bool searchable = passable.has(cell) && layers.has(cell.z) && !blocked(n,path, cell); + if (searchable && (start.z == cell.z || static_cast(path->call(n.k__guest_batch_has_permitted_layer_crossing, start, cell, layers, access)))) return unsupported; + } + if (!key_suffix_ready) { + key_suffix = cache_key_suffix(n,path, layers, access); + key_suffix_ready = true; + } + const String key = cache_key_with_suffix(start, cell, key_suffix); + if (cache.has(key)) return unsupported; + } + const int64_t started = ticks.call(); + if (!static_cast(batch[n.k_ready])) { + batch[n.k_tree] = path->call(n.k__build_guest_query_tree_compact, start, targets, layers, access); + batch[n.k_arithmetic_wrapped] = path->get(n.k__guest_tree_arithmetic_wrapped); + batch[n.k_ready] = true; + } + const Dictionary tree = batch[n.k_tree]; + if (!static_cast(tree.get(n.k_usable, false)) || static_cast(batch.get(n.k_arithmetic_wrapped, false))) return unsupported; + Vector3i best_cell = fallback_target; + bool found = false; + int64_t best_cost = 0; + const Dictionary settled = tree[n.k_settled]; + for (int64_t j = 0; j < goals.size(); ++j) { + const Vector3i cell = goals[j]; + if (!targets.has(cell) || !settled.has(cell)) continue; + if (!tree_has_cost(n,tree, cell)) return unsupported; + const int64_t cost = tree_cost(n,tree, cell); + if (!found || cost < best_cost) { + found = true; + best_cost = cost; + best_cell = cell; + } + } + TypedArray best_path; + if (found) { + best_path = resolve_ready_guest_point(n,path, start, best_cell, tree, layers, access); + if (best_path.is_empty()) return unsupported; + } + if (!goals.is_empty() && (!found || goals[goals.size() - 1] != Variant(best_cell))) { + resolve_ready_guest_point(n,path, start, goals[goals.size() - 1], tree, layers, access); + } + const int64_t elapsed = the_tree_native::signed_add(static_cast(ticks.call()), the_tree_native::signed_add(~started, 1)); + path->emit_signal(n.k_path_query_measured, std::max(elapsed, 0)); + Dictionary result; + result[n.k_supported] = true; + result[n.k_reachable] = found; + result[n.k_path] = best_path; + result[n.k_target_cell] = best_cell; + return result; + } +private: + static bool blocked(const ProjectionNames &n,Object *path, const Vector3i &cell) { + const Dictionary traffic_map = path->get(n.k__cell_traffic); + const Dictionary traffic = traffic_map.get(cell, Dictionary()); + return !traffic.is_empty() && static_cast(traffic[n.k_temporary_block]); + } + static bool tree_has_cost(const ProjectionNames &n,const Dictionary &tree, const Vector3i &cell) { + if (!static_cast(tree.get(n.k_compact, false))) { + const Dictionary values = tree[n.k_costs]; + return values.has(cell); + } + const Dictionary indices = tree[n.k_indices]; + if (!indices.has(cell)) return false; + const int64_t index = indices[cell]; + const PackedInt64Array values = tree[n.k_cost_values]; + return index >= 0 && index < values.size(); + } + static int64_t tree_cost(const ProjectionNames &n,const Dictionary &tree, const Vector3i &cell) { + if (!static_cast(tree.get(n.k_compact, false))) { + const Dictionary values = tree[n.k_costs]; + return static_cast(values[cell]); + } + const Dictionary indices = tree[n.k_indices]; + const PackedInt64Array values = tree[n.k_cost_values]; + return values[static_cast(indices[cell])]; + } + static TypedArray resolve_ready_guest_point(const ProjectionNames &n,Object *path, + const Vector3i &start, const Vector3i &goal, const Dictionary &tree, + const TypedArray &layers, const TypedArray &access) { + const Dictionary passable = path->get(n.k__passable_cells); + if (!passable.has(start)) return path->call(n.k__route_failure, n.k_START_NOT_PASSABLE); + if (!passable.has(goal)) return path->call(n.k__route_failure, n.k_GOAL_NOT_PASSABLE); + if (!layers.has(start.z) || !layers.has(goal.z)) return path->call(n.k__route_failure, n.k_ACCESS_LAYER_DENIED); + if (blocked(n,path, start)) return path->call(n.k__route_failure, n.k_START_TEMPORARILY_BLOCKED); + if (blocked(n,path, goal)) return path->call(n.k__route_failure, n.k_GOAL_TEMPORARILY_BLOCKED); + // ticks/tree callbacks may have changed the script or revision. Recheck + // at this original call position and never reuse the pre-tick suffix. + const String key = builtin(n,path,"res://scripts/world/path_service.gd") ? + cache_key_with_suffix(start, goal, cache_key_suffix(n,path, layers, access)) : + String(path->call(n.k__cache_key, start, goal, layers, access)); + Dictionary cache = path->get(n.k__path_cache); + const Dictionary batch = path->get(n.k__query_batch); + const Dictionary targets = batch[n.k_targets]; + if (cache.has(key) || !targets.has(goal)) return path->call(n.k__find_path_internal, start, goal); + path->set(n.k_cache_misses, the_tree_native::signed_add(static_cast(path->get(n.k_cache_misses)), 1)); + if (start.z != goal.z && !static_cast(path->call(n.k__guest_batch_has_permitted_layer_crossing, start, goal, layers, access))) return path->call(n.k__route_failure, n.k_GOAL_UNREACHABLE); + TypedArray route; + const Dictionary settled = tree[n.k_settled]; + if (start == goal) route.push_back(start); + else if (settled.has(goal)) route = Array(path->call(n.k__guest_tree_reconstruct_path, tree, goal)); + if (route.is_empty()) return path->call(n.k__route_failure, path->call(n.k__diagnose_no_route_reason, start, goal, layers, access)); + cache[key] = path->call(n.k__copy_path, route); + path->set(n.k_last_no_route_reason, n.k_OK); + path->set(n.k_last_path_cost, tree_cost(n,tree, goal)); + path->set(n.k_last_error, String("")); + return route; + } +public: +private: + // One existing builtin provider operation, with no new value cache. Only + // connector-free WALK rows qualify; unsupported cases call the old provider. + // All work stays private until the original final shared[current] assignment. + struct WalkEdgeNames { + const StringName resource_path{"resource_path",false}, constants_method{"get_script_constant_map",false}; + const StringName front{"FRONT",false}, back{"BACK",false}, walk{"MOVEMENT_WALK",false}; + const StringName base{"ORTHOGONAL_MOVE_COST",false}, congestion{"CONGESTION_COST_PER_EXCESS",false}; + const StringName workspace{"_guest_tree_workspace",false}, edges{"edges",false}, indices{"indices",false}; + const StringName adjacency{"_adjacency",false}, traffic{"_cell_traffic",false}, vertical{"_vertical_walk_requires_connector",false}; + const StringName to{"to",false}, connector{"connector_id",false}, access{"access_id",false}, movement{"movement_type",false}; + const StringName base_cost{"base_cost",false}, cost{"cost",false}, temporary{"temporary_block",false}; + const StringName dynamic{"dynamic_cost",false}, density{"current_density",false}, capacity{"base_capacity",false}; + const StringName provider{"_guest_tree_shared_edges",false}; + }; + struct WalkEdgeContext { + Object *path=nullptr; + int64_t front=0, back=0, base=0, congestion=0; + StringName walk; + }; + static bool walk_edge_context(const WalkEdgeNames &n,Object *path,const Array &layers, + const Array &access,WalkEdgeContext &context) { + if (!path || layers.size()!=2 || !access.is_empty() || + layers[0].get_type()!=Variant::INT || layers[1].get_type()!=Variant::INT) return false; + Object *script=path->get_script(); + if (!script || String(script->get(n.resource_path))!="res://scripts/world/path_service.gd" || + !script->has_method(n.constants_method)) return false; + const Variant value=script->call(n.constants_method); + if (value.get_type()!=Variant::DICTIONARY) return false; + const Dictionary constants=value; + for (const StringName &key : {n.front,n.back,n.base,n.congestion}) + if (constants.get(key,Variant()).get_type()!=Variant::INT) return false; + if (constants.get(n.walk,Variant()).get_type()!=Variant::STRING_NAME || + int64_t(layers[0])!=int64_t(constants[n.front]) || + int64_t(layers[1])!=int64_t(constants[n.back])) return false; + context.path=path;context.front=constants[n.front];context.back=constants[n.back]; + context.base=constants[n.base];context.congestion=constants[n.congestion];context.walk=constants[n.walk]; + return true; + } + static bool builtin_walk_edge_rows(const WalkEdgeNames &n,const WalkEdgeContext &context, + const Vector3i ¤t,Array &rows) { + if (!context.path) return false; + const Variant workspace_value=context.path->get(n.workspace); + if (workspace_value.get_type()!=Variant::DICTIONARY) return false; + const Dictionary workspace=workspace_value; + const Variant shared_value=workspace.get(n.edges,Variant()); + if (shared_value.get_type()!=Variant::DICTIONARY) return false; + Dictionary shared=shared_value; + // Original cached-row branch precedes readonly and all other state reads. + if (shared.has(current)) { + const Variant cached=shared[current]; + if (cached.get_type()!=Variant::ARRAY) return false; + rows=cached;return true; + } + if (shared.is_read_only()) return false; + const Variant indices_value=workspace.get(n.indices,Variant()), adjacency_value=context.path->get(n.adjacency); + const Variant traffic_value=context.path->get(n.traffic), vertical_value=context.path->get(n.vertical); + if (indices_value.get_type()!=Variant::DICTIONARY || adjacency_value.get_type()!=Variant::DICTIONARY || + traffic_value.get_type()!=Variant::DICTIONARY || vertical_value.get_type()!=Variant::BOOL) return false; + const Dictionary indices=indices_value, adjacency=adjacency_value, traffic=traffic_value; + const Variant raw_value=adjacency.get(current,Array()); + if (raw_value.get_type()!=Variant::ARRAY) return false; + const Array raw=raw_value;Array result; + for (int64_t i=0;i0?excess:0,context.congestion)); + } + const int64_t cost=the_tree_native::signed_add(int64_t(base),dynamic); + Array pair;pair.push_back(neighbor);pair.push_back(cost);result.push_back(pair); + // Same short circuit and first invalid prefix as the original method. + if (cost<=0 || !indices.has(neighbor)) break; + } + shared[current]=result;rows=result;return true; + } +public: + Dictionary guest_tree_edge_rows(Object *path,const Vector3i ¤t,const Array &layers,const Array &access) { + const WalkEdgeNames names;WalkEdgeContext context;Array rows; + Dictionary result;const StringName supported{"supported",false}, row_key{"rows",false}; + result[supported]=false; + if (!walk_edge_context(names,path,layers,access,context) || + !builtin_walk_edge_rows(names,context,current,rows)) return result; + result[supported]=true;result[row_key]=rows;return result; + } +private: + Dictionary search_impl(const Array &cells, const Dictionary &indices, I start_index, + const Dictionary &goals, const Callable &edge_provider, bool use_edge_cache) { + Dictionary output; + output[StringName("status")] = String("unusable"); + if (start_index < 0 || start_index >= cells.size() || !edge_provider.is_valid()) return output; + try { + std::vector goal_indices; + const Array goal_keys = goals.keys(); + for (I j = 0; j < goal_keys.size(); ++j) + goal_indices.push_back(static_cast(indices.get(goal_keys[j], I(-1)))); + Array arguments; + arguments.resize(1); + const WalkEdgeNames walk_names;WalkEdgeContext walk_context; + if (edge_provider.get_method()==walk_names.provider && edge_provider.get_argument_count()==1 && + edge_provider.get_bound_arguments_count()==2 && edge_provider.get_unbound_arguments_count()==0) { + const Array bound=edge_provider.get_bound_arguments(); + if (bound.size()==2 && bound[0].get_type()==Variant::ARRAY && bound[1].get_type()==Variant::ARRAY) + walk_edge_context(walk_names,edge_provider.get_object(),bound[0],bound[1],walk_context); + } + // Call the original bound Godot edge method only when the search expands a node. + // Preserve its lazy cache population, filter ordering and first invalid row. + auto original_edges = [&](I current) { + arguments[0] = cells[current]; + Array fused;bool fused_supported=false; + if (cells[current].get_type()==Variant::VECTOR3I) { + const Vector3i cell=cells[current]; + fused_supported=builtin_walk_edge_rows(walk_names,walk_context,cell,fused); + } + const Variant value = fused_supported ? Variant(fused) : edge_provider.callv(arguments); + if (value.get_type() != Variant::ARRAY) return std::vector{{-1, 0}}; + const Array rows = value; + std::vector result; + result.reserve(rows.size()); + for (I j = 0; j < rows.size(); ++j) { + if (rows[j].get_type() != Variant::ARRAY) { result.push_back({-1, 0}); break; } + const Array row = rows[j]; + if (row.size() != 2 || row[1].get_type() != Variant::INT) { + result.push_back({-1, 0}); break; + } + const I cost = static_cast(row[1]); + // Nonpositive cost is rejected before requesting the neighbor index. + if (cost <= 0) { result.push_back({-1, cost}); break; } + const I neighbor = static_cast(indices.get(row[0], I(-1))); + result.push_back({neighbor, cost}); + if (neighbor < 0) break; + } + return result; + }; + auto edges = [&](I current) { + if (!use_edge_cache) return original_edges(current); + const auto found = cached_edges.find(current); + if (found != cached_edges.end()) return found->second; + // Populate only when the old algorithm expands this same node. + // Retain original provider validation and first-invalid prefix. + auto converted = original_edges(current); + cached_edges.emplace(current, converted); + return converted; + }; + const auto result = the_tree_native::search(cells.size(), start_index, goal_indices, edges); + output[StringName("status")] = String(result.status.c_str()); + if (result.status != "usable") return output; + PackedInt64Array costs, parents; + if (costs.resize(result.costs.size()) != OK || parents.resize(result.parents.size()) != OK) { + output[StringName("status")] = String("unusable"); + return output; + } + for (I j = 0; j < cells.size(); ++j) { costs.set(j, result.costs[j]); parents.set(j, result.parents[j]); } + TypedArray discovered, parent_discovered; + for (I j : result.discovered) discovered.push_back(j); + for (I j : result.parent_discovered) parent_discovered.push_back(j); + Dictionary settled; + for (I j : result.settled) settled[cells[j]] = true; + output[StringName("cost_values")] = costs; + output[StringName("parent_indices")] = parents; + output[StringName("discovered")] = discovered; + output[StringName("parent_discovered")] = parent_discovered; + output[StringName("settled")] = settled; + return output; + } catch (const std::exception &) { + output = Dictionary(); + output[StringName("status")] = String("unusable"); + return output; + } + } +}; + +void initialize_tree_numeric_core(ModuleInitializationLevel level) { + if (level == MODULE_INITIALIZATION_LEVEL_SCENE) GDREGISTER_CLASS(TheTreeNumericCore); +} +void uninitialize_tree_numeric_core(ModuleInitializationLevel) {} + +extern "C" { +GDExtensionBool GDE_EXPORT tree_numeric_core_init(GDExtensionInterfaceGetProcAddress get_proc, + GDExtensionClassLibraryPtr library, GDExtensionInitialization *initialization) { + GDExtensionBinding::InitObject init(get_proc, library, initialization); + init.register_initializer(initialize_tree_numeric_core); + init.register_terminator(uninitialize_tree_numeric_core); + init.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE); + return init.init(); +} +} diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/manifest.json b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/manifest.json new file mode 100644 index 0000000..a2a66b2 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/manifest.json @@ -0,0 +1,119 @@ +{ + "schema": 1, + "plan_id": "P23-02", + "candidate": "r285-r02", + "base_ledger_commit": "21d89b988d360269321d79a23f011858777e2fbf", + "scope": "Development source and finite static evidence checkpoint, not production adoption or acceptance", + "static_review_accepted": true, + "build_preexecution_review_accepted": true, + "build_executed": false, + "engine_executed": false, + "performance_accepted": false, + "candidate_adopted": false, + "unit_accepted": false, + "completed_units_added": 0, + "files": [ + { + "checkpoint_path": "source/tree_numeric_core.cpp", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_numeric_core.cpp", + "bytes": 59396, + "sha256": "75bc2f659f62889fccac5990461f5b51e8b87f30ca0791e4a4c542d37a7c5236" + }, + { + "checkpoint_path": "source/tree_core.hpp", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_core.hpp", + "bytes": 3299, + "sha256": "be46852fe55aeee4e18996b4d87222662b031fd1b946977c81092f4d0707e480" + }, + { + "checkpoint_path": "source/input.json", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/input.json", + "bytes": 4325, + "sha256": "38fb6adc0ec74c0f37631da3f1ddecf185879be9655574a920f1c12566beaa8f" + }, + { + "checkpoint_path": "parent-r274/tree_numeric_core.cpp", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_numeric_core.cpp", + "bytes": 54002, + "sha256": "ce20a90adb8a410dc1b6cbf607b7bfa8bf21eaef158c5c6bfc7a9bbcc703d2b2" + }, + { + "checkpoint_path": "parent-r274/tree_core.hpp", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-pure-tag-projection-candidate-r274/source/tree_core.hpp", + "bytes": 3299, + "sha256": "be46852fe55aeee4e18996b4d87222662b031fd1b946977c81092f4d0707e480" + }, + { + "checkpoint_path": "history-r285/tree_numeric_core.cpp", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285/source/tree_numeric_core.cpp", + "bytes": 59281, + "sha256": "2edd9d6d782cd4072272f0c24b50ce74691899c5a4bbc9ccc946a991217d814a" + }, + { + "checkpoint_path": "history-r285/static-review.json", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-independent-review-r285.json", + "bytes": 9547, + "sha256": "c3f3525ee6b172bcbbc79838d49beac137d2dbd86deb61cdbefc1a921e743f06" + }, + { + "checkpoint_path": "evidence/static-review-r285-r02.json", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-independent-review-r285-r02.json", + "bytes": 10950, + "sha256": "bffbdcb491ba0aa68eeac764228c04418d2ef3834624cb1fcb98db773e8369fd" + }, + { + "checkpoint_path": "evidence/static-root-verification-r285-r02.json", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-static-root-verification-r285-r02.json", + "bytes": 4849, + "sha256": "27b0b957737d79a3047f2b2a8fa936ac0ec368414d61bb6f097a524a3fd27ead" + }, + { + "checkpoint_path": "evidence/build-preexecution-review-r286.json", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-build-preexecution-independent-review-r286.json", + "bytes": 19698, + "sha256": "f3fab769c0baeacbec945e745debaf16c78dfed134bffa33af4683d1779ec72f" + }, + { + "checkpoint_path": "reference/marshalls.cpp", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/marshalls.cpp", + "bytes": 55439, + "sha256": "183c43e46d3e4b73c0fb1fc8018da37faeb88c7414dd928b1fb6ff4f4a91a374" + }, + { + "checkpoint_path": "reference/source.json", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-integer-window-codec-source-r284/source.json", + "bytes": 585, + "sha256": "cbdfe256f152bc8f0c44b849848a94e3eec1e84d6a55f5da69188a6430a148a9" + }, + { + "checkpoint_path": "dependencies/performance_budget.candidate.gd", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-budget-record-candidate-r257-r04/performance_budget.candidate.gd", + "bytes": 11250, + "sha256": "1010129d3124c3aec037c840a5766a7cdabe60c654999dfb6f23b224140a73f8" + }, + { + "checkpoint_path": "preparation/prepare-r285.py", + "original_path": "/private/tmp/thetree-prepare-integer-window-codec-r285.py", + "bytes": 8488, + "sha256": "ef011afc1f7a8d590330ab9f24bbd973b5bdda6e1923675f55c4f4c83ed9d93b" + }, + { + "checkpoint_path": "preparation/prepare-r285-r02.py", + "original_path": "/private/tmp/thetree-prepare-integer-window-codec-r285-r02.py", + "bytes": 8607, + "sha256": "7316b5b10bc65f7e286b66940767175f1f6b07182b84c8c2b326907bc668f9b5" + }, + { + "checkpoint_path": "preparation/build-r286.py", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-build-r286.py", + "bytes": 16592, + "sha256": "14bdaa2dcfab62f594fcb95a9ead5bc6defbc35e727fbb0de46a7494af780e3a" + }, + { + "checkpoint_path": "preparation/build-preview-r286.json", + "original_path": "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-build-preview-r286.json", + "bytes": 3402, + "sha256": "cba922a40684eaf3206c17ac8eaa588b04015a9f09d0dbc5f79a16bf7f4159b2" + } + ] +} diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/parent-r274/tree_core.hpp b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/parent-r274/tree_core.hpp new file mode 100644 index 0000000..a440355 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/parent-r274/tree_core.hpp @@ -0,0 +1,75 @@ +#pragma once +// Standalone numeric prototype; not connected to Godot or production. +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace the_tree_native { +using I = std::int64_t; +struct Edge { I neighbor, cost; }; +struct Result { + std::string status = "usable"; + std::vector costs, parents, discovered, parent_discovered, settled; +}; +I signed_add(I a, I b) { + const auto sum = static_cast(a) + static_cast(b); + if (sum <= static_cast(std::numeric_limits::max())) return static_cast(sum); + return std::numeric_limits::min() + static_cast(sum - (std::uint64_t(1) << 63)); +} +template +Result search(I n, I start, const std::vector& goals, EdgeProvider&& edge_provider) { + Result r; + if (start < 0 || start >= n) { r.status = "unusable"; return r; } + r.costs.assign(n, std::numeric_limits::max()); + r.parents.assign(n, -1); + std::vector finalized(n, 0), pending(n, 0); + bool unknown_goal = false; + I remaining = 0; + for (I goal : goals) { + if (goal < 0 || goal >= n) { unknown_goal = true; continue; } + if (!pending[goal]) { pending[goal] = 1; ++remaining; } + } + r.costs[start] = 0; r.discovered.push_back(start); + std::map> frontier; + frontier[0].push_back(start); + while (!frontier.empty()) { + auto it = frontier.begin(); + const I entry_cost = it->first; + auto active = std::move(it->second); + frontier.erase(it); + std::sort(active.begin(), active.end()); + for (I current : active) { + if (finalized[current] || entry_cost != r.costs[current]) continue; + finalized[current] = 1; + r.settled.push_back(current); + if (pending[current]) { pending[current] = 0; --remaining; } + if (!remaining && !unknown_goal) return r; + for (const Edge& edge : edge_provider(current)) { + if (edge.cost <= 0) { r.status = "unusable"; return r; } + const I neighbor = edge.neighbor; + if (neighbor < 0 || neighbor >= n) { r.status = "unusable"; return r; } + const I cost = signed_add(r.costs[current], edge.cost); + if (cost < r.costs[current]) { r.status = "wrapped"; return r; } + const I known = r.costs[neighbor]; + const bool better_parent = cost == known && r.parents[neighbor] >= 0 && current < r.parents[neighbor]; + if (cost > known || (cost == known && !better_parent)) continue; + if (r.parents[neighbor] < 0) { + r.parent_discovered.push_back(neighbor); + if (neighbor != start) r.discovered.push_back(neighbor); + } + r.parents[neighbor] = current; + r.costs[neighbor] = cost; + if (finalized[neighbor]) r.settled.erase(std::remove(r.settled.begin(), r.settled.end(), neighbor), r.settled.end()); + finalized[neighbor] = 0; + frontier[cost].push_back(neighbor); + } + } + } + return r; +} +} // namespace the_tree_native diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/parent-r274/tree_numeric_core.cpp b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/parent-r274/tree_numeric_core.cpp new file mode 100644 index 0000000..d6efbbb --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/parent-r274/tree_numeric_core.cpp @@ -0,0 +1,823 @@ +// Isolated, uncompiled bridge prototype. No production registration or integration yet. +#include "tree_core.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace godot; +using the_tree_native::I; +using the_tree_native::Edge; + +class TheTreeNumericCore : public RefCounted { + GDCLASS(TheTreeNumericCore, RefCounted) +protected: + static void _bind_methods() { + ClassDB::bind_method(D_METHOD("performance_record_sample", "owner", "metric_id", "duration_us"), &TheTreeNumericCore::performance_record_sample); + ClassDB::bind_method(D_METHOD("guest_tree_edge_rows", "path", "current", "layers", "access"), &TheTreeNumericCore::guest_tree_edge_rows); + ClassDB::bind_method(D_METHOD("search", "cells", "indices", "start_index", "goals", "edge_provider"), &TheTreeNumericCore::search); + ClassDB::bind_method(D_METHOD("search_cached", "cells", "indices", "start_index", "goals", "edge_provider"), &TheTreeNumericCore::search_cached); + ClassDB::bind_method(D_METHOD("clear_edge_cache"), &TheTreeNumericCore::clear_edge_cache); + ClassDB::bind_method(D_METHOD("nearest_guest_access", "path", "start", "goals", "fallback_target", "layers", "access", "ticks"), &TheTreeNumericCore::nearest_guest_access); + ClassDB::bind_method(D_METHOD("project_guest_candidates", "runtime", "guest_id", "open_state", "degraded_state", "movement_scale", "stair_credit", "orthogonal_cost", "ticks"), &TheTreeNumericCore::project_guest_candidates); + } +private: + // Cache belongs to this instance and one caller-owned graph workspace. + // No reuse after cells, indices, filters or edge values change: the caller + // must clear it or release this core. The original search never uses it. + std::map> cached_edges; + // Per-public-call immutable names. No static/global lifetime, cached + // object values, script dispatch result or profile; recursive calls own + // separate scopes. Destruction precedes leaving the engine call. + struct ProjectionNames { + const StringName k_ACCESS_LAYER_DENIED{"ACCESS_LAYER_DENIED",false}; + const StringName k_CONNECTOR{"CONNECTOR",false}; + const StringName k_GOAL_NOT_PASSABLE{"GOAL_NOT_PASSABLE",false}; + const StringName k_GOAL_TEMPORARILY_BLOCKED{"GOAL_TEMPORARILY_BLOCKED",false}; + const StringName k_GOAL_UNREACHABLE{"GOAL_UNREACHABLE",false}; + const StringName k_OK{"OK",false}; + const StringName k_START_NOT_PASSABLE{"START_NOT_PASSABLE",false}; + const StringName k_START_TEMPORARILY_BLOCKED{"START_TEMPORARILY_BLOCKED",false}; + const StringName k__build_guest_query_tree_compact{"_build_guest_query_tree_compact",false}; + const StringName k__cache_key{"_cache_key",false}; + const StringName k__cell_traffic{"_cell_traffic",false}; + const StringName k__copy_path{"_copy_path",false}; + const StringName k__diagnose_no_route_reason{"_diagnose_no_route_reason",false}; + const StringName k__find_facility_access_path{"_find_facility_access_path",false}; + const StringName k__find_path_internal{"_find_path_internal",false}; + const StringName k__guest_access_batch_can_select{"_guest_access_batch_can_select",false}; + const StringName k__guest_batch_has_permitted_layer_crossing{"_guest_batch_has_permitted_layer_crossing",false}; + const StringName k__guest_has_checked_in{"_guest_has_checked_in",false}; + const StringName k__guest_step_connector_memo{"_guest_step_connector_memo",false}; + const StringName k__guest_tree_arithmetic_wrapped{"_guest_tree_arithmetic_wrapped",false}; + const StringName k__guest_tree_reconstruct_path{"_guest_tree_reconstruct_path",false}; + const StringName k__need_relief_for_facility_tags{"_need_relief_for_facility_tags",false}; + const StringName k__passable_cells{"_passable_cells",false}; + const StringName k__path_cache{"_path_cache",false}; + const StringName k__query_batch{"_query_batch",false}; + const StringName k__route_failure{"_route_failure",false}; + const StringName k__service_category_for_tags{"_service_category_for_tags",false}; + const StringName k__sorted_name_keys{"_sorted_name_keys",false}; + const StringName k_arithmetic_wrapped{"arithmetic_wrapped",false}; + const StringName k_available_quantity{"available_quantity",false}; + const StringName k_base_quality{"base_quality",false}; + const StringName k_base_service_minutes{"base_service_minutes",false}; + const StringName k_begin_guest_path_query_batch{"begin_guest_path_query_batch",false}; + const StringName k_cache_misses{"cache_misses",false}; + const StringName k_calculate_guest_batch_path_cost{"calculate_guest_batch_path_cost",false}; + const StringName k_candidates{"candidates",false}; + const StringName k_capacity{"capacity",false}; + const StringName k_compact{"compact",false}; + const StringName k_cost{"cost",false}; + const StringName k_cost_values{"cost_values",false}; + const StringName k_costs{"costs",false}; + const StringName k_current_cell{"current_cell",false}; + const StringName k_definition_id{"definition_id",false}; + const StringName k_definition_registry{"definition_registry",false}; + const StringName k_elevators{"elevators",false}; + const StringName k_end_guest_path_query_batch{"end_guest_path_query_batch",false}; + const StringName k_entrance{"entrance",false}; + const StringName k_estimated_total_gold{"estimated_total_gold",false}; + const StringName k_expected_quality{"expected_quality",false}; + const StringName k_expected_wait{"expected_wait",false}; + const StringName k_facility_id{"facility_id",false}; + const StringName k_facility_service{"facility_service",false}; + const StringName k_facility_tags{"facility_tags",false}; + const StringName k_get_connector{"get_connector",false}; + const StringName k_get_facility{"get_facility",false}; + const StringName k_get_facility_business_price{"get_facility_business_price",false}; + const StringName k_get_guest{"get_guest",false}; + const StringName k_get_instances{"get_instances",false}; + const StringName k_get_step_connector{"get_step_connector",false}; + const StringName k_graph_revision{"graph_revision",false}; + const StringName k_group_fit{"group_fit",false}; + const StringName k_guest_service{"guest_service",false}; + const StringName k_illegal_level{"illegal_level",false}; + const StringName k_indices{"indices",false}; + const StringName k_inputs_available{"inputs_available",false}; + const StringName k_instance_id{"instance_id",false}; + const StringName k_inventory_inputs{"inventory_inputs",false}; + const StringName k_inventory_service{"inventory_service",false}; + const StringName k_is_open{"is_open",false}; + const StringName k_last_error{"last_error",false}; + const StringName k_last_no_route_reason{"last_no_route_reason",false}; + const StringName k_last_path_cost{"last_path_cost",false}; + const StringName k_local_inventory_id{"local_inventory_id",false}; + const StringName k_movement_type{"movement_type",false}; + const StringName k_need_relief{"need_relief",false}; + const StringName k_occupied_cells{"occupied_cells",false}; + const StringName k_origin{"origin",false}; + const StringName k_owns_connector{"owns_connector",false}; + const StringName k_path{"path",false}; + const StringName k_path_handle{"path_handle",false}; + const StringName k_path_query_measured{"path_query_measured",false}; + const StringName k_path_service{"path_service",false}; + const StringName k_queue_entries{"queue_entries",false}; + const StringName k_reachable{"reachable",false}; + const StringName k_ready{"ready",false}; + const StringName k_resource_path{"resource_path",false}; + const StringName k_risk_level{"risk_level",false}; + const StringName k_service_category{"service_category",false}; + const StringName k_settled{"settled",false}; + const StringName k_staff_only{"staff_only",false}; + const StringName k_start{"start",false}; + const StringName k_state{"state",false}; + const StringName k_supported{"supported",false}; + const StringName k_tags{"tags",false}; + const StringName k_tagproj_hunger{"hunger",false}; + const StringName k_tagproj_sleep{"sleep",false}; + const StringName k_tagproj_hygiene{"hygiene",false}; + const StringName k_tagproj_medical{"medical",false}; + const StringName k_tagproj_leisure{"leisure",false}; + const StringName k_tagproj_intimacy{"intimacy",false}; + const StringName k_tagproj_dining{"dining",false}; + const StringName k_tagproj_lodging{"lodging",false}; + const StringName k_tagproj_social{"social",false}; + const StringName k_tagproj_bath{"bath",false}; + const StringName k_tagproj_wellness{"wellness",false}; + const StringName k_tagproj_adult_only{"adult_only",false}; + const StringName k_tagproj_restricted_service{"restricted_service",false}; + const StringName k_tagproj_food{"food",false}; + const StringName k_tagproj_service{"service",false}; + const StringName k_target_cell{"target_cell",false}; + const StringName k_targets{"targets",false}; + const StringName k_temporary_block{"temporary_block",false}; + const StringName k_travel_minutes{"travel_minutes",false}; + const StringName k_tree{"tree",false}; + const StringName k_usable{"usable",false}; + }; +public: + // Whole builtin integer record operation. No retained sample values or time + // suppression. Unsupported data returns before any caller-owned mutation. + Dictionary performance_record_sample(Object *owner, const StringName &metric, int64_t duration) { + const StringName supported("supported",false), report_key("report",false); + Dictionary unsupported; unsupported[supported]=false; + Object *script=owner ? owner->get_script() : nullptr; + if (!script || String(script->get(StringName("resource_path",false))) != "res://scripts/core/performance_budget.gd" || metric==StringName() || duration<0) return unsupported; + const StringName samples_key("_samples",false), ordered_key("_ordered_samples",false), bytes_key("_ordered_sample_bytes",false), integer_key("_integer_window_bytes",false), totals_key("_totals",false), counts_key("_sample_counts",false), budgets_key("_budgets",false); + const Variant sv=owner->get(samples_key), ov=owner->get(ordered_key), bv=owner->get(bytes_key), iv=owner->get(integer_key), tv=owner->get(totals_key), cv=owner->get(counts_key), uv=owner->get(budgets_key), capacityv=owner->get(StringName("sample_capacity",false)); + if (sv.get_type()!=Variant::DICTIONARY || ov.get_type()!=Variant::DICTIONARY || bv.get_type()!=Variant::DICTIONARY || iv.get_type()!=Variant::DICTIONARY || tv.get_type()!=Variant::DICTIONARY || cv.get_type()!=Variant::DICTIONARY || uv.get_type()!=Variant::DICTIONARY || capacityv.get_type()!=Variant::INT) return unsupported; + Dictionary samples=sv, orders=ov, rawbytes=bv, integers=iv, totals=tv, counts=cv, budgets=uv; + if (samples.is_read_only() || orders.is_read_only() || rawbytes.is_read_only() || integers.is_read_only() || totals.is_read_only() || counts.is_read_only()) return unsupported; + const std::vector maps{samples,orders,rawbytes,integers,totals,counts,budgets}; + for (size_t i=0;i ordered; + Variant savedbytes=rawbytes.get(metric,PackedByteArray()); + bool reuse=existing && orders.has(metric) && savedbytes.get_type()==Variant::PACKED_BYTE_ARRAY && PackedByteArray(savedbytes)==before; + if (reuse) { + Variant orderv=orders[metric]; + if (orderv.get_type()!=Variant::ARRAY) return unsupported; + Array prior=orderv; + if (prior.is_read_only() || !prior.is_typed() || prior.get_typed_builtin()!=Variant::INT || prior.size()!=values.size()) return unsupported; + ordered=prior; + } else { + for (int64_t i=0;iint64_t(capacityv)) { + Variant removed=values.pop_front(); + ordered.remove_at(ordered.bsearch(removed)); + } + PackedByteArray after=UtilityFunctions::var_to_bytes(values); + rawbytes[metric]=after; integers[metric]=after; + const int64_t lifetime_total=the_tree_native::signed_add(int64_t(totalv),duration); + const int64_t lifetime_count=the_tree_native::signed_add(int64_t(countv),1); + totals[metric]=lifetime_total; counts[metric]=lifetime_count; + const int64_t average=lifetime_count>0 ? lifetime_total/lifetime_count : 0; + const int64_t maximum=ordered.is_empty() ? 0 : std::max(0,int64_t(ordered[ordered.size()-1])); + int64_t p95=0; + if (!ordered.is_empty()) { + const int64_t index=std::max(the_tree_native::signed_add(the_tree_native::signed_add(signed_product(95,ordered.size()),99)/100,-1),0); + p95=ordered[std::min(index,ordered.size()-1)]; + } + const int64_t aggregation=aggregationv, limit=limitv; + // Original default match is P95, including unknown aggregation values. + const int64_t measured=aggregation==0 ? average : (aggregation==2 ? maximum : p95); + Dictionary report; + report[StringName("metric_id",false)]=metric; + report[StringName("window_sample_count",false)]=values.size(); + report[StringName("lifetime_sample_count",false)]=lifetime_count; + report[StringName("average_us",false)]=average; + report[StringName("p95_us",false)]=p95; + report[StringName("maximum_us",false)]=maximum; + report[aggregation_key]=aggregation; + report[StringName("measured_us",false)]=measured; + report[limit_key]=limit; + report[StringName("budget_exceeded",false)]=limit>0 && measured>limit; + Dictionary result; result[supported]=true; result[report_key]=report; return result; + } + void clear_edge_cache() { cached_edges.clear(); } + Dictionary search(const Array &cells, const Dictionary &indices, I start_index, + const Dictionary &goals, const Callable &edge_provider) { + return search_impl(cells, indices, start_index, goals, edge_provider, false); + } + Dictionary search_cached(const Array &cells, const Dictionary &indices, I start_index, + const Dictionary &goals, const Callable &edge_provider) { + return search_impl(cells, indices, start_index, goals, edge_provider, true); + } + // One ordered projection, with no new persistent ownership/cache. Only + // builtin pure getters and the already guarded sole budget observer qualify. + Dictionary project_guest_candidates(Object *runtime, const StringName &guest_id, + int64_t open_state, int64_t degraded_state, int64_t movement_scale, + int64_t stair_credit, int64_t orthogonal_cost, const Callable &ticks) { + const ProjectionNames n; + Dictionary unsupported; + unsupported[n.k_supported] = false; + if (!builtin(n,runtime, "res://autoload/simulation_runtime.gd") || !ticks.is_valid()) return unsupported; + Object *path = runtime->get(n.k_path_service); + Object *elevators = runtime->get(n.k_elevators); + Object *facilities = runtime->get(n.k_facility_service); + Object *definitions = runtime->get(n.k_definition_registry); + Object *inventory = runtime->get(n.k_inventory_service); + Object *guests = runtime->get(n.k_guest_service); + if (!builtin(n,path,"res://scripts/world/path_service.gd") || + !builtin(n,elevators,"res://scripts/transport/elevator_service.gd") || + !builtin(n,facilities,"res://scripts/facility/facility_service.gd") || + !builtin(n,definitions,"res://scripts/core/definition_registry.gd") || + !builtin(n,inventory,"res://scripts/inventory/inventory_service.gd") || + !builtin(n,guests,"res://scripts/guest/guest_service.gd") || + !static_cast(runtime->call(n.k__guest_access_batch_can_select))) return unsupported; + Object *guest = guests->call(n.k_get_guest,guest_id); + Array candidates; + if (!guest) { + Dictionary result; result[n.k_supported] = true; + result[n.k_candidates] = candidates; return result; + } + if (!builtin(n,guest,"res://scripts/guest/guest_runtime.gd")) return unsupported; + const Array initial = facilities->call(n.k_get_instances); + // Preflight is read-only: default registry/get_instances have no public + // error/counter effects. Custom resources retain the original whole loop. + for (int64_t i=0;icall(n.k_get_facility,facility->get(n.k_definition_id)); + if (definition && !builtin(n,definition,"res://scripts/data/facility_definition.gd")) return unsupported; + } + Array goals; + for (int64_t i=0;iget(n.k_current_cell); + path->call(n.k_begin_guest_path_query_batch,start,goals); + const Array ordered = facilities->call(n.k_get_instances); + TypedArray layers; layers.push_back(0); layers.push_back(1); + TypedArray access_ids; + for (int64_t i=0;icall(n.k_get_facility,facility->get(n.k_definition_id)); + if (!definition) continue; + const Array tags = definition->get(n.k_tags); + if (tags.has(n.k_staff_only)) continue; + if (tags.has(n.k_entrance) && static_cast(runtime->call(n.k__guest_has_checked_in,guest))) continue; + bool has_inputs = true; + const Dictionary inputs = definition->get(n.k_inventory_inputs); + const Array items = runtime->call(n.k__sorted_name_keys,inputs); + for (int64_t j=0;jcall(n.k_available_quantity,facility->get(n.k_local_inventory_id),items[j]); + if (quantity < static_cast(inputs[items[j]])) {has_inputs=false;break;} + } + if (!has_inputs) { + Dictionary row;row[n.k_facility_id]=facility->get(n.k_instance_id); + row[n.k_inputs_available]=false;candidates.push_back(row);continue; + } + const Array destinations = facility_access_cells(n,path,facility); + Dictionary route = nearest_guest_access_impl(n,path,start,destinations,facility->get(n.k_origin),layers,access_ids,ticks); + if (static_cast(route.get(n.k_supported,false))) route.erase(n.k_supported); + else route = Dictionary(runtime->call(n.k__find_facility_access_path,start,facility)); + const Array walk = route.get(n.k_path,Array()); + const bool plain_tag_relief = builtin(n,runtime,"res://autoload/simulation_runtime.gd") && + tags.is_typed() && tags.get_typed_builtin()==Variant::STRING_NAME; + const Dictionary relief = plain_tag_relief ? builtin_tag_relief(n,tags) : + Dictionary(runtime->call(n.k__need_relief_for_facility_tags,tags)); + Dictionary row; + row[n.k_facility_id]=facility->get(n.k_instance_id); + row[n.k_facility_tags]=tags.duplicate(); + const int64_t state = facility->get(n.k_state); + row[n.k_is_open]=(state==open_state || state==degraded_state); + row[n.k_reachable]=route.get(n.k_reachable,false); + row[n.k_travel_minutes]=guest_path_minutes(n,path,elevators,walk,movement_scale,stair_credit,orthogonal_cost); + const Array queue = facility->get(n.k_queue_entries); + const int64_t capacity = facility->get(n.k_capacity); + row[n.k_expected_wait]=signed_product(queue.size(),facility->get(n.k_base_service_minutes))/std::max(capacity,1); + row[n.k_estimated_total_gold]=runtime->call(n.k_get_facility_business_price,facility); + const int64_t quality = facility->get(n.k_base_quality); + row[n.k_expected_quality]=std::max(0,std::min(quality,100)); + row[n.k_need_relief]=relief; + row[n.k_risk_level]=int64_t(0);row[n.k_illegal_level]=int64_t(0); + row[n.k_group_fit]=signed_product(std::min(capacity,4),5); + // Recheck at the original call position: preceding price/observer + // callbacks must retain a replaced/custom runtime's original call. + const bool plain_tag_category = builtin(n,runtime,"res://autoload/simulation_runtime.gd") && + tags.is_typed() && tags.get_typed_builtin()==Variant::STRING_NAME; + row[n.k_service_category]=plain_tag_category ? Variant(builtin_tag_category(n,tags)) : + runtime->call(n.k__service_category_for_tags,tags); + Dictionary handle;handle[n.k_target_cell]=route.get(n.k_target_cell,guest->get(n.k_current_cell)); + handle[n.k_graph_revision]=path->get(n.k_graph_revision); + row[n.k_path_handle]=handle;candidates.push_back(row); + } + path->call(n.k_end_guest_path_query_batch); + Dictionary result;result[n.k_supported]=true;result[n.k_candidates]=candidates;return result; + } +private: + // Direct translation of the two pure builtin tag methods. Fresh result, + // original insertion/branch order, no retained definition/tag memo. + static Dictionary builtin_tag_relief(const ProjectionNames &n,const Array &tags) { + Dictionary relief; + relief[n.k_tagproj_hunger]=int64_t(0);relief[n.k_tagproj_sleep]=int64_t(0); + relief[n.k_tagproj_hygiene]=int64_t(0);relief[n.k_tagproj_medical]=int64_t(0); + relief[n.k_tagproj_leisure]=int64_t(0);relief[n.k_tagproj_intimacy]=int64_t(0); + if(tags.has(n.k_tagproj_dining)) {relief[n.k_tagproj_hunger]=int64_t(80);relief[n.k_tagproj_leisure]=int64_t(10);} + if(tags.has(n.k_tagproj_lodging)) {relief[n.k_tagproj_sleep]=int64_t(90);relief[n.k_tagproj_hygiene]=std::max(int64_t(relief[n.k_tagproj_hygiene]),10);} + if(tags.has(n.k_tagproj_social)||tags.has(n.k_tagproj_leisure)) relief[n.k_tagproj_leisure]=std::max(int64_t(relief[n.k_tagproj_leisure]),40); + if(tags.has(n.k_tagproj_hygiene)||tags.has(n.k_tagproj_bath)) relief[n.k_tagproj_hygiene]=std::max(int64_t(relief[n.k_tagproj_hygiene]),80); + if(tags.has(n.k_tagproj_medical)) relief[n.k_tagproj_medical]=int64_t(90); + else if(tags.has(n.k_tagproj_wellness)) relief[n.k_tagproj_medical]=std::max(int64_t(relief[n.k_tagproj_medical]),20); + if(tags.has(n.k_tagproj_adult_only)||tags.has(n.k_tagproj_restricted_service)) relief[n.k_tagproj_intimacy]=int64_t(80); + return relief; + } + static StringName builtin_tag_category(const ProjectionNames &n,const Array &tags) { + if(tags.has(n.k_tagproj_dining))return n.k_tagproj_food; + if(tags.has(n.k_tagproj_lodging))return n.k_tagproj_lodging; + if(tags.has(n.k_tagproj_social))return n.k_tagproj_leisure; + return n.k_tagproj_service; + } + static bool builtin(const ProjectionNames &n,Object *object,const char *resource) { + if (!object) return false;Object *script=object->get_script(); + return script && String(script->get(n.k_resource_path))==resource; + } + // Exact builtin cache-key spelling. No normalized/reordered profile and no + // persistent cache; String lengths count Unicode codepoints as GDScript does. + static String cache_key_suffix(const ProjectionNames &n,Object *path, const TypedArray &layers, + const TypedArray &access) { + String layer_text, access_text; + for (int64_t i=0; i(layers[i])); + } + for (int64_t i=0; i(access[i])); + access_text += String::num_int64(value.length()) + ":" + value; + } + return String("|L:") + layer_text + "|A:" + access_text + "|R:" + + String::num_int64(static_cast(path->get(n.k_graph_revision))); + } + static String cache_key_with_suffix(const Vector3i &start, const Vector3i &goal, + const String &suffix) { + return String::num_int64(start.x) + "," + String::num_int64(start.y) + "," + + String::num_int64(start.z) + ">" + String::num_int64(goal.x) + "," + + String::num_int64(goal.y) + "," + String::num_int64(goal.z) + suffix; + } + static int64_t signed_product(int64_t a,int64_t b) { + const uint64_t product=static_cast(a)*static_cast(b); + if (product<=static_cast(std::numeric_limits::max())) return static_cast(product); + return std::numeric_limits::min()+static_cast(product-(uint64_t(1)<<63)); + } + static Array facility_access_cells(const ProjectionNames &n,Object *path,Object *facility) { + const Dictionary passable=path->get(n.k__passable_cells); + Array occupied=Array(facility->get(n.k_occupied_cells)).duplicate(); + if (occupied.is_empty()) occupied.push_back(facility->get(n.k_origin)); + Dictionary unique; + for (int64_t i=0;iget(n.k_origin);if(passable.has(origin)) unique[origin]=true; + const Array keys=unique.keys();std::vector sorted;sorted.reserve(keys.size()); + for (int64_t i=0;iget(n.k__guest_step_connector_memo); + // Route-local only. Reuse an ownership result only after an actual + // BOOL return and a typed cached step; no script callback occurs on a + // repeated typed memo hit. A miss/conversion/custom script keeps calls. + const bool builtin_pair = builtin(n,path,"res://scripts/world/path_service.gd") && + builtin(n,elevators,"res://scripts/transport/elevator_service.gd"); + bool ownership_valid = false; + bool ownership_value = false; + StringName ownership_connector; + for(int64_t i=1;i access;connector=path->call(n.k_get_step_connector,from,to,access);} + bool special; + if (builtin_pair && typed_memo_hit && ownership_valid && connector == ownership_connector) { + special = ownership_value; + } else { + const Variant owned = elevators->call(n.k_owns_connector,connector); + special = static_cast(owned); + ownership_valid = builtin_pair && typed_memo_hit && owned.get_type() == Variant::BOOL; + ownership_value = special; + ownership_connector = connector; + } + if(!special && String(connector).begins_with("infra.connector:") && from.x==to.x && from.z==to.z && + std::abs(int64_t(from.y)-int64_t(to.y))==1) { + const Dictionary detail=path->call(n.k_get_connector,connector); + special=detail.get(n.k_movement_type,StringName())==Variant(n.k_CONNECTOR) && + static_cast(detail.get(n.k_cost,int64_t(0)))==150 && stair_credit>movement_scale; + } + if(special) { + const int64_t cost=path->call(n.k_calculate_guest_batch_path_cost,route[0],route[route.size()-1],route); + return static_cast(std::ceil(static_cast(cost)/static_cast(orthogonal_cost))); + } + } + return std::max(route.size()-1,0); + } +public: + + // Stateless translation of the builtin nearest access query. The caller + // supplies the existing typed default profile and the real Time callable. + // Public cache publication, failure diagnostics and fallback stay ordered. + Dictionary nearest_guest_access(Object *path, const Vector3i &start, + const Array &goals, const Vector3i &fallback_target, + const TypedArray &layers, const TypedArray &access, + const Callable &ticks) { + const ProjectionNames n; + return nearest_guest_access_impl(n,path,start,goals,fallback_target,layers,access,ticks); + } +private: + Dictionary nearest_guest_access_impl(const ProjectionNames &n,Object *path, const Vector3i &start, + const Array &goals, const Vector3i &fallback_target, + const TypedArray &layers, const TypedArray &access, + const Callable &ticks) { + Dictionary unsupported; + unsupported[n.k_supported] = false; + if (!path || !ticks.is_valid() || goals.is_empty()) return unsupported; + Object *script = path->get_script(); + if (!script || String(script->get(n.k_resource_path)) != "res://scripts/world/path_service.gd") return unsupported; + Dictionary batch = path->get(n.k__query_batch); + if (batch.is_empty() || start != static_cast(batch[n.k_start])) return unsupported; + const Dictionary passable = path->get(n.k__passable_cells); + if (!passable.has(start) || blocked(n,path, start) || !layers.has(start.z)) return unsupported; + const Dictionary targets = batch[n.k_targets]; + Dictionary cache = path->get(n.k__path_cache); + // Exact builtin validation loop has no callback before ticks.call(). + // Build the unchanged profile/revision suffix lazily at the first key. + String key_suffix; + bool key_suffix_ready = false; + for (int64_t j = 0; j < goals.size(); ++j) { + if (goals[j].get_type() != Variant::VECTOR3I) return unsupported; + const Vector3i cell = goals[j]; + if (!targets.has(cell)) { + const bool searchable = passable.has(cell) && layers.has(cell.z) && !blocked(n,path, cell); + if (searchable && (start.z == cell.z || static_cast(path->call(n.k__guest_batch_has_permitted_layer_crossing, start, cell, layers, access)))) return unsupported; + } + if (!key_suffix_ready) { + key_suffix = cache_key_suffix(n,path, layers, access); + key_suffix_ready = true; + } + const String key = cache_key_with_suffix(start, cell, key_suffix); + if (cache.has(key)) return unsupported; + } + const int64_t started = ticks.call(); + if (!static_cast(batch[n.k_ready])) { + batch[n.k_tree] = path->call(n.k__build_guest_query_tree_compact, start, targets, layers, access); + batch[n.k_arithmetic_wrapped] = path->get(n.k__guest_tree_arithmetic_wrapped); + batch[n.k_ready] = true; + } + const Dictionary tree = batch[n.k_tree]; + if (!static_cast(tree.get(n.k_usable, false)) || static_cast(batch.get(n.k_arithmetic_wrapped, false))) return unsupported; + Vector3i best_cell = fallback_target; + bool found = false; + int64_t best_cost = 0; + const Dictionary settled = tree[n.k_settled]; + for (int64_t j = 0; j < goals.size(); ++j) { + const Vector3i cell = goals[j]; + if (!targets.has(cell) || !settled.has(cell)) continue; + if (!tree_has_cost(n,tree, cell)) return unsupported; + const int64_t cost = tree_cost(n,tree, cell); + if (!found || cost < best_cost) { + found = true; + best_cost = cost; + best_cell = cell; + } + } + TypedArray best_path; + if (found) { + best_path = resolve_ready_guest_point(n,path, start, best_cell, tree, layers, access); + if (best_path.is_empty()) return unsupported; + } + if (!goals.is_empty() && (!found || goals[goals.size() - 1] != Variant(best_cell))) { + resolve_ready_guest_point(n,path, start, goals[goals.size() - 1], tree, layers, access); + } + const int64_t elapsed = the_tree_native::signed_add(static_cast(ticks.call()), the_tree_native::signed_add(~started, 1)); + path->emit_signal(n.k_path_query_measured, std::max(elapsed, 0)); + Dictionary result; + result[n.k_supported] = true; + result[n.k_reachable] = found; + result[n.k_path] = best_path; + result[n.k_target_cell] = best_cell; + return result; + } +private: + static bool blocked(const ProjectionNames &n,Object *path, const Vector3i &cell) { + const Dictionary traffic_map = path->get(n.k__cell_traffic); + const Dictionary traffic = traffic_map.get(cell, Dictionary()); + return !traffic.is_empty() && static_cast(traffic[n.k_temporary_block]); + } + static bool tree_has_cost(const ProjectionNames &n,const Dictionary &tree, const Vector3i &cell) { + if (!static_cast(tree.get(n.k_compact, false))) { + const Dictionary values = tree[n.k_costs]; + return values.has(cell); + } + const Dictionary indices = tree[n.k_indices]; + if (!indices.has(cell)) return false; + const int64_t index = indices[cell]; + const PackedInt64Array values = tree[n.k_cost_values]; + return index >= 0 && index < values.size(); + } + static int64_t tree_cost(const ProjectionNames &n,const Dictionary &tree, const Vector3i &cell) { + if (!static_cast(tree.get(n.k_compact, false))) { + const Dictionary values = tree[n.k_costs]; + return static_cast(values[cell]); + } + const Dictionary indices = tree[n.k_indices]; + const PackedInt64Array values = tree[n.k_cost_values]; + return values[static_cast(indices[cell])]; + } + static TypedArray resolve_ready_guest_point(const ProjectionNames &n,Object *path, + const Vector3i &start, const Vector3i &goal, const Dictionary &tree, + const TypedArray &layers, const TypedArray &access) { + const Dictionary passable = path->get(n.k__passable_cells); + if (!passable.has(start)) return path->call(n.k__route_failure, n.k_START_NOT_PASSABLE); + if (!passable.has(goal)) return path->call(n.k__route_failure, n.k_GOAL_NOT_PASSABLE); + if (!layers.has(start.z) || !layers.has(goal.z)) return path->call(n.k__route_failure, n.k_ACCESS_LAYER_DENIED); + if (blocked(n,path, start)) return path->call(n.k__route_failure, n.k_START_TEMPORARILY_BLOCKED); + if (blocked(n,path, goal)) return path->call(n.k__route_failure, n.k_GOAL_TEMPORARILY_BLOCKED); + // ticks/tree callbacks may have changed the script or revision. Recheck + // at this original call position and never reuse the pre-tick suffix. + const String key = builtin(n,path,"res://scripts/world/path_service.gd") ? + cache_key_with_suffix(start, goal, cache_key_suffix(n,path, layers, access)) : + String(path->call(n.k__cache_key, start, goal, layers, access)); + Dictionary cache = path->get(n.k__path_cache); + const Dictionary batch = path->get(n.k__query_batch); + const Dictionary targets = batch[n.k_targets]; + if (cache.has(key) || !targets.has(goal)) return path->call(n.k__find_path_internal, start, goal); + path->set(n.k_cache_misses, the_tree_native::signed_add(static_cast(path->get(n.k_cache_misses)), 1)); + if (start.z != goal.z && !static_cast(path->call(n.k__guest_batch_has_permitted_layer_crossing, start, goal, layers, access))) return path->call(n.k__route_failure, n.k_GOAL_UNREACHABLE); + TypedArray route; + const Dictionary settled = tree[n.k_settled]; + if (start == goal) route.push_back(start); + else if (settled.has(goal)) route = Array(path->call(n.k__guest_tree_reconstruct_path, tree, goal)); + if (route.is_empty()) return path->call(n.k__route_failure, path->call(n.k__diagnose_no_route_reason, start, goal, layers, access)); + cache[key] = path->call(n.k__copy_path, route); + path->set(n.k_last_no_route_reason, n.k_OK); + path->set(n.k_last_path_cost, tree_cost(n,tree, goal)); + path->set(n.k_last_error, String("")); + return route; + } +public: +private: + // One existing builtin provider operation, with no new value cache. Only + // connector-free WALK rows qualify; unsupported cases call the old provider. + // All work stays private until the original final shared[current] assignment. + struct WalkEdgeNames { + const StringName resource_path{"resource_path",false}, constants_method{"get_script_constant_map",false}; + const StringName front{"FRONT",false}, back{"BACK",false}, walk{"MOVEMENT_WALK",false}; + const StringName base{"ORTHOGONAL_MOVE_COST",false}, congestion{"CONGESTION_COST_PER_EXCESS",false}; + const StringName workspace{"_guest_tree_workspace",false}, edges{"edges",false}, indices{"indices",false}; + const StringName adjacency{"_adjacency",false}, traffic{"_cell_traffic",false}, vertical{"_vertical_walk_requires_connector",false}; + const StringName to{"to",false}, connector{"connector_id",false}, access{"access_id",false}, movement{"movement_type",false}; + const StringName base_cost{"base_cost",false}, cost{"cost",false}, temporary{"temporary_block",false}; + const StringName dynamic{"dynamic_cost",false}, density{"current_density",false}, capacity{"base_capacity",false}; + const StringName provider{"_guest_tree_shared_edges",false}; + }; + struct WalkEdgeContext { + Object *path=nullptr; + int64_t front=0, back=0, base=0, congestion=0; + StringName walk; + }; + static bool walk_edge_context(const WalkEdgeNames &n,Object *path,const Array &layers, + const Array &access,WalkEdgeContext &context) { + if (!path || layers.size()!=2 || !access.is_empty() || + layers[0].get_type()!=Variant::INT || layers[1].get_type()!=Variant::INT) return false; + Object *script=path->get_script(); + if (!script || String(script->get(n.resource_path))!="res://scripts/world/path_service.gd" || + !script->has_method(n.constants_method)) return false; + const Variant value=script->call(n.constants_method); + if (value.get_type()!=Variant::DICTIONARY) return false; + const Dictionary constants=value; + for (const StringName &key : {n.front,n.back,n.base,n.congestion}) + if (constants.get(key,Variant()).get_type()!=Variant::INT) return false; + if (constants.get(n.walk,Variant()).get_type()!=Variant::STRING_NAME || + int64_t(layers[0])!=int64_t(constants[n.front]) || + int64_t(layers[1])!=int64_t(constants[n.back])) return false; + context.path=path;context.front=constants[n.front];context.back=constants[n.back]; + context.base=constants[n.base];context.congestion=constants[n.congestion];context.walk=constants[n.walk]; + return true; + } + static bool builtin_walk_edge_rows(const WalkEdgeNames &n,const WalkEdgeContext &context, + const Vector3i ¤t,Array &rows) { + if (!context.path) return false; + const Variant workspace_value=context.path->get(n.workspace); + if (workspace_value.get_type()!=Variant::DICTIONARY) return false; + const Dictionary workspace=workspace_value; + const Variant shared_value=workspace.get(n.edges,Variant()); + if (shared_value.get_type()!=Variant::DICTIONARY) return false; + Dictionary shared=shared_value; + // Original cached-row branch precedes readonly and all other state reads. + if (shared.has(current)) { + const Variant cached=shared[current]; + if (cached.get_type()!=Variant::ARRAY) return false; + rows=cached;return true; + } + if (shared.is_read_only()) return false; + const Variant indices_value=workspace.get(n.indices,Variant()), adjacency_value=context.path->get(n.adjacency); + const Variant traffic_value=context.path->get(n.traffic), vertical_value=context.path->get(n.vertical); + if (indices_value.get_type()!=Variant::DICTIONARY || adjacency_value.get_type()!=Variant::DICTIONARY || + traffic_value.get_type()!=Variant::DICTIONARY || vertical_value.get_type()!=Variant::BOOL) return false; + const Dictionary indices=indices_value, adjacency=adjacency_value, traffic=traffic_value; + const Variant raw_value=adjacency.get(current,Array()); + if (raw_value.get_type()!=Variant::ARRAY) return false; + const Array raw=raw_value;Array result; + for (int64_t i=0;i0?excess:0,context.congestion)); + } + const int64_t cost=the_tree_native::signed_add(int64_t(base),dynamic); + Array pair;pair.push_back(neighbor);pair.push_back(cost);result.push_back(pair); + // Same short circuit and first invalid prefix as the original method. + if (cost<=0 || !indices.has(neighbor)) break; + } + shared[current]=result;rows=result;return true; + } +public: + Dictionary guest_tree_edge_rows(Object *path,const Vector3i ¤t,const Array &layers,const Array &access) { + const WalkEdgeNames names;WalkEdgeContext context;Array rows; + Dictionary result;const StringName supported{"supported",false}, row_key{"rows",false}; + result[supported]=false; + if (!walk_edge_context(names,path,layers,access,context) || + !builtin_walk_edge_rows(names,context,current,rows)) return result; + result[supported]=true;result[row_key]=rows;return result; + } +private: + Dictionary search_impl(const Array &cells, const Dictionary &indices, I start_index, + const Dictionary &goals, const Callable &edge_provider, bool use_edge_cache) { + Dictionary output; + output[StringName("status")] = String("unusable"); + if (start_index < 0 || start_index >= cells.size() || !edge_provider.is_valid()) return output; + try { + std::vector goal_indices; + const Array goal_keys = goals.keys(); + for (I j = 0; j < goal_keys.size(); ++j) + goal_indices.push_back(static_cast(indices.get(goal_keys[j], I(-1)))); + Array arguments; + arguments.resize(1); + const WalkEdgeNames walk_names;WalkEdgeContext walk_context; + if (edge_provider.get_method()==walk_names.provider && edge_provider.get_argument_count()==1 && + edge_provider.get_bound_arguments_count()==2 && edge_provider.get_unbound_arguments_count()==0) { + const Array bound=edge_provider.get_bound_arguments(); + if (bound.size()==2 && bound[0].get_type()==Variant::ARRAY && bound[1].get_type()==Variant::ARRAY) + walk_edge_context(walk_names,edge_provider.get_object(),bound[0],bound[1],walk_context); + } + // Call the original bound Godot edge method only when the search expands a node. + // Preserve its lazy cache population, filter ordering and first invalid row. + auto original_edges = [&](I current) { + arguments[0] = cells[current]; + Array fused;bool fused_supported=false; + if (cells[current].get_type()==Variant::VECTOR3I) { + const Vector3i cell=cells[current]; + fused_supported=builtin_walk_edge_rows(walk_names,walk_context,cell,fused); + } + const Variant value = fused_supported ? Variant(fused) : edge_provider.callv(arguments); + if (value.get_type() != Variant::ARRAY) return std::vector{{-1, 0}}; + const Array rows = value; + std::vector result; + result.reserve(rows.size()); + for (I j = 0; j < rows.size(); ++j) { + if (rows[j].get_type() != Variant::ARRAY) { result.push_back({-1, 0}); break; } + const Array row = rows[j]; + if (row.size() != 2 || row[1].get_type() != Variant::INT) { + result.push_back({-1, 0}); break; + } + const I cost = static_cast(row[1]); + // Nonpositive cost is rejected before requesting the neighbor index. + if (cost <= 0) { result.push_back({-1, cost}); break; } + const I neighbor = static_cast(indices.get(row[0], I(-1))); + result.push_back({neighbor, cost}); + if (neighbor < 0) break; + } + return result; + }; + auto edges = [&](I current) { + if (!use_edge_cache) return original_edges(current); + const auto found = cached_edges.find(current); + if (found != cached_edges.end()) return found->second; + // Populate only when the old algorithm expands this same node. + // Retain original provider validation and first-invalid prefix. + auto converted = original_edges(current); + cached_edges.emplace(current, converted); + return converted; + }; + const auto result = the_tree_native::search(cells.size(), start_index, goal_indices, edges); + output[StringName("status")] = String(result.status.c_str()); + if (result.status != "usable") return output; + PackedInt64Array costs, parents; + if (costs.resize(result.costs.size()) != OK || parents.resize(result.parents.size()) != OK) { + output[StringName("status")] = String("unusable"); + return output; + } + for (I j = 0; j < cells.size(); ++j) { costs.set(j, result.costs[j]); parents.set(j, result.parents[j]); } + TypedArray discovered, parent_discovered; + for (I j : result.discovered) discovered.push_back(j); + for (I j : result.parent_discovered) parent_discovered.push_back(j); + Dictionary settled; + for (I j : result.settled) settled[cells[j]] = true; + output[StringName("cost_values")] = costs; + output[StringName("parent_indices")] = parents; + output[StringName("discovered")] = discovered; + output[StringName("parent_discovered")] = parent_discovered; + output[StringName("settled")] = settled; + return output; + } catch (const std::exception &) { + output = Dictionary(); + output[StringName("status")] = String("unusable"); + return output; + } + } +}; + +void initialize_tree_numeric_core(ModuleInitializationLevel level) { + if (level == MODULE_INITIALIZATION_LEVEL_SCENE) GDREGISTER_CLASS(TheTreeNumericCore); +} +void uninitialize_tree_numeric_core(ModuleInitializationLevel) {} + +extern "C" { +GDExtensionBool GDE_EXPORT tree_numeric_core_init(GDExtensionInterfaceGetProcAddress get_proc, + GDExtensionClassLibraryPtr library, GDExtensionInitialization *initialization) { + GDExtensionBinding::InitObject init(get_proc, library, initialization); + init.register_initializer(initialize_tree_numeric_core); + init.register_terminator(uninitialize_tree_numeric_core); + init.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE); + return init.init(); +} +} diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/build-preview-r286.json b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/build-preview-r286.json new file mode 100644 index 0000000..72ff068 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/build-preview-r286.json @@ -0,0 +1,61 @@ +{ + "plan": [ + [ + "compile-062", + [ + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++", + "-o", + "/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-build-r286/objects/062-tree_numeric_core.os", + "-c", + "-std=c++17", + "-isystem", + "/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-sdk-lifetime-candidate-r131/sdk/include", + "-isystem", + "/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-sdk-lifetime-candidate-r131/sdk/gen/include", + "-Wall", + "-Wextra", + "-Werror", + "-fexceptions", + "-arch", + "arm64", + "-isysroot", + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk", + "-fvisibility=hidden", + "-O3", + "-fPIC", + "-DMACOS_ENABLED", + "-DUNIX_ENABLED", + "-DTHREADS_ENABLED", + "-DDEBUG_ENABLED", + "-DNDEBUG", + "-DGDEXTENSION", + "-I/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source", + "/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02/source/tree_numeric_core.cpp" + ] + ], + [ + "link", + [ + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++", + "-o", + "/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-build-r286/libtree_numeric_core.macos.template_debug.dylib", + "-arch", + "arm64", + "-isysroot", + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk", + "-fvisibility=hidden", + "-Wl,-S", + "-Wl,-x", + "-Wl,-dead_strip", + "-shared", + "/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-build-r286/objects/062-tree_numeric_core.os", + "/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-sdk-lifetime-build-r133/libgodot-cpp.macos.template_debug.arm64.a" + ] + ] + ], + "planned_bridge_compilations": 1, + "planned_SDK_compilations": 0, + "Godot_loaded": false, + "source_candidate": "/Users/korizatou114/Projects/\u3068\u308a\u306b\u304f\u5de5\u623f\u30b2\u30fc\u30e0\u5236\u4f5c\u90e8/artifacts/original-completion-2026-10-02/p23-02-native-integer-window-codec-candidate-r285-r02", + "scope": "one bridge compile and link; SDK133 archive reused; no Godot, local or performance acceptance" +} \ No newline at end of file diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/build-r286.py b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/build-r286.py new file mode 100644 index 0000000..1a4b630 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/build-r286.py @@ -0,0 +1,181 @@ +# coding: utf-8 +"""Compile only r285-r02 integer Array codec bridge against authenticated unchanged r133 SDK archive; no Godot execution.""" +from pathlib import Path +import importlib.util, json, os, platform, shutil, subprocess, sys, time, signal, shlex +sys.dont_write_bytecode=True +R=Path(__file__).resolve().parents[2];A=R/'artifacts/original-completion-2026-10-02' +C=A/'p23-02-native-integer-window-codec-candidate-r285-r02';O=A/'p23-02-native-integer-window-codec-build-r286' +BASE=A/'p23-02-native-bridge-build-r76';BASE_SDK=BASE/'sdk';SDK_C=A/'p23-02-native-sdk-lifetime-candidate-r131';SDK=SDK_C/'sdk';HOST=A/'p23-02-native-sdk-lifetime-build-r133' +FLOOR=512*1048576;GROWTH=16*1048576 +def mod(name,path): + spec=importlib.util.spec_from_file_location(name,path);m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m);return m +def main(): + r=mod('buffer_build_runner',R/'tools/run_all_tests.py');outer=mod('buffer_build_owned',r.SUPPORT/'owned_outer.py') + build_helper_path=A/'p23-02-native-bridge-build-r76.py' + build_helper=mod('retained_build_ownership',build_helper_path) + def pin(p):return dict(path=str(p),bytes=p.stat().st_size,sha256=r.sha(p)) + D=R/'docs/plans/original-completion-2026-10-02';names=['IMPLEMENTATION_PLAN.md','PROGRESS_INTEGRATION.md','work_packages.json','progress_snapshot.json'] + preexecution_review=A/'p23-02-native-integer-window-codec-build-preexecution-independent-review-r286.json' + preexecution=r.read(preexecution_review) + assert preexecution['execution_allowed'] and not preexecution['blockers'] + for group in ['evidence_sha256','canonical_doc4_context_pins']: + values=preexecution[group] + for q in values.values() if isinstance(values,dict) else values: + p=Path(q['path']);assert p.stat().st_size==q['bytes'] and r.sha(p)==q['sha256'] + pre_root=r.read(A/'p23-02-native-integer-window-codec-build-preexecution-root-verification-r286.json');assert pre_root['passed'] and pre_root['review_sha256']==r.sha(preexecution_review) + source=r.source_refs(R);player=r.default_player(R);docs={n:r.sha(D/n) for n in names} + assert {n:v['sha256'] for n,v in source.items()}==r.read(A/'p23-02-final-candidate-r32-source-adoption-r03/source-after.json') + assert platform.machine()=='arm64' and not O.exists() and not outer.native.helper['live_engines']() + assert shutil.disk_usage(A).free>=FLOOR+GROWTH + review=A/'p23-02-native-bridge-build-validation-independent-review-r77.json' + assert r.sha(review)=='75d3bbff767fb88af266c4b1b9da37d96294ab72b9e07fcac9a3e7e567a29d49' + auth=r.read(review)['evidence_sha256'] + base_input=BASE/'input.json';archive=BASE_SDK/'bin/libgodot-cpp.macos.template_debug.arm64.a' + accepted_receipt=A/'p23-02-native-bridge-build-validation-r77/execution.json' + for p in [base_input,archive,accepted_receipt]: + v=auth[str(p)];assert p.stat().st_size==v['bytes'] and r.sha(p)==v['sha256'] + old=r.read(base_input);compiler=Path(old['compiler_pins']['clang++']['path']) + assert pin(compiler)==old['compiler_pins']['clang++'] + for p in old['macos_sdk']['pins']:assert pin(Path(p['path']))==p + sdk_path=old['macos_sdk']['path'] + assert str(Path(subprocess.run(['/usr/bin/xcrun','--sdk','macosx','--show-sdk-path'],capture_output=True,text=True,check=True,timeout=10).stdout.strip()).resolve())==sdk_path + candidate_input=C/'input.json';candidate_review=A/'p23-02-native-integer-window-codec-static-independent-review-r285-r02.json' + candidate_root=r.read(A/'p23-02-native-integer-window-codec-static-root-verification-r285-r02.json') + assert candidate_root['passed'] and candidate_root['review_sha256']==r.sha(candidate_review) + v=r.read(candidate_input);support=r.read(candidate_review) + assert support['implementation_supported'] and not support['blockers'] + # Authenticate candidate evidence; current canonical184 context pins must still match at preexecution. + for path,q in support['evidence_sha256'].items(): + p=Path(q.get('path',path));assert p.stat().st_size==q['bytes'] and r.sha(p)==q['sha256'] + canonical_context=support['canonical_doc4_context_pins'] + for q in canonical_context.values() if isinstance(canonical_context,dict) else canonical_context: + p=Path(q['path']);assert p.stat().st_size==q['bytes'] and r.sha(p)==q['sha256'] + host_review=A/'p23-02-native-sdk-lifetime-build-actual-independent-review-r133.json' + assert r.sha(host_review)=='c3cbeb45c1353dfea5f8181d10cc60f8a9b81db55d766ac5db902ac28c159a61' + host_support=r.read(host_review);assert host_support['host_build_accepted'] and not host_support['blockers'] + host_input=HOST/'input.json';new_archive=HOST/'libgodot-cpp.macos.template_debug.arm64.a' + for p in [host_input,new_archive]: + q=host_support['evidence_sha256'][str(p)];assert p.stat().st_size==q['bytes'] and r.sha(p)==q['sha256'] + host=r.read(host_input);sdk_inventory=host['SDK_inventory'];assert r.inventory(SDK)==sdk_inventory + sdk_candidate_inventory=host['candidate_inventory'];assert r.inventory(SDK_C)==sdk_candidate_inventory + accepted_inventory=r.read(accepted_receipt)['original_r76_inventory'] + parent_sdk_inventory={key[len('sdk/'):]:value for key,value in accepted_inventory.items() if key.startswith('sdk/')} + assert parent_sdk_inventory and r.inventory(BASE_SDK)==parent_sdk_inventory + source_inventory=r.inventory(C/'source') + assert pin(C/'source/tree_numeric_core.cpp')==v['candidate_cpp'] and pin(C/'source/tree_core.hpp')==v['candidate_header'] + candidate_inventory=r.inventory(C);base_source_inventory=r.inventory(BASE/'source') + compile_db=BASE/'compile_commands.json' + authenticated_compile_db=auth[str(compile_db)] + assert compile_db.stat().st_size==authenticated_compile_db['bytes'] and r.sha(compile_db)==authenticated_compile_db['sha256'] + commands=r.read(compile_db);assert len(commands)==63 + fixed=[review,base_input,archive,accepted_receipt,compiler,candidate_input,candidate_review,C/'source/tree_numeric_core.cpp',C/'source/tree_core.hpp',compile_db,host_review,host_input,new_archive,build_helper_path,Path(__file__)] + fixed += [A/'p23-02-native-integer-window-codec-static-root-verification-r285-r02.json'] + fixed += [preexecution_review] + fixed += [Path(p['path']) for p in old['macos_sdk']['pins']] + pins={str(p):pin(p) for p in fixed} + O.mkdir();(O/'objects').mkdir();library=O/'libtree_numeric_core.macos.template_debug.dylib' + compile_plan=[];sdk_objects=[];bridge_object=None + for i,row in enumerate(commands): + if row['file'].startswith('sdk/'):continue + argv=shlex.split(row['command']);assert argv[0]=='clang++' and '-c' in argv + argv[0]=str(compiler);out_index=argv.index('-o')+1;assert argv[out_index]==row['output'] + obj=O/'objects'/('%03d-'%i+Path(row['output']).name);argv[out_index]=str(obj) + for j,t in enumerate(argv): + if t.startswith('sdk/'):argv[j]=str(SDK_C/t) + elif t.startswith('source/'):argv[j]=str(C/t) + elif t.startswith('-Isdk/'):argv[j]='-I'+str(SDK_C/t[2:]) + elif t=='-Isource':argv[j]='-I'+str(C/t[2:]) + source_file=C/row['file'];assert source_file.is_file();pins[str(source_file)]=pin(source_file) + compile_plan.append(('compile-%03d'%i,argv)) + if row['file'].startswith('sdk/'):sdk_objects.append(obj) + else:assert row['file']=='source/tree_numeric_core.cpp' and bridge_object is None;bridge_object=obj + assert len(sdk_objects)==0 and len(compile_plan)==1 and bridge_object is not None + link_argv=[str(compiler),'-o',str(library),'-arch','arm64','-isysroot',sdk_path,'-fvisibility=hidden','-Wl,-S','-Wl,-x','-Wl,-dead_strip','-shared',str(bridge_object),str(new_archive)] + plan=compile_plan+[('link',link_argv)] + assert json.loads(json.dumps(plan))==r.read(A/'p23-02-native-integer-window-codec-build-preview-r286.json')['plan'] + r.write(O/'input.json',dict(source_before=source,default_player_before=player,doc4_before=docs,pins=pins,SDK_path=str(SDK),SDK_inventory=sdk_inventory,parent_SDK_inventory=parent_sdk_inventory,SDK_identity_source=pin(accepted_receipt),candidate_inventory=candidate_inventory,base_source_inventory=base_source_inventory,plan=plan,capacity_floor_bytes=FLOOR,maximum_growth_bytes=GROWTH,expected_duration_seconds=[2,30],watchdog_seconds_each=90,serial=True,authenticated_compile_database=authenticated_compile_db,full_input_inventory_before_and_after_each_phase=True,planned_bridge_compilations=1,planned_SDK_compilations=0,SDK_archive_reused=pin(new_archive),old_bridge_object_reused=False,Godot_loaded=False,unit_accepted=False)) + env=r.fresh_environment(os.environ) + for key in list(env): + if key.startswith('CCACHE_') or key in ['CFLAGS','CXXFLAGS','CCFLAGS','LDFLAGS','CPATH','CPLUS_INCLUDE_PATH','LIBRARY_PATH','SDKROOT','MACOSX_DEPLOYMENT_TARGET']: + env.pop(key) + phases=[];error=None;cleanup=[];cleanup_errors=[];binary_checks={};spawned=[] + def verify_protected_inputs(): + assert r.inventory(C)==candidate_inventory + assert r.inventory(SDK)==sdk_inventory and r.inventory(SDK_C)==sdk_candidate_inventory + assert r.inventory(BASE/'source')==base_source_inventory + assert r.inventory(BASE_SDK)==parent_sdk_inventory + for path,q in pins.items():assert pin(Path(path))==q + + def run_build_phase(name,argv): + # Compiler diagnostics have no Godot banner. Use retained build ownership, + # not the engine-specific diagnostic parser or a synthesized banner. + folder=O/name;folder.mkdir();process=None;phase_error=None;phase_cleanup=[];errors=[];remaining=None + started=time.monotonic();timed_out=False;exit_code=None + try: + with (folder/'stdout.log').open('wb') as stdout,(folder/'stderr.log').open('wb') as stderr: + process=subprocess.Popen(argv,cwd=folder,env=env,stdout=stdout,stderr=stderr,start_new_session=True) + spawned.append(dict(phase=name,pid=process.pid,argv=argv)) + initial=build_helper.group_members(process.pid) + if process.poll() is None: + assert os.getpgid(process.pid)==process.pid and os.getsid(process.pid)==process.pid + assert any(q['pid']==process.pid and q['ppid']==os.getpid() for q in initial) + r.write(folder/'started.json',dict(pid=process.pid,owner_pid=os.getpid(),pgid=process.pid,argv=argv,started_utc=r.now(),initial_members=initial,owned_new_session=True)) + print(json.dumps(dict(build_phase=name,pid=process.pid)),flush=True) + while process.poll() is None: + if time.monotonic()-started>90: + timed_out=True;raise TimeoutError('owned compiler watchdog90s') + assert shutil.disk_usage(A).free>=FLOOR + assert sum(p.stat().st_size for p in O.rglob('*') if p.is_file())<=GROWTH + time.sleep(0.1) + exit_code=process.wait(timeout=5) + except BaseException as caught:phase_error=type(caught).__name__+': '+str(caught) + finally: + if process is not None: + try: + phase_cleanup,remaining=build_helper.cleanup_owned_parent(process,process.pid,errors) + except BaseException as caught: + errors.append('retained cleanup exception: '+repr(caught)) + # An unexpected helper exception never skips exact-Popen cleanup. + # No group is discovered or signalled by this fallback. + for sig in [signal.SIGTERM,signal.SIGKILL]: + try: + if process.poll() is None:process.send_signal(sig) + except BaseException as failure:errors.append('tracked signal: '+repr(failure)) + try:process.wait(timeout=3) + except BaseException as failure:errors.append('tracked wait: '+repr(failure)) + try:exit_code=process.wait(timeout=5) + except BaseException as caught:errors.append('final tracked wait: '+repr(caught)) + r.write(folder/'ended.json',dict(pid=process.pid,argv=argv,pgid=process.pid,ended_utc=r.now(),exit_code=exit_code,duration_seconds=time.monotonic()-started,cleanup=phase_cleanup,remaining=remaining,cleanup_errors=errors,foreign_process_or_group_signals=0)) + result=dict(pid=process.pid if process else None,exit_code=exit_code,timed_out=timed_out,error_lines=[phase_error] if phase_error else [],duration_seconds=time.monotonic()-started) + capture=dict(passed=process is not None and phase_error is None and not errors and remaining==[],cleanup=phase_cleanup,cleanup_errors=errors,all_captured_ended=process is not None and process.poll() is not None,foreign_process_or_group_signals=0) + return result,capture + try: + for name,argv in plan: + assert shutil.disk_usage(A).free>=FLOOR+GROWTH and not outer.native.helper['live_engines']() + # Authenticate every header/source and retained parent before and after each owned phase. + verify_protected_inputs() + result,capture=run_build_phase(name,argv) + post_input_error=None + try:verify_protected_inputs() + except BaseException as caught:post_input_error=type(caught).__name__+': '+str(caught) + row=dict(name=name,result=result,capture=capture,full_input_inventory_before_verified=True,full_input_inventory_after_verified=post_input_error is None,post_input_error=post_input_error);phases.append(row);r.write(O/(name+'-phase.json'),row) + assert post_input_error is None, post_input_error + assert result is not None and result['exit_code']==0 and not result['error_lines'] and not result['timed_out'] and capture['passed'] + assert (O/name/'stderr.log').read_bytes()==b'' and (O/name/'stdout.log').read_bytes()==b'' + assert sum(p.stat().st_size for p in O.rglob('*') if p.is_file())<=GROWTH + assert library.is_file() and bridge_object.is_file() and new_archive.is_file() + for name,argv in [('file',['/usr/bin/file',str(library)]),('arch',['/usr/bin/lipo','-archs',str(library)]),('dependencies',['/usr/bin/otool','-L',str(library)]),('exports',['/usr/bin/nm','-gU',str(library)])]: + q=subprocess.run(argv,capture_output=True,text=True,check=True,timeout=10) + assert not q.stderr;binary_checks[name]=q.stdout + assert binary_checks['arch'].strip()=='arm64' and '_tree_numeric_core_init' in binary_checks['exports'] and 'dynamically linked shared library' in binary_checks['file'] + except BaseException as caught:error=type(caught).__name__+': '+str(caught) + finally: + cleanup=[row['capture']['cleanup'] for row in phases] + cleanup_errors=[message for row in phases for message in row['capture']['cleanup_errors']] + preserved=r.source_refs(R)==source and r.default_player(R)==player and {n:r.sha(D/n) for n in names}==docs and r.inventory(C)==candidate_inventory and r.inventory(SDK)==sdk_inventory and r.inventory(SDK_C)==sdk_candidate_inventory and r.inventory(BASE/'source')==base_source_inventory and r.inventory(BASE_SDK)==parent_sdk_inventory + for name_pin,q in pins.items():preserved=preserved and pin(Path(name_pin))==q + assert preserved + passed=error is None and len(phases)==2 and not cleanup_errors + r.write(O/'execution.json',dict(passed=passed,error=error,phases=phases,cleanup=cleanup,cleanup_errors=cleanup_errors,binary_checks=binary_checks,object=pin(bridge_object) if bridge_object.exists() else None,library=pin(library) if library.exists() else None,original_inputs_preserved=preserved,bridge_compilations=sum(q['phase']=='compile-062' for q in spawned),link_attempts=sum(q['phase']=='link' for q in spawned),spawned_children=spawned,SDK_compilations=sum(q['phase'].startswith('compile-') and q['phase']!='compile-062' for q in spawned),SDK_archive_reused=pin(new_archive),SDK_archive_rebuilt=False,old_bridge_object_reused=False,Godot_loaded=False,selected=False,unit_accepted=False,performance_accepted=False,limits=['Exact modified r285-r02 integer Array codec bridge one-object compile and link to authenticated unchanged r133 SDK archive only; no SDK recompilation, Godot load, protocol, performance or unit acceptance.'])) + print(json.dumps(dict(passed=passed,error=error)),flush=True);return 0 if passed else 1 +if __name__=='__main__':raise SystemExit(main()) diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/prepare-r285-r02.py b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/prepare-r285-r02.py new file mode 100644 index 0000000..7e1a968 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/prepare-r285-r02.py @@ -0,0 +1,124 @@ +# coding: utf-8 +from pathlib import Path +import hashlib,json,shutil +R=Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部');A=R/'artifacts/original-completion-2026-10-02';C=A/'p23-02-native-integer-window-codec-candidate-r285-r02';P=A/'p23-02-native-pure-tag-projection-candidate-r274/source';assert not C.exists();assert shutil.disk_usage(A).free>=528*1048576 +(C/'source').mkdir(parents=True);original=(P/'tree_numeric_core.cpp').read_text();text=original +helpers=r''' + // Godot ed1daf0bf's integer Array wire layout; checked against this engine + // once per core, never sample values. Every caller-owned Array stays intact. + bool integer_wire_checked=false; + bool integer_wire_compatible=false; + static void wire32(uint8_t *p,uint32_t value) { + for (unsigned i=0;i<4;++i) p[i]=uint8_t(value>>(8*i)); + } + static void wire64(uint8_t *p,uint64_t value) { + for (unsigned i=0;i<8;++i) p[i]=uint8_t(value>>(8*i)); + } + static int64_t integer_wire_width(int64_t value) { + return valueint64_t(INT32_MAX) ? 12 : 8; + } + static void wire_integer(uint8_t *p,int64_t value) { + const bool wide=integer_wire_width(value)==12; + wire32(p,uint32_t(Variant::INT) | (wide ? uint32_t(1)<<16 : 0)); + if (wide) wire64(p+4,uint64_t(value)); else wire32(p+4,uint32_t(value)); + } + static bool integer_wire_encode(const Array &values,PackedByteArray &out) { + const bool typed=values.is_typed(); + if (typed && (values.get_typed_builtin()!=Variant::INT || + !values.get_typed_class_name().is_empty() || values.get_typed_script().get_type()!=Variant::NIL)) return false; + const int64_t count=values.size(),header=typed ? 12 : 8; + // The engine encoder uses a signed-int byte length. Preserve fallback + // for oversized inputs and failed allocations, before owner mutation. + if (count<0 || count>(int64_t(INT32_MAX)-header)/12) return false; + int64_t size=header; + for (int64_t i=0;i typed_empty,typed_probe; + const int64_t boundaries[]={INT64_MIN,int64_t(INT32_MIN)-1,INT32_MIN,-1,0,1,INT32_MAX,int64_t(INT32_MAX)+1,INT64_MAX}; + for (const int64_t value: boundaries) {probe.append(value);typed_probe.append(value);} + bool matches=true; + for (const Array &value: {empty,probe,Array(typed_empty),Array(typed_probe)}) { + PackedByteArray encoded; + matches=integer_wire_encode(value,encoded) && encoded==UtilityFunctions::var_to_bytes(value) && matches; + } + integer_wire_compatible=matches;integer_wire_checked=true; + return matches; + } + static bool integer_wire_update(const PackedByteArray &before,bool typed,int64_t old_count, + int64_t appended,bool pop_front,PackedByteArray &after) { + const int64_t header=typed ? 12 : 8; + if (before.size()
0) { + if (before.size()INT32_MAX || after.resize(size)!=OK) return false; + uint8_t *p=after.ptrw();const uint8_t *q=before.ptr(); + std::memcpy(p,q,size_t(header)); + wire32(p+header-4,uint32_t(old_count+1-(pop_front ? 1 : 0))); + const int64_t kept=before.size()-header-skipped; + if (kept>0) std::memcpy(p+header,q+header+skipped,size_t(kept)); + if (added>0) wire_integer(p+header+kept,appended); + return true; + } +''' +text=text.replace('#include ','#include \n#include \n#include ',1) +needle=' std::map> cached_edges;';assert text.count(needle)==1;text=text.replace(needle,needle+helpers,1) +needle=' ClassDB::bind_method(D_METHOD("performance_record_sample", "owner", "metric_id", "duration_us"), &TheTreeNumericCore::performance_record_sample);';assert text.count(needle)==1 +text=text.replace(needle,needle+'\n ClassDB::bind_method(D_METHOD("encode_integer_window", "values"), &TheTreeNumericCore::encode_integer_window);',1) +needle=' // Whole builtin integer record operation.' +method=''' Dictionary encode_integer_window(const Array &values) { + Dictionary result;const StringName supported("supported",false),bytes("bytes",false); + result[supported]=false;PackedByteArray encoded; + if (!integer_wire_ready() || !integer_wire_encode(values,encoded)) return result; + result[supported]=true;result[bytes]=encoded;return result; + } +''' +assert text.count(needle)==1;text=text.replace(needle,method+needle,1) +old=' for (int64_t i=0;iint64_t(capacityv); + if (!fast_wire || !integer_wire_update(before,values.is_typed(),old_count,duration,popped,after)) + after=UtilityFunctions::var_to_bytes(values);''';text=text.replace(old,new,1) +(C/'source/tree_numeric_core.cpp').write_text(text);shutil.copyfile(P/'tree_core.hpp',C/'source/tree_core.hpp') +def pin(p):b=p.read_bytes();return dict(path=str(p),bytes=len(b),sha256=hashlib.sha256(b).hexdigest()) +D=R/'docs/plans/original-completion-2026-10-02' +with (C/'input.json').open('x') as f:json.dump(dict(parent_cpp=pin(P/'tree_numeric_core.cpp'),parent_header=pin(P/'tree_core.hpp'),candidate_cpp=pin(C/'source/tree_numeric_core.cpp'),candidate_header=pin(C/'source/tree_core.hpp'),author=pin(Path(__file__)),primary_encoder=pin(A/'p23-02-integer-window-codec-source-r284/marshalls.cpp'),primary_encoder_reference=pin(A/'p23-02-integer-window-codec-source-r284/source.json'),budget=pin(A/'p23-02-native-budget-record-candidate-r257-r04/performance_budget.candidate.gd'),ledger_review=pin(A/'p23-02-progress-integration-actual-independent-review-r282.json'),doc4={n:pin(D/n) for n in ['IMPLEMENTATION_PLAN.md','PROGRESS_INTEGRATION.md','work_packages.json','progress_snapshot.json']},scope='source-only integer Array exact bytes encode and append/pop transformation; per-object engine format check, no cached sample values; old encoding fallback retained; report/values/thresholds/notifications/typed/ownership unchanged; performance and load unproven',engine_runs=0,compiler_runs=0,stage_clones=0,candidate_adopted=False,unit_accepted=False),f,ensure_ascii=False,indent=2) +print('source candidate prepared; source-only, no build or engine') diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/prepare-r285.py b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/prepare-r285.py new file mode 100644 index 0000000..6ba05ba --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/preparation/prepare-r285.py @@ -0,0 +1,121 @@ +# coding: utf-8 +from pathlib import Path +import hashlib,json,shutil +R=Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部');A=R/'artifacts/original-completion-2026-10-02';C=A/'p23-02-native-integer-window-codec-candidate-r285';P=A/'p23-02-native-pure-tag-projection-candidate-r274/source';assert not C.exists();assert shutil.disk_usage(A).free>=528*1048576 +(C/'source').mkdir(parents=True);original=(P/'tree_numeric_core.cpp').read_text();text=original +helpers=r''' + // Godot ed1daf0bf's integer Array wire layout; checked against this engine + // once per core, never sample values. Every caller-owned Array stays intact. + bool integer_wire_checked=false; + bool integer_wire_compatible=false; + static void wire32(uint8_t *p,uint32_t value) { + for (unsigned i=0;i<4;++i) p[i]=uint8_t(value>>(8*i)); + } + static void wire64(uint8_t *p,uint64_t value) { + for (unsigned i=0;i<8;++i) p[i]=uint8_t(value>>(8*i)); + } + static int64_t integer_wire_width(int64_t value) { + return valueint64_t(INT32_MAX) ? 12 : 8; + } + static void wire_integer(uint8_t *p,int64_t value) { + const bool wide=integer_wire_width(value)==12; + wire32(p,uint32_t(Variant::INT) | (wide ? uint32_t(1)<<16 : 0)); + if (wide) wire64(p+4,uint64_t(value)); else wire32(p+4,uint32_t(value)); + } + static bool integer_wire_encode(const Array &values,PackedByteArray &out) { + const bool typed=values.is_typed(); + if (typed && (values.get_typed_builtin()!=Variant::INT || + !values.get_typed_class_name().is_empty() || values.get_typed_script().get_type()!=Variant::NIL)) return false; + const int64_t count=values.size(),header=typed ? 12 : 8; + // The engine encoder uses a signed-int byte length. Preserve fallback + // for oversized inputs and failed allocations, before owner mutation. + if (count<0 || count>(int64_t(INT32_MAX)-header)/12) return false; + std::vector integers; + integers.reserve(size_t(count)); + int64_t size=header; + for (int64_t i=0;i typed_empty,typed_probe; + const int64_t boundaries[]={INT64_MIN,int64_t(INT32_MIN)-1,INT32_MIN,-1,0,1,INT32_MAX,int64_t(INT32_MAX)+1,INT64_MAX}; + for (const int64_t value: boundaries) {probe.append(value);typed_probe.append(value);} + bool matches=true; + for (const Array &value: {empty,probe,Array(typed_empty),Array(typed_probe)}) { + PackedByteArray encoded; + matches=integer_wire_encode(value,encoded) && encoded==UtilityFunctions::var_to_bytes(value) && matches; + } + integer_wire_compatible=matches;integer_wire_checked=true; + return matches; + } + static bool integer_wire_update(const PackedByteArray &before,bool typed,int64_t old_count, + int64_t appended,bool pop_front,PackedByteArray &after) { + const int64_t header=typed ? 12 : 8; + if (before.size()
0) { + if (before.size()INT32_MAX || after.resize(size)!=OK) return false; + uint8_t *p=after.ptrw();const uint8_t *q=before.ptr(); + std::memcpy(p,q,size_t(header)); + wire32(p+header-4,uint32_t(old_count+1-(pop_front ? 1 : 0))); + const int64_t kept=before.size()-header-skipped; + if (kept>0) std::memcpy(p+header,q+header+skipped,size_t(kept)); + if (added>0) wire_integer(p+header+kept,appended); + return true; + } +''' +text=text.replace('#include ','#include \n#include \n#include ',1) +needle=' std::map> cached_edges;';assert text.count(needle)==1;text=text.replace(needle,needle+helpers,1) +needle=' ClassDB::bind_method(D_METHOD("performance_record_sample", "owner", "metric_id", "duration_us"), &TheTreeNumericCore::performance_record_sample);';assert text.count(needle)==1 +text=text.replace(needle,needle+'\n ClassDB::bind_method(D_METHOD("encode_integer_window", "values"), &TheTreeNumericCore::encode_integer_window);',1) +needle=' // Whole builtin integer record operation.' +method=''' Dictionary encode_integer_window(const Array &values) { + Dictionary result;const StringName supported("supported",false),bytes("bytes",false); + result[supported]=false;PackedByteArray encoded; + if (!integer_wire_ready() || !integer_wire_encode(values,encoded)) return result; + result[supported]=true;result[bytes]=encoded;return result; + } +''' +assert text.count(needle)==1;text=text.replace(needle,method+needle,1) +old=' for (int64_t i=0;iint64_t(capacityv); + if (!fast_wire || !integer_wire_update(before,values.is_typed(),old_count,duration,popped,after)) + after=UtilityFunctions::var_to_bytes(values);''';text=text.replace(old,new,1) +(C/'source/tree_numeric_core.cpp').write_text(text);shutil.copyfile(P/'tree_core.hpp',C/'source/tree_core.hpp') +def pin(p):b=p.read_bytes();return dict(path=str(p),bytes=len(b),sha256=hashlib.sha256(b).hexdigest()) +D=R/'docs/plans/original-completion-2026-10-02' +with (C/'input.json').open('x') as f:json.dump(dict(parent_cpp=pin(P/'tree_numeric_core.cpp'),parent_header=pin(P/'tree_core.hpp'),candidate_cpp=pin(C/'source/tree_numeric_core.cpp'),candidate_header=pin(C/'source/tree_core.hpp'),author=pin(Path(__file__)),primary_encoder=pin(A/'p23-02-integer-window-codec-source-r284/marshalls.cpp'),primary_encoder_reference=pin(A/'p23-02-integer-window-codec-source-r284/source.json'),budget=pin(A/'p23-02-native-budget-record-candidate-r257-r04/performance_budget.candidate.gd'),ledger_review=pin(A/'p23-02-progress-integration-actual-independent-review-r282.json'),doc4={n:pin(D/n) for n in ['IMPLEMENTATION_PLAN.md','PROGRESS_INTEGRATION.md','work_packages.json','progress_snapshot.json']},scope='source-only integer Array exact bytes encode and append/pop transformation; per-object engine format check, no cached sample values; old encoding fallback retained; report/values/thresholds/notifications/typed/ownership unchanged; performance and load unproven',engine_runs=0,compiler_runs=0,stage_clones=0,candidate_adopted=False,unit_accepted=False),f,ensure_ascii=False,indent=2) +print('source candidate prepared; source-only, no build or engine') diff --git a/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/reference/marshalls.cpp b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/reference/marshalls.cpp new file mode 100644 index 0000000..4579fb9 --- /dev/null +++ b/docs/plans/original-completion-2026-10-02/checkpoints/integer-window-codec-r285-r02/reference/marshalls.cpp @@ -0,0 +1,2155 @@ +/**************************************************************************/ +/* marshalls.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "marshalls.h" + +#include "core/io/resource_loader.h" +#include "core/object/class_db.h" +#include "core/object/ref_counted.h" +#include "core/object/script_language.h" +#include "core/variant/container_type_validate.h" + +#include +#include + +void EncodedObjectAsID::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_object_id", "id"), &EncodedObjectAsID::set_object_id); + ClassDB::bind_method(D_METHOD("get_object_id"), &EncodedObjectAsID::get_object_id); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "object_id"), "set_object_id", "get_object_id"); +} + +void EncodedObjectAsID::set_object_id(ObjectID p_id) { + id = p_id; +} + +ObjectID EncodedObjectAsID::get_object_id() const { + return id; +} + +#define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(((int32_t)(b)) < 0 || ((int32_t)(a)) < 0 || ((int32_t)(a)) > INT_MAX - ((int32_t)(b)), err) +#define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(((int32_t)(a)) < 0 || ((int32_t)(b)) <= 0 || ((int32_t)(a)) > INT_MAX / ((int32_t)(b)), err) + +// Byte 0: `Variant::Type`, byte 1: unused, bytes 2 and 3: additional data. +#define HEADER_TYPE_MASK 0xFF + +// For `Variant::INT`, `Variant::FLOAT` and other math types. +#define HEADER_DATA_FLAG_64 (1 << 16) + +// For `Variant::OBJECT`. +#define HEADER_DATA_FLAG_OBJECT_AS_ID (1 << 16) + +// For `Variant::ARRAY`. +// Occupies bits 16 and 17. +#define HEADER_DATA_FIELD_TYPED_ARRAY_MASK (0b11 << 16) +#define HEADER_DATA_FIELD_TYPED_ARRAY_SHIFT 16 + +// For `Variant::DICTIONARY`. +// Occupies bits 16 and 17. +#define HEADER_DATA_FIELD_TYPED_DICTIONARY_KEY_MASK (0b11 << 16) +#define HEADER_DATA_FIELD_TYPED_DICTIONARY_KEY_SHIFT 16 +// Occupies bits 18 and 19. +#define HEADER_DATA_FIELD_TYPED_DICTIONARY_VALUE_MASK (0b11 << 18) +#define HEADER_DATA_FIELD_TYPED_DICTIONARY_VALUE_SHIFT 18 + +enum ContainerTypeKind { + CONTAINER_TYPE_KIND_NONE = 0b00, + CONTAINER_TYPE_KIND_BUILTIN = 0b01, + CONTAINER_TYPE_KIND_CLASS_NAME = 0b10, + CONTAINER_TYPE_KIND_SCRIPT = 0b11, +}; + +#define GET_CONTAINER_TYPE_KIND(m_header, m_field) \ + ((ContainerTypeKind)(((m_header) & HEADER_DATA_FIELD_##m_field##_MASK) >> HEADER_DATA_FIELD_##m_field##_SHIFT)) + +static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r_string) { + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + + int32_t strlen = decode_uint32(buf); + int32_t pad = 0; + + // Handle padding. + if (strlen % 4) { + pad = 4 - strlen % 4; + } + + buf += 4; + len -= 4; + + // Ensure buffer is big enough. + ERR_FAIL_ADD_OF(strlen, pad, ERR_FILE_EOF); + ERR_FAIL_COND_V(strlen < 0 || strlen + pad > len, ERR_FILE_EOF); + + String str; + ERR_FAIL_COND_V(str.append_utf8((const char *)buf, strlen) != OK, ERR_INVALID_DATA); + r_string = str; + + // Add padding. + strlen += pad; + + // Update buffer pos, left data count, and return size. + buf += strlen; + len -= strlen; + if (r_len) { + (*r_len) += 4 + strlen; + } + + return OK; +} + +static Error _decode_container_type(const uint8_t *&buf, int &len, int *r_len, bool p_allow_objects, ContainerTypeKind p_type_kind, ContainerType &r_type) { + switch (p_type_kind) { + case CONTAINER_TYPE_KIND_NONE: { + return OK; + } break; + case CONTAINER_TYPE_KIND_BUILTIN: { + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + + int32_t bt = decode_uint32(buf); + buf += 4; + len -= 4; + if (r_len) { + (*r_len) += 4; + } + + ERR_FAIL_INDEX_V(bt, Variant::VARIANT_MAX, ERR_INVALID_DATA); + r_type.builtin_type = (Variant::Type)bt; + if (!p_allow_objects && r_type.builtin_type == Variant::OBJECT) { + r_type.class_name = EncodedObjectAsID::get_class_static(); + } + return OK; + } break; + case CONTAINER_TYPE_KIND_CLASS_NAME: { + String str; + Error err = _decode_string(buf, len, r_len, str); + if (err) { + return err; + } + + r_type.builtin_type = Variant::OBJECT; + if (p_allow_objects) { + r_type.class_name = str; + } else { + r_type.class_name = EncodedObjectAsID::get_class_static(); + } + return OK; + } break; + case CONTAINER_TYPE_KIND_SCRIPT: { + String path; + Error err = _decode_string(buf, len, r_len, path); + if (err) { + return err; + } + + r_type.builtin_type = Variant::OBJECT; + if (p_allow_objects) { + ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, vformat("Invalid script path \"%s\".", path)); + r_type.script = ResourceLoader::load(path, "Script"); + ERR_FAIL_COND_V_MSG(r_type.script.is_null(), ERR_INVALID_DATA, vformat("Can't load script at path \"%s\".", path)); + r_type.class_name = r_type.script->get_instance_base_type(); + } else { + r_type.class_name = EncodedObjectAsID::get_class_static(); + } + return OK; + } break; + } + ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Invalid container type kind."); // Future proofing. +} + +Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_objects, int p_depth) { + ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ERR_OUT_OF_MEMORY, "Variant is too deep. Bailing."); + const uint8_t *buf = p_buffer; + int len = p_len; + + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + + uint32_t header = decode_uint32(buf); + + ERR_FAIL_COND_V((header & HEADER_TYPE_MASK) >= Variant::VARIANT_MAX, ERR_INVALID_DATA); + + buf += 4; + len -= 4; + if (r_len) { + *r_len = 4; + } + + // NOTE: We cannot use `sizeof(real_t)` for decoding, in case a different size is encoded. + // Decoding math types always checks for the encoded size, while encoding always uses compilation setting. + // This does lead to some code duplication for decoding, but compatibility is the priority. + switch (header & HEADER_TYPE_MASK) { + case Variant::NIL: { + r_variant = Variant(); + } break; + case Variant::BOOL: { + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + bool val = decode_uint32(buf); + r_variant = val; + if (r_len) { + (*r_len) += 4; + } + } break; + case Variant::INT: { + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); + int64_t val = int64_t(decode_uint64(buf)); + r_variant = val; + if (r_len) { + (*r_len) += 8; + } + + } else { + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + int32_t val = int32_t(decode_uint32(buf)); + r_variant = val; + if (r_len) { + (*r_len) += 4; + } + } + + } break; + case Variant::FLOAT: { + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double), ERR_INVALID_DATA); + double val = decode_double(buf); + r_variant = val; + if (r_len) { + (*r_len) += sizeof(double); + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float), ERR_INVALID_DATA); + float val = decode_float(buf); + r_variant = val; + if (r_len) { + (*r_len) += sizeof(float); + } + } + + } break; + case Variant::STRING: { + String str; + Error err = _decode_string(buf, len, r_len, str); + if (err) { + return err; + } + r_variant = str; + + } break; + + // Math types. + case Variant::VECTOR2: { + Vector2 val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 2, ERR_INVALID_DATA); + val.x = decode_double(&buf[0]); + val.y = decode_double(&buf[sizeof(double)]); + + if (r_len) { + (*r_len) += sizeof(double) * 2; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 2, ERR_INVALID_DATA); + val.x = decode_float(&buf[0]); + val.y = decode_float(&buf[sizeof(float)]); + + if (r_len) { + (*r_len) += sizeof(float) * 2; + } + } + r_variant = val; + + } break; + case Variant::VECTOR2I: { + ERR_FAIL_COND_V(len < 4 * 2, ERR_INVALID_DATA); + Vector2i val; + val.x = decode_uint32(&buf[0]); + val.y = decode_uint32(&buf[4]); + r_variant = val; + + if (r_len) { + (*r_len) += 4 * 2; + } + + } break; + case Variant::RECT2: { + Rect2 val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA); + val.position.x = decode_double(&buf[0]); + val.position.y = decode_double(&buf[sizeof(double)]); + val.size.x = decode_double(&buf[sizeof(double) * 2]); + val.size.y = decode_double(&buf[sizeof(double) * 3]); + + if (r_len) { + (*r_len) += sizeof(double) * 4; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 4, ERR_INVALID_DATA); + val.position.x = decode_float(&buf[0]); + val.position.y = decode_float(&buf[sizeof(float)]); + val.size.x = decode_float(&buf[sizeof(float) * 2]); + val.size.y = decode_float(&buf[sizeof(float) * 3]); + + if (r_len) { + (*r_len) += sizeof(float) * 4; + } + } + r_variant = val; + + } break; + case Variant::RECT2I: { + ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); + Rect2i val; + val.position.x = decode_uint32(&buf[0]); + val.position.y = decode_uint32(&buf[4]); + val.size.x = decode_uint32(&buf[8]); + val.size.y = decode_uint32(&buf[12]); + r_variant = val; + + if (r_len) { + (*r_len) += 4 * 4; + } + + } break; + case Variant::VECTOR3: { + Vector3 val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 3, ERR_INVALID_DATA); + val.x = decode_double(&buf[0]); + val.y = decode_double(&buf[sizeof(double)]); + val.z = decode_double(&buf[sizeof(double) * 2]); + + if (r_len) { + (*r_len) += sizeof(double) * 3; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 3, ERR_INVALID_DATA); + val.x = decode_float(&buf[0]); + val.y = decode_float(&buf[sizeof(float)]); + val.z = decode_float(&buf[sizeof(float) * 2]); + + if (r_len) { + (*r_len) += sizeof(float) * 3; + } + } + r_variant = val; + + } break; + case Variant::VECTOR3I: { + ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA); + Vector3i val; + val.x = decode_uint32(&buf[0]); + val.y = decode_uint32(&buf[4]); + val.z = decode_uint32(&buf[8]); + r_variant = val; + + if (r_len) { + (*r_len) += 4 * 3; + } + + } break; + case Variant::VECTOR4: { + Vector4 val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA); + val.x = decode_double(&buf[0]); + val.y = decode_double(&buf[sizeof(double)]); + val.z = decode_double(&buf[sizeof(double) * 2]); + val.w = decode_double(&buf[sizeof(double) * 3]); + + if (r_len) { + (*r_len) += sizeof(double) * 4; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 4, ERR_INVALID_DATA); + val.x = decode_float(&buf[0]); + val.y = decode_float(&buf[sizeof(float)]); + val.z = decode_float(&buf[sizeof(float) * 2]); + val.w = decode_float(&buf[sizeof(float) * 3]); + + if (r_len) { + (*r_len) += sizeof(float) * 4; + } + } + r_variant = val; + + } break; + case Variant::VECTOR4I: { + ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); + Vector4i val; + val.x = decode_uint32(&buf[0]); + val.y = decode_uint32(&buf[4]); + val.z = decode_uint32(&buf[8]); + val.w = decode_uint32(&buf[12]); + r_variant = val; + + if (r_len) { + (*r_len) += 4 * 4; + } + + } break; + case Variant::TRANSFORM2D: { + Transform2D val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 6, ERR_INVALID_DATA); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 2; j++) { + val.columns[i][j] = decode_double(&buf[(i * 2 + j) * sizeof(double)]); + } + } + + if (r_len) { + (*r_len) += sizeof(double) * 6; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 6, ERR_INVALID_DATA); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 2; j++) { + val.columns[i][j] = decode_float(&buf[(i * 2 + j) * sizeof(float)]); + } + } + + if (r_len) { + (*r_len) += sizeof(float) * 6; + } + } + r_variant = val; + + } break; + case Variant::PLANE: { + Plane val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA); + val.normal.x = decode_double(&buf[0]); + val.normal.y = decode_double(&buf[sizeof(double)]); + val.normal.z = decode_double(&buf[sizeof(double) * 2]); + val.d = decode_double(&buf[sizeof(double) * 3]); + + if (r_len) { + (*r_len) += sizeof(double) * 4; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 4, ERR_INVALID_DATA); + val.normal.x = decode_float(&buf[0]); + val.normal.y = decode_float(&buf[sizeof(float)]); + val.normal.z = decode_float(&buf[sizeof(float) * 2]); + val.d = decode_float(&buf[sizeof(float) * 3]); + + if (r_len) { + (*r_len) += sizeof(float) * 4; + } + } + r_variant = val; + + } break; + case Variant::QUATERNION: { + Quaternion val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA); + val.x = decode_double(&buf[0]); + val.y = decode_double(&buf[sizeof(double)]); + val.z = decode_double(&buf[sizeof(double) * 2]); + val.w = decode_double(&buf[sizeof(double) * 3]); + + if (r_len) { + (*r_len) += sizeof(double) * 4; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 4, ERR_INVALID_DATA); + val.x = decode_float(&buf[0]); + val.y = decode_float(&buf[sizeof(float)]); + val.z = decode_float(&buf[sizeof(float) * 2]); + val.w = decode_float(&buf[sizeof(float) * 3]); + + if (r_len) { + (*r_len) += sizeof(float) * 4; + } + } + r_variant = val; + + } break; + case Variant::AABB: { + AABB val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 6, ERR_INVALID_DATA); + val.position.x = decode_double(&buf[0]); + val.position.y = decode_double(&buf[sizeof(double)]); + val.position.z = decode_double(&buf[sizeof(double) * 2]); + val.size.x = decode_double(&buf[sizeof(double) * 3]); + val.size.y = decode_double(&buf[sizeof(double) * 4]); + val.size.z = decode_double(&buf[sizeof(double) * 5]); + + if (r_len) { + (*r_len) += sizeof(double) * 6; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 6, ERR_INVALID_DATA); + val.position.x = decode_float(&buf[0]); + val.position.y = decode_float(&buf[sizeof(float)]); + val.position.z = decode_float(&buf[sizeof(float) * 2]); + val.size.x = decode_float(&buf[sizeof(float) * 3]); + val.size.y = decode_float(&buf[sizeof(float) * 4]); + val.size.z = decode_float(&buf[sizeof(float) * 5]); + + if (r_len) { + (*r_len) += sizeof(float) * 6; + } + } + r_variant = val; + + } break; + case Variant::BASIS: { + Basis val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 9, ERR_INVALID_DATA); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + val.rows[i][j] = decode_double(&buf[(i * 3 + j) * sizeof(double)]); + } + } + + if (r_len) { + (*r_len) += sizeof(double) * 9; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 9, ERR_INVALID_DATA); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + val.rows[i][j] = decode_float(&buf[(i * 3 + j) * sizeof(float)]); + } + } + + if (r_len) { + (*r_len) += sizeof(float) * 9; + } + } + r_variant = val; + + } break; + case Variant::TRANSFORM3D: { + Transform3D val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 12, ERR_INVALID_DATA); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + val.basis.rows[i][j] = decode_double(&buf[(i * 3 + j) * sizeof(double)]); + } + } + val.origin[0] = decode_double(&buf[sizeof(double) * 9]); + val.origin[1] = decode_double(&buf[sizeof(double) * 10]); + val.origin[2] = decode_double(&buf[sizeof(double) * 11]); + + if (r_len) { + (*r_len) += sizeof(double) * 12; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 12, ERR_INVALID_DATA); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + val.basis.rows[i][j] = decode_float(&buf[(i * 3 + j) * sizeof(float)]); + } + } + val.origin[0] = decode_float(&buf[sizeof(float) * 9]); + val.origin[1] = decode_float(&buf[sizeof(float) * 10]); + val.origin[2] = decode_float(&buf[sizeof(float) * 11]); + + if (r_len) { + (*r_len) += sizeof(float) * 12; + } + } + r_variant = val; + + } break; + case Variant::PROJECTION: { + Projection val; + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_COND_V((size_t)len < sizeof(double) * 16, ERR_INVALID_DATA); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + val.columns[i][j] = decode_double(&buf[(i * 4 + j) * sizeof(double)]); + } + } + if (r_len) { + (*r_len) += sizeof(double) * 16; + } + } else { + ERR_FAIL_COND_V((size_t)len < sizeof(float) * 16, ERR_INVALID_DATA); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + val.columns[i][j] = decode_float(&buf[(i * 4 + j) * sizeof(float)]); + } + } + + if (r_len) { + (*r_len) += sizeof(float) * 16; + } + } + r_variant = val; + + } break; + + // Misc types. + case Variant::COLOR: { + ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); + Color val; + val.r = decode_float(&buf[0]); + val.g = decode_float(&buf[4]); + val.b = decode_float(&buf[8]); + val.a = decode_float(&buf[12]); + r_variant = val; + + if (r_len) { + (*r_len) += 4 * 4; // Colors should always be in single-precision. + } + } break; + case Variant::STRING_NAME: { + String str; + Error err = _decode_string(buf, len, r_len, str); + if (err) { + return err; + } + r_variant = StringName(str); + + } break; + + case Variant::NODE_PATH: { + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + int32_t strlen = decode_uint32(buf); + + if (strlen & 0x80000000) { + // New format. + ERR_FAIL_COND_V(len < 12, ERR_INVALID_DATA); + Vector names; + Vector subnames; + + uint32_t namecount = strlen &= 0x7FFFFFFF; + uint32_t subnamecount = decode_uint32(buf + 4); + uint32_t np_flags = decode_uint32(buf + 8); + + len -= 12; + buf += 12; + + if (np_flags & 2) { // Obsolete format with property separate from subpath. + subnamecount++; + } + + uint32_t total = namecount + subnamecount; + + if (r_len) { + (*r_len) += 12; + } + + for (uint32_t i = 0; i < total; i++) { + String str; + Error err = _decode_string(buf, len, r_len, str); + if (err) { + return err; + } + + if (i < namecount) { + names.push_back(str); + } else { + subnames.push_back(str); + } + } + + r_variant = NodePath(names, subnames, np_flags & 1); + + } else { + // Old format, just a string. + ERR_FAIL_V(ERR_INVALID_DATA); + } + + } break; + case Variant::RID: { + ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); + uint64_t id = decode_uint64(buf); + if (r_len) { + (*r_len) += 8; + } + + r_variant = RID::from_uint64(id); + } break; + case Variant::OBJECT: { + if (header & HEADER_DATA_FLAG_OBJECT_AS_ID) { + // This _is_ allowed. + ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); + ObjectID val = ObjectID(decode_uint64(buf)); + if (r_len) { + (*r_len) += 8; + } + + if (val.is_null()) { + r_variant = (Object *)nullptr; + } else { + Ref obj_as_id; + obj_as_id.instantiate(); + obj_as_id->set_object_id(val); + + r_variant = obj_as_id; + } + } else { + ERR_FAIL_COND_V(!p_allow_objects, ERR_UNAUTHORIZED); + + String str; + Error err = _decode_string(buf, len, r_len, str); + if (err) { + return err; + } + + if (str.is_empty()) { + r_variant = (Object *)nullptr; + } else { + ERR_FAIL_COND_V(!ClassDB::can_instantiate(str), ERR_INVALID_DATA); + + Object *obj = ClassDB::instantiate(str); + ERR_FAIL_NULL_V(obj, ERR_UNAVAILABLE); + + // Avoid premature free `RefCounted`. This must be done before properties are initialized, + // since script functions (setters, implicit initializer) may be called. See GH-68666. + Variant variant; + if (Object::cast_to(obj)) { + Ref ref = Ref(Object::cast_to(obj)); + variant = ref; + } else { + variant = obj; + } + + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + int32_t count = decode_uint32(buf); + buf += 4; + len -= 4; + if (r_len) { + (*r_len) += 4; // Size of count number. + } + + for (int i = 0; i < count; i++) { + str = String(); + err = _decode_string(buf, len, r_len, str); + if (err) { + return err; + } + + Variant value; + int used; + err = decode_variant(value, buf, len, &used, p_allow_objects, p_depth + 1); + if (err) { + return err; + } + + buf += used; + len -= used; + if (r_len) { + (*r_len) += used; + } + + if (str == "script" && value.get_type() != Variant::NIL) { + ERR_FAIL_COND_V_MSG(value.get_type() != Variant::STRING, ERR_INVALID_DATA, "Invalid value for \"script\" property, expected script path as String."); + String path = value; + ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, vformat("Invalid script path \"%s\".", path)); + Ref