Skip to content

docs: separate current contracts from implementation records - #185

Merged
link1345 merged 2 commits into
mainfrom
docs/separate-contracts-from-work-logs
Oct 29, 2026
Merged

link1345 merged 2 commits into
mainfrom
docs/separate-contracts-from-work-logs

Conversation

@link1345

@link1345 link1345 commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Current protocol specifications and guides mixed reusable contracts with one-time implementation progress and test results. Keep requirements, assertions, reproduction procedures, compatibility boundaries and current limitations in the durable documentation; link historical results to their preserved records.

Changes:

  • Observe/transport and Value: remove dated local success counts and review-fix reports; retain fixture expectations, engine/Web reproduction and unverified scope.
  • Spatial/distribution and Trace: replace implementation milestone/closure narratives with evidence references and current contract descriptions. Clarify historical PR Verify spatial nonleakage and real packaged engine routes #168 route scope so it does not imply current-head acceptance.
  • Developer guide: define the boundary between current contracts, PR reports and historical evidence.

Preservation: pre-cleanup originals and provenance, linked to immutable source b398e53, were saved and fetched before removal. Existing intentional evidence histories, release documentation and measured engine profiles remain in place. Historical Observe records do not supply an exact executed SHA/log URL; no provenance was invented.

Validation at 679902e:

  • Documentation-only cumulative diff: 8 Markdown files; no runtime/schema/fixture/workflow changes.
  • Local consistency check: 99 relative links/anchors, balanced code fences, 5 removed headings without incoming references; git diff --check passed.
  • One bounded independent read-only gua-bug-hunt documentation audit: no actionable findings. It fetched the preservation record and checked contract/limit retention. This does not reset or repeat prior implementation audits.
  • Final-head Syntax Check completed successfully: 18/18 jobs passed, no failed, pending or skipped jobs. Includes Godot Web, four-RID Godot desktop, four-RID native bridge and package smoke, NuGet packing, C#/C++/TypeScript and version metadata. Intel macOS Godot desktop took 28m44s and completed normally; no retry or code change was needed. Earlier-head runs are not counted.
  • Final automatic-review observation: 0 review submissions, 0 inline review comments, 18 checks all from GitHub Actions and no separate review workflow/check found. This reports the visible configuration/results, not a completed automatic code review.

Unverified scope: runtime, GUI, actual game and Playtest E2E were not rerun locally for this documentation change. Native Intel macOS Unity Editor remains UNVERIFIED; built-in privileged browser spatial remains Unsupported. Draft only; no merge, formal approval, auto-merge or release.

link1345 commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator Author

Preserved pre-cleanup records

Before removing duplicated work reports from durable guides/specifications, retain their original text below. Canonical source snapshot: https://github.com/gua-project/gua/tree/b398e531558f38220baf0b606e7c3f33904a87a5 . Each SOURCE path below resolves against that immutable revision. This snapshot is the provenance of the documents, not a claim that the historical tests executed on b398e53. Where the original record supplies no exact tested SHA or log URL, that remains unspecified; no new runtime/GUI/E2E execution is claimed.

The Observe local record (2026-09-29), transport execution results and Value local-result column move here. Spatial prerequisite/closure progress and the distribution acceptance narrative remain accessible in this snapshot and the existing docs/evidence, remaining-route-acceptance.md and spatial-acceptance-followup.md records. Trace's implementation milestone table remains available here and in trace-integrated-acceptance.md. Intentional historical evidence files, release plans and measured engine profiling are retained in place.

SOURCE: protocol/specs/observe-v1.md
## 公開profileと秘密値

既定はDebugのみ。Playerへの公開には登録のallow_playerと、既存のOwner投影条件の
両方が必要。World Propertyにはノードの親がないため明示allow_playerを条件とする。
標準fieldの個別field-ruleを同名Observeへ流用しない。秘密の追加値にはsensitiveを指定する。
sensitiveの値はコピー・Snapshot・通知履歴へ入れる前に除外し、取得不能理由だけを残す。
getterは通常どおり評価するが、その戻り値・例外本文を診断へ出さない。

PlayerとDebugのsequence/revision/historyは分離する。Playerで見えるOwner集合に
含むのは、allow_playerの登録を一つ以上持ち、Owner投影条件も満たすOwnerだけである。
登録なし・Debug専用登録だけのOwnerの作成・破棄ではPlayer履歴やrevisionを変更しない。
Playerで見えるOwner集合が
変わるとPlayer履歴を破棄して既存cursorをgapにする。これは削除・非表示・公開範囲変更を
含む。Playerは再購読して現在の公開集合を取得する。Debugは通常のremoved等を受け取る。
この再同期により、非公開化前の履歴を後からpollして読めない。
すでに呼出側へ返却したimmutable Snapshot/Changeの回収は保証しない。

## 公開APIと互換性

C: `gua/observe.h`。全status APIは0成功、1引数、2失効、3重複、4フレームなし、5内部失敗。
versioned登録descriptor、不透明な結果ハンドルを使う。Valueコピーのため
`gua_value_clone`を追加する。既存ABI構造体・version番号・既存wireレスポンスは変更しない。
ABI呼出とcontext破棄は他のcontext APIと同様にホスト側で同期する。

