DDD ドキュメントを Single Source of Truth として、slice ごとに軽量 TDD + CoDD 流の変更伝播を回す開発フレームワーク。
- ori(織)— "weave" / 織りなす
- ori-ori(折々)— "from time to time" / "season by season"(四季折々)
DDD 文書・slice / page・コードを 1 つのグラフに織り込み、節目(折々)に変更を伝播させる、という二重の意味を込めています。npm scope @ori-ori/ もこの語源に由来します。
ori は以下を統合した開発支援ツールです:
- DDD ドキュメント生成(distill-ddd ベース)
- slice 単位の軽量 TDD ワークフロー(VCSDD を軽量化、cc-sdd を参考)
- CoDD 流の変更伝播(ドメイン文書 ↔ slice / page ↔ コードを単一グラフで管理)
- multi-CLI 配布(APM 経由で Claude Code / Codex / OpenCode / Cursor / Copilot / Gemini / Windsurf 対応)
ori は「AI に任意のコードを書かせるための薄いハーネス」ではありません。「DDD ドキュメント → slice / page + DDD のコード骨格」というアーキテクチャまで指定する、opinionated(oriented)なハーネスです。
ori init --template ddd-typescriptは、slice ごとにdomain / application / infrastructure / presentation / testsを切り、index.tsを唯一の public API として slice 間の直接 import を禁ずる、slice ベース DDD の雛形を吐きます。.ori/architecture.mdを SSoT として、@ori-ori/arch-adapter-*系の adapter が ESLint や言語ネイティブ linter にコンパイルされ、規約逸脱を CI で止めます。- AI に与えるのは「任意のスタイルで書く自由」ではなく「決められたスロットを埋める自由」です。創造性は domain modeling と slice 内ロジックに集中させます。
「ハーネスは中立であるべき」という設計とは明確に立場を分けます。ori は中立ではなく、「これで書け」という方向(ori-ent)を持ったハーネスです。
- DDD ドキュメントが Single Source of Truth
- slice / page への分割は構造から自動抽出(Phase 9 workflows と Phase 11 ui-fields)
- 変更伝播は単一アルゴリズム + edit-time guardrail(
--forceで SSoT 保護を解除) - CLI = 決定的重処理 / AI = 創造的判断の責務分離
- vendor lock-in 回避:APM で全 AI ツール対応、capability-role でモデル抽象化
ori/
├── packages/
│ ├── cli/ # @ori-ori/cli — npm 配布の TypeScript CLI
│ ├── parser/ # markdown/frontmatter/section parsing
│ ├── coherence/ # propagation 計算 + ハッシュ管理
│ ├── slice-runner/ # 7-phase workflow runner + beads bridge
│ └── templates/ # DDD コード生成テンプレート(TS/Tauri 等)
├── .apm/ # APM 配布アセット
│ ├── apm.yml
│ ├── instructions/ # 7 ファイル(規約の自動適用)
│ ├── skills/ # /ori-init, /ori-flow, /ori-sync 等
│ ├── agents/ # ori-reviewer(fresh-context Opus)
│ └── hooks/ # post-write-domain → 自動 sync
└── docs/ # 設計文書
スタック別の開始ガイドは docs/start/index.md に まとまっています。代表例:
- docs/start/typescript-web.md — TS 単体(web / Node)
- docs/start/tauri-v2.md — TS + Rust (Tauri 2)
共通ステップ:
# 1. CLI バイナリ(決定的処理)
npm i -g @ori-ori/cli
# 2. AI コンテキスト(skill/agent/hook を各 CLI に配置)
apm install dev-komenzar/ori
# 3. プロジェクトを scaffold
$ cd my-project
$ ori init --template ddd-typescript # or ddd-typescript-tauri
$ /ori-distill # AI が distill-ddd phase 1-11 を対話実行
$ /ori-flow app-startup # 1 slice を 7 phase で実装
$ ori sync # 変更伝播計算現状の ori init は MVP として ddd-typescript(slice ベース + DDD)を中心にサポートしています。将来的にはコミュニティから init テンプレートを集めたいと考えています:
- 言語別: Python / Go / Rust / Kotlin / Scala / Swift...
- フレームワーク別: Next.js / Nuxt / Remix / Django / FastAPI / Spring / Axum / Tauri...
- アーキテクチャ別: slice + DDD / Clean Architecture / Hexagonal / Onion / VSA...
各テンプレートは「slice ごとのディレクトリ骨格 + 単一 public API(index.ts 相当)+ .ori/architecture.md を生成する arch-adapter 設定」の 3 点を満たせば ori と整合します。adapter は現在 ESLint / 汎用 regex / Rust (@ori-ori/arch-adapter-rust) が利用可能で、Python (import-linter) / JVM (ArchUnit) / Go (depguard) などは計画中です。
興味がある方は issues または discussions で声をかけてください。
1 slice を 7 phase で完走した後、ヒューマンチェックでバグが発覚した場合、バグの所在をグラフ上のどのノードに帰属させるかで分類し、それぞれ対応する動線を取ります。
| # | バグの所在 | 症状 | 起点 |
|---|---|---|---|
| 1 | ドメインモデルが誤り | 不変条件が抜けていた、概念の境界が違った | .ori/domain/ を編集 |
| 2 | spec は正しいが impl が誤り(テスト網羅漏れ) | impl がエッジケースで落ちる | 失敗テストを追加 |
| 3 | spec 自体に欠陥(domain は正しいが derive が悪い) | 派生時に取りこぼし/曲解 | --force で spec 編集 → proposal |
| 4 | 複数 slice の統合バグ | 単体ではテスト通るが組み合わせで破綻 | 新規 slice 作成 |
判別の質問順序:
- 「ドメインモデルが捉え損ねている事象か?」→ Yes → ケース 1
- 「spec.md にこの動作の規定があるか?」→ No → ケース 3
- 「spec の規定通り impl が動かない?」→ Yes → ケース 2
- 「単一 slice の範囲を超える?」→ Yes → ケース 4
例:aggregates.md#note-aggregate の不変条件「body 編集後 updatedAt が必ず増分」が抜けていた。
$ vim .ori/domain/aggregates.md # 不変条件を追加
$ ori sync
⚠ Changed: domain/aggregates.md#note-aggregate
Propagating to derived slices:
- slices/capture-auto-save (spec.md is now dirty)
- slices/edit-past-note-start (spec.md is now dirty)
✓ Reopened beads issues: ori-derive-capture-auto-save, ori-derive-edit-past-note-start
$ /ori-flow capture-auto-save # 再 derive → test-red → impl-green → review1 つのドメイン編集 → 影響する全 slice が自動で dirty 化。ori が manifest の derives_from を辿って影響範囲を計算します。
例:spec.md には「空 Note を破棄」と書かれているが、impl が「空白だけの Note」を見逃していた。
$ vim .ori/slices/capture-auto-save/tests/empty-note.test.ts
# 失敗テストを追加(whitespace-only も isEmpty に含める)
$ pnpm test
✗ FAIL
$ ori slice run capture-auto-save --phase impl-green \
--reason "manual bug report: whitespace handling"
✓ AI が isEmpty() を String#trim() ベースに修正
$ ori slice run capture-auto-save --phase review # 推奨ドメイン文書には触れず、--phase impl-green で該当 phase だけピンポイント再実行。--reason が beads コメントに残ります。
例:domain には「Tag は小文字正規化」と書かれているのに、spec.md がそれを取りこぼしていた。
$ vim .ori/slices/ui-tag-chip/spec.md
$ ori sync
✗ ERROR: spec.md is derived. Edit blocked.
Options:
[1] Edit domain source: domain/aggregates.md#tag-vo
[2] Force edit + upstream proposal: ori sync --force slices/ui-tag-chip/spec.mdSSoT 保護が「曖昧な箇所をドメインに戻す動線」を強制します。多くの場合 domain を直すのが正解。どうしても spec で局所決定したい場合は --force + proposal で上流レビューを残します。
例:capture-auto-save と edit-past-note-start が個別では正しいが、組み合わせ時の自動保存タイミングが競合する。
$ /ori-distill phase=workflows
# distill-ddd Phase 9 に戻り、欠落していたシナリオを workflows/switch-edit-target.md として追加
$ ori slice new switch-edit-target
$ /ori-flow switch-edit-target統合バグは「ドメインモデルにシナリオが欠けていた」こととほぼ同義。既存 slice を編集せず新規 slice として切り出すことで境界を明確にします。
バグの所在を ori graph 上のノードに対応づける → そのノードを編集する → propagation が必要な phase を自動 reopen → AI が phase を再走 → review で再検証
人間がやるべき判断は「どのノードにバグがあるか」のみ。残りの dirty 計算・再 derive・実装修正・レビューは ori workflow が機械的に運びます。
| やってはいけないこと | 理由 |
|---|---|
| impl を直接 patch、テスト・spec は触らない | 次の derive で実装が上書きされ消える。テストが守らない |
spec.md を --force なしで直接編集 |
guardrail が止める。drift が git history で検出される |
| ドメインを直さず、複数 slice の spec で局所対応 | 同じバグの暗黒コピーが各所に発生。CoDD の意義を失う |
| review を skip | adversarial 視点なしで「自分の修正は正しい」と確信してしまう |
🚧 作業中:MVP scaffold 段階。動作可能な機能はまだ提供されていません。
詳細な設計議論は docs/design.md を参照。
MIT — LICENSE を参照。