Skip to content

Strand の考え方

7 レイヤ=役割の分離

Strand のアプリは 7 種類の定義の集合。ファイル境界やモジュールはなく、各定義は名前で参照し合う。

layer一言でReact で言うと
typeドメインの形TypeScript の型
slot状態useState
effect外界との副作用useEffect + fetch ラッパ
reducerイベント → 状態更新イベントハンドラ + setState
tileUI 部品コンポーネント(JSX)
fn純粋関数ただの関数(ただし state を読めない)
app根(caps/routes/init/theme)ルートの設定 + ルーター

暗黙を排す

Strand には Hooks の呼び出し順序ルールも、依存配列も、Context の暗黙スコープもない。

  • 状態は slot に集約され、reducer:= でのみ変わる。どこで何が書き換わるかが文面で追える。
  • 副作用は effect に閉じ、必要な capabilityapp.caps で明示する。宣言にない能力を使うと E0301
  • fn は純粋。slot を読めない(E0305)。テストしやすく、AI も推論しやすい。

1 reducer 1 書き込み(パス形状粒度)

1 つの reducer 内で同じ パス形状へ複数回書くと E0601。これは「更新が 1 箇所に集約される」ことを保証し、部分編集を安全にする。

strand
# NG: tasks への二重書き込み
tasks := tasks.remove(id)
tasks := tasks.filter(pred)

# OK: チェーンで 1 回に
tasks := tasks.remove(id).filter(pred)

tasks[id].statustasks[id].updatedAt は別形状なので共存できる。

AI が部分編集しやすい設計

各定義が独立し参照が明示的なので、@strand/cli / @strand/mcp定義単位で list / view / add / replace / remove / rename / fix できる。これが「AI が並列に触れる」狙いの中核。詳しくは ../spec/ai-edit.md