C++: `gua/observe.hpp` のObserveOwner、ObserveRegistration、ObserveSubscription。
Contextの寿命tokenを追跡し、破棄後のハンドル解放はnativeへアクセスしない。
登録はRAIIで保持する。getterは`Value`を返し、getter保持とフレーム呼出はホスト側で同期する。

.NET: GuaContext.CreateObserveOwner / SubscribeObservations / GetObserveSnapshotJson。
UI/ObjectはOwner.Observe、WorldはOwner.Property(C++はproperty)を使う。
getterは**新しい所有GuaValue**を返す。wrapperがコピー後Disposeするので、
共有して使い回すValueを返さない。登録tokenを保持し、不要時にDisposeする。新規APIは
reset/Disposeと同期し、返却JSONのnative handleはSafeHandleで解放する。

```csharp
using var owner = context.CreateObserveOwner(GuaObserveSource.Object, "enemy-1");
using var phase = owner.Observe("phase", () => GuaValue.String(enemy.Phase));
using var subscription = context.SubscribeObservations();
var initial = subscription.SnapshotJson;
// ゲーム側で中間変化を公開したい時点:
phase.Notify();
var changes = subscription.PollJson(); // statusを必ず確認する
```

## 要件・検証・後続

| 要件 | G-02の検証 | 後続 |
| --- | --- | --- |
| AT-OBS-001 | 複数Owner同名、重複拒否、解除・破棄・再生成、reset | #120 実エンジン寿命への接続 |
| AT-OBS-003 | added/changed/removed、取得不能・復旧、理由、秘密値 | #125 Trace保存 |
| AT-OBS-004 | 原子的Snapshot+cursor、並列publish、独立購読、件数/byte欠損 | #120 transport切断、#125 欠損保存 |
| VALUE-002 | 共通Value等価・不正値・collectionコピー | #120 wireでの型保持 |
| TIME-002 | frame/explicitの順序、UI/World別frame、epoch | #125 収集時計との関連付け |

共通fixtureは `protocol/fixtures/observe-v1.json`。native/C++と.NETが遷移例を実行し、
Bun/Ajvが正常・異常documentを検証する。既存Value/UI/World/reset試験を維持する。
Godot/Unity、Gua.Runtime/bridge、MCP/WebMCP、Inspectorの接続は[Observe transport v1](observe-transport-v1.md)を参照。
Trace writer/reader/Viewerと製品E2Eは#125ほか。GuaのCIからPlaytestを参照しない。
検証実績は変更の引き渡し時に記載し、未実行のremote CIやengine E2Eを成功扱いしない。

### ローカル検証記録(2026-09-29)

- MSVC 19.51 + Ninja、Godot無効・WebSocket bridge有効でビルド成功。
  VS2026標準presetはローカルのinstance検出に失敗したため、VsDevCmd経由のNinja構成を使用。
- CTest 8/8、Gua.Selector.Tests 144/144(skipなし)。C++ getter内Context moveの追加回帰も成功。
- Gua.Coreのnet10.0 / netstandard2.1ビルド、全workspaceの`bun run check`成功。
- Value/ObserveのBun 87/87、実native/.NET出力8 documentのAjv検証成功。
- 読み取り専用監査のOwner明示破棄後Player履歴、.NET getter内Disposeを失敗試験で再現し修正。
  C++ getter内Context moveも寿命tokenを維持する回帰試験で修正を確認。
- remote CI、他OS、エンジンのObserve接続、Traceへの保存は未実行・今回の統合完了対象外。
SOURCE: protocol/specs/observe-transport-v1.md
各要素のvalue/before/afterは、そのValueで使用するEnum Catalog v1の定義一つだけを含む。
非enum・取得不能の箇所は省略する。欠損時はevents/catalogsをともに空にする。
標準worldPositionはWorld Object TreeのruntimeIdで関連付け、追加phaseだけ登録する。
両方の取得は同時Snapshotとは限らず、sourceId/epoch/UI・World frame/revisionを保持する。

## 検証

実native登録→runtime→WebSocket→実.NET clientで型・候補、同名Owner、変更、
getter失敗、gap、reset、他接続の拒否、Player秘密値を検証する。
実エンジンの検証結果、Web export、他OS、remote CIの未実行は引き渡しで区別する。

## ホストでの登録例

登録はUI/Worldの最初の公開後に行う。標準位置はWorld treeの`position`を読み、
追加値の`runtimeId`で同じObjectに関連付ける。登録tokenとOwnerをObjectの寿命中保持する。

```csharp
// GuaRuntimeで最初のWorld frameを公開した後
using var catalog = new GuaEnumCatalog();
catalog.Register("game.Phase", "First", "Second");
using var owner = runtime.CreateObserveOwner(GuaObserveSource.Object, "enemy-1");
using var phase = owner.Observe("phase", () => GuaValue.Enum("game.Phase", enemy.Phase, catalog), allowPlayer: true);
// 通常はEndWorldFrameでsample。必要ならphase.Notify()で明示通知。
```

Godotは`adapter.register_value_enum("game.Phase", ["First", "Second"])`、
`adapter.create_observe_owner(2, "enemy-1", enemy)`から`owner.observe(...)`を使う。
Ownerを保持して、treeから消えると登録を無効化、target解放とadapter破棄でも解除する。
Unityは公開済み`GuaWorldObject.Observe(...)`を使う。OnDestroyとID変更でOwnerを解除する。
Webのnative clientはPlayer固定で、detach/OnDestroyで購読を解放する。

