Reference site / build (push) Canceled after 0s
Expose Rust Text View tokens and safely highlight signatures and JSON results. Add animated Interface and inline Run disclosures with a shared 10ms line cadence, typed argument inputs, and explicit execution. Update documentation and browser regressions for the new controls and explicit counter-value responses.
149 lines
16 KiB
Markdown
149 lines
16 KiB
Markdown
# WIP Reference
|
||
|
||
Worldspace Interface Protocolの仕様文書と、その文書を実際のWIPで読むサイトです。
|
||
|
||
## 構成
|
||
|
||
- [`contents/`](contents/) — 仕様の正本。番号付きMarkdownを章順に読みます。
|
||
- [`contents/draft/`](contents/draft/) — 検討中の草案。公開サイトとWIPの生成データには含めません。
|
||
- [`site/`](site/) — Astroの静的サイトと、ブラウザ内で動くRust Client / Host。
|
||
|
||
[第1章:コンセプト](contents/1-concept.md) / [Core Model](contents/2-core-model.md) / [Protocol](contents/3-protocol.md) / [Client](contents/4-client.md) / [WIP over HTTP](contents/5.1-wip-over-http.md)
|
||
|
||
## ブラウザ内のWIP
|
||
|
||
```text
|
||
ツリー・本文UI (TypeScript)
|
||
→ BrowserSession (WASM公開API)
|
||
→ wip-client::direct::Client
|
||
→ 型付き要求・応答の直接呼び出し
|
||
→ サイト用Worldspace / wip-host
|
||
```
|
||
|
||
ClientとHostは同じWASM内にあります。三つのinteraction(observe、fetch_interface、call_operation)にHTTP binding、JSON wire envelope、socketは使いません。WASMと`worldspace.json`の取得、Astroによる静的ページ遷移は通常のasset/page配信です。
|
||
|
||
公開文書と既存のhome/indexコンポーネントから`worldspace.json`をビルド時に生成します。本文の別コピーを編集する必要はありません。Rust Providerはそれを変更不可の文書Objectとして公開し、本文はroot scopeの`document.read()`で取得します。章Objectは本文と子の節を同時に持ちます。
|
||
|
||
Worldspace path、表示用の既存識別子、Web URLは別です。たとえば:
|
||
|
||
- Worldspace: `/book/1-concept.md/1.1-interaction-abstraction.md`
|
||
- 表示識別子: `/1.1-interaction-abstraction.md`
|
||
- Web URL: `/book/1.1-interaction-abstraction/`
|
||
|
||
ツリーはClientの観測とOperation結果を使い、URL・履歴・折りたたみ・読書位置はUIが管理します。WASM sessionはAstroのページ切替をまたいで存続します。JavaScriptなし、WASM未対応、asset読み込み失敗時も、静的HTMLと通常リンクで閲覧できます。`data-wip-state="ready"`だけが実WIP経由の反映成功を表し、失敗時は`fallback`です。
|
||
|
||
主なファイル:
|
||
|
||
- `site/worldspace/` — サイト専用Rust Provider、入力検証、再帰observe、document Interface。
|
||
- `site/browser/` — Rust ClientとHostを所有するWASM session。
|
||
- `site/src/pages/worldspace.json.ts` — 公開文書・home/indexのデータ生成。
|
||
- `site/src/scripts/browser-wip.ts` — WASM初期化、session寿命、結果検証と本文反映。
|
||
- `site/src/scripts/landing.ts` — 共通ツリー、導入演出、ページ切替と読書位置。
|
||
|
||
### Protocolモード
|
||
|
||
右上の`Read` / `Protocol`で切り替えます。Protocolでは通常モードとは独立したClient session・WASM instanceを使い、`?mode=protocol`をツリー遷移と再読込で保持します。Protocol開始時とツリーでのObject選択時には、選択済みObjectをDepth=1で自動Observeします。直リンク・再読込・履歴移動でも現在のObjectを対象とし、Interface取得と本文Operationは自動実行しません。
|
||
|
||
1. Protocolを開くと、Rust `wip-text-view`が生成した選択済みObjectのText Viewを表示します。ツリーで別Objectを選ぶと、そのText Viewに切り替わります。同じObjectの再選択でもObserveします。
|
||
2. 未取得のInterfaceは`? /::document`の形式で表示します。クリックするとDescriptorとInterface Text Viewを取得して`v /::document`となり、再クリックで`> /::document`に折りたたみます。取得済みの再展開はClientのfresh cacheを利用します。
|
||
3. 各Operationのコメントと宣言の間にある`▶ Run`を押すと、その場に`create(name: "…")`のような引数入力フォームが展開されます。`Execute`または単一行入力でのEnterで実行します。引数なしの`document.read()`もフォームを開くだけでは呼び出さず、明示実行が必要です。フォームは再クリックまたはEscapeで閉じられます。
|
||
|
||
文字列は引用符内の欄にそのまま入力し、整数は10進表記で入力します。UIがパラメーターごとにtagged Valueへ変換し、WASM APIには従来と同じJSON record(例:`{"name":{"kind":"string","value":"example"}}`)を渡します。`integer`はJSのNumberを経由せず文字列として渡し、Protocol Integerの範囲(±9,007,199,254,740,991)などはClientで検証します。省略可能な引数はincludeで送信を選択でき、複合型・名前付き型には個別のtagged Value JSON欄を使います。`bytes`は0〜255の配列、`record`と`list`は再帰的なtagged Value、`unit`は`{"kind":"unit"}`です。API入力上限は64KiB・32階層・4096値、path/scope/name/operationは各4096 UTF-8 bytesです。
|
||
|
||
Object/Interfaceのハイライトには`wip-text-view`の`tokenize_object` / `tokenize_interface`を使います。WASMは同じtoken列から`textView`と`textViewTokens`(kind/text)を返し、UIは文字列を再解析せず、安全なテキストノードで種別を着色します。ライト/ダークのパレットは`site/src/styles/text-view.css`に定義しています。空白・改行・引用は保持し、未知の種別は無装飾、不整合やtokenなしの応答は元のplain textで表示します。
|
||
|
||
InterfaceとRunフォームの開閉は同じ行アニメーションを使います。展開時は上から、折りたたみ時は下から1行10msずつフェードし、高さも行数×10msで変化します。reduced-motion設定と印刷では省略します。
|
||
|
||
Operation結果のハイライトには[Kirari](https://github.com/vortexkit/kirari)(`@vortexlabs/kirari`)のcoreとJSON grammarだけを使い、token配列を安全なspan/text nodeへ変換します。キー・文字列・数値・真偽値・null・記号をライト/ダーク対応で色分けし、整形済みJSONの文字列は変更しません。ハイライトに失敗した場合もplain textで結果を保持します。
|
||
|
||
Object/InterfaceのText ViewとOperation結果は別領域です。結果はpath・Interface・Operation付きのtagged JSONで、本文HTMLも文字列として表示し、markupとして実行しません。対象・Interface・Operationの変更で以前の結果表示を消します。ObserveとInterface取得はClientのfresh cacheを使えますが、Operationは明示実行ごとに1回呼び出し、自動再試行しません。ページ遷移・モード往復ではsessionを保持し、再読込で新sessionになります。
|
||
|
||
初期化失敗時は利用不可、trap後はその手動instanceを再利用・解放せず再読込が必要と表示します。`Read`では静的本文を閲覧できます。JavaScriptなしではProtocol URLでも通常の静的閲覧を維持し、未実行を実行成功として表示しません。
|
||
|
||
### Sources / Packages
|
||
|
||
`/sources/`と`/packages/`は`/book`と並ぶルート直下の葉Objectです。リンク先リポジトリや各crateを子Objectにはしません。通常ページと`document.read()`は同じrendererから本文を生成します。
|
||
|
||
- Sources: `wip-reference`と`wip-rs`の2リポジトリ。
|
||
- Packages: Rust workspaceのREADMEとCargo manifestに基づく`wip-protocol`、`wip-interface-macros`、`wip-interface`、`wip-host`、`wip-http`、`wip-client`、`wip-text-view`。各crateのsourceとworkspace READMEへリンクします。レジストリでの公開状況や公開バージョンは表しません。
|
||
- 一覧の正本は`site/src/lib/catalog.ts`です。内部crate、examples、draftは公開一覧に含めません。
|
||
|
||
### Playground
|
||
|
||
`/playground/?mode=protocol`で、メモリ内のObjectを操作できます。親は`/::document`と`/::collection`、子カウンターは`/::counter`を公開します。
|
||
|
||
- `collection.create(name)` / `remove(name)`:子Objectを作成・削除。名前は`[A-Za-z0-9_-]{1,32}`、最大32個。新規値は0です。
|
||
- `counter.get()` / `increment(amount)` / `reset()`:現在値の取得・増減・0へのリセット。Protocol Integerの範囲外への変更は失敗し、状態を変更しません。
|
||
- 初期状態は`apple = 3`、`orange = 0`。ツリーはObject名だけを表示します。`description`は`An in-memory counter.`という説明文で、現在値や機械可読データとして解釈しません。値は明示的な`counter.get()` / `increment()` / `reset()`のOperationレスポンスに表示します。
|
||
- 操作成功後に親と選択中Objectを再Observeします。変更可能なPlaygroundのObserveはClientの`refresh_observed`で実取得し、作成・削除による子一覧の変更をツリーへ反映します。Observeからカウンター値を読み取ったり、値の取得Operationを自動実行したりしません。再観測に失敗しても成功済みOperationを再実行しません。
|
||
- 子の選択は`/playground/?mode=protocol&object=%2Fplayground%2Fapple`のようなURLで保持します。ページ・履歴・Read/Protocol往復ではProtocol sessionが残り、ブラウザの再読み込みで初期化します。削除済みObjectへの履歴移動はエラーを表示し、復活させません。
|
||
- 通常Readは静的な操作説明を表示します。状態の永続化・外部送信・文書変更はありません。
|
||
|
||
例:createの`name`欄に`banana`、incrementの`amount`欄に`2`を入力すると、それぞれ`create(name: "banana")`、`increment(amount: 2)`の呼び出しになります。
|
||
|
||
### 実行上の境界
|
||
|
||
このサイトの操作は同期・メモリ内です。文書は読み取り専用で、Playgroundだけがsession内の変更を許可します。入力JSONは16MiB、Object数4096、階層32を上限とし、Clientにもstate/history上限を設けています。JS APIにdeadlineや並行実行中のcancellation設定はなく、HostにはdeadlineなしのExecutionContextを渡します。ブラウザ非対応の`std::time::Instant::now()`を呼ぶdeadline経路は利用しません。将来deadlineを公開する場合はブラウザ対応時計と実行テストが必要です。
|
||
|
||
release WASMは`panic=abort`です。Rustのpanic/trapは`catch_unwind`でProtocol failureへ回復できるとは扱いません。通常の入力・ProtocolエラーはJS例外として返り、サイトは静的表示へfallbackします。trapしたinstanceは以後呼び出し・解放せず、そのブラウザdocumentの残りの寿命は静的表示へfallbackします。ページ切替でOperationを再実行せず、復帰には再読み込みによる新instanceを使います。
|
||
|
||
JS境界のJSONはサイト専用のtree/document DTOであり、汎用WIP wire形式ではありません。本文はビルド時に既存Markdown rendererが生成した公開HTMLです。任意の外部Hostが返すHTMLを無条件に挿入する汎用クライアントではありません。
|
||
|
||
## 開発・検証
|
||
|
||
Node.js 22.12以上(CIは24)、npm、Rust 1.97.1、`wasm32-unknown-unknown`標準ライブラリ、`wasm-bindgen-cli` 0.2.121を使います。Rust sourceはこのrepoの隣の`wip-rs/`に置き、`site/rust-source.json`で指定するrevisionをcheckoutします。
|
||
|
||
```sh
|
||
# このrepositoryのrootで実行
|
||
# 既存の隣接checkoutがある場合はcloneせず、その作業を保全してください。
|
||
git clone https://gitea.hareworks.net/Hare/wip-rs ../wip-rs
|
||
git -C ../wip-rs checkout "$(node -p 'require("./site/rust-source.json").revision')"
|
||
rustup toolchain install 1.97.1 --component rustfmt --component clippy --target wasm32-unknown-unknown
|
||
cargo +1.97.1 install wasm-bindgen-cli --version 0.2.121 --locked
|
||
cd site
|
||
npm ci
|
||
npm run dev
|
||
```
|
||
|
||
`npm run dev`と`npm run build`は先にWASMをsourceから生成します。Rustとwasm-bindgenがPATHにないNix環境では、隣接`wip-rs/flake.lock`を使って開発環境・LLD・wasm-bindgenを起動します。Cargo.lockとwasm-bindgenのバージョンは固定し、rustup環境では`site/rust-toolchain.toml`を使います。通常のWASMビルドはRust sourceのrevisionとclean状態を確認します。Rust側を同時編集するローカル開発に限り`WIP_ALLOW_DIRTY_SOURCE=1`で明示的に解除できますが、release検証では解除しません。生成物`site/public/wip-wasm/`と`site/target/`はGit管理しません。
|
||
|
||
```sh
|
||
npm run verify # unit tests → Astro check → WASM/build → link checks
|
||
WIP_TEST_GENERATED=1 node --test tests/worldspace-data.test.mjs
|
||
cargo test --workspace --locked -- --include-ignored # build後の実文書テストも実施
|
||
cargo clippy --workspace --all-targets --locked -- -D warnings
|
||
npx playwright install chromium
|
||
npm run test:browser
|
||
npm run test:dev # dev serverでも実WASMの読み込み・本文反映とフォント配信を確認
|
||
# インストール済みChromeを使う場合:CHROME_PATH=/path/to/chrome npm run test:browser
|
||
npm run preview
|
||
```
|
||
|
||
Nixでnativeテストを行う場合は`nix develop ../../wip-rs --command cargo test --workspace --locked -- --include-ignored`のように実行します。テスト用previewは`127.0.0.1:4322`、`test:dev`は別のdev serverを4323で起動し、通常のdev server(4321)を再利用・停止しません。`SITE_BASE=/reference npm run test:dev`でサブパスのWASM・全6書体の読み込みも確認できます。フォント定義は`public/fonts/fonts.css`をbase付きURLで参照し、各WOFF2はCSSからの相対URLで解決します。
|
||
|
||
`npm run test:browser`は先に`test-probes` feature付きの別WASMを`site/test-assets/`へ生成します。`wasm-limits.spec.ts`は実WASMの入力上限と意図的なRust panicを検証し、trapがProtocol failureへ誤変換されず、サイトがsessionを再利用しないことを確認します。このprobeはテストrouteでのみ配信され、通常の`public/`・`dist/`には入りません。
|
||
|
||
ブラウザテストはPC/mobile、no-JS、実WASMの独立session・三つのinteraction、WIP結果によるUI更新、失敗fallback、履歴、初回演出、ライト/ダークを検証します。`wasm.spec.ts`は静的asset取得後にfetchを禁止して直接呼び出しを確認し、`wip.spec.ts`は壊した初期HTMLを実WIP結果が修復することまで確認します。
|
||
|
||
## 表示と文書編集
|
||
|
||
`/`が独立したホーム、`/book/`が目次です。各章の既存Web URLを維持し、共通ツリーでは章の下に節を表示します。初回ホームの導入演出は入力で開始し、EscapeやSkipで完了できます。`prefers-reduced-motion`では演出を省略します。配色はOSの`prefers-color-scheme`へ追従し、JavaScriptなしでも有効です。
|
||
|
||
文書は`contents/`だけを編集します。先頭の`#`見出しをタイトルに使うためfrontmatterは不要です。Markdownの相対`.md`リンクはビルド時にBook URLへ変換し、query/fragmentを維持します。draftへのリンクは公開リンクにしません。`npm run check:links`で生成ページ・内部リンク・見出しanchorを検証します。
|
||
|
||
## サイト公開
|
||
|
||
静的出力の`site/dist/`を公開します。常駐WIPサーバー、Nodeサーバー、データベースは不要です。このrepositoryへのpushだけでインターネットへ自動デプロイする設定ではありません。
|
||
|
||
```sh
|
||
SITE_URL=https://your-domain.example npm run verify
|
||
# サブパス配信の検証
|
||
SITE_URL=https://your-domain.example SITE_BASE=/wip-reference npm run verify
|
||
SITE_URL=https://your-domain.example SITE_BASE=/wip-reference npm run test:browser
|
||
```
|
||
|
||
- `SITE_URL`はorigin、`SITE_BASE`はpath prefixです。既定のbaseは`/`です。
|
||
- Static hostはディレクトリの`index.html`を配信し、未知URLに`404.html`を返します。SPA fallbackは不要です。
|
||
- `.wasm`は`application/wasm`で配信してください。モジュール、WASM、manifest、HTMLを同じbuildの成果物として公開します。
|
||
- Gitea Actionsは固定revisionのRust sourceとサイトを組み合わせ、通常/サブパスの検証後に`wip-reference-site` artifactを作ります。Rust revisionの更新時は両repositoryのテストを実施し、参照commitを取得可能にしてからCIを動かしてください。
|