Skip to content

設計理念

0.1 動機

React は人間中心の最適点である。Hooks / Context / JSX は人が読み書きするうえで自然に感じる慣用句であり、20 年近い試行錯誤の到達点でもある。しかしコードを書くのが AI に移っていくにつれ、次のような特性が摩擦になる。

摩擦点内容
構文オーバーヘッドJSX/TSX は閉じタグ・キャメル属性・式埋め込みでトークンが嵩む
暗黙の副作用useEffect の依存配列、クロージャの stale capture、cleanup 忘れ
順序依存ルールHooks の呼び出し順、条件分岐内禁止、リスト内禁止
暗黙スコープProvider 階層、Context の解決、子孫からの参照
非局所的レンダリング親の再レンダーが子に波及、memo で部分的に抑制する複雑性

これらは「AI が書く分には書ける」が「AI が直す・並列で触る」と急激に難しくなる。バグの原因がプログラム外(実行履歴・依存配列・stale closure)にあると、AI はコンテキスト窓に履歴を全部詰めないと推論できない。

Strand はこの摩擦を構造で消す。

0.2 設計要件

  1. トークン効率: 同じ UI を React より少ないトークンで表現できる
  2. 副作用の静的追跡可能性: どの副作用がどの状態に依存し、どこから発火するかが構文から自明
  3. アーキテクチャの予測可能性: バグ箇所が局所化される、エラーメッセージが機械可読
  4. 並列開発耐性: 数十のエージェントが同時に編集してもセマンティックに壊れない
  5. 可読性の放棄を許容: 人間が読めるかは二次目標。一次目標は AI が正確に書ける・直せる

0.3 先行研究のレッスン

設計に至るまでに参照した試みと、そこから取り入れた / 避けた要素:

試み取り入れた避けた
Elm完全な副作用分離、Result/Option 型ボイラープレートの膨張、ローカル状態禁止の硬直さ
Unisoncontent-addressable な定義、ハッシュベース参照テキスト/Git エコシステムからの完全分断
Eve / Differential Dataflowデータフローとしての UI、宣言的クエリ高頻度更新ツリーでの IVM 計算爆発
Hazel / Subtexttyped holes、構文エラーゼロ入力摩擦による開発体験の悪化
Darktrace 駆動のデプロイ、UI と実行の融合エコシステムロックイン
SolidJSfine-grained reactivity、コンパイル時依存解析シグナルの stale 問題、隠れた追跡範囲
Qwikresumability、SSR 後の O(1) 起動学習コストとデバッグの複雑さ
HyperscriptDOM 局所性、コンテキストスイッチゼロ大規模化での密結合スパゲティ
Datomicappend-only fact log、時間旅行クエリ高頻度更新には向かない

0.4 4 案ブレストの収束点

設計検討で 4 つの独立案を出した:

出所一言
IR + Actor + Effect descriptorCodex 1 回目S 式 IR、Elm Architecture、capability 付き effect、compile-to-DOM
Loom: Episode-oriented RuntimeCodex 2 回目Episode / Intent / Capability / Projection / Trace
Pyramid: Effect-Typed Tile LanguageClaudeTSV 1 行 1 宣言、5 層分離、グローバル slot
Nexus: CRDT-Native Triple-GraphGeminiグラフ DB、Triple op、Reactive Datalog

4 案を批判的に比較した結果、表面の表現は違っても全員が同じ 4 点に収束していることが判明した。

収束した 4 つの核

  1. 副作用は明示 descriptor(関数呼び出しではない)
  2. ローカル状態の禁止 / 最小化(全状態が静的に位置特定可能)
  3. source ≠ runtime(IR とコンパイルを必須化)
  4. append-only causal log(debug/replay/audit を一つの基盤に統合)

残った論点は ソース表現の物理形式だけ だった。

0.5 Strand のポジション

Strand は 4 案のハイブリッドである。各案の強い部分を取り、弱い部分を別の案で補う。

採用出所
7 レイヤ強制分離(type / slot / effect / reducer / tile / fn / app)Pyramid + Strand 拡張
capability 付き effect descriptorIR+Actor / Pyramid
episode log + replayLoom
content-addressable な定義ストアIR+Actor / Nexus
名前付き slot(opaque ID ではなく可読名)Pyramid
CRDT op による並列編集Nexus
局所ネスト許容(tile 内のみ S 式風)IR+Actor
グラフコンパイラ(参照整合性を静的検査)Nexus
--ai-fix モード(エラー→自動修復ループ)Strand 新規

各案の弱点を Strand がどう避けるか

弱点由来Strand での回避
S 式の括弧地獄IR+Actortile 内のみネスト許容、それ以外は 1 行 1 宣言
Effect type 伝搬地獄IR+Actoreffect は descriptor、伝搬は capability 集合のみ
Projection の IVM 計算爆発Loomsignal graph による局所更新(projection を全体再構築しない)
trace スキーマ進化非互換Loomcontent-hash と episode の versioning で過去 trace は immutable
TSV の表現力限界Pyramidtile 内ネスト許容、reducer の do= は複数文
アセンブリ退化Pyramid名前付き slot + コンパイラが命名強制
CRDT の意味的衝突Nexusコンパイラが ref-integrity を CRDT op レベルで検査
opaque ID の長距離参照Nexus表面は名前、内部は hash、参照は CLI が解決
Reactive Datalog の計算コストNexusDatalog ではなく compiled signal graph

0.6 用語

用語意味
definitiontype / slot / effect / reducer / tile / fn / app のいずれか 1 件
layer7 種の定義カテゴリ
fn補助の純粋関数(slot 読み書き禁止、effect emit 禁止)
content-hash定義の本体と推移依存をハッシュした 256bit 識別子
slot名前付きグローバル状態
effect副作用を表す純粋なレコード値(実行ではない)
emitreducer から effect 値を放出する操作
reducerevent → state 変更 + effect emit の純粋関数
tileslot から DOM 投影への純粋関数
episode1 つのトリガから派生した因果列(reducer 実行・effect 実行・状態変化の集合)
capabilityアプリ起動時に宣言する副作用許可の集合
CRDT opAI エージェントが definition store に対して行う編集操作

0.7 非目標

Strand は次のものを目指さない。

  • 既存 React コードの段階移行: 互換性ゼロでよい。新規アプリ専用
  • 人間によるフルスクラッチ開発: 人間も書けるが快適ではない
  • 任意の DSL/言語拡張: マクロ・プラグインを許さない(AI の学習対象を 1 つに保つため)
  • 動的型・実行時型生成: すべて静的
  • 複数のレンダリングターゲット: DOM のみ(Native / Canvas は別言語)

0.8 次に読む