C ABIには`gua_value_copy_enum_catalog_json`、
`gua_observe_result_copy_transport_json`を追加した。既存copy JSONは以前の形式を維持する。
C++は`enum_catalog_json()`、`observe_snapshot_transport`、
`ObserveSubscription.snapshot_transport(初期snapshot)/poll_transport()`。
.NETのlocal Contextは`GetObserveSnapshotTransportJson`と`SnapshotTransportJson/PollTransportJson`、
remote `GuaWebSocketContext`のObserve APIはtransport形式を返す。
InspectorはObserve panelで候補と通知を表示し、gap/staleで再購読を要求する。
MCP/WebMCPは同名の4 commandを公開し、remote側から登録・profile選択はできない。

## 実行した検証と残る境界

Windows MSVC / Godot 4.7 / Unity 6000.7.0b2で検証。

- native C/C++ CTest 8/8。catalog破棄後のsnapshotと履歴、空enum set、buffer契約を含む。
- .NET Selector tests 193/193(Observe transport統合9件を含む)。実native runtime→WebSocket→.NET。
- 実Godot GDScript smoke:enum、空list、Player投影、非公開化のgap、破棄通知。
- 実Unity desktop Player:Debug/Player 2/2。World位置、追加phase、候補、空list、秘密値除外、変更、reset。
- 実Godot→Inspector/MCPの各WebSocket client:独立購読、semantic click、変更poll。
- TypeScript全workspace check成功。対象Bun tests 226/226。
  WebMCPはcapability、購読解除、timeout後の遅延応答の解除を試験。

外部clientの再現はGodotで`--headless --path examples/godot-gdscript --script scripts/gua_observe_fixture.gd`
を起動し、`GUA_BRIDGE_PORT`と`GUA_OBSERVE_BRIDGE_URL`を揃え、
`bun scripts/run-observe-client-smoke.ts`を実行する。
Godot Web/Unity WebGLの実exportをheadless Chromeで起動し、実Object登録→Player snapshot→
SDK toolからsemantic click→両独立購読の変更通知→解除を確認した。
Godotは空enum set、Unityは空enum list。両方ともenumTypeと候補を保持する。
UnityのIL2CPPで非参照Bootstrap assemblyが除去される問題を再現し、
`AlwaysLinkAssembly`でフレーム駆動を維持する修正後の実exportで確認した。
.NETは応答喪失時のsocket破棄・再接続と64件上限の明示拒否後の既存token維持を試験。
不足symbolのDLL注入では初期化失敗時のnative destroyが一度だけ呼ばれることを確認した。

Webの再現はGodotのmain sceneを`GuaObserve.tscn`へ設定してWeb debug exportし、
Unityは通常fixtureをWebGLへexportする(TMP準備は既存`import-unity-tmp-resources.ps1`)。
`bun scripts/verify-observe-web-export.ts godot <export-directory>`、
`bun scripts/verify-observe-web-export.ts unity <export-directory>`を実行する。
Godot desktop/Webは同じ`gua_observe_fixture_host.gd`で登録し、Unityもdesktop/Webで同じfixtureを使う。
Web試験のmodelContext登録先はtool実行を呼び出す試験hostであり、データと操作は実エンジン。
Chrome実験版のネイティブmodelContext API、他OS、remote CIは未検証。
SOURCE: protocol/specs/value-v1.md
- C: `gua/value.h`。不透明なValue/Catalogハンドル、versioned descriptor、
  型付き生成、JSON読取・出力、型情報、登録、比較、破棄を提供する。
  `gua_enum_catalog_validate_type`で候補取得前にもUnicode・ID形式・登録有無を検証する。
  `gua_value_text_t.size`はUTF-8バイト数。入力をコピーし、collectionも要素を所有する。
  関係する元ValueやCatalogの破棄後も生成済みValueは有効。
- C++: `gua/value.hpp`の`gua::Value`/`gua::EnumCatalog`。
  move可能なRAIIラッパーと型別factoryを提供する。C ABIへ委譲し、別の比較実装を作らない。
- C#: `Gua.Core.GuaValue`/`GuaEnumCatalog`。SafeHandle/P/Invokeで同じnative実装を使用。
  `Bool`、`Integer`、`Number`、`String`、`Enum`、`Collection`、`FromJson`、`ToJson`、
  `ValueEquals`を提供する。Disposeとの競合ではSafeHandle参照でnative寿命を保持する。
- TS: `gua-value-tools`。判別union、`createValue`、`parseValue`、`serializeValue`、
  `valuesEqual`、`EnumCatalog`を提供する。検証時にコピー・freezeする。
  enum値の検証・出力・比較には対応するcatalogを渡す。

Cのstatusは0が成功。失敗時のoutハンドルはNULL。C++/C#/TSは型付き例外へ変換する。
生成済みValueは不変で並行読取可。Catalog登録・破棄は読取と呼出側で同期する。
C出力は終端NULを含む必要バイト数を返す。NULL/0でサイズ取得し、短いbufferは空文字にする。
0の戻り値は不正なbuffer指定などの失敗。切れたJSONは返さない。
C ABI境界のC++例外は捕捉し、allocation等の失敗はinternalに変換する。

| Cコード | TSコード | 意味 |
| --- | --- | --- |
| 1 | structure | JSON構造、必須・未知フィールド、API引数の不正 |
| 2 | forbidden_type | 禁止型、入れ子、未知のtype |
| 3 | range | integer範囲外または非整数 |
| 4 | non_finite | 非有限numberまたはoverflow |
| 5 | unicode | 不正UTF-8または孤立サロゲート |
| 6 | enum_unknown | 未登録enumType |
| 7 | enum_conflict | 同じIDで異なる候補集合 |
| 8 | enum_member | 候補にない名前 |
| 9 | element_type | scalar値/collection要素の型不一致 |
| 10 | duplicate | set要素/enum候補の重複 |
| 11 | internal | メモリ割当等の内部失敗 |

## 互換性と後続統合(OPEN-01 / OPEN-02)

G-01のOPEN-01は独立Value v1 schemaと追加のC ABIシンボルで解決する。
既存ABI構造体・wire schema・protocolSchemaVersion・abiVersionは変更しない。
旧clientがadditionalPropertiesを拒否する既存レスポンスへ新フィールドを追加しない。
型生成器は導入せず、手書きの各言語型を共通fixtureで照合する。

G-01のOPEN-02は上記enum・Unicode・integer/number・collection規則で解決する。
containsAll/Any、regex等の条件演算子はP-03で定義する。Observe/Property、
Snapshot/Change、Assertion、注釈への組み込み時にはこのValue契約を参照する。
それらのエンドポイント・新field・capability negotiationはG-02/G-03以降で実装し、
本変更だけで旧clientとの新Observe通信が完成したとは扱わない。

## 要件と検証の対応

共通fixtureは `protocol/fixtures/value-v1.json`。`valid`と`invalid`は元JSON文字列を保持し、
丸め前の整数や重複キーも照合する。`comparisons`は型を含む等価期待値、
`generators`はNaN/Infinity/BigIntの生成指示である。BigIntを型として持たないC/C#では
対応factoryが存在しないことと未知タグ拒否を確認する。

JSON Schemaは構造・型・通常の数値範囲・uniqueItemsを検証する。
enum参照/定義衝突、Unicode、重複JSONキー、丸め前の整数、非JSON値は意味検証で保証する。
`schemaReject`は汎用JS schema validatorでも拒否できる異常例を区別する。

| 要件 | 検証 | ローカル結果 |
| --- | --- | --- |
| AT-VALUE-001 | 全7型、各空collection、往復、型保持 | native / C# / TS 成功 |
| AT-VALUE-002 | 整数境界・丸め、小数、非有限、禁止型、Unicode、識別可能な拒否 | native / C# / TS 成功 |
| AT-VALUE-003 | enum候補取得、型違い、alias、定義衝突 | native / C# / TS 成功 |
| AT-VALUE-004 | set順序、list順序、重複、-0、空の型 | native / C# / TS 成功 |
| AT-VALUE-005 | 既存World nullとInput vector2、新Value制限の分離 | 互換回帰試験で確認 |
| ASSERT-003 | integer/number、enumType、collection型を含む等価 | native / C# / TS 成功 |

MSVC CTest、NUnit、Bun/Ajvで同じfixtureを消費する。CIにはportable native jobの
CTest/NUnitと両managed targetビルド、既存TS jobのValue試験を組み込む。
ローカルWindowsの成功と、未実行のリモートCI・他OS・後続Observe統合は区別する。
SOURCE: protocol/specs/spatial-r1.md
fractions for bracket; for estimate it uses distance units if distance exists,
otherwise fractions. Never convert an estimate to a rigorous safe bound, or
require motion evidence to decide clear versus non-clear. Matched estimate
distance cannot exceed delta length. Distance/fraction relations are native
evidence, not recomputed. zeroLength is the separate overlap-only tag.
clear with a nativeBracket requires both fractions to be 1; a native unsafe
boundary partway through the delta contradicts clear. A ray hit distance is
measured from the segment origin and cannot exceed its finite segment length.

## SP-06: version, ABI and .NET

`gua/spatial.h` adds independent immutable owned document handles, v1 options
(uint32 struct_size + int32 document_type), error (int32 code + char path[128]),
length-delimited UTF-8 input and JSON copy/destroy/check APIs. Exact v1 size is
required. Future layouts need a new API; future schema versions return Version.
Dedicated schema JSON carries all fields losslessly (decimal lexemes retained);
no arbitrary object is added to common Value or existing stable ABI structures.
Input storage is copied. C callers synchronize destruction with readers.
Short output buffers are cleared; required bytes include NUL; invalid buffer
arguments return 0. Failure clears the output handle and catches C++ exceptions.
Errors contain safe protocol paths, never submitted values/unknown keys.

| Contract | C ABI | C++ | .NET |
| --- | --- | --- | --- |
| request/result/provider | opaque document + type 1/2/3 | SpatialDocument | GuaSpatialDocument + authoring DTOs |
| vector/basis/shape/segment | schema JSON, finite binary64 | native-owned JSON | GuaSpatialVector/Basis/Shape/Segment |
| metadata | exact safe integers, UTF-8 strings | same native validation | long/string, native range validation |
| optional facts | absent fields + reasons/tags | lossless copy | nullable properties, omitted on serialization |
| matching | check_request/check_result | same methods | CheckRequest/CheckResult |
| lifetime | explicit destroy | move-only RAII | SafeHandle retained during calls |

.NET authoring DTOs are mutable copies; FromRequest/Result/Provider serializes
and native-validates an immutable document. Read methods return independent
typed copies. net10.0 and netstandard2.1 delegate via P/Invoke, with gua or
__Internal under GUA_STATIC_LINK. No second semantic implementation is added.
Native-validated integral decimal/exponent metadata (1.0 / 1e0) is decoded into
managed integers without precision loss. Typed authoring copies normalize
number spelling while native JSON copy preserves original decimal lexemes.
Status codes 1..7 map to Invalid/Version/Geometry/Context/Unsupported/Semantics/
Internal. Validator Unsupported is distinct from an executed unsupported result.
Nonfinite authoring doubles are rejected by System.Text.Json before native parse.

`spatial_read_r1` is the canonical additive runtime capability. Supporting hosts
negotiate it plus provider r1 metadata before dedicated typed reads. Offline
validation does not advertise it. The #132/#133 host pump and readers plus the
[#134 transports](../../docs/spatial-transport-r1.md) advertise it only after
explicit host authorization and provider binding. Existing clients do not require
it. Spatial-r1 is explicitly enabled Testing/Debug only, denied for Player/
Public Agent. Old default profiles, abiVersion/protocolSchemaVersion, World/
Input schemas, Observe sources/values and Trace remain unchanged.

## Acceptance mapping and evidence

Shared spatial-r1 fixtures are consumed by native C++ and .NET. C tests verify
layout/import/error handling; Ajv verifies schema-expressible cases. Semantic
cases (orthogonality, ordering inequalities, exact decimal integers, duplicate
keys) are marked schemaReject false. Existing four-RID native/.NET CI picks up
the tests; the Value Bun suite picks up schema tests. Legacy tests remain active.

| #131 acceptance | Decision | Evidence |
| --- | --- | --- |
| schema/mappings + normal/rejected/unsupported/unknown | SP-02/03/06 | valid/invalid fixtures and typed roundtrips |
| NaN/Infinity, dimensions, basis, spaces/epochs, zero/unsupported | SP-01/02 | invalid + requestChecks/resultChecks |
| initial/travel, contact/penetration, hits/truncation/coverage | SP-03 | independent facts and semantic rejections |
| bracket/estimate, missing normals/refs | SP-03 | anonymous/truncated bracket and estimate fixtures |
| legacy World/Input and old clients | SP-06 | unchanged schemas, existing tests, additive version check |

Fresh prerequisites #72/#73/#98/#118 were closed/completed at implementation
start on main 60c903b3b218310cc2bf13d2d583fdcc987dee51. Contract tests are not
adapter execution, engine precision, performance, distribution or Trace proof.
SOURCE: protocol/specs/trace-v1.md

| 子 Issue | 実装済みの範囲 | 保証境界・利用側の責務 |
| --- | --- | --- |
| #123 T-01 | schema、writer/reader、有限上限、4 保存組合せ、部分末尾、redaction、容量/中断の故障 fixture | 強制終了時の未flush/メモリのみの保存は保証対象外 |
| #124 T-02 | Selector/解決ID、明示/自動Step、native UI/Input/cleanup lifecycle、遅い結果、非破壊履歴 | native履歴未提供hostのphaseは未提供と表示。ゲーム画面でのGodot/Unity E2Eは別途 |
| #125 T-03 | Snapshot/観測の分離、Observeの実native/実WebSocket購読、Value/カタログ、中間Change、欠損、独立UI/World読取 | ゲーム内部の未公開変化、失われた履歴の復元は保証対象外。各Runnerが取得契機を明示する |
| #126 T-04 | 外部 Runner API、共通 Value、未知注釈/添付、評価/主結果/cleanup分離、native/Observe横断fixture、framework-free配布consumer | 任意の外部Runnerの採点・非公開情報の自動判別・ゲーム画面のE2Eは保証対象外 |
| #127 T-05 | 共通 React、静的 HTML、timeline/状態/JSON/区間差分、caller-authorized PNGとbounds overlay、全端点・欠損表示、版固定資産/schema配布 | 同時pixel/snapshot取得とpixel秘密判別はcaller責務。ゲーム操作・Replay・外部添付fetchは対象外 |
| #128 T-06 | 明示Lint report、明示baseline comparison、既存diagnostics session、Recordingの実API接続とnative/Observe統合fixture | 実ゲーム/利用側RunnerのE2E、pixel秘密判別は保証対象外。実行証拠はtrace-validation.md |

## T-06 既存機能の明示接続(#128)

`GuaTraceCapture.Lint(trace, step, report)` は明示実行済みの
`GuaSemanticLinter.Analyze` のreportを `gua.semantic-lint.v1` 添付にする。
実行や採点は行わず、reportのprofileとTraceのprofileが違えば保存しない。

`SemanticSnapshotOptions.Trace/TraceStepId/TraceProfile` は呼出側が実行した
`CompareSnapshot/ExpectSnapshot` の結果を `gua.semantic-comparison.v1` にする。
既存getterと保存baselineのPlayer投影を証明できないため、この自動添付はDebug限定。
`TraceProfile = Player`でもPlayer TraceへDebugのactual/expectedを添付しない。
添付拒否は明示比較/baseline更新の既存動作を変えず、品質へ残す。
matched/baselineUpdated/reason/runId、rules適用済みexpected/actual/differencesを保存する。
比較artifactやbaselineの絶対pathは含めず、任意ファイルを読み込まない。
Traceがなくても既存の結果・例外・artifact・明示更新の契約は同じである。
Traceを指定しても `UpdateBaselines` / 明示環境変数を変更しない。
runtime metadata/geometryの比較除外は比較添付だけに適用し、Tree/Observeからは削除しない。
TraceProfileは既に認可された取得元のprofileで、DebugからPlayerへの変換機能ではない。
context/World getterの認可、profile/build別のBaselineVariantとmask rulesは呼出側の責務。

`GuaRecordingTrace.Attach` は `GuaRecordingFile.Validate` 済みRecordingを
`gua.trace.recording.v1` 添付にし、元のRecording Save/Load形式を変更しない。
`trace-recording.schema.json`のschemaVersion=1/recording envelopeを使う。recording内は
redaction済みのopaque JSONで、敏感Stepの`{redacted:true}`も含む。元Recording parserで読み込まない。
Trace側のwhole-object redactionによりsensitive stepは伏せられる。
`gua.recording.references.v1` は元stepのindex、十進文字列requestId/eventIdと安全なsecretKey参照を
別に保持する。source/epochは関連Trace Stepの実測要求相関を使い、RecordingのrequestIdだけから
別接続/epochへ推定相関しない。Traceの伏せられたRecording添付はReplay可能と称さない。
secretKey自体に秘密を使わず、必要ならSecretsへ登録する。拒否/Timeout/中断は通常の
Trace Eventへ残し、Recordingの成功stepを捏造しない。

`GuaDiagnosticOptions.Trace/TraceStepId/TraceProfile` を指定すると既存の
`GuaDiagnosticsSession` / Writerはcontext解放前に公開diagnosticsを同じStepへ保存する。
未profile選択の既存getterを使う自動添付はDebug限定。Playerは下記の認可済みgetter
overloadを使う。ラベルだけでDebug payloadをPlayerとして保存しない。
logs/pendingRequests/environment等を保ち、Screenshotは常に取り除く。
元payloadを全`diagnostics.schema.json`(version/UI/logs等の参照を含む)で先にvalidateする。
既存`gua.diagnostics.v1`は互換性を保つTrace projectionで、`trace-diagnostics.schema.json`を契約にする。
Screenshot省略とnested redactionを許し、元runtime diagnostics形式とは区別する。
version、呼出側environment/callerMetadataは `gua.environment.v1` の別添付にする。
このlegacy自動コピーもDebug限定。Playerへ既存environment/callerMetadataをラベルだけで移さず、
明示的に認可済みdataを渡す`GuaTraceCapture.Environment` APIを使う。
`gua.environment.v1`共通fieldはcamelCaseのversion/environment(自動Debugコピーには任意callerMetadata)。
両APIは同じTrace serializerを使う。既存version.jsonのPascalCaseは変更しない。
既存diagnosticsのディスクファイルや例外本文をTraceへimportせず、それらの既存policyを
再マスクする機能ではない。取得/保存/表示故障はTrace品質として扱い、元例外を置き換えない。
live読取後のJSON必須property欠損、file生成、supplement/sink故障もdiagnostics-failed品質と
capture.failureへ記録する。故障の例外本文やpathはTraceへコピーしない。
`GuaTraceCapture.Diagnostics(trace, step, IGuaContext)` はprofile未選択のためDebug限定。
Player/remoteは認可済みgetterとprofileを明示するoverloadを使う。

`JsonAttachment` はprofile不一致をgetter実行前に拒否する。失敗はfalseとcapture.failure、
attachment-failed/attachment-unavailable/profile-mismatch等の品質issueを残し、
大きなpayloadのlimit停止後も小さなterminal failure eventは通常の予算内で記録を試みる。
queue/artifactが満杯なら追加eventを保証せず、最大64品質issue内の
`capture-failure:<retained stepId>:<channel>:<reason>`へ相関を残す。容量上限を緩めない。
主結果PassedでもOnFailureで破棄しない。JSON redactionは保持/hash前、Screenshotのpixel認可は
別APIのまま。汎用添付schemaや未知recordはViewerが安全なtextとして表示する。

Gua は Gua Playtest に依存しない。Observe 本体、InputAction metadata、Replay 時間制御は
この変更では実装しない。未提供の依存 API を仮実装して完了扱いにはしない。
SOURCE: docs/distribution-contract.md
unknown-property rules. No failure was demonstrated on the supported
same-release paths; this caveat does not require a runtime compatibility fix
or a major-version change before the proposed 1.1.0 publication.
The current native version API reports `abiVersion: 1` and
`protocolSchemaVersion: "2"`; versioned descriptor structs remain additive C ABI
extensions. The external consumer asserts these values and retains
`core-version.json` / `runtime-version.json`, including actual capability lists.
Use `GuaVersion.EnsureCompatible` to check a consumer's required ABI/protocol and
capabilities before operation. Those lists describe the connected context and
must not be copied into an engine-wide support claim.
The resource API and `schemas/` package directory are additive; existing `trace/`
entries stay available. UI tree schema v2, Trace v1, Selector and InputAction
metadata schemas retain their independent versions. The Recording JSON schema
accepts v1/v2. `GuaRecordingFile` retains its UI Recording v1 reader/writer and
rejects v2; `GuaTimedSegmentImport.FromRecording` explicitly converts only
game-input v2 to an independent timed-segment v1 plan. The merged #122 contract
ships `timed-segment-v1.schema.json` and `timed-segment-result-v1.schema.json`.
`GuaTimedSegmentFile.Save/Load` round-trips a bounded plan without native code.
The external smoke retains legacy UI v1 compatibility, preserves imported
offsets/defaults and `legacy-unknown` provenance, rejects undeclared versions,
validates package-local schema references and round-trips a values-free timing
result serialization fixture through Trace. A file round trip does not execute
Replay or establish host application timing.

| Serialized contract | Read/write support at this candidate boundary |
| --- | --- |
| UI tree | v2; additive optional state fields remain omitted when unsupported |
| Trace | v1 reader/writer; unknown major versions rejected, additive fields retained |
| Recording | JSON schema v1/v2; managed UI v1 round trip and v2 rejection; explicit game-input v2 timed import |
| Timed Segment | Independent v1 plan/result schemas; managed plan import/file round trip with unknown original timing provenance and result serialization fixture; host Replay support verified separately |
| Semantic Selector | Existing `selector.schema.json` string-criterion objects; no new selector grammar |
| InputAction map | Existing v1 preserved; explicit v2 metadata map/search use their separate schemas and `semantic_game_input_metadata_v1` capability |
| Observe / Value / Spatial | Independently pinned v1/r1 schemas; execution/provider support negotiated separately |

`syntax-check.yml` runs package-only acceptance on all four real RID runners and
uploads `gua-distribution-<rid>-<commit>` evidence. No skip counts as a pass.
`nuget-publish.yml` repeats the same gate before public NuGet publication. The
GitHub release asset packer extracts and validates both actual Godot ZIPs,
including `gua_spatial.gd`, licenses and required desktop/Web binaries, before
uploading them. Composition checks do not substitute for engine execution.

Run the candidate consumer from an exact package feed:

```powershell
scripts/verify-distribution-consumer.ps1 -PackageDirectory artifacts/packages `
  -Version 0.0.0-ci -SourceCommit <full-commit> -Rid win-x64 `
  -OutputDirectory artifacts/distribution-evidence
```

| Requirement | Inspectable evidence |
| --- | --- |
| AT-BOUND-001 | Package-only consumer project; no ProjectReference, source Include or HintPath; no Gua-to-Playtest reference |
| AT-FILE-002 | Exported pinned schemas, source commit/hash manifest; offline run with native libraries removed; embedded Viewer metadata |
| AT-PACK-002 | Consumer copied outside the repository; isolated NuGet caches; local-feed-only acceptance restore; native overrides rejected |
| AT-PACK-003 | Extracted self-contained consumer ZIP and fresh installed .NET Tool run, package manifests and embedded report |

Candidate acceptance incorporates merged #122 at
`989163781a0e5ce6ac629e99a7d140a47e0db1ad` and repeats the four-RID consumer gates.
Issue closure requires exact-head required CI/audit success and a mapping of
the original #129 acceptance conditions to the identified target artifacts,
environment, assertions, results and remaining support scope. Retain package
versions, source commits, hashes, dependency/license manifests, Viewer evidence
and actual launch/attach/operation evidence for each declared RID/route; skips,
loading alone and unrelated consumer success do not satisfy those conditions.
The four-RID package gates and PR #168 Godot evidence can be reused within their
measured scope. The owner closed #129/#130 with the native Intel Editor
unverified limitation retained and tracked in #174; see the current acceptance
record above. Closure is not a claim that every declared route passed. Public
publication is separate and is neither required for closure nor authorized by
successful artifact acceptance.
SOURCE: docs/spatial-transport-r1.md

1. scene / spaceEpoch / 衝突 policy / 許可領域をホストで明示登録し、実測済み
   backend の `GuaUnitySpatial` または `GuaSpatialReader` を作成する。
2. 同じ scheduler を現在の sessionEpoch の Testing 許可で runtime へ bind し、
   既存 bridge を開始する。Debug 設定だけでは照会を公開しない。
3. `GetSpatialInfo()` / `get_spatial_info` で能力と上限を確認し、公開された
   space/epoch/policy の Overlap / Sweep batch を送る。
4. 各 item の state/reason と coverage/truncation/未知情報を確認する。
   不明、未対応、途中停止は「完全に通れる」結果に置き換えない。再接続後に再送しない。
5. 呼出元の outcome で Trace を確定し、既存 Viewer の汎用 attachment 表示で
   sample、実効 policy revision、backend、失敗理由を確認する。

raw 地形は明示許可された policy と領域でのみ読める。空間照会は通常移動の
成功を保証しない。Recording / Replay の入力順序や Action 件数は変更しない。

## Trace and distribution / 証拠・配布

One batch creates one Lifecycle read step, never one Action per ray. Receipt,
terminal item states, request IDs and the native sample interval are correlated.
The bounded typed attachment holds the already received result plus the provider
advertisement. It contains no re-exploration command. Saved Viewer display proves
only saved evidence, not another live query. Storage omission/attachment-limit
quality is separate from backend query truncation. The receipt starts with storage
unconfirmed; successful storage has its own event. Any storage rejection uses the
bounded `capture.failure` marker for `gua.spatial.batch.r1`, or a correlated quality
summary when an event cannot fit. A missing marker never proves storage succeeded.
Caller failure remains the
Trace primary outcome even if detail capture stops; input Recording is untouched.

`examples/spatial-fixtures/client` uses only Gua.Testing/Core and creates a report;
`-p:GuaUsePackages=true` selects a local NuGet consumer. No Playtest types, build,
engine binaries, engine assets or credentials are dependencies of that consumer.
`scripts/verify-spatial-route.ts` exercises the real bridge plus built Native MCP.
The Godot fixture uses `transport.gd`; the Unity fixture builds a standalone Mono
Player with `SpatialTransportBuild.Build` and pumps in real FixedUpdate callbacks.
The existing Trace Viewer must be built with `bun scripts/build-trace-viewer.ts`
before packing Gua.Testing. No release or deployment is performed by these checks.

## Measured support / 実測対応表

| Engine / OS / backend | Native scheduler & bindings | WebSocket / Native MCP | Built-in browser privilege |
| --- | --- | --- | --- |
| Godot 4.7 stable / Windows x64 / GodotPhysics3D | Real packaged addon and host pump | TypeScript, built native MCP and isolated candidate NuGet consumer passed; common Trace/report generated | Unsupported |
| Godot 4.7 stable / Windows x64 / Jolt | Real packaged addon and host pump | TypeScript, built native MCP and isolated NuGet consumer passed; offline report generated | Unsupported |
| Godot 4.7 stable / Linux x64, macOS x64, macOS arm64 / GodotPhysics3D and Jolt | Real packaged addon and physics callback pump in each desktop CI lane | TypeScript, built native MCP and isolated candidate NuGet consumer passed; common Trace/report generated | Unsupported |
| Unity 6000.5.3f1 / Windows x64 / PhysX | Real standalone Mono Player and FixedUpdate pump | TypeScript, built native MCP and isolated candidate NuGet consumer passed; common Trace/report generated | Unsupported |
| Unity Linux/macOS / other engine patches/backends | Unverified for #134; no inherited transport acceptance claim | Unverified | Unsupported built-in privilege path |
| Godot Web / Unity WebGL | Existing ports project Player/PublicAgent | No authorized r1 Testing/Debug browser channel | Unsupported; tools absent |

The current engine/consumer execution record is [PR #168](https://github.com/gua-project/gua/pull/168)
and [parent #130](https://github.com/gua-project/gua/issues/130): tested commits,
commands, per-RID CI artifacts and unverified scope are recorded there. The
desktop Godot CI checks require three actual physics batches (TypeScript, MCP,
NuGet consumer) and a clean engine exit. Full 67-result geometry, 360-sample CPU
profiling and 34 lease-race reruns were measured on the pinned Windows engines;
those full-fixture measurements are not inherited by the other OS route checks.
Candidate package checks alone do not establish #129's declared engine routes.
Actual identified commit/version artifacts can satisfy its distribution
conditions; public publication is a separate future operation. See the
[distribution contract](distribution-contract.md) for the remaining route gates.
Report payload/HTML checks do not imply a new browser visual QA pass.

`guaSpatialBrowserSupport` reports Unsupported. Registering tool names or a fake
`document.modelContext` does not authorize physics. The existing browser UI/World/
Input ports remain public projections. A future privileged browser transport
needs its own host authorization and actual engine/browser verification.

Parent #130 evidence is mapped to #131 contracts, #132 scheduling, #133 engine
geometry/profiling and #134 routes/Trace/package acceptance. Distribution #129
remains open; neither this change nor the previous engine merge completes #130.

link1345 commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator Author

Final CI verification: head 679902e; https://github.com/gua-project/gua/actions/runs/40814603658 is completed / success. All 18 jobs passed; 0 failed, pending or skipped. Intel macOS Godot desktop finished normally in 28m44s, with no retry or code change. The CI run started against this exact head; earlier-head results are not substituted.

Final review observation: 0 review submissions, 0 inline review comments; all 18 check runs are GitHub Actions. No dedicated automatic-review workflow/check or bot comment was found. The earlier independent bounded documentation audit remains the completed audit; it is not repeated or reset.

Final local checks: clean worktree, unchanged HEAD, git diff --check origin/main passed; 8 changed Markdown files, 99 relative links/anchors, 5 removed headings without incoming references, balanced fences, 0 runtime file changes. No further fixes were required. GUI/real-game/Playtest E2E and retained Intel Unity Editor UNVERIFIED/browser privileged spatial Unsupported scopes remain as documented. PR remains Draft; no merge, formal Approve or release.

@link1345
link1345 marked this pull request as ready for review October 29, 2026 10:18
@link1345
link1345 merged commit decece4 into main Oct 29, 2026
18 checks passed
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-29T10:19:42.814130Z 679902e Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant