chore: Initialize Miyabi project with full planning
- Add .claude/ configuration (agents, commands, prompts, templates) - Add comprehensive documentation: - WBS.md - Work Breakdown Structure - SPRINT_PLANNING.md - 4-sprint detailed plan - OPERATION_PLAN.md - Execution procedures - PRODUCT_SPEC.md - Product requirements - PREPARATION_OPS.md - Pre-sprint checklist - Add PlantUML diagrams (wbs-diagram, gantt-chart) - Configure Miyabi (.miyabi.yml) - Set up Rust workspace structure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
0eb74b7af1
commit
00d5d4d4e9
53 changed files with 6950 additions and 0 deletions
37
.claude/QUICK_START.md
Normal file
37
.claude/QUICK_START.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# miyabi-cli-standalone - Quick Start Guide
|
||||
|
||||
## 🚀 3分で始めるMiyabi
|
||||
|
||||
### 1. 環境変数設定
|
||||
|
||||
```bash
|
||||
export GITHUB_TOKEN=ghp_xxx
|
||||
export ANTHROPIC_API_KEY=sk-xxx
|
||||
```
|
||||
|
||||
### 2. ステータス確認
|
||||
|
||||
```bash
|
||||
miyabi status
|
||||
```
|
||||
|
||||
### 3. Issue作成
|
||||
|
||||
GitHubでIssueを作成し、以下のラベルを付与:
|
||||
- `type:feature` または `type:bug`
|
||||
- `priority:P1-High`
|
||||
|
||||
### 4. Agent実行
|
||||
|
||||
```bash
|
||||
miyabi agent coordinator --issue 1
|
||||
```
|
||||
|
||||
## 📚 詳細ドキュメント
|
||||
|
||||
- [CLAUDE.md](../CLAUDE.md) - プロジェクトコンテキスト
|
||||
- [.claude/README.md](./README.md) - .claudeディレクトリ説明
|
||||
|
||||
---
|
||||
|
||||
**Miyabi** - Beauty in Autonomous Development 🌸
|
||||
53
.claude/README.md
Normal file
53
.claude/README.md
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# .claude Directory
|
||||
|
||||
Claude Code設定ディレクトリ
|
||||
|
||||
## 構造
|
||||
|
||||
```
|
||||
.claude/
|
||||
├── agents/
|
||||
│ ├── specs/ # Agent仕様定義
|
||||
│ ├── prompts/ # 実行プロンプト
|
||||
│ └── README.md
|
||||
├── commands/ # カスタムスラッシュコマンド
|
||||
├── prompts/ # 汎用プロンプト
|
||||
└── templates/ # テンプレート
|
||||
```
|
||||
|
||||
## カスタムコマンド
|
||||
|
||||
`commands/` 配下に `*.md` ファイルを作成:
|
||||
|
||||
```markdown
|
||||
# commands/build.md
|
||||
プロジェクトをビルドして、エラーがあれば修正してください。
|
||||
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
使用: `/project:build`
|
||||
|
||||
## Agent仕様
|
||||
|
||||
`agents/specs/` でAgent定義:
|
||||
- 役割・責任範囲
|
||||
- 使用可能ツール
|
||||
- エスカレーション条件
|
||||
|
||||
## プロンプト
|
||||
|
||||
`prompts/` に再利用可能プロンプト:
|
||||
- コードレビュー
|
||||
- リファクタリング
|
||||
- テスト生成
|
||||
|
||||
## 使い方
|
||||
|
||||
```bash
|
||||
# カスタムコマンド実行
|
||||
/project:build
|
||||
|
||||
# Agent実行
|
||||
miyabi agent run <agent-name> --issue <番号>
|
||||
```
|
||||
59
.claude/agents/README.md
Normal file
59
.claude/agents/README.md
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# Miyabi Agents
|
||||
|
||||
このディレクトリには、Miyabiプロジェクトで使用するAgent仕様とプロンプトを配置します。
|
||||
|
||||
## 📁 ディレクトリ構造
|
||||
|
||||
```
|
||||
agents/
|
||||
├── specs/ # Agent仕様定義
|
||||
│ ├── coding/ # コーディング系Agent(7種類)
|
||||
│ └── business/ # ビジネス系Agent(14種類)
|
||||
└── prompts/ # 実行プロンプト
|
||||
├── coding/ # コーディング系Agentプロンプト
|
||||
└── business/ # ビジネス系Agentプロンプト
|
||||
```
|
||||
|
||||
## 🤖 Coding Agents(7種類)
|
||||
|
||||
1. **CoordinatorAgent** - タスク統括・DAG分解
|
||||
2. **CodeGenAgent** - AI駆動コード生成
|
||||
3. **ReviewAgent** - コード品質レビュー
|
||||
4. **IssueAgent** - Issue分析・ラベリング
|
||||
5. **PRAgent** - Pull Request自動作成
|
||||
6. **DeploymentAgent** - CI/CDデプロイ自動化
|
||||
7. **RefresherAgent** - Issue状態監視・更新
|
||||
|
||||
## 💼 Business Agents(14種類)
|
||||
|
||||
### 戦略・企画系(6種類)
|
||||
- AIEntrepreneurAgent, ProductConceptAgent, ProductDesignAgent
|
||||
- FunnelDesignAgent, PersonaAgent, SelfAnalysisAgent
|
||||
|
||||
### マーケティング系(5種類)
|
||||
- MarketResearchAgent, MarketingAgent, ContentCreationAgent
|
||||
- SNSStrategyAgent, YouTubeAgent
|
||||
|
||||
### 営業・顧客管理系(3種類)
|
||||
- SalesAgent, CRMAgent, AnalyticsAgent
|
||||
|
||||
## 📝 Agent仕様の書き方
|
||||
|
||||
詳細は各ディレクトリのREADME.mdを参照してください:
|
||||
- [specs/coding/README.md](specs/coding/README.md)
|
||||
- [specs/business/README.md](specs/business/README.md)
|
||||
|
||||
## 🚀 Agent実行方法
|
||||
|
||||
```bash
|
||||
# CoordinatorAgentでIssue処理
|
||||
miyabi agent run coordinator --issue 123
|
||||
|
||||
# 複数Issue並列処理
|
||||
miyabi agent run coordinator --issues 123,124,125 --concurrency 3
|
||||
```
|
||||
|
||||
## 🔗 参考リンク
|
||||
|
||||
- [Miyabi Agent SDK](https://docs.rs/miyabi-agents)
|
||||
- [CLAUDE.md](../../CLAUDE.md) - プロジェクトコンテキスト
|
||||
135
.claude/agents/issue-workflow-example.md
Normal file
135
.claude/agents/issue-workflow-example.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
# Issue Creation Workflow Example
|
||||
|
||||
このファイルは、miyabi-cli-standaloneプロジェクトでの標準的なIssue作成フローです。
|
||||
|
||||
## ステップ1: Issue作成
|
||||
|
||||
### GitHub Web UIで作成
|
||||
1. リポジトリの"Issues"タブをクリック
|
||||
2. "New issue"をクリック
|
||||
3. Issueテンプレートを使用(推奨)
|
||||
|
||||
### GitHub CLIで作成(推奨)
|
||||
```bash
|
||||
gh issue create \
|
||||
--title "✨ Add user authentication" \
|
||||
--body "$(cat <<'EOF'
|
||||
## 概要
|
||||
ユーザー認証機能を追加する
|
||||
|
||||
## 要件
|
||||
- [ ] JWT トークン認証
|
||||
- [ ] ログイン/ログアウトエンドポイント
|
||||
- [ ] トークンリフレッシュ機能
|
||||
|
||||
## 期待される成果
|
||||
- 認証付きAPIエンドポイント
|
||||
- テストカバレッジ90%以上
|
||||
- セキュリティ監査パス
|
||||
EOF
|
||||
)" \
|
||||
--label "type:feature,priority:P1-High,state:pending"
|
||||
```
|
||||
|
||||
## ステップ2: Agent実行
|
||||
|
||||
### 方法1: 新しいwork-onコマンド(推奨)
|
||||
```bash
|
||||
# Issue番号で実行
|
||||
miyabi work-on 1
|
||||
|
||||
# または作業説明で実行(Issue作成を提案)
|
||||
miyabi work-on "Add user authentication"
|
||||
```
|
||||
|
||||
### 方法2: 従来のagentコマンド
|
||||
```bash
|
||||
miyabi agent run coordinator --issue 1
|
||||
```
|
||||
|
||||
### 方法3: 並列実行
|
||||
```bash
|
||||
miyabi parallel --issues 1,2,3 --concurrency 2
|
||||
```
|
||||
|
||||
## ステップ3: 進捗確認
|
||||
|
||||
```bash
|
||||
# プロジェクトステータス確認
|
||||
miyabi status
|
||||
|
||||
# Issue状態確認
|
||||
gh issue view 1
|
||||
|
||||
# Worktree確認
|
||||
git worktree list
|
||||
|
||||
# ログ確認
|
||||
tail -f logs/miyabi-$(date +%Y%m%d).log
|
||||
```
|
||||
|
||||
## ステップ4: レビュー
|
||||
|
||||
Agentが自動的に:
|
||||
1. コード生成
|
||||
2. テスト作成
|
||||
3. Linter実行
|
||||
4. PR作成
|
||||
|
||||
あなたがすべきこと:
|
||||
1. PRレビュー
|
||||
2. 追加修正(必要なら)
|
||||
3. マージ
|
||||
|
||||
## 実際の例
|
||||
|
||||
### 成功例: Issue #42 "Setup CI/CD pipeline"
|
||||
|
||||
```bash
|
||||
$ miyabi work-on 42
|
||||
|
||||
🚀 Let's work on it!
|
||||
📋 Issue #42
|
||||
|
||||
🤖 CoordinatorAgent starting...
|
||||
✅ Analyzed issue
|
||||
✅ Created 3 tasks
|
||||
✅ Assigned CodeGenAgent, ReviewAgent, DeploymentAgent
|
||||
|
||||
⏱️ Estimated time: 15 minutes
|
||||
🌳 Created worktree: .worktrees/issue-42
|
||||
|
||||
[15 minutes later]
|
||||
|
||||
✅ All tasks completed!
|
||||
📊 Quality score: 95/100
|
||||
🔗 PR created: #43
|
||||
```
|
||||
|
||||
## トラブルシューティング
|
||||
|
||||
### Agentがスタックした場合
|
||||
```bash
|
||||
# ログ確認
|
||||
grep -i "error" logs/miyabi-*.log
|
||||
|
||||
# Worktreeクリーンアップ
|
||||
git worktree prune
|
||||
|
||||
# 再実行
|
||||
miyabi work-on 42
|
||||
```
|
||||
|
||||
### より詳しいヘルプ
|
||||
```bash
|
||||
# トラブルシューティングガイド
|
||||
cat docs/TROUBLESHOOTING.md
|
||||
|
||||
# Agent仕様確認
|
||||
cat .claude/agents/README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**miyabi-cli-standaloneプロジェクトの標準ワークフロー**
|
||||
**Miyabi - Beauty in Autonomous Development 🌸**
|
||||
53
.claude/agents/prompts/coding/example-prompt.md
Normal file
53
.claude/agents/prompts/coding/example-prompt.md
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Example Agent Prompt
|
||||
|
||||
このファイルは、Agentプロンプトのサンプルです。
|
||||
|
||||
## プロンプト構造
|
||||
|
||||
```markdown
|
||||
# [Task名]
|
||||
|
||||
## Context
|
||||
プロジェクトのコンテキスト情報
|
||||
|
||||
## Objective
|
||||
このAgentが達成すべき目標
|
||||
|
||||
## Inputs
|
||||
- Issue URL: https://github.com/user/repo/issues/123
|
||||
- Task ID: TASK-456
|
||||
- Dependencies: TASK-123, TASK-124
|
||||
|
||||
## Instructions
|
||||
1. ステップ1を実行
|
||||
2. ステップ2を実行
|
||||
3. ...
|
||||
|
||||
## Output Format
|
||||
期待される出力形式(JSON, Markdown, Code等)
|
||||
|
||||
## Success Criteria
|
||||
- 基準1
|
||||
- 基準2
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
Worktree内でClaude Codeセッションを起動する際、このプロンプトが自動的に読み込まれます。
|
||||
|
||||
```bash
|
||||
cd .worktrees/issue-123
|
||||
# Claude Codeがこのプロンプトを参照して実行
|
||||
```
|
||||
|
||||
## カスタマイズ
|
||||
|
||||
プロジェクト固有のプロンプトを作成する場合:
|
||||
|
||||
1. このファイルをコピー
|
||||
2. 内容をカスタマイズ
|
||||
3. `.claude/agents/prompts/coding/` に配置
|
||||
|
||||
## 🔗 参考
|
||||
|
||||
実際のプロンプト例は、Miyabiプロジェクトの `.claude/agents/prompts/coding/` を参照してください。
|
||||
64
.claude/agents/specs/business/README.md
Normal file
64
.claude/agents/specs/business/README.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# Business Agent 仕様
|
||||
|
||||
このディレクトリには、ビジネス系Agent(14種類)の仕様を配置します。
|
||||
|
||||
## Agent仕様ファイルのフォーマット
|
||||
|
||||
各Agentの仕様は以下の構造で記述します:
|
||||
|
||||
```markdown
|
||||
# [Agent名] 仕様
|
||||
|
||||
## 概要
|
||||
Agentの役割とビジネス目標
|
||||
|
||||
## 入力
|
||||
- ユーザー要求(市場情報、目標KPI等)
|
||||
- 必須パラメータ
|
||||
|
||||
## 実行フェーズ
|
||||
1. Phase 1: データ収集
|
||||
2. Phase 2: 分析
|
||||
3. Phase 3: 戦略立案
|
||||
4. ...
|
||||
|
||||
## 出力
|
||||
- 生成するビジネスドキュメント
|
||||
- レポート形式
|
||||
|
||||
## 品質基準
|
||||
- 検証項目
|
||||
- スコアリング基準(100点満点)
|
||||
|
||||
## 実行例
|
||||
\`\`\`bash
|
||||
miyabi agent run ai-entrepreneur --output business-plan.md
|
||||
\`\`\`
|
||||
```
|
||||
|
||||
## 📊 Business Agent一覧
|
||||
|
||||
### 戦略・企画系
|
||||
- **AIEntrepreneurAgent** - 包括的ビジネスプラン作成
|
||||
- **ProductConceptAgent** - 製品コンセプト設計
|
||||
- **ProductDesignAgent** - サービス詳細設計
|
||||
- **FunnelDesignAgent** - 導線設計
|
||||
- **PersonaAgent** - ターゲット顧客ペルソナ
|
||||
- **SelfAnalysisAgent** - 自己分析
|
||||
|
||||
### マーケティング系
|
||||
- **MarketResearchAgent** - 市場調査
|
||||
- **MarketingAgent** - マーケティング戦略
|
||||
- **ContentCreationAgent** - コンテンツ制作
|
||||
- **SNSStrategyAgent** - SNS戦略
|
||||
- **YouTubeAgent** - YouTube運用最適化
|
||||
|
||||
### 営業・顧客管理系
|
||||
- **SalesAgent** - セールスプロセス最適化
|
||||
- **CRMAgent** - 顧客関係管理
|
||||
- **AnalyticsAgent** - データ分析・PDCA
|
||||
|
||||
## 🔗 参考
|
||||
|
||||
- [SaaS Business Model Guide](https://github.com/ShunsukeHayashi/Miyabi/blob/main/docs/SAAS_BUSINESS_MODEL.md)
|
||||
- [Business Agents User Guide](https://github.com/ShunsukeHayashi/Miyabi/blob/main/docs/BUSINESS_AGENTS_USER_GUIDE.md)
|
||||
33
.claude/agents/specs/business/coordinator.md
Normal file
33
.claude/agents/specs/business/coordinator.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Coordinator Agent Spec
|
||||
|
||||
## Role
|
||||
タスク調整とAgent間連携を担当
|
||||
|
||||
## Responsibilities
|
||||
- Issue分析と分解
|
||||
- Agent割り当て
|
||||
- 進捗管理
|
||||
- 品質ゲートチェック
|
||||
|
||||
## Tools
|
||||
- GitHub (Issues, PRs)
|
||||
- Agent invocation
|
||||
- Read/Grep
|
||||
|
||||
## Workflow
|
||||
1. Issue受領
|
||||
2. 要件分析
|
||||
3. タスク分解
|
||||
4. Agent割り当て
|
||||
5. 進捗監視
|
||||
6. PR作成
|
||||
|
||||
## Escalation
|
||||
- ブロッカー発生 → User
|
||||
- 優先度判断 → User
|
||||
- スコープ変更 → User
|
||||
|
||||
## Output
|
||||
- タスク計画
|
||||
- 進捗レポート
|
||||
- PR
|
||||
50
.claude/agents/specs/coding/README.md
Normal file
50
.claude/agents/specs/coding/README.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Coding Agent 仕様
|
||||
|
||||
このディレクトリには、コーディング系Agent(7種類)の仕様を配置します。
|
||||
|
||||
## Agent仕様ファイルのフォーマット
|
||||
|
||||
各Agentの仕様は以下の構造で記述します:
|
||||
|
||||
```markdown
|
||||
# [Agent名] 仕様
|
||||
|
||||
## 概要
|
||||
Agentの役割と責任範囲
|
||||
|
||||
## 入力
|
||||
- 受け取るTask/Issueの形式
|
||||
- 必須パラメータ
|
||||
|
||||
## 処理フロー
|
||||
1. ステップ1
|
||||
2. ステップ2
|
||||
3. ...
|
||||
|
||||
## 出力
|
||||
- 生成する成果物
|
||||
- 更新するIssue/PR
|
||||
|
||||
## エスカレーション条件
|
||||
- 上位Agentへのエスカレーション基準
|
||||
- エラーハンドリング
|
||||
|
||||
## 実行例
|
||||
\`\`\`bash
|
||||
miyabi agent run [agent-type] --issue 123
|
||||
\`\`\`
|
||||
```
|
||||
|
||||
## 📋 テンプレート
|
||||
|
||||
新しいAgent仕様を作成する場合、以下のテンプレートを使用してください:
|
||||
|
||||
```bash
|
||||
cp example-agent-spec.md my-custom-agent.md
|
||||
```
|
||||
|
||||
## 🔗 参考
|
||||
|
||||
既存のAgent仕様は以下を参照:
|
||||
- Miyabiプロジェクトの `.claude/agents/specs/coding/` ディレクトリ
|
||||
- [Agent Operations Manual](https://github.com/ShunsukeHayashi/Miyabi/blob/main/docs/AGENT_OPERATIONS_MANUAL.md)
|
||||
87
.claude/agents/specs/coding/codegen-agent-example.md
Normal file
87
.claude/agents/specs/coding/codegen-agent-example.md
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
# CodeGenAgent Specification
|
||||
|
||||
## 概要
|
||||
CodeGenAgentは、AI駆動のコード生成を担当するSpecialist Agentです。
|
||||
Claude Sonnet 4を使用して、型安全で高品質なRustコードを生成します。
|
||||
|
||||
## 入力
|
||||
- **Task**: CoordinatorAgentから受け取ったTask
|
||||
- Task ID
|
||||
- 依存関係(Dependencies)
|
||||
- 生成すべきコードの仕様
|
||||
- **Issue Context**: 元のIssue情報
|
||||
|
||||
## 処理フロー
|
||||
|
||||
### 1. 要件分析
|
||||
- Taskの内容を解析
|
||||
- 必要なモジュール・トレイト・構造体を特定
|
||||
- 既存コードとの整合性確認
|
||||
|
||||
### 2. コード生成
|
||||
```rust
|
||||
// 例: 新しいAgent構造体の生成
|
||||
pub struct NewAgent {
|
||||
config: AgentConfig,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl BaseAgent for NewAgent {
|
||||
async fn execute(&self, task: Task) -> Result<AgentResult> {
|
||||
// Implementation
|
||||
Ok(AgentResult::success(data))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. テスト生成
|
||||
```rust
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_new_agent() {
|
||||
let agent = NewAgent::new(config);
|
||||
let result = agent.execute(task).await.unwrap();
|
||||
assert_eq!(result.status, ResultStatus::Success);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. ドキュメント生成
|
||||
- Rustdocコメント(`///`)の追加
|
||||
- 使用例の記述
|
||||
- パラメータ・戻り値の説明
|
||||
|
||||
## 出力
|
||||
- **生成コード**: Rust source files
|
||||
- **テスト**: `#[cfg(test)]` mod
|
||||
- **ドキュメント**: Rustdoc comments
|
||||
- **Commit**: Conventional Commits形式
|
||||
|
||||
## エスカレーション条件
|
||||
- 既存コードとの大規模なコンフリクト
|
||||
- セキュリティ上の懸念(unsafe使用等)
|
||||
- 外部依存の追加が必要
|
||||
|
||||
## 品質基準
|
||||
- ✅ Clippy警告0件
|
||||
- ✅ テストカバレッジ80%以上
|
||||
- ✅ すべてのpublic APIにRustdoc
|
||||
- ✅ エラーハンドリング完備
|
||||
|
||||
## 実行例
|
||||
```bash
|
||||
miyabi agent run codegen --issue 123
|
||||
```
|
||||
|
||||
または簡易コマンド:
|
||||
```bash
|
||||
miyabi work-on 123
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**このファイルはClaude Codeが参照する実際のAgent仕様です。**
|
||||
**プロジェクト固有の要件に合わせてカスタマイズしてください。**
|
||||
30
.claude/agents/specs/coding/developer.md
Normal file
30
.claude/agents/specs/coding/developer.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Developer Agent Spec
|
||||
|
||||
## Role
|
||||
Rustコード実装を担当する開発Agent
|
||||
|
||||
## Responsibilities
|
||||
- 機能実装
|
||||
- バグ修正
|
||||
- コードレビュー対応
|
||||
- テスト作成
|
||||
|
||||
## Tools
|
||||
- Read/Write/Edit
|
||||
- Bash (cargo commands)
|
||||
- Grep/Glob
|
||||
|
||||
## Constraints
|
||||
- Conventional Commits準拠
|
||||
- `cargo clippy` 警告ゼロ
|
||||
- テストカバレッジ維持
|
||||
|
||||
## Escalation
|
||||
- アーキテクチャ変更 → Architect Agent
|
||||
- 要件不明確 → User
|
||||
- 外部依存の問題 → User
|
||||
|
||||
## Output
|
||||
- 実装コード
|
||||
- テストコード
|
||||
- コミットメッセージ
|
||||
32
.claude/agents/specs/coding/reviewer.md
Normal file
32
.claude/agents/specs/coding/reviewer.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Reviewer Agent Spec
|
||||
|
||||
## Role
|
||||
コードレビューを担当するAgent
|
||||
|
||||
## Responsibilities
|
||||
- コード品質チェック
|
||||
- セキュリティレビュー
|
||||
- パフォーマンス分析
|
||||
- ベストプラクティス適用
|
||||
|
||||
## Tools
|
||||
- Read
|
||||
- Grep/Glob
|
||||
- Bash (lint/test)
|
||||
|
||||
## Review Checklist
|
||||
- [ ] 可読性
|
||||
- [ ] エラーハンドリング
|
||||
- [ ] テストカバレッジ
|
||||
- [ ] ドキュメント
|
||||
- [ ] セキュリティ
|
||||
- [ ] パフォーマンス
|
||||
|
||||
## Escalation
|
||||
- 重大なセキュリティ問題 → User
|
||||
- アーキテクチャ懸念 → Architect Agent
|
||||
|
||||
## Output
|
||||
- レビューコメント
|
||||
- 改善提案
|
||||
- 承認/要修正判定
|
||||
35
.claude/agents/specs/coding/tester.md
Normal file
35
.claude/agents/specs/coding/tester.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Tester Agent Spec
|
||||
|
||||
## Role
|
||||
テスト作成・実行を担当するAgent
|
||||
|
||||
## Responsibilities
|
||||
- ユニットテスト作成
|
||||
- 統合テスト作成
|
||||
- テスト実行・分析
|
||||
- カバレッジ向上
|
||||
|
||||
## Tools
|
||||
- Read/Write/Edit
|
||||
- Bash (cargo test)
|
||||
- Grep/Glob
|
||||
|
||||
## Test Types
|
||||
- Unit tests
|
||||
- Integration tests
|
||||
- Property-based tests
|
||||
- Benchmark tests
|
||||
|
||||
## Constraints
|
||||
- AAA pattern (Arrange-Act-Assert)
|
||||
- 意味のあるテスト名
|
||||
- エッジケース網羅
|
||||
|
||||
## Escalation
|
||||
- テスト環境の問題 → User
|
||||
- 仕様不明確 → Developer Agent
|
||||
|
||||
## Output
|
||||
- テストコード
|
||||
- カバレッジレポート
|
||||
- 失敗分析
|
||||
7
.claude/commands/build.md
Normal file
7
.claude/commands/build.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
プロジェクトをビルドしてください。
|
||||
|
||||
```bash
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
エラーがあれば修正してください。
|
||||
8
.claude/commands/lint.md
Normal file
8
.claude/commands/lint.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
Lintを実行してコード品質をチェックしてください。
|
||||
|
||||
```bash
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
cargo fmt --all --check
|
||||
```
|
||||
|
||||
警告やエラーがあれば修正してください。
|
||||
14
.claude/commands/review.md
Normal file
14
.claude/commands/review.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
現在の変更をコードレビューしてください。
|
||||
|
||||
```bash
|
||||
git diff
|
||||
```
|
||||
|
||||
以下の観点でレビュー:
|
||||
- コード品質
|
||||
- パフォーマンス
|
||||
- セキュリティ
|
||||
- エラーハンドリング
|
||||
- テストカバレッジ
|
||||
|
||||
改善点があれば提案してください。
|
||||
11
.claude/commands/status.md
Normal file
11
.claude/commands/status.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
プロジェクトの状態を確認してください。
|
||||
|
||||
1. Gitステータス
|
||||
2. Miyabiステータス
|
||||
3. 未完了のTODO
|
||||
4. 最近のコミット
|
||||
|
||||
```bash
|
||||
git status
|
||||
miyabi status
|
||||
```
|
||||
7
.claude/commands/test.md
Normal file
7
.claude/commands/test.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
全てのテストを実行してください。
|
||||
|
||||
```bash
|
||||
cargo test --all
|
||||
```
|
||||
|
||||
失敗したテストがあれば原因を分析し、修正してください。
|
||||
31
.claude/prompts/debug.md
Normal file
31
.claude/prompts/debug.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Debug Prompt
|
||||
|
||||
問題をデバッグして修正してください。
|
||||
|
||||
## プロセス
|
||||
|
||||
1. **問題の再現** - 症状の確認
|
||||
2. **原因調査** - ログ、スタックトレース分析
|
||||
3. **仮説立案** - 可能性のある原因
|
||||
4. **検証** - 仮説のテスト
|
||||
5. **修正** - 根本原因の解決
|
||||
6. **回帰テスト** - 再発防止の確認
|
||||
|
||||
## デバッグツール
|
||||
|
||||
```bash
|
||||
# ログ確認
|
||||
RUST_LOG=debug cargo run
|
||||
|
||||
# バックトレース
|
||||
RUST_BACKTRACE=1 cargo run
|
||||
|
||||
# テスト
|
||||
cargo test <test_name> -- --nocapture
|
||||
```
|
||||
|
||||
## 出力
|
||||
|
||||
- 根本原因の説明
|
||||
- 修正コード
|
||||
- 再発防止策
|
||||
30
.claude/prompts/implement-feature.md
Normal file
30
.claude/prompts/implement-feature.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Feature Implementation Prompt
|
||||
|
||||
新機能を実装してください。
|
||||
|
||||
## プロセス
|
||||
|
||||
1. **要件理解** - 仕様の確認と質問
|
||||
2. **設計** - アーキテクチャ決定
|
||||
3. **実装** - コード作成
|
||||
4. **テスト** - ユニット/統合テスト
|
||||
5. **ドキュメント** - 必要に応じて
|
||||
|
||||
## コーディング規約
|
||||
|
||||
### Rust
|
||||
- `cargo fmt` でフォーマット
|
||||
- `cargo clippy` 警告ゼロ
|
||||
- Result型でエラーハンドリング
|
||||
- 適切なドキュメントコメント
|
||||
|
||||
### 構造
|
||||
- 単一責任の関数/構造体
|
||||
- 適切な抽象化レベル
|
||||
- テスト可能な設計
|
||||
|
||||
## 出力
|
||||
|
||||
- 実装コード
|
||||
- テストコード
|
||||
- 使用例
|
||||
22
.claude/prompts/refactor.md
Normal file
22
.claude/prompts/refactor.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Refactoring Prompt
|
||||
|
||||
対象コードをリファクタリングしてください。
|
||||
|
||||
## 方針
|
||||
|
||||
1. **可読性向上** - 命名、構造の改善
|
||||
2. **DRY原則** - 重複コードの排除
|
||||
3. **SOLID原則** - 責務の分離
|
||||
4. **パフォーマンス** - 不要な処理の削除
|
||||
|
||||
## 制約
|
||||
|
||||
- 既存の機能を維持
|
||||
- テストが通ること
|
||||
- 破壊的変更を避ける
|
||||
|
||||
## 出力
|
||||
|
||||
- 変更内容の説明
|
||||
- 改善点のリスト
|
||||
- 必要に応じてテストの追加
|
||||
24
.claude/templates/issue.md
Normal file
24
.claude/templates/issue.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Issue Template
|
||||
|
||||
## Title
|
||||
[type]: Short description
|
||||
|
||||
## Description
|
||||
明確で簡潔な説明
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Criterion 1
|
||||
- [ ] Criterion 2
|
||||
- [ ] Criterion 3
|
||||
|
||||
## Technical Notes
|
||||
実装に関する技術的な注意点
|
||||
|
||||
## Labels
|
||||
- `type:feature` / `type:bug` / `type:refactor`
|
||||
- `priority:high` / `priority:medium` / `priority:low`
|
||||
- `component:tui` / `component:cli` / `component:core`
|
||||
|
||||
## Related
|
||||
- Related Issue: #xxx
|
||||
- Related PR: #xxx
|
||||
33
.claude/templates/pr.md
Normal file
33
.claude/templates/pr.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Pull Request Template
|
||||
|
||||
## Summary
|
||||
変更内容の要約(1-3行)
|
||||
|
||||
## Changes
|
||||
- Change 1
|
||||
- Change 2
|
||||
- Change 3
|
||||
|
||||
## Type
|
||||
- [ ] Feature
|
||||
- [ ] Bug Fix
|
||||
- [ ] Refactor
|
||||
- [ ] Documentation
|
||||
- [ ] Test
|
||||
|
||||
## Testing
|
||||
- [ ] Unit tests added/updated
|
||||
- [ ] Integration tests added/updated
|
||||
- [ ] Manual testing performed
|
||||
|
||||
## Checklist
|
||||
- [ ] `cargo fmt` passed
|
||||
- [ ] `cargo clippy` passed
|
||||
- [ ] `cargo test` passed
|
||||
- [ ] Documentation updated
|
||||
|
||||
## Screenshots
|
||||
(if applicable)
|
||||
|
||||
## Related Issues
|
||||
Closes #xxx
|
||||
52
.claude/templates/rust-module.md
Normal file
52
.claude/templates/rust-module.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Rust Module Template
|
||||
|
||||
```rust
|
||||
//! Module description
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```rust
|
||||
//! use crate::module_name;
|
||||
//!
|
||||
//! // Example usage
|
||||
//! ```
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
/// Description
|
||||
pub struct StructName {
|
||||
/// Field description
|
||||
field: Type,
|
||||
}
|
||||
|
||||
impl StructName {
|
||||
/// Creates a new instance
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
field: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Method description
|
||||
pub fn method(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_example() {
|
||||
// Arrange
|
||||
let instance = StructName::new();
|
||||
|
||||
// Act
|
||||
let result = instance.method();
|
||||
|
||||
// Assert
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
```
|
||||
25
.env.example
Normal file
25
.env.example
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# GitHub Configuration
|
||||
# Get token at: https://github.com/settings/tokens
|
||||
# Required scopes: repo, workflow, admin:org (for Projects)
|
||||
GITHUB_TOKEN=ghp_your_github_token_here
|
||||
|
||||
# Repository Information
|
||||
# Format: owner/repo (e.g., YourUsername/my-project)
|
||||
REPOSITORY=ShunsukeHayashi/miyabi-cli-standalone
|
||||
|
||||
# Anthropic API Key (optional for local development)
|
||||
# Get key at: https://console.anthropic.com/
|
||||
# Required for running agents locally
|
||||
ANTHROPIC_API_KEY=sk-ant-your_anthropic_key_here
|
||||
|
||||
# Device Identifier (for logging)
|
||||
DEVICE_IDENTIFIER=MyComputer
|
||||
|
||||
# Agent Configuration
|
||||
LOG_DIRECTORY=.ai/logs
|
||||
REPORT_DIRECTORY=.ai/parallel-reports
|
||||
DEFAULT_CONCURRENCY=2
|
||||
|
||||
# Development Options
|
||||
USE_TASK_TOOL=false
|
||||
USE_WORKTREE=false
|
||||
33
.gitignore
vendored
33
.gitignore
vendored
|
|
@ -137,3 +137,36 @@ dist
|
|||
# Vite logs files
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
|
||||
# Agentic OS
|
||||
# Dependencies
|
||||
node_modules/
|
||||
package-lock.json
|
||||
|
||||
# Build output
|
||||
dist/
|
||||
*.tsbuildinfo
|
||||
|
||||
# Environment variables
|
||||
.env
|
||||
.env.local
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Test coverage
|
||||
coverage/
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.worktrees/
|
||||
.ai/
|
||||
.env
|
||||
|
|
|
|||
21
.miyabi.yml
Normal file
21
.miyabi.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Miyabi Configuration
|
||||
project_name: miyabi-cli-standalone
|
||||
version: "0.1.0"
|
||||
|
||||
# GitHub settings (use environment variables for sensitive data)
|
||||
# github_token: ${{ GITHUB_TOKEN }}
|
||||
|
||||
# Agent settings
|
||||
agents:
|
||||
enabled: true
|
||||
use_worktree: true
|
||||
worktree_base_path: ".worktrees"
|
||||
|
||||
# Logging
|
||||
logging:
|
||||
level: info
|
||||
directory: "./logs"
|
||||
|
||||
# Reporting
|
||||
reporting:
|
||||
directory: "./reports"
|
||||
119
CLAUDE.md
Normal file
119
CLAUDE.md
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
ターゲットとする機能のベースライン: codex cli Ref_URL=https://github.com/openai/codex.git
|
||||
|
||||
ターゲットとする機能をベースに拡張すべき機能を有するPJ: /Users/shunsuke/dev/01-miyabi/_core/miyabi-private
|
||||
|
||||
===
|
||||
|
||||
|
||||
# miyabi-cli-standalone
|
||||
|
||||
**Miyabi CLI Standalone** - 軽量スタンドアロン版 Miyabi CLI/TUI
|
||||
|
||||
## プロジェクト概要
|
||||
|
||||
Miyabi本体から独立した軽量CLIツール。TUI (Terminal User Interface) とCLI機能を提供。
|
||||
|
||||
## 技術スタック
|
||||
|
||||
- **言語**: Rust 2021 Edition, TypeScript
|
||||
- **TUIフレームワーク**: Ratatui + Crossterm
|
||||
- **CLIフレームワーク**: Clap
|
||||
- **非同期ランタイム**: Tokio
|
||||
|
||||
## ディレクトリ構造
|
||||
|
||||
```
|
||||
miyabi-cli-standalone/
|
||||
├── crates/
|
||||
│ ├── miyabi-cli/ # CLI実装
|
||||
│ ├── miyabi-core/ # コアライブラリ
|
||||
│ └── miyabi-tui/ # TUI実装
|
||||
├── src/ # TypeScriptソース
|
||||
│ └── index.ts
|
||||
├── tests/ # テスト
|
||||
├── .claude/ # Claude Code設定
|
||||
│ ├── agents/ # Agent仕様
|
||||
│ ├── commands/ # カスタムコマンド
|
||||
│ └── prompts/ # プロンプト
|
||||
├── docs/ # ドキュメント
|
||||
├── logs/ # ログ
|
||||
├── reports/ # レポート
|
||||
├── Cargo.toml # Rustワークスペース設定
|
||||
├── package.json # Node.js設定
|
||||
└── .miyabi.yml # Miyabi設定
|
||||
```
|
||||
|
||||
## 開発コマンド
|
||||
|
||||
### Rust
|
||||
|
||||
```bash
|
||||
# ビルド
|
||||
cargo build --release
|
||||
|
||||
# テスト
|
||||
cargo test --all
|
||||
|
||||
# Lint
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
|
||||
# フォーマット
|
||||
cargo fmt --all
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
```bash
|
||||
# インストール
|
||||
npm install
|
||||
|
||||
# ビルド
|
||||
npm run build
|
||||
|
||||
# Lint
|
||||
npm run lint
|
||||
```
|
||||
|
||||
## コミット規約
|
||||
|
||||
Conventional Commits準拠:
|
||||
- `feat:` - 新機能
|
||||
- `fix:` - バグ修正
|
||||
- `refactor:` - リファクタリング
|
||||
- `docs:` - ドキュメント
|
||||
- `test:` - テスト
|
||||
- `chore:` - その他
|
||||
|
||||
## 環境変数
|
||||
|
||||
```bash
|
||||
GITHUB_TOKEN=ghp_xxx # GitHub PAT
|
||||
RUST_LOG=info # ログレベル
|
||||
RUST_BACKTRACE=1 # バックトレース
|
||||
```
|
||||
|
||||
## Miyabi統合
|
||||
|
||||
```bash
|
||||
# ステータス確認
|
||||
miyabi status
|
||||
|
||||
# Agent実行
|
||||
miyabi agent run coordinator --issue <番号>
|
||||
```
|
||||
|
||||
## コーディング規約
|
||||
|
||||
### Rust
|
||||
- `cargo fmt` でフォーマット
|
||||
- `cargo clippy` 警告ゼロ
|
||||
- Result型でエラーハンドリング
|
||||
- async/awaitでの非同期処理
|
||||
|
||||
### TypeScript
|
||||
- ESLint設定に従う
|
||||
- 厳格な型付け
|
||||
|
||||
---
|
||||
|
||||
**このファイルはClaude Codeが自動参照します。**
|
||||
1463
Cargo.lock
generated
Normal file
1463
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
56
Cargo.toml
Normal file
56
Cargo.toml
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"crates/miyabi-cli",
|
||||
"crates/miyabi-tui",
|
||||
"crates/miyabi-core",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.75"
|
||||
authors = ["Miyabi Team"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/ShunsukeHayashi/miyabi-cli-standalone"
|
||||
homepage = "https://github.com/ShunsukeHayashi/miyabi-cli-standalone"
|
||||
description = "Miyabi - Autonomous AI Development Framework"
|
||||
keywords = ["ai", "cli", "tui", "autonomous", "development"]
|
||||
categories = ["command-line-utilities", "development-tools"]
|
||||
|
||||
[workspace.dependencies]
|
||||
# Async Runtime
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "macros", "io-std", "sync", "process", "signal"] }
|
||||
futures = "0.3"
|
||||
|
||||
# TUI Framework
|
||||
ratatui = { version = "0.29.0", features = [
|
||||
"scrolling-regions",
|
||||
"unstable-backend-writer",
|
||||
"unstable-rendered-line-info",
|
||||
"unstable-widget-ref",
|
||||
] }
|
||||
crossterm = { version = "0.29.0", features = ["bracketed-paste", "event-stream"] }
|
||||
|
||||
# Text Processing
|
||||
textwrap = "0.16"
|
||||
unicode-width = "0.2"
|
||||
|
||||
# CLI
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
|
||||
# Error Handling
|
||||
anyhow = "1"
|
||||
thiserror = "2"
|
||||
|
||||
# Serialization
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
# Logging
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
# Utilities
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
uuid = { version = "1", features = ["v4", "serde"] }
|
||||
188
GOALS.md
Normal file
188
GOALS.md
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
# Miyabi CLI - Development Goals
|
||||
|
||||
## Reference Projects
|
||||
|
||||
### Baseline
|
||||
- **Codex CLI**: https://github.com/openai/codex.git
|
||||
|
||||
### Extension Source
|
||||
- **Miyabi Private**: /Users/shunsuke/dev/01-miyabi/_core/miyabi-private
|
||||
|
||||
---
|
||||
|
||||
## Mission
|
||||
**Codex CLI同等の品質を持つ、Production-Ready Miyabi CLIを構築する**
|
||||
|
||||
---
|
||||
|
||||
## Gap Analysis Summary
|
||||
|
||||
| Metric | Codex CLI | Current Miyabi | Target |
|
||||
|--------|-----------|----------------|--------|
|
||||
| Total Lines | 20,969 | 1,200 | 15,000+ |
|
||||
| Files | 50+ | 10 | 40+ |
|
||||
| Features | Complete | Basic | Full Parity |
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Core TUI Foundation ✅ COMPLETED
|
||||
**Status**: Done (1,200 lines)
|
||||
|
||||
- [x] Cargo workspace setup
|
||||
- [x] wrapping.rs - Text wrapping with textwrap
|
||||
- [x] history_cell.rs - Card design UI
|
||||
- [x] markdown_render.rs - Basic markdown
|
||||
- [x] app.rs - Main TUI loop
|
||||
- [x] event.rs - Event handling
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Advanced Text Rendering 🔄 IN PROGRESS
|
||||
**Target**: +1,500 lines
|
||||
|
||||
### 2.1 markdown_stream.rs (690 lines)
|
||||
- [ ] Streaming markdown rendering
|
||||
- [ ] Progressive display during generation
|
||||
- [ ] Cursor position tracking
|
||||
- [ ] Partial code block handling
|
||||
|
||||
### 2.2 diff_render.rs (715 lines)
|
||||
- [ ] Git diff visualization
|
||||
- [ ] Syntax highlighting for diffs
|
||||
- [ ] Line number display
|
||||
- [ ] Add/Remove/Change indicators
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Chat Composer Separation
|
||||
**Target**: +4,000 lines
|
||||
|
||||
### 3.1 chat_composer.rs (3,938 lines)
|
||||
- [ ] Separate input handling from main app
|
||||
- [ ] Multi-line input support
|
||||
- [ ] Command history
|
||||
- [ ] Auto-completion
|
||||
- [ ] Syntax highlighting in input
|
||||
|
||||
### 3.2 textarea.rs (2,213 lines)
|
||||
- [ ] Full-featured text area widget
|
||||
- [ ] Selection support
|
||||
- [ ] Copy/paste
|
||||
- [ ] Undo/redo
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Approval & Feedback
|
||||
**Target**: +1,500 lines
|
||||
|
||||
### 4.1 approval_overlay.rs (656 lines)
|
||||
- [ ] Tool execution approval UI
|
||||
- [ ] Y/N/Always/Never options
|
||||
- [ ] Risk level display
|
||||
- [ ] Preview of changes
|
||||
|
||||
### 4.2 feedback_view.rs (555 lines)
|
||||
- [ ] User feedback collection
|
||||
- [ ] Rating system
|
||||
- [ ] Comment input
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Advanced Navigation
|
||||
**Target**: +2,500 lines
|
||||
|
||||
### 5.1 resume_picker.rs (1,580 lines)
|
||||
- [ ] Session resume selection
|
||||
- [ ] Conversation history browser
|
||||
- [ ] Search functionality
|
||||
- [ ] Preview pane
|
||||
|
||||
### 5.2 pager_overlay.rs (913 lines)
|
||||
- [ ] Full-screen content viewer
|
||||
- [ ] Scroll and search
|
||||
- [ ] Jump to line
|
||||
- [ ] Keyboard shortcuts
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: LLM Integration
|
||||
**Target**: +2,000 lines
|
||||
|
||||
### 6.1 Claude API Integration
|
||||
- [ ] Anthropic API client
|
||||
- [ ] Streaming responses
|
||||
- [ ] Token counting
|
||||
- [ ] Rate limiting
|
||||
- [ ] Error handling
|
||||
|
||||
### 6.2 Conversation Management
|
||||
- [ ] Context window management
|
||||
- [ ] Message history
|
||||
- [ ] System prompts
|
||||
- [ ] Tool definitions
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Tool Execution
|
||||
**Target**: +2,500 lines
|
||||
|
||||
### 7.1 A2A Bridge Integration
|
||||
- [ ] Tool registry
|
||||
- [ ] Execution engine
|
||||
- [ ] Result formatting
|
||||
- [ ] Error recovery
|
||||
|
||||
### 7.2 Built-in Tools
|
||||
- [ ] File operations (Read, Write, Edit)
|
||||
- [ ] Bash execution
|
||||
- [ ] Search (Glob, Grep)
|
||||
- [ ] Web fetch
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### Functional Requirements
|
||||
- [ ] Real Claude API conversations
|
||||
- [ ] Tool execution with approval
|
||||
- [ ] Session persistence and resume
|
||||
- [ ] Markdown rendering with streaming
|
||||
- [ ] Full keyboard navigation
|
||||
|
||||
### Quality Requirements
|
||||
- [ ] 15,000+ lines of code
|
||||
- [ ] 90%+ test coverage
|
||||
- [ ] < 100ms response latency
|
||||
- [ ] Memory efficient (< 100MB)
|
||||
- [ ] Cross-platform (macOS, Linux)
|
||||
|
||||
### User Experience
|
||||
- [ ] Intuitive keyboard shortcuts
|
||||
- [ ] Clear visual feedback
|
||||
- [ ] Smooth scrolling
|
||||
- [ ] Proper error messages
|
||||
- [ ] Help system
|
||||
|
||||
---
|
||||
|
||||
## Timeline
|
||||
|
||||
| Phase | Duration | Deliverable |
|
||||
|-------|----------|-------------|
|
||||
| Phase 1 | ✅ Done | Core TUI |
|
||||
| Phase 2 | 1 week | Streaming Markdown |
|
||||
| Phase 3 | 2 weeks | Chat Composer |
|
||||
| Phase 4 | 1 week | Approval System |
|
||||
| Phase 5 | 1 week | Navigation |
|
||||
| Phase 6 | 2 weeks | LLM Integration |
|
||||
| Phase 7 | 2 weeks | Tool Execution |
|
||||
|
||||
**Total**: ~10 weeks to Production-Ready
|
||||
|
||||
---
|
||||
|
||||
## Next Action
|
||||
|
||||
**Phase 2.1: Implement markdown_stream.rs**
|
||||
|
||||
Create streaming markdown renderer that can display partial content during LLM generation.
|
||||
36
crates/miyabi-cli/Cargo.toml
Normal file
36
crates/miyabi-cli/Cargo.toml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
[package]
|
||||
name = "miyabi-cli"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
description = "Miyabi CLI - Main command-line interface"
|
||||
|
||||
[[bin]]
|
||||
name = "miyabi"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
# Workspace crates
|
||||
miyabi-core = { path = "../miyabi-core" }
|
||||
miyabi-tui = { path = "../miyabi-tui" }
|
||||
|
||||
# CLI
|
||||
clap = { workspace = true }
|
||||
|
||||
# TUI Framework
|
||||
ratatui = { workspace = true }
|
||||
crossterm = { workspace = true }
|
||||
|
||||
# Async Runtime
|
||||
tokio = { workspace = true }
|
||||
|
||||
# Error Handling
|
||||
anyhow = { workspace = true }
|
||||
|
||||
# Logging
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { workspace = true }
|
||||
70
crates/miyabi-cli/src/main.rs
Normal file
70
crates/miyabi-cli/src/main.rs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//! Miyabi CLI - Main entry point
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "miyabi")]
|
||||
#[command(author, version, about = "Miyabi - Autonomous AI Development Framework", long_about = None)]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
command: Option<Commands>,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// Start the TUI interface
|
||||
Tui,
|
||||
/// Show status
|
||||
Status,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
// Initialize logging
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(EnvFilter::from_default_env())
|
||||
.init();
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli.command {
|
||||
Some(Commands::Tui) | None => {
|
||||
// Run TUI
|
||||
use miyabi_tui::App;
|
||||
use crossterm::{
|
||||
event::{DisableMouseCapture, EnableMouseCapture},
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
};
|
||||
use ratatui::prelude::*;
|
||||
use std::io;
|
||||
|
||||
enable_raw_mode()?;
|
||||
let mut stdout = io::stdout();
|
||||
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
|
||||
let backend = CrosstermBackend::new(stdout);
|
||||
let mut terminal = Terminal::new(backend)?;
|
||||
|
||||
let mut app = App::new();
|
||||
let res = app.run(&mut terminal).await;
|
||||
|
||||
disable_raw_mode()?;
|
||||
execute!(
|
||||
terminal.backend_mut(),
|
||||
LeaveAlternateScreen,
|
||||
DisableMouseCapture
|
||||
)?;
|
||||
terminal.show_cursor()?;
|
||||
|
||||
if let Err(err) = res {
|
||||
eprintln!("Error: {}", err);
|
||||
}
|
||||
}
|
||||
Some(Commands::Status) => {
|
||||
println!("Miyabi Status: Ready");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
20
crates/miyabi-core/Cargo.toml
Normal file
20
crates/miyabi-core/Cargo.toml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "miyabi-core"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
description = "Miyabi Core - Shared types and utilities"
|
||||
|
||||
[dependencies]
|
||||
tokio = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
23
crates/miyabi-core/src/error.rs
Normal file
23
crates/miyabi-core/src/error.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
//! Error types for Miyabi
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("IO error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
#[error("JSON error: {0}")]
|
||||
Json(#[from] serde_json::Error),
|
||||
|
||||
#[error("Configuration error: {0}")]
|
||||
Config(String),
|
||||
|
||||
#[error("Agent error: {0}")]
|
||||
Agent(String),
|
||||
|
||||
#[error("{0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
9
crates/miyabi-core/src/lib.rs
Normal file
9
crates/miyabi-core/src/lib.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
//! Miyabi Core - Shared types and utilities
|
||||
//!
|
||||
//! This crate provides core types and utilities shared across the Miyabi framework.
|
||||
|
||||
pub mod error;
|
||||
pub mod types;
|
||||
|
||||
pub use error::Error;
|
||||
pub use types::*;
|
||||
77
crates/miyabi-core/src/types.rs
Normal file
77
crates/miyabi-core/src/types.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//! Core types for Miyabi
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
/// Message role in a conversation
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Role {
|
||||
User,
|
||||
Assistant,
|
||||
System,
|
||||
Tool,
|
||||
}
|
||||
|
||||
/// Chat message
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ChatMessage {
|
||||
pub role: Role,
|
||||
pub content: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_name: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_call_id: Option<String>,
|
||||
pub timestamp: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl ChatMessage {
|
||||
pub fn user(content: impl Into<String>) -> Self {
|
||||
Self {
|
||||
role: Role::User,
|
||||
content: content.into(),
|
||||
tool_name: None,
|
||||
tool_call_id: None,
|
||||
timestamp: Utc::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assistant(content: impl Into<String>) -> Self {
|
||||
Self {
|
||||
role: Role::Assistant,
|
||||
content: content.into(),
|
||||
tool_name: None,
|
||||
tool_call_id: None,
|
||||
timestamp: Utc::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn system(content: impl Into<String>) -> Self {
|
||||
Self {
|
||||
role: Role::System,
|
||||
content: content.into(),
|
||||
tool_name: None,
|
||||
tool_call_id: None,
|
||||
timestamp: Utc::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tool(name: impl Into<String>, content: impl Into<String>, call_id: impl Into<String>) -> Self {
|
||||
Self {
|
||||
role: Role::Tool,
|
||||
content: content.into(),
|
||||
tool_name: Some(name.into()),
|
||||
tool_call_id: Some(call_id.into()),
|
||||
timestamp: Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tool execution result
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ToolResult {
|
||||
pub name: String,
|
||||
pub content: String,
|
||||
pub success: bool,
|
||||
pub execution_time_ms: u64,
|
||||
}
|
||||
45
crates/miyabi-tui/Cargo.toml
Normal file
45
crates/miyabi-tui/Cargo.toml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
[package]
|
||||
name = "miyabi-tui"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
description = "Miyabi TUI - Terminal User Interface following Codex patterns"
|
||||
|
||||
[[bin]]
|
||||
name = "miyabi-tui"
|
||||
path = "src/main.rs"
|
||||
|
||||
[lib]
|
||||
name = "miyabi_tui"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
# Workspace dependencies
|
||||
miyabi-core = { path = "../miyabi-core" }
|
||||
|
||||
# TUI Framework
|
||||
ratatui = { workspace = true }
|
||||
crossterm = { workspace = true }
|
||||
|
||||
# Text Processing
|
||||
textwrap = { workspace = true }
|
||||
unicode-width = { workspace = true }
|
||||
|
||||
# Async Runtime
|
||||
tokio = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
|
||||
# Error Handling
|
||||
anyhow = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
# Serialization
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
# Utilities
|
||||
chrono = { workspace = true }
|
||||
223
crates/miyabi-tui/src/app.rs
Normal file
223
crates/miyabi-tui/src/app.rs
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
//! Main TUI Application
|
||||
|
||||
use ratatui::{
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
style::{Color, Modifier, Style},
|
||||
text::{Line, Span},
|
||||
widgets::{Block, Borders, Paragraph, Scrollbar, ScrollbarOrientation, ScrollbarState},
|
||||
Frame,
|
||||
};
|
||||
use crossterm::event::{KeyCode, KeyModifiers};
|
||||
|
||||
use crate::event::{Event, EventHandler};
|
||||
use crate::history_cell::{
|
||||
HistoryCell, UserMessageCell, AssistantMessageCell, SystemMessageCell, SystemMessageType,
|
||||
};
|
||||
|
||||
/// Main application state
|
||||
pub struct App {
|
||||
/// Whether the app should quit
|
||||
pub should_quit: bool,
|
||||
/// Current input buffer
|
||||
pub input: String,
|
||||
/// Chat history cells
|
||||
pub cells: Vec<Box<dyn HistoryCell>>,
|
||||
/// Scroll position
|
||||
pub scroll: u16,
|
||||
/// Maximum scroll
|
||||
pub max_scroll: u16,
|
||||
}
|
||||
|
||||
impl App {
|
||||
/// Create a new app
|
||||
pub fn new() -> Self {
|
||||
let timestamp = chrono::Local::now().format("%H:%M").to_string();
|
||||
|
||||
let welcome_cell: Box<dyn HistoryCell> = Box::new(SystemMessageCell {
|
||||
content: "Welcome to Miyabi CLI! Type your message and press Enter.".to_string(),
|
||||
timestamp: timestamp.clone(),
|
||||
message_type: SystemMessageType::Info,
|
||||
});
|
||||
|
||||
Self {
|
||||
should_quit: false,
|
||||
input: String::new(),
|
||||
cells: vec![welcome_cell],
|
||||
scroll: 0,
|
||||
max_scroll: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Run the main app loop
|
||||
pub async fn run(
|
||||
&mut self,
|
||||
terminal: &mut ratatui::Terminal<impl ratatui::backend::Backend>,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut events = EventHandler::new(100);
|
||||
|
||||
loop {
|
||||
terminal.draw(|f| self.draw(f))?;
|
||||
|
||||
if let Some(event) = events.next().await {
|
||||
match event {
|
||||
Event::Key(key) => {
|
||||
if key.modifiers.contains(KeyModifiers::CONTROL) && key.code == KeyCode::Char('c') {
|
||||
self.should_quit = true;
|
||||
} else {
|
||||
match key.code {
|
||||
KeyCode::Enter => {
|
||||
if !self.input.is_empty() {
|
||||
self.send_message();
|
||||
}
|
||||
}
|
||||
KeyCode::Char(c) => {
|
||||
self.input.push(c);
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
self.input.pop();
|
||||
}
|
||||
KeyCode::Esc => {
|
||||
self.should_quit = true;
|
||||
}
|
||||
KeyCode::Up => {
|
||||
self.scroll = self.scroll.saturating_sub(1);
|
||||
}
|
||||
KeyCode::Down => {
|
||||
if self.scroll < self.max_scroll {
|
||||
self.scroll += 1;
|
||||
}
|
||||
}
|
||||
KeyCode::PageUp => {
|
||||
self.scroll = self.scroll.saturating_sub(10);
|
||||
}
|
||||
KeyCode::PageDown => {
|
||||
self.scroll = (self.scroll + 10).min(self.max_scroll);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::Resize(_, _) => {}
|
||||
Event::Tick => {}
|
||||
Event::Mouse(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
if self.should_quit {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Draw the UI
|
||||
fn draw(&mut self, frame: &mut Frame) {
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Length(3), // Header
|
||||
Constraint::Min(1), // Chat area
|
||||
Constraint::Length(3), // Input
|
||||
])
|
||||
.split(frame.area());
|
||||
|
||||
self.draw_header(frame, chunks[0]);
|
||||
self.draw_chat(frame, chunks[1]);
|
||||
self.draw_input(frame, chunks[2]);
|
||||
}
|
||||
|
||||
fn draw_header(&self, frame: &mut Frame, area: Rect) {
|
||||
let title = Paragraph::new(Line::from(vec![
|
||||
Span::styled(" Miyabi ", Style::default().fg(Color::Magenta).add_modifier(Modifier::BOLD)),
|
||||
Span::styled("CLI", Style::default().fg(Color::Cyan)),
|
||||
]))
|
||||
.block(Block::default().borders(Borders::ALL).border_style(Style::default().fg(Color::Rgb(86, 95, 137))));
|
||||
|
||||
frame.render_widget(title, area);
|
||||
}
|
||||
|
||||
fn draw_chat(&mut self, frame: &mut Frame, area: Rect) {
|
||||
let block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::default().fg(Color::Rgb(86, 95, 137)))
|
||||
.title(Span::styled(" Chat ", Style::default().fg(Color::Rgb(192, 202, 245))));
|
||||
|
||||
let inner = block.inner(area);
|
||||
frame.render_widget(block, area);
|
||||
|
||||
// Render cells
|
||||
let mut lines: Vec<Line<'static>> = Vec::new();
|
||||
let width = inner.width.saturating_sub(4);
|
||||
|
||||
for cell in &self.cells {
|
||||
lines.push(Line::from(""));
|
||||
lines.extend(cell.render(width));
|
||||
}
|
||||
|
||||
let total_lines = lines.len() as u16;
|
||||
self.max_scroll = total_lines.saturating_sub(inner.height);
|
||||
|
||||
let paragraph = Paragraph::new(lines)
|
||||
.scroll((self.scroll, 0));
|
||||
|
||||
frame.render_widget(paragraph, inner);
|
||||
|
||||
// Scrollbar
|
||||
if self.max_scroll > 0 {
|
||||
let scrollbar = Scrollbar::default()
|
||||
.orientation(ScrollbarOrientation::VerticalRight)
|
||||
.thumb_style(Style::default().fg(Color::Magenta));
|
||||
|
||||
let mut scrollbar_state = ScrollbarState::new(self.max_scroll as usize)
|
||||
.position(self.scroll as usize);
|
||||
|
||||
frame.render_stateful_widget(scrollbar, area, &mut scrollbar_state);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_input(&self, frame: &mut Frame, area: Rect) {
|
||||
let input = Paragraph::new(Line::from(vec![
|
||||
Span::styled("› ", Style::default().fg(Color::Cyan)),
|
||||
Span::raw(self.input.clone()),
|
||||
Span::styled("█", Style::default().fg(Color::Cyan)),
|
||||
]))
|
||||
.block(
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::default().fg(Color::Rgb(86, 95, 137)))
|
||||
.title(Span::styled(" Input ", Style::default().fg(Color::Rgb(192, 202, 245)))),
|
||||
);
|
||||
|
||||
frame.render_widget(input, area);
|
||||
}
|
||||
|
||||
/// Send a message
|
||||
fn send_message(&mut self) {
|
||||
let message = std::mem::take(&mut self.input);
|
||||
let timestamp = chrono::Local::now().format("%H:%M").to_string();
|
||||
|
||||
// Add user message
|
||||
self.cells.push(Box::new(UserMessageCell {
|
||||
content: message.clone(),
|
||||
timestamp: timestamp.clone(),
|
||||
}));
|
||||
|
||||
// Add demo assistant response
|
||||
let response = format!("You said: {}\n\nThis is a **demo response** with `markdown` support!", message);
|
||||
self.cells.push(Box::new(AssistantMessageCell {
|
||||
content: response,
|
||||
timestamp,
|
||||
streaming: false,
|
||||
}));
|
||||
|
||||
// Auto-scroll to bottom
|
||||
self.scroll = self.max_scroll;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for App {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
75
crates/miyabi-tui/src/event.rs
Normal file
75
crates/miyabi-tui/src/event.rs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
//! Event handling for the TUI
|
||||
|
||||
use crossterm::event::{self, Event as CrosstermEvent, KeyEvent, MouseEvent};
|
||||
use std::time::Duration;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
/// Terminal events
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event {
|
||||
/// Terminal tick
|
||||
Tick,
|
||||
/// Key press
|
||||
Key(KeyEvent),
|
||||
/// Mouse event
|
||||
Mouse(MouseEvent),
|
||||
/// Terminal resize
|
||||
Resize(u16, u16),
|
||||
}
|
||||
|
||||
/// Event handler for terminal events
|
||||
pub struct EventHandler {
|
||||
/// Event sender
|
||||
#[allow(dead_code)]
|
||||
sender: mpsc::UnboundedSender<Event>,
|
||||
/// Event receiver
|
||||
receiver: mpsc::UnboundedReceiver<Event>,
|
||||
}
|
||||
|
||||
impl EventHandler {
|
||||
/// Create a new event handler with the given tick rate
|
||||
pub fn new(tick_rate: u64) -> Self {
|
||||
let tick_rate = Duration::from_millis(tick_rate);
|
||||
let (sender, receiver) = mpsc::unbounded_channel();
|
||||
|
||||
let sender_clone = sender.clone();
|
||||
|
||||
// Spawn event polling task
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
if event::poll(tick_rate).unwrap_or(false) {
|
||||
match event::read() {
|
||||
Ok(CrosstermEvent::Key(key)) => {
|
||||
if sender_clone.send(Event::Key(key)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(CrosstermEvent::Mouse(mouse)) => {
|
||||
if sender_clone.send(Event::Mouse(mouse)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(CrosstermEvent::Resize(w, h)) => {
|
||||
if sender_clone.send(Event::Resize(w, h)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
// Send tick event
|
||||
if sender_clone.send(Event::Tick).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Self { sender, receiver }
|
||||
}
|
||||
|
||||
/// Get the next event
|
||||
pub async fn next(&mut self) -> Option<Event> {
|
||||
self.receiver.recv().await
|
||||
}
|
||||
}
|
||||
272
crates/miyabi-tui/src/history_cell.rs
Normal file
272
crates/miyabi-tui/src/history_cell.rs
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
//! History Cell Abstraction - Premium Card Design
|
||||
//!
|
||||
//! Following OpenAI Codex TUI patterns with functional colors:
|
||||
//! - Cyan: User input, tool names
|
||||
//! - Green: Success
|
||||
//! - Red: Errors
|
||||
//! - Magenta: Assistant/Miyabi brand
|
||||
//! - Dim: Secondary, timestamps
|
||||
|
||||
use ratatui::{
|
||||
style::{Color, Modifier, Style},
|
||||
text::{Line, Span},
|
||||
};
|
||||
|
||||
use crate::markdown_render::MarkdownRenderer;
|
||||
use crate::wrapping::wrap_text;
|
||||
|
||||
/// Trait for renderable history items
|
||||
pub trait HistoryCell: Send + Sync {
|
||||
fn render(&self, width: u16) -> Vec<Line<'static>>;
|
||||
fn timestamp(&self) -> &str;
|
||||
fn is_streaming(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// User message cell - Cyan accented card
|
||||
pub struct UserMessageCell {
|
||||
pub content: String,
|
||||
pub timestamp: String,
|
||||
}
|
||||
|
||||
impl HistoryCell for UserMessageCell {
|
||||
fn render(&self, width: u16) -> Vec<Line<'static>> {
|
||||
let mut lines = Vec::new();
|
||||
let inner_width = (width as usize).saturating_sub(6).min(70);
|
||||
let border = "─".repeat(inner_width);
|
||||
|
||||
// Top border
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("┌", Style::default().fg(Color::Cyan)),
|
||||
Span::styled(border.clone(), Style::default().fg(Color::Cyan)),
|
||||
Span::styled("┐", Style::default().fg(Color::Cyan)),
|
||||
]));
|
||||
|
||||
// Header
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("│ ", Style::default().fg(Color::Cyan)),
|
||||
Span::styled("You", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
|
||||
Span::styled(
|
||||
format!("{:>width$}", self.timestamp, width = inner_width - 4),
|
||||
Style::default().add_modifier(Modifier::DIM)
|
||||
),
|
||||
Span::styled(" │", Style::default().fg(Color::Cyan)),
|
||||
]));
|
||||
|
||||
// Content with proper text wrapping
|
||||
let content_width = inner_width.saturating_sub(2);
|
||||
for line in self.content.lines() {
|
||||
let wrapped = wrap_text(line, content_width);
|
||||
for wrapped_line in wrapped {
|
||||
let content_str: String = wrapped_line.spans.iter()
|
||||
.map(|s| s.content.as_ref())
|
||||
.collect();
|
||||
let padded = format!("{:<width$}", content_str, width = content_width);
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("│ ", Style::default().fg(Color::Cyan)),
|
||||
Span::raw(padded),
|
||||
Span::styled(" │", Style::default().fg(Color::Cyan)),
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom border
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("└", Style::default().fg(Color::Cyan)),
|
||||
Span::styled(border, Style::default().fg(Color::Cyan)),
|
||||
Span::styled("┘", Style::default().fg(Color::Cyan)),
|
||||
]));
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> &str {
|
||||
&self.timestamp
|
||||
}
|
||||
}
|
||||
|
||||
/// Assistant message cell - Magenta accented card with markdown
|
||||
pub struct AssistantMessageCell {
|
||||
pub content: String,
|
||||
pub timestamp: String,
|
||||
pub streaming: bool,
|
||||
}
|
||||
|
||||
impl HistoryCell for AssistantMessageCell {
|
||||
fn render(&self, width: u16) -> Vec<Line<'static>> {
|
||||
let mut lines = Vec::new();
|
||||
let inner_width = (width as usize).saturating_sub(6).min(70);
|
||||
let border = "─".repeat(inner_width);
|
||||
|
||||
// Top border
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("┌", Style::default().fg(Color::Magenta)),
|
||||
Span::styled(border.clone(), Style::default().fg(Color::Magenta)),
|
||||
Span::styled("┐", Style::default().fg(Color::Magenta)),
|
||||
]));
|
||||
|
||||
// Header with streaming indicator
|
||||
let header_text = if self.streaming { "Assistant ●" } else { "Assistant" };
|
||||
let header_style = Style::default().fg(Color::Magenta).add_modifier(Modifier::BOLD);
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("│ ", Style::default().fg(Color::Magenta)),
|
||||
Span::styled(header_text, header_style),
|
||||
Span::styled(
|
||||
format!("{:>width$}", self.timestamp, width = inner_width - header_text.len() - 1),
|
||||
Style::default().add_modifier(Modifier::DIM)
|
||||
),
|
||||
Span::styled(" │", Style::default().fg(Color::Magenta)),
|
||||
]));
|
||||
|
||||
// Markdown rendered content
|
||||
let renderer = MarkdownRenderer::new();
|
||||
let md_lines = renderer.render(&self.content);
|
||||
|
||||
if md_lines.is_empty() && self.streaming {
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("│ ", Style::default().fg(Color::Magenta)),
|
||||
Span::styled("...", Style::default().add_modifier(Modifier::DIM)),
|
||||
Span::styled(
|
||||
format!("{:>width$}", "", width = inner_width - 5),
|
||||
Style::default()
|
||||
),
|
||||
Span::styled(" │", Style::default().fg(Color::Magenta)),
|
||||
]));
|
||||
} else {
|
||||
for md_line in md_lines {
|
||||
let mut content_spans = vec![
|
||||
Span::styled("│ ", Style::default().fg(Color::Magenta)),
|
||||
];
|
||||
content_spans.extend(md_line.spans);
|
||||
content_spans.push(Span::styled(" │", Style::default().fg(Color::Magenta)));
|
||||
lines.push(Line::from(content_spans));
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom border
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("└", Style::default().fg(Color::Magenta)),
|
||||
Span::styled(border, Style::default().fg(Color::Magenta)),
|
||||
Span::styled("┘", Style::default().fg(Color::Magenta)),
|
||||
]));
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> &str {
|
||||
&self.timestamp
|
||||
}
|
||||
|
||||
fn is_streaming(&self) -> bool {
|
||||
self.streaming
|
||||
}
|
||||
}
|
||||
|
||||
/// Tool result cell - Green/Red based on success
|
||||
pub struct ToolResultCell {
|
||||
pub tool_name: String,
|
||||
pub content: String,
|
||||
pub timestamp: String,
|
||||
pub execution_time_ms: u64,
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
impl HistoryCell for ToolResultCell {
|
||||
fn render(&self, width: u16) -> Vec<Line<'static>> {
|
||||
let mut lines = Vec::new();
|
||||
let inner_width = (width as usize).saturating_sub(8).min(68);
|
||||
let border = "═".repeat(inner_width);
|
||||
let border_color = if self.success { Color::Green } else { Color::Red };
|
||||
|
||||
// Top border (double line for tool)
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled(" ╔", Style::default().fg(border_color)),
|
||||
Span::styled(border.clone(), Style::default().fg(border_color)),
|
||||
Span::styled("╗", Style::default().fg(border_color)),
|
||||
]));
|
||||
|
||||
// Header with status icon
|
||||
let icon = if self.success { "✔" } else { "✗" };
|
||||
let time_str = format!("{}ms", self.execution_time_ms);
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled(" ║ ", Style::default().fg(border_color)),
|
||||
Span::styled(format!("{} ", icon), Style::default().fg(border_color)),
|
||||
Span::styled(self.tool_name.clone(), Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
|
||||
Span::styled(
|
||||
format!("{:>width$}", time_str, width = inner_width - self.tool_name.len() - 4),
|
||||
Style::default().add_modifier(Modifier::DIM)
|
||||
),
|
||||
Span::styled(" ║", Style::default().fg(border_color)),
|
||||
]));
|
||||
|
||||
// Content with proper text wrapping
|
||||
let content_width = inner_width.saturating_sub(2);
|
||||
for line in self.content.lines() {
|
||||
let wrapped = wrap_text(line, content_width);
|
||||
for wrapped_line in wrapped {
|
||||
let content_str: String = wrapped_line.spans.iter()
|
||||
.map(|s| s.content.as_ref())
|
||||
.collect();
|
||||
let padded = format!("{:<width$}", content_str, width = content_width);
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled(" ║ ", Style::default().fg(border_color)),
|
||||
Span::styled(padded, Style::default().add_modifier(Modifier::DIM)),
|
||||
Span::styled(" ║", Style::default().fg(border_color)),
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom border
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled(" ╚", Style::default().fg(border_color)),
|
||||
Span::styled(border, Style::default().fg(border_color)),
|
||||
Span::styled("╝", Style::default().fg(border_color)),
|
||||
]));
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> &str {
|
||||
&self.timestamp
|
||||
}
|
||||
}
|
||||
|
||||
/// System message cell
|
||||
pub struct SystemMessageCell {
|
||||
pub content: String,
|
||||
pub timestamp: String,
|
||||
pub message_type: SystemMessageType,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum SystemMessageType {
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
Success,
|
||||
}
|
||||
|
||||
impl HistoryCell for SystemMessageCell {
|
||||
fn render(&self, _width: u16) -> Vec<Line<'static>> {
|
||||
let (icon, color) = match self.message_type {
|
||||
SystemMessageType::Info => ("ℹ", Color::Cyan),
|
||||
SystemMessageType::Warning => ("⚠", Color::Yellow),
|
||||
SystemMessageType::Error => ("✗", Color::Red),
|
||||
SystemMessageType::Success => ("✔", Color::Green),
|
||||
};
|
||||
|
||||
vec![
|
||||
Line::from(vec![
|
||||
Span::styled(format!("{} ", icon), Style::default().fg(color)),
|
||||
Span::styled(self.content.clone(), Style::default().add_modifier(Modifier::DIM)),
|
||||
]),
|
||||
]
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> &str {
|
||||
&self.timestamp
|
||||
}
|
||||
}
|
||||
16
crates/miyabi-tui/src/lib.rs
Normal file
16
crates/miyabi-tui/src/lib.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//! Miyabi TUI - Terminal User Interface
|
||||
//!
|
||||
//! A premium TUI following the OpenAI Codex patterns for clean,
|
||||
//! functional design with proper text wrapping and markdown rendering.
|
||||
|
||||
pub mod app;
|
||||
pub mod event;
|
||||
pub mod wrapping;
|
||||
pub mod history_cell;
|
||||
pub mod markdown_render;
|
||||
|
||||
pub use app::App;
|
||||
pub use event::{Event, EventHandler};
|
||||
pub use wrapping::{word_wrap_line, wrap_text, display_width, WrapOptions};
|
||||
pub use history_cell::{HistoryCell, UserMessageCell, AssistantMessageCell, ToolResultCell, SystemMessageCell};
|
||||
pub use markdown_render::{MarkdownRenderer, MarkdownStyles};
|
||||
41
crates/miyabi-tui/src/main.rs
Normal file
41
crates/miyabi-tui/src/main.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//! Miyabi TUI - Terminal User Interface
|
||||
//!
|
||||
//! A premium terminal interface following OpenAI Codex patterns.
|
||||
|
||||
use miyabi_tui::App;
|
||||
use crossterm::{
|
||||
event::{DisableMouseCapture, EnableMouseCapture},
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
};
|
||||
use ratatui::prelude::*;
|
||||
use std::io;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
// Setup terminal
|
||||
enable_raw_mode()?;
|
||||
let mut stdout = io::stdout();
|
||||
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
|
||||
let backend = CrosstermBackend::new(stdout);
|
||||
let mut terminal = Terminal::new(backend)?;
|
||||
|
||||
// Create app and run
|
||||
let mut app = App::new();
|
||||
let res = app.run(&mut terminal).await;
|
||||
|
||||
// Restore terminal
|
||||
disable_raw_mode()?;
|
||||
execute!(
|
||||
terminal.backend_mut(),
|
||||
LeaveAlternateScreen,
|
||||
DisableMouseCapture
|
||||
)?;
|
||||
terminal.show_cursor()?;
|
||||
|
||||
if let Err(err) = res {
|
||||
eprintln!("Error: {}", err);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
241
crates/miyabi-tui/src/markdown_render.rs
Normal file
241
crates/miyabi-tui/src/markdown_render.rs
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
//! Markdown to Terminal Renderer
|
||||
//!
|
||||
//! Converts markdown text to styled ratatui Lines/Spans
|
||||
|
||||
use ratatui::{
|
||||
style::{Color, Modifier, Style},
|
||||
text::{Line, Span},
|
||||
};
|
||||
|
||||
/// Markdown styling configuration
|
||||
pub struct MarkdownStyles {
|
||||
pub h1: Style,
|
||||
pub h2: Style,
|
||||
pub h3: Style,
|
||||
pub bold: Style,
|
||||
pub italic: Style,
|
||||
pub code: Style,
|
||||
pub code_block: Style,
|
||||
pub link: Style,
|
||||
pub list_marker: Style,
|
||||
pub blockquote: Style,
|
||||
}
|
||||
|
||||
impl Default for MarkdownStyles {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
h1: Style::default()
|
||||
.fg(Color::Rgb(224, 175, 104))
|
||||
.add_modifier(Modifier::BOLD | Modifier::UNDERLINED),
|
||||
h2: Style::default()
|
||||
.fg(Color::Rgb(224, 175, 104))
|
||||
.add_modifier(Modifier::BOLD),
|
||||
h3: Style::default()
|
||||
.fg(Color::Rgb(192, 202, 245))
|
||||
.add_modifier(Modifier::ITALIC),
|
||||
bold: Style::default().add_modifier(Modifier::BOLD),
|
||||
italic: Style::default().add_modifier(Modifier::ITALIC),
|
||||
code: Style::default().fg(Color::Rgb(125, 207, 255)),
|
||||
code_block: Style::default().fg(Color::Rgb(125, 207, 255)),
|
||||
link: Style::default()
|
||||
.fg(Color::Rgb(125, 207, 255))
|
||||
.add_modifier(Modifier::UNDERLINED),
|
||||
list_marker: Style::default().fg(Color::Rgb(158, 206, 106)),
|
||||
blockquote: Style::default().fg(Color::Rgb(158, 206, 106)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Markdown renderer
|
||||
pub struct MarkdownRenderer {
|
||||
styles: MarkdownStyles,
|
||||
}
|
||||
|
||||
impl MarkdownRenderer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
styles: MarkdownStyles::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_styles(styles: MarkdownStyles) -> Self {
|
||||
Self { styles }
|
||||
}
|
||||
|
||||
/// Render markdown text to styled Lines
|
||||
pub fn render(&self, text: &str) -> Vec<Line<'static>> {
|
||||
let mut lines = Vec::new();
|
||||
let mut in_code_block = false;
|
||||
let mut code_block_content: Vec<String> = Vec::new();
|
||||
|
||||
for line in text.lines() {
|
||||
if line.trim().starts_with("```") {
|
||||
if in_code_block {
|
||||
// End code block
|
||||
lines.push(Line::from(Span::styled(
|
||||
"┌─────────────────────────────────────────────────────────────┐",
|
||||
Style::default().fg(Color::Rgb(86, 95, 137)),
|
||||
)));
|
||||
for code_line in &code_block_content {
|
||||
lines.push(Line::from(vec![
|
||||
Span::styled("│ ", Style::default().fg(Color::Rgb(86, 95, 137))),
|
||||
Span::styled(code_line.clone(), self.styles.code_block),
|
||||
]));
|
||||
}
|
||||
lines.push(Line::from(Span::styled(
|
||||
"└─────────────────────────────────────────────────────────────┘",
|
||||
Style::default().fg(Color::Rgb(86, 95, 137)),
|
||||
)));
|
||||
code_block_content.clear();
|
||||
in_code_block = false;
|
||||
} else {
|
||||
in_code_block = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if in_code_block {
|
||||
code_block_content.push(line.to_string());
|
||||
continue;
|
||||
}
|
||||
|
||||
let rendered = self.render_line(line);
|
||||
lines.push(rendered);
|
||||
}
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
fn render_line(&self, line: &str) -> Line<'static> {
|
||||
let trimmed = line.trim();
|
||||
|
||||
// Headers
|
||||
if trimmed.starts_with("### ") {
|
||||
return Line::from(vec![
|
||||
Span::styled(" ", Style::default()),
|
||||
Span::styled(trimmed[4..].to_string(), self.styles.h3),
|
||||
]);
|
||||
}
|
||||
if trimmed.starts_with("## ") {
|
||||
return Line::from(vec![
|
||||
Span::styled(" ", Style::default()),
|
||||
Span::styled(trimmed[3..].to_string(), self.styles.h2),
|
||||
]);
|
||||
}
|
||||
if trimmed.starts_with("# ") {
|
||||
return Line::from(vec![
|
||||
Span::styled(" ", Style::default()),
|
||||
Span::styled(trimmed[2..].to_string(), self.styles.h1),
|
||||
]);
|
||||
}
|
||||
|
||||
// Blockquotes
|
||||
if trimmed.starts_with("> ") {
|
||||
return Line::from(vec![
|
||||
Span::styled(" > ", self.styles.blockquote),
|
||||
Span::styled(trimmed[2..].to_string(), Style::default().fg(Color::Rgb(192, 202, 245))),
|
||||
]);
|
||||
}
|
||||
|
||||
// Unordered lists
|
||||
if trimmed.starts_with("- ") || trimmed.starts_with("* ") {
|
||||
let indent = line.len() - line.trim_start().len();
|
||||
let prefix = " ".repeat(indent / 2);
|
||||
return Line::from(vec![
|
||||
Span::raw(prefix),
|
||||
Span::styled("• ", self.styles.list_marker),
|
||||
Span::styled(trimmed[2..].to_string(), Style::default()),
|
||||
]);
|
||||
}
|
||||
|
||||
// Horizontal rule
|
||||
if trimmed == "---" || trimmed == "***" || trimmed == "___" {
|
||||
return Line::from(Span::styled(
|
||||
"────────────────────────────────────────────────────────────",
|
||||
Style::default().fg(Color::Rgb(86, 95, 137)),
|
||||
));
|
||||
}
|
||||
|
||||
// Regular paragraph with inline formatting
|
||||
self.render_inline_line(line)
|
||||
}
|
||||
|
||||
fn render_inline_line(&self, line: &str) -> Line<'static> {
|
||||
let mut spans = Vec::new();
|
||||
let mut current = String::new();
|
||||
let mut chars = line.chars().peekable();
|
||||
let mut in_bold = false;
|
||||
let mut in_italic = false;
|
||||
let mut in_code = false;
|
||||
|
||||
while let Some(c) = chars.next() {
|
||||
match c {
|
||||
'`' if !in_bold && !in_italic => {
|
||||
if !current.is_empty() {
|
||||
spans.push(Span::styled(
|
||||
current.clone(),
|
||||
if in_code { self.styles.code } else { Style::default().fg(Color::Rgb(192, 202, 245)) },
|
||||
));
|
||||
current.clear();
|
||||
}
|
||||
in_code = !in_code;
|
||||
}
|
||||
'*' if chars.peek() == Some(&'*') && !in_code => {
|
||||
chars.next();
|
||||
if !current.is_empty() {
|
||||
let style = if in_bold {
|
||||
self.styles.bold
|
||||
} else if in_italic {
|
||||
self.styles.italic
|
||||
} else {
|
||||
Style::default().fg(Color::Rgb(192, 202, 245))
|
||||
};
|
||||
spans.push(Span::styled(current.clone(), style));
|
||||
current.clear();
|
||||
}
|
||||
in_bold = !in_bold;
|
||||
}
|
||||
'*' | '_' if !in_code && !in_bold => {
|
||||
if !current.is_empty() {
|
||||
let style = if in_italic {
|
||||
self.styles.italic
|
||||
} else {
|
||||
Style::default().fg(Color::Rgb(192, 202, 245))
|
||||
};
|
||||
spans.push(Span::styled(current.clone(), style));
|
||||
current.clear();
|
||||
}
|
||||
in_italic = !in_italic;
|
||||
}
|
||||
_ => {
|
||||
current.push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !current.is_empty() {
|
||||
let style = if in_code {
|
||||
self.styles.code
|
||||
} else if in_bold {
|
||||
self.styles.bold
|
||||
} else if in_italic {
|
||||
self.styles.italic
|
||||
} else {
|
||||
Style::default().fg(Color::Rgb(192, 202, 245))
|
||||
};
|
||||
spans.push(Span::styled(current, style));
|
||||
}
|
||||
|
||||
if spans.is_empty() {
|
||||
Line::from("")
|
||||
} else {
|
||||
Line::from(spans)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MarkdownRenderer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
268
crates/miyabi-tui/src/wrapping.rs
Normal file
268
crates/miyabi-tui/src/wrapping.rs
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
//! Text Wrapping Module
|
||||
//!
|
||||
//! Provides intelligent text wrapping for terminal display,
|
||||
//! following the OpenAI Codex TUI pattern with textwrap integration.
|
||||
|
||||
use ratatui::text::{Line, Span};
|
||||
use std::borrow::Cow;
|
||||
use textwrap::{wrap_algorithms::Penalties, Options, WordSeparator, WordSplitter, WrapAlgorithm};
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
/// Wrapping options configuration
|
||||
pub struct WrapOptions<'a> {
|
||||
/// Target width for wrapping
|
||||
pub width: usize,
|
||||
/// Prefix for the first line
|
||||
pub initial_indent: Cow<'a, str>,
|
||||
/// Prefix for subsequent lines
|
||||
pub subsequent_indent: Cow<'a, str>,
|
||||
/// Whether to break words that exceed width
|
||||
pub break_words: bool,
|
||||
}
|
||||
|
||||
impl<'a> Default for WrapOptions<'a> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
width: 80,
|
||||
initial_indent: Cow::Borrowed(""),
|
||||
subsequent_indent: Cow::Borrowed(""),
|
||||
break_words: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> WrapOptions<'a> {
|
||||
/// Create options with specified width
|
||||
pub fn new(width: usize) -> Self {
|
||||
Self {
|
||||
width,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Set initial indent
|
||||
pub fn initial_indent(mut self, indent: impl Into<Cow<'a, str>>) -> Self {
|
||||
self.initial_indent = indent.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set subsequent indent
|
||||
pub fn subsequent_indent(mut self, indent: impl Into<Cow<'a, str>>) -> Self {
|
||||
self.subsequent_indent = indent.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set word breaking behavior
|
||||
pub fn break_words(mut self, break_words: bool) -> Self {
|
||||
self.break_words = break_words;
|
||||
self
|
||||
}
|
||||
|
||||
/// Convert to textwrap Options
|
||||
fn to_textwrap_options(&self) -> Options<'_> {
|
||||
Options::new(self.width)
|
||||
.initial_indent(&self.initial_indent)
|
||||
.subsequent_indent(&self.subsequent_indent)
|
||||
.break_words(self.break_words)
|
||||
.word_separator(WordSeparator::UnicodeBreakProperties)
|
||||
.word_splitter(WordSplitter::NoHyphenation)
|
||||
.wrap_algorithm(WrapAlgorithm::OptimalFit(Penalties::default()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrap a single line of text into multiple lines
|
||||
pub fn word_wrap_line(line: &Line<'_>, width: usize) -> Vec<Line<'static>> {
|
||||
let options = WrapOptions::new(width);
|
||||
word_wrap_line_with_options(line, &options)
|
||||
}
|
||||
|
||||
/// Wrap a single line with custom options
|
||||
pub fn word_wrap_line_with_options(
|
||||
line: &Line<'_>,
|
||||
options: &WrapOptions<'_>,
|
||||
) -> Vec<Line<'static>> {
|
||||
if line.spans.is_empty() {
|
||||
return vec![Line::from("")];
|
||||
}
|
||||
|
||||
// Track spans with their byte ranges in the flattened string
|
||||
let mut flat_text = String::new();
|
||||
let mut span_ranges: Vec<(usize, usize, ratatui::style::Style)> = Vec::new();
|
||||
|
||||
for span in &line.spans {
|
||||
let start = flat_text.len();
|
||||
flat_text.push_str(&span.content);
|
||||
let end = flat_text.len();
|
||||
span_ranges.push((start, end, span.style));
|
||||
}
|
||||
|
||||
if flat_text.is_empty() {
|
||||
return vec![Line::from("")];
|
||||
}
|
||||
|
||||
// Use textwrap to compute line breaks
|
||||
let textwrap_opts = options.to_textwrap_options();
|
||||
let wrapped = textwrap::wrap(&flat_text, textwrap_opts);
|
||||
|
||||
let mut result = Vec::new();
|
||||
let mut current_pos = 0;
|
||||
|
||||
for wrapped_line in wrapped {
|
||||
let line_str = wrapped_line.trim_start();
|
||||
if line_str.is_empty() {
|
||||
result.push(Line::from(""));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find position in original text (skip leading whitespace)
|
||||
let skip_ws = wrapped_line.len() - line_str.len();
|
||||
let line_start = current_pos + skip_ws;
|
||||
let line_end = line_start + line_str.len();
|
||||
|
||||
// Build spans for this wrapped line
|
||||
let mut line_spans = Vec::new();
|
||||
|
||||
for &(span_start, span_end, style) in &span_ranges {
|
||||
// Check if this span overlaps with current line
|
||||
if span_end <= line_start || span_start >= line_end {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate overlap
|
||||
let overlap_start = span_start.max(line_start);
|
||||
let overlap_end = span_end.min(line_end);
|
||||
|
||||
if overlap_start < overlap_end {
|
||||
let text = &flat_text[overlap_start..overlap_end];
|
||||
line_spans.push(Span::styled(text.to_string(), style));
|
||||
}
|
||||
}
|
||||
|
||||
if line_spans.is_empty() {
|
||||
result.push(Line::from(line_str.to_string()));
|
||||
} else {
|
||||
result.push(Line::from(line_spans));
|
||||
}
|
||||
|
||||
current_pos = line_end;
|
||||
}
|
||||
|
||||
if result.is_empty() {
|
||||
vec![Line::from("")]
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrap multiple lines of text
|
||||
pub fn word_wrap_lines<'a, I>(lines: I, width: usize) -> Vec<Line<'static>>
|
||||
where
|
||||
I: IntoIterator<Item = Line<'a>>,
|
||||
{
|
||||
let mut result = Vec::new();
|
||||
for line in lines {
|
||||
result.extend(word_wrap_line(&line, width));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Wrap plain text string into styled lines
|
||||
pub fn wrap_text(text: &str, width: usize) -> Vec<Line<'static>> {
|
||||
let options = WrapOptions::new(width);
|
||||
let textwrap_opts = options.to_textwrap_options();
|
||||
let wrapped = textwrap::wrap(text, textwrap_opts);
|
||||
|
||||
wrapped
|
||||
.into_iter()
|
||||
.map(|s| Line::from(s.into_owned()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Calculate display width of text (Unicode-aware)
|
||||
pub fn display_width(text: &str) -> usize {
|
||||
UnicodeWidthStr::width(text)
|
||||
}
|
||||
|
||||
/// Truncate text to fit within width, adding ellipsis if needed
|
||||
pub fn truncate_with_ellipsis(text: &str, width: usize) -> String {
|
||||
let text_width = display_width(text);
|
||||
if text_width <= width {
|
||||
return text.to_string();
|
||||
}
|
||||
|
||||
if width < 3 {
|
||||
return "...".chars().take(width).collect();
|
||||
}
|
||||
|
||||
let target_width = width - 3;
|
||||
let mut result = String::new();
|
||||
let mut current_width = 0;
|
||||
|
||||
for ch in text.chars() {
|
||||
let ch_width = UnicodeWidthStr::width(ch.to_string().as_str());
|
||||
if current_width + ch_width > target_width {
|
||||
break;
|
||||
}
|
||||
result.push(ch);
|
||||
current_width += ch_width;
|
||||
}
|
||||
|
||||
result.push_str("...");
|
||||
result
|
||||
}
|
||||
|
||||
/// Pad text to specified width
|
||||
pub fn pad_to_width(text: &str, width: usize) -> String {
|
||||
let text_width = display_width(text);
|
||||
if text_width >= width {
|
||||
return text.to_string();
|
||||
}
|
||||
|
||||
let padding = width - text_width;
|
||||
format!("{}{}", text, " ".repeat(padding))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ratatui::style::{Color, Style};
|
||||
|
||||
#[test]
|
||||
fn test_wrap_simple_text() {
|
||||
let result = wrap_text("hello world", 5);
|
||||
assert_eq!(result.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrap_empty() {
|
||||
let result = wrap_text("", 10);
|
||||
assert_eq!(result.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_display_width() {
|
||||
assert_eq!(display_width("hello"), 5);
|
||||
assert_eq!(display_width("日本語"), 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_truncate_with_ellipsis() {
|
||||
assert_eq!(truncate_with_ellipsis("hello world", 8), "hello...");
|
||||
assert_eq!(truncate_with_ellipsis("short", 10), "short");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pad_to_width() {
|
||||
assert_eq!(pad_to_width("hello", 10), "hello ");
|
||||
assert_eq!(pad_to_width("hello", 5), "hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_word_wrap_line_preserves_style() {
|
||||
let style = Style::default().fg(Color::Cyan);
|
||||
let line = Line::from(vec![Span::styled("hello world foo bar", style)]);
|
||||
|
||||
let wrapped = word_wrap_line(&line, 10);
|
||||
assert!(wrapped.len() >= 2);
|
||||
}
|
||||
}
|
||||
244
docs/GETTING_STARTED.md
Normal file
244
docs/GETTING_STARTED.md
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
# Getting Started with miyabi-cli-standalone
|
||||
|
||||
Miyabiプロジェクトへようこそ!このガイドでは、ゼロからMiyabiを使い始めるまでの手順を詳しく解説します。
|
||||
|
||||
## 📋 前提条件
|
||||
|
||||
### 必須
|
||||
|
||||
- **Rust**: 1.75.0以上
|
||||
```bash
|
||||
rustc --version # 確認
|
||||
```
|
||||
|
||||
- **Git**: バージョン管理用
|
||||
```bash
|
||||
git --version
|
||||
```
|
||||
|
||||
- **GitHubアカウント**: Issue/PR管理用
|
||||
|
||||
### 推奨
|
||||
|
||||
- **GitHub CLI (`gh`)**: GitHub操作を簡単に
|
||||
```bash
|
||||
brew install gh # macOS
|
||||
gh --version
|
||||
```
|
||||
|
||||
## 🚀 セットアップ手順
|
||||
|
||||
### Step 1: 環境変数の設定
|
||||
|
||||
#### 1.1 GitHub Personal Access Token取得
|
||||
|
||||
1. https://github.com/settings/tokens/new にアクセス
|
||||
2. Token名を入力(例: "Miyabi Local Dev")
|
||||
3. 以下のスコープを選択:
|
||||
- ✅ `repo` (Full control of private repositories)
|
||||
- ✅ `workflow` (Update GitHub Action workflows)
|
||||
4. "Generate token"をクリック
|
||||
5. トークンをコピー(**一度しか表示されません!**)
|
||||
|
||||
#### 1.2 環境変数をシェルプロファイルに追加
|
||||
|
||||
**Bash (.bashrc / .bash_profile):**
|
||||
```bash
|
||||
echo 'export GITHUB_TOKEN=ghp_xxxxx' >> ~/.bashrc
|
||||
echo 'export ANTHROPIC_API_KEY=sk-ant-xxxxx' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
**Zsh (.zshrc):**
|
||||
```bash
|
||||
echo 'export GITHUB_TOKEN=ghp_xxxxx' >> ~/.zshrc
|
||||
echo 'export ANTHROPIC_API_KEY=sk-ant-xxxxx' >> ~/.zshrc
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
#### 1.3 環境変数確認
|
||||
```bash
|
||||
echo $GITHUB_TOKEN
|
||||
echo $ANTHROPIC_API_KEY
|
||||
```
|
||||
|
||||
### Step 2: GitHubリポジトリ作成
|
||||
|
||||
#### 2.1 GitHub CLI使用(推奨)
|
||||
```bash
|
||||
cd miyabi-cli-standalone
|
||||
gh repo create miyabi-cli-standalone --private --source=. --remote=origin
|
||||
```
|
||||
|
||||
#### 2.2 手動作成
|
||||
1. https://github.com/new にアクセス
|
||||
2. Repository nameに `miyabi-cli-standalone` を入力
|
||||
3. "Private"を選択
|
||||
4. "Create repository"をクリック
|
||||
5. ローカルリポジトリと接続:
|
||||
```bash
|
||||
git remote add origin https://github.com/YOUR_USERNAME/miyabi-cli-standalone.git
|
||||
git branch -M main
|
||||
git add .
|
||||
git commit -m "feat: initial commit 🚀"
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
### Step 3: Label体系のセットアップ
|
||||
|
||||
Miyabiは53ラベル体系で自動化を制御します。
|
||||
|
||||
#### 3.1 自動セットアップ(将来実装予定)
|
||||
```bash
|
||||
miyabi setup labels
|
||||
```
|
||||
|
||||
#### 3.2 手動セットアップ
|
||||
GitHubリポジトリの設定から、以下のラベルを作成:
|
||||
|
||||
**STATE(8個)**:
|
||||
- `📥 state:pending` (Gray)
|
||||
- `🔍 state:analyzing` (Blue)
|
||||
- `🏗️ state:implementing` (Yellow)
|
||||
- `👀 state:reviewing` (Orange)
|
||||
- `✅ state:done` (Green)
|
||||
- `❌ state:blocked` (Red)
|
||||
- `⏸️ state:on-hold` (Purple)
|
||||
- `🔄 state:reopened` (Pink)
|
||||
|
||||
(残り45ラベルは`.github/labels.yml`を参照)
|
||||
|
||||
### Step 4: 最初のIssue作成
|
||||
|
||||
#### 4.1 GitHub Web UIで作成
|
||||
1. リポジトリの"Issues"タブをクリック
|
||||
2. "New issue"をクリック
|
||||
3. Title: "✨ Setup project configuration"
|
||||
4. Body:
|
||||
```markdown
|
||||
## 概要
|
||||
プロジェクトの初期設定を行う
|
||||
|
||||
## タスク
|
||||
- [ ] .miyabi.yml の設定確認
|
||||
- [ ] GitHub Actionsの設定
|
||||
- [ ] 開発環境の準備
|
||||
|
||||
## 期待される成果
|
||||
- プロジェクトが動作可能な状態
|
||||
```
|
||||
5. Labels:
|
||||
- `✨ type:feature`
|
||||
- `⚠️ priority:P1-High`
|
||||
- `📥 state:pending`
|
||||
6. "Submit new issue"をクリック
|
||||
|
||||
#### 4.2 GitHub CLIで作成
|
||||
```bash
|
||||
gh issue create --title "✨ Setup project configuration" \
|
||||
--body "初期設定タスク" \
|
||||
--label "type:feature,priority:P1-High,state:pending"
|
||||
```
|
||||
|
||||
### Step 5: Agent実行
|
||||
|
||||
#### 5.1 ステータス確認
|
||||
```bash
|
||||
miyabi status
|
||||
```
|
||||
|
||||
出力例:
|
||||
```
|
||||
📊 Project Status
|
||||
|
||||
Miyabi Installation:
|
||||
✅ Miyabi is installed
|
||||
✓ .claude/agents
|
||||
✓ .github/workflows
|
||||
|
||||
Environment:
|
||||
✅ GITHUB_TOKEN is set
|
||||
✅ DEVICE_IDENTIFIER: YourMac.local
|
||||
|
||||
Git Repository:
|
||||
✅ Git repository detected
|
||||
Branch: main
|
||||
Remotes: origin
|
||||
```
|
||||
|
||||
#### 5.2 CoordinatorAgent実行
|
||||
```bash
|
||||
miyabi agent run coordinator --issue 1
|
||||
```
|
||||
|
||||
Agentは以下を実行します:
|
||||
1. Issue分析
|
||||
2. Task分解(DAG構築)
|
||||
3. Worktree作成
|
||||
4. Specialist Agent割り当て
|
||||
5. 並列実行
|
||||
6. 結果統合
|
||||
|
||||
## 🎯 よくある使い方
|
||||
|
||||
### Issue処理の基本フロー
|
||||
```bash
|
||||
# 1. Issue作成(GitHub UI または gh CLI)
|
||||
gh issue create --title "新機能実装" --label "type:feature"
|
||||
|
||||
# 2. Agent実行
|
||||
miyabi agent run coordinator --issue 2
|
||||
|
||||
# 3. ステータス確認
|
||||
miyabi status
|
||||
|
||||
# 4. ログ確認
|
||||
cat logs/miyabi-*.log
|
||||
```
|
||||
|
||||
### 複数Issue並列処理
|
||||
```bash
|
||||
miyabi agent run coordinator --issues 1,2,3 --concurrency 2
|
||||
```
|
||||
|
||||
### Worktree確認
|
||||
```bash
|
||||
git worktree list
|
||||
```
|
||||
|
||||
## 📚 次に読むべきドキュメント
|
||||
|
||||
1. **CLAUDE.md** - プロジェクトコンテキスト(Claude Codeが自動参照)
|
||||
2. **.claude/QUICK_START.md** - 3分で始めるクイックガイド
|
||||
3. **.claude/agents/README.md** - Agent一覧と使い方
|
||||
4. **docs/TROUBLESHOOTING.md** - トラブルシューティング
|
||||
|
||||
## 🆘 困ったときは
|
||||
|
||||
### エラーが出た場合
|
||||
1. `docs/TROUBLESHOOTING.md` を確認
|
||||
2. `miyabi status` で環境確認
|
||||
3. GitHub Issuesで質問: https://github.com/ShunsukeHayashi/Miyabi/issues
|
||||
|
||||
### ログ確認
|
||||
```bash
|
||||
# 最新のログファイル
|
||||
tail -f logs/miyabi-$(date +%Y%m%d).log
|
||||
|
||||
# エラーログのみ抽出
|
||||
grep -i error logs/miyabi-*.log
|
||||
```
|
||||
|
||||
## 🎉 次のステップ
|
||||
|
||||
おめでとうございます!Miyabiのセットアップが完了しました。
|
||||
|
||||
次は:
|
||||
1. **独自のAgent仕様作成**: `.claude/agents/specs/coding/` にカスタムAgent追加
|
||||
2. **Label体系のカスタマイズ**: プロジェクトに合わせたLabel追加
|
||||
3. **GitHub Actionsの設定**: `.github/workflows/` でCI/CD自動化
|
||||
4. **Worktree並列実行**: 複数Issueの同時処理
|
||||
|
||||
---
|
||||
|
||||
**Miyabi** - Beauty in Autonomous Development 🌸
|
||||
341
docs/OPERATION_PLAN.md
Normal file
341
docs/OPERATION_PLAN.md
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
# Operation Plan - miyabi-cli-standalone
|
||||
|
||||
**Project**: miyabi-cli-standalone
|
||||
**Created**: 2025-11-22
|
||||
**Execution Method**: Miyabi Autonomous Agents
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
```bash
|
||||
# 1. 環境確認
|
||||
miyabi status
|
||||
|
||||
# 2. 環境変数設定
|
||||
export GITHUB_TOKEN=ghp_xxx
|
||||
export ANTHROPIC_API_KEY=sk-ant-xxx
|
||||
|
||||
# 3. Miyabiバイナリへのパス(オプション)
|
||||
alias miyabi='/Users/shunsuke/Dev/01-miyabi/_core/miyabi-private/target/release/miyabi'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Execution Workflow
|
||||
|
||||
### Phase 1: Sprint 1 開始
|
||||
|
||||
#### Day 1: Parallel Foundation Tasks
|
||||
|
||||
```bash
|
||||
# Stream A: TUI
|
||||
miyabi agent run coordinator --issue 10 # Core Structure
|
||||
miyabi agent run coordinator --issue 15 # Diff Core
|
||||
|
||||
# Stream B: LLM (CRITICAL)
|
||||
miyabi agent run coordinator --issue 19 # API Client
|
||||
|
||||
# Stream C: Tools
|
||||
miyabi agent run coordinator --issue 24 # Tool Trait
|
||||
```
|
||||
|
||||
#### 進捗監視
|
||||
|
||||
```bash
|
||||
# ステータス確認
|
||||
miyabi status
|
||||
|
||||
# Issue一覧
|
||||
gh issue list --repo ShunsukeHayashi/miyabi-cli-standalone \
|
||||
--label "🏗️ state:implementing"
|
||||
|
||||
# PR確認
|
||||
gh pr list --repo ShunsukeHayashi/miyabi-cli-standalone
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Daily Operations
|
||||
|
||||
### Morning Routine
|
||||
|
||||
```bash
|
||||
# 1. 前日のPRをレビュー
|
||||
gh pr list --repo ShunsukeHayashi/miyabi-cli-standalone --state open
|
||||
|
||||
# 2. ブロッカー確認
|
||||
gh issue list --label "🚫 state:blocked"
|
||||
|
||||
# 3. 今日のタスク開始
|
||||
miyabi agent run coordinator --issue <次のissue番号>
|
||||
```
|
||||
|
||||
### Task Execution
|
||||
|
||||
```bash
|
||||
# 単一Issue実行
|
||||
miyabi agent run coordinator --issue <番号>
|
||||
|
||||
# 並列実行(別ターミナルで)
|
||||
miyabi agent run coordinator --issue 10 &
|
||||
miyabi agent run coordinator --issue 15 &
|
||||
miyabi agent run coordinator --issue 19 &
|
||||
```
|
||||
|
||||
### Evening Review
|
||||
|
||||
```bash
|
||||
# 完了タスク確認
|
||||
gh issue list --label "✅ state:done" --state closed
|
||||
|
||||
# 明日の計画
|
||||
gh issue list --label "📥 state:pending" --milestone "v0.2.0 - Advanced Text Rendering"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Sprint Execution Plan
|
||||
|
||||
### Sprint 1 (Week 1)
|
||||
|
||||
| Day | Tasks | Command |
|
||||
|-----|-------|---------|
|
||||
| Mon | #10, #15, #19, #24 | `miyabi agent run coordinator --issue 10` (x4 parallel) |
|
||||
| Tue | Continue + Review | Review PRs, merge if ready |
|
||||
| Wed | #11, #16, #20, #25 | Start dependent tasks |
|
||||
| Thu | Continue + Review | Review PRs |
|
||||
| Fri | Integration testing | Manual testing, bug fixes |
|
||||
|
||||
### Sprint 2-4
|
||||
|
||||
同様のパターンで継続
|
||||
|
||||
---
|
||||
|
||||
## 📊 Monitoring Commands
|
||||
|
||||
### Real-time Status
|
||||
|
||||
```bash
|
||||
# Miyabiステータス
|
||||
miyabi status
|
||||
|
||||
# GitHub Issues
|
||||
gh issue list --repo ShunsukeHayashi/miyabi-cli-standalone
|
||||
|
||||
# ラベル別
|
||||
gh issue list --label "📊 priority:P0-Critical"
|
||||
gh issue list --label "🏗️ state:implementing"
|
||||
gh issue list --label "👀 state:reviewing"
|
||||
```
|
||||
|
||||
### PR Management
|
||||
|
||||
```bash
|
||||
# PR一覧
|
||||
gh pr list
|
||||
|
||||
# 特定PRの詳細
|
||||
gh pr view <番号>
|
||||
|
||||
# PRをマージ
|
||||
gh pr merge <番号> --squash
|
||||
```
|
||||
|
||||
### Logs
|
||||
|
||||
```bash
|
||||
# Miyabiログ
|
||||
ls -la logs/
|
||||
|
||||
# 最新ログ
|
||||
tail -f logs/*.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Agent Commands Reference
|
||||
|
||||
### Coordinator Agent
|
||||
|
||||
```bash
|
||||
# Issue分析と実装
|
||||
miyabi agent run coordinator --issue <番号>
|
||||
|
||||
# ドライラン(実行せず計画のみ)
|
||||
miyabi agent run coordinator --issue <番号> --dry-run
|
||||
|
||||
# 詳細ログ
|
||||
RUST_LOG=debug miyabi agent run coordinator --issue <番号>
|
||||
```
|
||||
|
||||
### CodeGen Agent (自動呼び出し)
|
||||
|
||||
Coordinatorが自動的にCodeGenを呼び出します。
|
||||
|
||||
### Review Agent (自動呼び出し)
|
||||
|
||||
PR作成後、自動的にレビューが実行されます。
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Troubleshooting
|
||||
|
||||
### Agent が停止した場合
|
||||
|
||||
```bash
|
||||
# 状態確認
|
||||
miyabi status
|
||||
|
||||
# ログ確認
|
||||
cat logs/latest.log
|
||||
|
||||
# Issue状態をリセット
|
||||
gh issue edit <番号> --remove-label "🏗️ state:implementing"
|
||||
gh issue edit <番号> --add-label "📥 state:pending"
|
||||
|
||||
# 再実行
|
||||
miyabi agent run coordinator --issue <番号>
|
||||
```
|
||||
|
||||
### Rate Limit エラー
|
||||
|
||||
```bash
|
||||
# GitHub API制限確認
|
||||
gh api rate_limit
|
||||
|
||||
# 待機後再実行
|
||||
sleep 3600 # 1時間待機
|
||||
miyabi agent run coordinator --issue <番号>
|
||||
```
|
||||
|
||||
### ビルドエラー
|
||||
|
||||
```bash
|
||||
# 手動ビルド確認
|
||||
cargo build --release
|
||||
|
||||
# テスト実行
|
||||
cargo test --all
|
||||
|
||||
# Lint
|
||||
cargo clippy --all-targets
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 Progress Tracking
|
||||
|
||||
### Milestone Progress
|
||||
|
||||
```bash
|
||||
# マイルストーン一覧
|
||||
gh api repos/ShunsukeHayashi/miyabi-cli-standalone/milestones
|
||||
|
||||
# 特定マイルストーンの進捗
|
||||
gh issue list --milestone "v0.2.0 - Advanced Text Rendering"
|
||||
```
|
||||
|
||||
### Metrics
|
||||
|
||||
```bash
|
||||
# コード行数
|
||||
find crates -name "*.rs" | xargs wc -l | tail -1
|
||||
|
||||
# Issue統計
|
||||
gh issue list --state all --json state | jq 'group_by(.state) | map({state: .[0].state, count: length})'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 CI/CD Integration
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
PRがマージされると自動的に:
|
||||
1. `cargo test` 実行
|
||||
2. `cargo clippy` チェック
|
||||
3. `cargo fmt` 確認
|
||||
|
||||
### 手動トリガー
|
||||
|
||||
```bash
|
||||
# ワークフロー実行
|
||||
gh workflow run build.yml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Best Practices
|
||||
|
||||
### 1. Critical Path 優先
|
||||
|
||||
常にP0タスクを優先:
|
||||
- #19 (API Client) → #20 → #22
|
||||
- #24 (Tool Trait) → #25 → #26
|
||||
|
||||
### 2. 並列実行
|
||||
|
||||
独立したタスクは並列実行:
|
||||
- Stream A (#10-14, #15-18)
|
||||
- Stream B (#19-23)
|
||||
- Stream C (#24-28)
|
||||
|
||||
### 3. 早期レビュー
|
||||
|
||||
PRは作成後すぐにレビュー:
|
||||
```bash
|
||||
gh pr review <番号> --approve
|
||||
gh pr merge <番号> --squash
|
||||
```
|
||||
|
||||
### 4. ブロッカー対応
|
||||
|
||||
ブロッカーは即座に対応:
|
||||
```bash
|
||||
gh issue list --label "🚫 state:blocked"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Execution Checklist
|
||||
|
||||
### Sprint Start
|
||||
|
||||
- [ ] `miyabi status` で環境確認
|
||||
- [ ] 当該Sprintのタスク確認
|
||||
- [ ] Critical Pathタスクを優先開始
|
||||
|
||||
### Daily
|
||||
|
||||
- [ ] PRレビュー・マージ
|
||||
- [ ] ブロッカー確認
|
||||
- [ ] 新タスク開始
|
||||
|
||||
### Sprint End
|
||||
|
||||
- [ ] 全PRマージ
|
||||
- [ ] 統合テスト
|
||||
- [ ] マイルストーン確認
|
||||
- [ ] 次Sprint計画
|
||||
|
||||
---
|
||||
|
||||
## 🚀 First Execution
|
||||
|
||||
```bash
|
||||
# 今すぐ開始
|
||||
cd /Users/shunsuke/Dev/miyabi-cli-standalone
|
||||
|
||||
# Critical Path開始
|
||||
miyabi agent run coordinator --issue 19 # API Client (最重要)
|
||||
miyabi agent run coordinator --issue 10 # Core Structure
|
||||
miyabi agent run coordinator --issue 24 # Tool Trait
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Happy Coding with Miyabi! 🤖**
|
||||
384
docs/PREPARATION_OPS.md
Normal file
384
docs/PREPARATION_OPS.md
Normal file
|
|
@ -0,0 +1,384 @@
|
|||
# Preparation Operations - miyabi-cli-standalone
|
||||
|
||||
**Purpose**: Sprint 1開始前の準備作業チェックリスト
|
||||
**Target Date**: 2025-11-25 (Sprint 1 Start)
|
||||
|
||||
---
|
||||
|
||||
## 📋 Pre-Sprint Checklist
|
||||
|
||||
### 1. Environment Setup
|
||||
|
||||
#### 1.1 Development Environment
|
||||
|
||||
- [ ] **Rust toolchain**
|
||||
```bash
|
||||
rustup update stable
|
||||
rustup component add clippy rustfmt
|
||||
cargo --version # 1.75+
|
||||
```
|
||||
|
||||
- [ ] **GitHub CLI**
|
||||
```bash
|
||||
gh --version
|
||||
gh auth status
|
||||
```
|
||||
|
||||
- [ ] **Miyabi CLI**
|
||||
```bash
|
||||
/Users/shunsuke/Dev/01-miyabi/_core/miyabi-private/target/release/miyabi --version
|
||||
```
|
||||
|
||||
#### 1.2 API Keys
|
||||
|
||||
- [ ] **GitHub Token**
|
||||
```bash
|
||||
# .env に設定
|
||||
echo "GITHUB_TOKEN=ghp_xxx" >> .env
|
||||
|
||||
# 必要なスコープ: repo, workflow
|
||||
gh auth refresh -s repo,workflow
|
||||
```
|
||||
|
||||
- [ ] **Anthropic API Key**
|
||||
```bash
|
||||
echo "ANTHROPIC_API_KEY=sk-ant-xxx" >> .env
|
||||
|
||||
# テスト
|
||||
curl https://api.anthropic.com/v1/messages \
|
||||
-H "x-api-key: $ANTHROPIC_API_KEY" \
|
||||
-H "anthropic-version: 2023-06-01" \
|
||||
-d '{"model":"claude-sonnet-4-20250514","max_tokens":10,"messages":[{"role":"user","content":"Hi"}]}'
|
||||
```
|
||||
|
||||
#### 1.3 Project Dependencies
|
||||
|
||||
- [ ] **Node.js dependencies**
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
- [ ] **Cargo dependencies** (初回ビルドで取得)
|
||||
```bash
|
||||
cargo fetch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Repository Setup
|
||||
|
||||
#### 2.1 Labels Verification
|
||||
|
||||
- [ ] **必要なラベル確認**
|
||||
```bash
|
||||
gh label list --repo ShunsukeHayashi/miyabi-cli-standalone | wc -l
|
||||
# Expected: 45+ labels
|
||||
```
|
||||
|
||||
- [ ] **不足ラベル追加**
|
||||
```bash
|
||||
# 必要に応じて
|
||||
gh label create "🔥 urgent" --color "d73a4a" --description "Urgent issue"
|
||||
```
|
||||
|
||||
#### 2.2 Milestones Verification
|
||||
|
||||
- [ ] **マイルストーン確認**
|
||||
```bash
|
||||
gh api repos/ShunsukeHayashi/miyabi-cli-standalone/milestones | jq '.[].title'
|
||||
```
|
||||
|
||||
Expected:
|
||||
- v0.2.0 - Advanced Text Rendering
|
||||
- v0.3.0 - Chat Composer
|
||||
- v0.4.0 - Approval & Navigation
|
||||
- v1.0.0 - Production Ready
|
||||
|
||||
#### 2.3 Issues Verification
|
||||
|
||||
- [ ] **Issue一覧確認**
|
||||
```bash
|
||||
gh issue list --repo ShunsukeHayashi/miyabi-cli-standalone --state all | wc -l
|
||||
# Expected: 28 issues
|
||||
```
|
||||
|
||||
- [ ] **Sprint 1タスク確認**
|
||||
```bash
|
||||
gh issue list --milestone "v0.2.0 - Advanced Text Rendering" --label "📊 priority:P0-Critical"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Codebase Preparation
|
||||
|
||||
#### 3.1 Directory Structure
|
||||
|
||||
- [ ] **必要ディレクトリ作成**
|
||||
```bash
|
||||
mkdir -p crates/miyabi-cli/src
|
||||
mkdir -p crates/miyabi-core/src
|
||||
mkdir -p crates/miyabi-tui/src
|
||||
mkdir -p tests
|
||||
```
|
||||
|
||||
#### 3.2 Cargo.toml Setup
|
||||
|
||||
- [ ] **ワークスペース設定確認**
|
||||
```bash
|
||||
cat Cargo.toml | grep "members"
|
||||
```
|
||||
|
||||
- [ ] **各crateのCargo.toml確認**
|
||||
```bash
|
||||
ls crates/*/Cargo.toml
|
||||
```
|
||||
|
||||
#### 3.3 Initial Build Test
|
||||
|
||||
- [ ] **ビルドテスト**
|
||||
```bash
|
||||
cargo build
|
||||
cargo test
|
||||
cargo clippy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. CI/CD Setup
|
||||
|
||||
#### 4.1 GitHub Actions
|
||||
|
||||
- [ ] **ワークフロー確認**
|
||||
```bash
|
||||
ls .github/workflows/
|
||||
```
|
||||
|
||||
- [ ] **CI設定** (create if not exists)
|
||||
```yaml
|
||||
# .github/workflows/ci.yml
|
||||
name: CI
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: cargo build --all
|
||||
- run: cargo test --all
|
||||
- run: cargo clippy --all -- -D warnings
|
||||
```
|
||||
|
||||
#### 4.2 Branch Protection
|
||||
|
||||
- [ ] **main ブランチ保護**
|
||||
- Require PR reviews
|
||||
- Require status checks
|
||||
- Require linear history
|
||||
|
||||
---
|
||||
|
||||
### 5. Documentation
|
||||
|
||||
#### 5.1 Required Documents
|
||||
|
||||
- [x] README.md
|
||||
- [x] CLAUDE.md
|
||||
- [x] GOALS.md
|
||||
- [x] docs/WBS.md
|
||||
- [x] docs/SPRINT_PLANNING.md
|
||||
- [x] docs/OPERATION_PLAN.md
|
||||
- [x] docs/PRODUCT_SPEC.md
|
||||
- [x] docs/PREPARATION_OPS.md (this file)
|
||||
|
||||
#### 5.2 PlantUML Diagrams
|
||||
|
||||
- [x] docs/wbs-diagram.puml
|
||||
- [x] docs/gantt-chart.puml
|
||||
|
||||
---
|
||||
|
||||
### 6. Reference Materials
|
||||
|
||||
#### 6.1 Codex CLI Reference
|
||||
|
||||
- [ ] **Clone Codex CLI**
|
||||
```bash
|
||||
git clone https://github.com/openai/codex.git /tmp/codex-reference
|
||||
```
|
||||
|
||||
- [ ] **主要ファイル確認**
|
||||
```bash
|
||||
ls /tmp/codex-reference/codex-rs/tui/src/
|
||||
```
|
||||
|
||||
- [ ] **参照用ブックマーク**
|
||||
- markdown_stream.rs
|
||||
- diff_render.rs
|
||||
- chat_composer.rs
|
||||
- textarea.rs
|
||||
|
||||
#### 6.2 Miyabi Private Reference
|
||||
|
||||
- [ ] **Agent実装参照**
|
||||
```bash
|
||||
ls /Users/shunsuke/Dev/01-miyabi/_core/miyabi-private/crates/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. Team Communication
|
||||
|
||||
#### 7.1 Notification Setup
|
||||
|
||||
- [ ] **Slack/Discord通知** (if applicable)
|
||||
|
||||
- [ ] **GitHub通知設定**
|
||||
- Watch repository
|
||||
- Enable PR notifications
|
||||
|
||||
#### 7.2 Daily Standup Schedule
|
||||
|
||||
- [ ] **Standup時間設定**
|
||||
- Time: 毎朝 9:00
|
||||
- Duration: 10分
|
||||
- Format: miyabi status確認
|
||||
|
||||
---
|
||||
|
||||
### 8. Monitoring Setup
|
||||
|
||||
#### 8.1 Miyabi Monitoring
|
||||
|
||||
- [ ] **ログディレクトリ確認**
|
||||
```bash
|
||||
mkdir -p logs
|
||||
mkdir -p reports
|
||||
```
|
||||
|
||||
- [ ] **ログローテーション設定**
|
||||
```bash
|
||||
# 30日以上のログを削除
|
||||
find logs -mtime +30 -delete
|
||||
```
|
||||
|
||||
#### 8.2 GitHub Insights
|
||||
|
||||
- [ ] **Pulse確認**
|
||||
```
|
||||
https://github.com/ShunsukeHayashi/miyabi-cli-standalone/pulse
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 9. Sprint 1 Kickoff Preparation
|
||||
|
||||
#### 9.1 First Tasks Ready
|
||||
|
||||
- [ ] **Issue #10 (MarkdownStream core)**
|
||||
```bash
|
||||
gh issue view 10 --repo ShunsukeHayashi/miyabi-cli-standalone
|
||||
```
|
||||
|
||||
- [ ] **Issue #15 (DiffRender core)**
|
||||
```bash
|
||||
gh issue view 15
|
||||
```
|
||||
|
||||
- [ ] **Issue #19 (API client)**
|
||||
```bash
|
||||
gh issue view 19
|
||||
```
|
||||
|
||||
- [ ] **Issue #24 (Tool trait)**
|
||||
```bash
|
||||
gh issue view 24
|
||||
```
|
||||
|
||||
#### 9.2 Agent Configuration
|
||||
|
||||
- [ ] **Miyabi設定確認**
|
||||
```bash
|
||||
cat .miyabi.yml
|
||||
```
|
||||
|
||||
- [ ] **.claude設定確認**
|
||||
```bash
|
||||
ls .claude/
|
||||
ls .claude/agents/specs/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Kickoff Commands
|
||||
|
||||
### Sprint 1 Day 1 (2025-11-25)
|
||||
|
||||
```bash
|
||||
# 1. 環境確認
|
||||
cd /Users/shunsuke/Dev/miyabi-cli-standalone
|
||||
miyabi status
|
||||
|
||||
# 2. Critical Path 開始
|
||||
miyabi agent run coordinator --issue 19 # API Client (CRITICAL)
|
||||
|
||||
# 3. Parallel tasks 開始
|
||||
miyabi agent run coordinator --issue 10 # Markdown Core
|
||||
miyabi agent run coordinator --issue 15 # Diff Core
|
||||
miyabi agent run coordinator --issue 24 # Tool Trait
|
||||
|
||||
# 4. 進捗監視
|
||||
watch -n 60 'gh issue list --label "🏗️ state:implementing"'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Final Checklist
|
||||
|
||||
### Must Have (Sprint開始前)
|
||||
|
||||
- [ ] Rust toolchain ready
|
||||
- [ ] API keys configured
|
||||
- [ ] GitHub labels/milestones set
|
||||
- [ ] Initial crate structure
|
||||
- [ ] CI workflow active
|
||||
|
||||
### Should Have
|
||||
|
||||
- [ ] Codex CLI reference cloned
|
||||
- [ ] PlantUML diagrams reviewed
|
||||
- [ ] All documentation in place
|
||||
|
||||
### Nice to Have
|
||||
|
||||
- [ ] Notification integrations
|
||||
- [ ] Performance baselines
|
||||
|
||||
---
|
||||
|
||||
## 📞 Emergency Contacts
|
||||
|
||||
| Issue | Action |
|
||||
|-------|--------|
|
||||
| API Key invalid | Regenerate at console.anthropic.com |
|
||||
| GitHub rate limit | Wait 1 hour or use different token |
|
||||
| Build failure | Check Cargo.toml, dependencies |
|
||||
| Agent stuck | Check logs, reset issue state |
|
||||
|
||||
---
|
||||
|
||||
## 📝 Sign-off
|
||||
|
||||
| Item | Status | Date | Notes |
|
||||
|------|--------|------|-------|
|
||||
| Environment | ⬜ | | |
|
||||
| Repository | ⬜ | | |
|
||||
| Codebase | ⬜ | | |
|
||||
| CI/CD | ⬜ | | |
|
||||
| Documentation | ✅ | 2025-11-22 | Complete |
|
||||
| References | ⬜ | | |
|
||||
| Monitoring | ⬜ | | |
|
||||
|
||||
---
|
||||
|
||||
**Ready for Sprint 1? Let's go! 🚀**
|
||||
648
docs/PRODUCT_SPEC.md
Normal file
648
docs/PRODUCT_SPEC.md
Normal file
|
|
@ -0,0 +1,648 @@
|
|||
# Product Specification - miyabi-cli-standalone
|
||||
|
||||
**Version**: 1.0.0
|
||||
**Status**: Draft
|
||||
**Last Updated**: 2025-11-22
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive Summary
|
||||
|
||||
### 1.1 Product Vision
|
||||
OpenAI Codex CLIと同等の機能を持ち、Miyabiの拡張機能を統合した次世代AI開発CLIツール
|
||||
|
||||
### 1.2 Target Users
|
||||
- ソフトウェア開発者
|
||||
- DevOpsエンジニア
|
||||
- AI/MLエンジニア
|
||||
|
||||
### 1.3 Core Value Proposition
|
||||
- **高速**: Rust実装による100ms以下の起動時間
|
||||
- **美しい**: Ratatui TUIによるリッチなターミナル体験
|
||||
- **自律的**: 完全自律型タスク実行
|
||||
- **拡張性**: プラグイン対応
|
||||
|
||||
---
|
||||
|
||||
## 2. Functional Requirements
|
||||
|
||||
### 2.1 TUI System
|
||||
|
||||
#### FR-TUI-001: Markdown Streaming Renderer
|
||||
|
||||
**Description**: LLMレスポンスをリアルタイムでレンダリング
|
||||
|
||||
**Requirements**:
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| FR-TUI-001-1 | Character-by-character streaming | Must | Pending |
|
||||
| FR-TUI-001-2 | Progressive code block rendering | Must | Pending |
|
||||
| FR-TUI-001-3 | Syntax highlighting (50+ languages) | Must | Pending |
|
||||
| FR-TUI-001-4 | Cursor position tracking | Should | Pending |
|
||||
| FR-TUI-001-5 | Auto-scroll during streaming | Should | Pending |
|
||||
| FR-TUI-001-6 | User scroll override | Could | Pending |
|
||||
|
||||
**Acceptance Criteria**:
|
||||
```gherkin
|
||||
Scenario: Streaming text display
|
||||
Given the LLM is generating a response
|
||||
When text chunks arrive
|
||||
Then each character is displayed immediately
|
||||
And the display scrolls to show latest content
|
||||
And there is no visible flickering
|
||||
```
|
||||
|
||||
**Performance**:
|
||||
- Render latency: < 16ms (60 FPS)
|
||||
- Memory: < 10MB for 100K characters
|
||||
- CPU: < 5% during streaming
|
||||
|
||||
---
|
||||
|
||||
#### FR-TUI-002: Git Diff Visualization
|
||||
|
||||
**Description**: Git diffの美しい視覚化
|
||||
|
||||
**Requirements**:
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| FR-TUI-002-1 | Unified diff parsing | Must | Pending |
|
||||
| FR-TUI-002-2 | Color-coded additions/deletions | Must | Pending |
|
||||
| FR-TUI-002-3 | Line numbers (old/new) | Must | Pending |
|
||||
| FR-TUI-002-4 | Syntax highlighting in diff | Should | Pending |
|
||||
| FR-TUI-002-5 | Hunk navigation (n/N) | Should | Pending |
|
||||
| FR-TUI-002-6 | Split view mode | Could | Pending |
|
||||
|
||||
**Color Scheme**:
|
||||
```
|
||||
Addition: #2ea043 (Green)
|
||||
Deletion: #f85149 (Red)
|
||||
Context: Default
|
||||
Hunk header: #8b949e (Gray)
|
||||
```
|
||||
|
||||
**Acceptance Criteria**:
|
||||
```gherkin
|
||||
Scenario: View file diff
|
||||
Given a unified diff output
|
||||
When rendered in the TUI
|
||||
Then additions are highlighted in green
|
||||
And deletions are highlighted in red
|
||||
And line numbers are correctly aligned
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### FR-TUI-003: Chat Composer
|
||||
|
||||
**Description**: マルチライン入力とコマンド補完
|
||||
|
||||
**Requirements**:
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| FR-TUI-003-1 | Multi-line text input | Must | Pending |
|
||||
| FR-TUI-003-2 | Command history (Up/Down) | Must | Pending |
|
||||
| FR-TUI-003-3 | Tab completion | Should | Pending |
|
||||
| FR-TUI-003-4 | Syntax highlighting in input | Should | Pending |
|
||||
| FR-TUI-003-5 | Vim keybindings | Could | Pending |
|
||||
| FR-TUI-003-6 | Emacs keybindings | Could | Pending |
|
||||
|
||||
**Key Bindings**:
|
||||
```
|
||||
Enter : Send message (single line)
|
||||
Shift+Enter : New line
|
||||
Ctrl+C : Cancel
|
||||
Ctrl+L : Clear screen
|
||||
Up/Down : History navigation
|
||||
Tab : Auto-complete
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### FR-TUI-004: Text Area Widget
|
||||
|
||||
**Description**: 完全機能テキストエディタ
|
||||
|
||||
**Requirements**:
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| FR-TUI-004-1 | Text selection (Shift+Arrow) | Must | Pending |
|
||||
| FR-TUI-004-2 | Copy/Paste (Ctrl+C/V) | Must | Pending |
|
||||
| FR-TUI-004-3 | Undo/Redo (Ctrl+Z/Y) | Must | Pending |
|
||||
| FR-TUI-004-4 | Word wrap | Should | Pending |
|
||||
| FR-TUI-004-5 | Find & Replace | Could | Pending |
|
||||
|
||||
---
|
||||
|
||||
#### FR-TUI-005: Approval Overlay
|
||||
|
||||
**Description**: ツール実行の承認UI
|
||||
|
||||
**Requirements**:
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| FR-TUI-005-1 | Show tool name and arguments | Must | Pending |
|
||||
| FR-TUI-005-2 | Y/N/A/N options | Must | Pending |
|
||||
| FR-TUI-005-3 | Risk level indicator | Should | Pending |
|
||||
| FR-TUI-005-4 | Remember "Always" choices | Should | Pending |
|
||||
| FR-TUI-005-5 | Preview changes | Could | Pending |
|
||||
|
||||
**Risk Levels**:
|
||||
- 🟢 Low: Read operations
|
||||
- 🟡 Medium: Write to files
|
||||
- 🔴 High: Execute commands, delete files
|
||||
|
||||
---
|
||||
|
||||
### 2.2 LLM Integration
|
||||
|
||||
#### FR-LLM-001: Anthropic API Client
|
||||
|
||||
**Description**: Claude APIとの通信
|
||||
|
||||
**Requirements**:
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| FR-LLM-001-1 | POST /v1/messages | Must | Pending |
|
||||
| FR-LLM-001-2 | SSE streaming | Must | Pending |
|
||||
| FR-LLM-001-3 | API key authentication | Must | Pending |
|
||||
| FR-LLM-001-4 | Error handling (4xx, 5xx) | Must | Pending |
|
||||
| FR-LLM-001-5 | Retry with exponential backoff | Must | Pending |
|
||||
| FR-LLM-001-6 | Request timeout (30s default) | Should | Pending |
|
||||
|
||||
**API Endpoint**:
|
||||
```
|
||||
POST https://api.anthropic.com/v1/messages
|
||||
Headers:
|
||||
x-api-key: $ANTHROPIC_API_KEY
|
||||
anthropic-version: 2023-06-01
|
||||
content-type: application/json
|
||||
```
|
||||
|
||||
**Error Handling**:
|
||||
| Code | Action |
|
||||
|------|--------|
|
||||
| 400 | Show error, don't retry |
|
||||
| 401 | Prompt for API key |
|
||||
| 429 | Wait, retry with backoff |
|
||||
| 500+ | Retry up to 3 times |
|
||||
|
||||
---
|
||||
|
||||
#### FR-LLM-002: Conversation Management
|
||||
|
||||
**Description**: 会話履歴と状態管理
|
||||
|
||||
**Requirements**:
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| FR-LLM-002-1 | Store message history | Must | Pending |
|
||||
| FR-LLM-002-2 | System prompt support | Must | Pending |
|
||||
| FR-LLM-002-3 | Conversation persistence | Should | Pending |
|
||||
| FR-LLM-002-4 | Resume from previous session | Should | Pending |
|
||||
| FR-LLM-002-5 | Export conversation | Could | Pending |
|
||||
|
||||
**Data Model**:
|
||||
```rust
|
||||
struct Message {
|
||||
role: Role, // user, assistant, system
|
||||
content: Content, // text, tool_use, tool_result
|
||||
timestamp: DateTime<Utc>,
|
||||
}
|
||||
|
||||
struct Conversation {
|
||||
id: Uuid,
|
||||
messages: Vec<Message>,
|
||||
system_prompt: Option<String>,
|
||||
created_at: DateTime<Utc>,
|
||||
updated_at: DateTime<Utc>,
|
||||
}
|
||||
```
|
||||
|
||||
**Storage**:
|
||||
- Location: `~/.miyabi/conversations/`
|
||||
- Format: JSON
|
||||
- Retention: 30 days default
|
||||
|
||||
---
|
||||
|
||||
#### FR-LLM-003: Token Management
|
||||
|
||||
**Description**: トークンカウントとコンテキスト管理
|
||||
|
||||
**Requirements**:
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| FR-LLM-003-1 | Token estimation | Must | Pending |
|
||||
| FR-LLM-003-2 | Display current usage | Must | Pending |
|
||||
| FR-LLM-003-3 | Auto-prune old messages | Must | Pending |
|
||||
| FR-LLM-003-4 | Warning at 80% capacity | Should | Pending |
|
||||
| FR-LLM-003-5 | Manual context clear | Should | Pending |
|
||||
|
||||
**Limits**:
|
||||
| Model | Context Window | Reserve |
|
||||
|-------|----------------|---------|
|
||||
| Claude Sonnet | 200K | 10K |
|
||||
| Claude Haiku | 200K | 5K |
|
||||
|
||||
**Pruning Strategy**:
|
||||
1. Keep system prompt always
|
||||
2. Keep last N messages
|
||||
3. Summarize old messages
|
||||
|
||||
---
|
||||
|
||||
#### FR-LLM-004: Tool Calling
|
||||
|
||||
**Description**: Function calling の実装
|
||||
|
||||
**Requirements**:
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| FR-LLM-004-1 | Send tool definitions | Must | Pending |
|
||||
| FR-LLM-004-2 | Parse tool_use blocks | Must | Pending |
|
||||
| FR-LLM-004-3 | Execute tool | Must | Pending |
|
||||
| FR-LLM-004-4 | Send tool_result | Must | Pending |
|
||||
| FR-LLM-004-5 | Multi-turn tool use | Must | Pending |
|
||||
|
||||
**Tool Schema Format**:
|
||||
```json
|
||||
{
|
||||
"name": "read_file",
|
||||
"description": "Read the contents of a file",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to the file"
|
||||
}
|
||||
},
|
||||
"required": ["path"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.3 Tool System
|
||||
|
||||
#### FR-TOOL-001: Tool Registry
|
||||
|
||||
**Description**: ツールの登録と管理
|
||||
|
||||
**Requirements**:
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| FR-TOOL-001-1 | Register tool by name | Must | Pending |
|
||||
| FR-TOOL-001-2 | Lookup tool | Must | Pending |
|
||||
| FR-TOOL-001-3 | List all tools | Should | Pending |
|
||||
| FR-TOOL-001-4 | Dynamic registration | Could | Pending |
|
||||
|
||||
**Tool Trait**:
|
||||
```rust
|
||||
#[async_trait]
|
||||
pub trait Tool: Send + Sync {
|
||||
fn name(&self) -> &str;
|
||||
fn description(&self) -> &str;
|
||||
fn input_schema(&self) -> Value;
|
||||
async fn execute(&self, input: Value) -> Result<ToolResult>;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### FR-TOOL-002: Read Tool
|
||||
|
||||
**Description**: ファイル読み込み
|
||||
|
||||
**Parameters**:
|
||||
| Name | Type | Required | Description |
|
||||
|------|------|----------|-------------|
|
||||
| file_path | string | Yes | Absolute path |
|
||||
| offset | number | No | Start line (0-based) |
|
||||
| limit | number | No | Max lines (default: 2000) |
|
||||
|
||||
**Output**:
|
||||
```
|
||||
Line numbered content (cat -n format)
|
||||
```
|
||||
|
||||
**Errors**:
|
||||
- File not found
|
||||
- Permission denied
|
||||
- Binary file
|
||||
|
||||
---
|
||||
|
||||
#### FR-TOOL-003: Write Tool
|
||||
|
||||
**Description**: ファイル書き込み
|
||||
|
||||
**Parameters**:
|
||||
| Name | Type | Required | Description |
|
||||
|------|------|----------|-------------|
|
||||
| file_path | string | Yes | Absolute path |
|
||||
| content | string | Yes | Content to write |
|
||||
|
||||
**Behavior**:
|
||||
- Create directories if needed
|
||||
- Overwrite existing file
|
||||
- Preserve permissions
|
||||
|
||||
---
|
||||
|
||||
#### FR-TOOL-004: Edit Tool
|
||||
|
||||
**Description**: ファイル編集
|
||||
|
||||
**Parameters**:
|
||||
| Name | Type | Required | Description |
|
||||
|------|------|----------|-------------|
|
||||
| file_path | string | Yes | Absolute path |
|
||||
| old_string | string | Yes | Text to find |
|
||||
| new_string | string | Yes | Replacement |
|
||||
| replace_all | bool | No | Replace all occurrences |
|
||||
|
||||
**Behavior**:
|
||||
- Exact string match
|
||||
- Fail if not unique (unless replace_all)
|
||||
- Preserve indentation
|
||||
|
||||
---
|
||||
|
||||
#### FR-TOOL-005: Bash Tool
|
||||
|
||||
**Description**: コマンド実行
|
||||
|
||||
**Parameters**:
|
||||
| Name | Type | Required | Description |
|
||||
|------|------|----------|-------------|
|
||||
| command | string | Yes | Command to execute |
|
||||
| timeout | number | No | Timeout in ms (default: 120000) |
|
||||
| cwd | string | No | Working directory |
|
||||
|
||||
**Security**:
|
||||
- Timeout enforcement
|
||||
- Output truncation (30K chars)
|
||||
- Dangerous command warning
|
||||
|
||||
---
|
||||
|
||||
#### FR-TOOL-006: Glob Tool
|
||||
|
||||
**Description**: ファイルパターン検索
|
||||
|
||||
**Parameters**:
|
||||
| Name | Type | Required | Description |
|
||||
|------|------|----------|-------------|
|
||||
| pattern | string | Yes | Glob pattern (e.g., "**/*.rs") |
|
||||
| path | string | No | Base directory |
|
||||
|
||||
**Output**:
|
||||
- Matching file paths
|
||||
- Sorted by modification time
|
||||
|
||||
---
|
||||
|
||||
#### FR-TOOL-007: Grep Tool
|
||||
|
||||
**Description**: テキスト検索
|
||||
|
||||
**Parameters**:
|
||||
| Name | Type | Required | Description |
|
||||
|------|------|----------|-------------|
|
||||
| pattern | string | Yes | Regex pattern |
|
||||
| path | string | No | Search path |
|
||||
| type | string | No | File type (e.g., "rs") |
|
||||
| output_mode | string | No | content/files/count |
|
||||
|
||||
**Output Modes**:
|
||||
- `content`: Matching lines with context
|
||||
- `files_with_matches`: File paths only
|
||||
- `count`: Match counts
|
||||
|
||||
---
|
||||
|
||||
## 3. Non-Functional Requirements
|
||||
|
||||
### 3.1 Performance
|
||||
|
||||
| Metric | Requirement |
|
||||
|--------|-------------|
|
||||
| Startup time | < 100ms |
|
||||
| Memory usage | < 50MB idle, < 200MB active |
|
||||
| Response latency | < 16ms (60 FPS) |
|
||||
| File operation | < 100ms for 1MB file |
|
||||
|
||||
### 3.2 Reliability
|
||||
|
||||
| Metric | Requirement |
|
||||
|--------|-------------|
|
||||
| Crash rate | < 0.1% |
|
||||
| Error recovery | Graceful degradation |
|
||||
| Data integrity | No data loss on crash |
|
||||
|
||||
### 3.3 Security
|
||||
|
||||
| Area | Requirement |
|
||||
|------|-------------|
|
||||
| API keys | Environment variables only |
|
||||
| File access | Validate paths, prevent traversal |
|
||||
| Command execution | Timeout, sandboxing |
|
||||
| Permissions | Follow least privilege |
|
||||
|
||||
### 3.4 Usability
|
||||
|
||||
| Aspect | Requirement |
|
||||
|--------|-------------|
|
||||
| Learning curve | < 5 minutes for basic use |
|
||||
| Error messages | Clear, actionable |
|
||||
| Help system | Built-in --help |
|
||||
| Keyboard shortcuts | Discoverable, consistent |
|
||||
|
||||
### 3.5 Compatibility
|
||||
|
||||
| Platform | Support |
|
||||
|----------|---------|
|
||||
| macOS | 12+ (Monterey) |
|
||||
| Linux | Ubuntu 20.04+, Debian 11+ |
|
||||
| Windows | WSL2 |
|
||||
|
||||
---
|
||||
|
||||
## 4. Technical Specifications
|
||||
|
||||
### 4.1 Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ miyabi-cli │
|
||||
│ (CLI entry point, argument parsing) │
|
||||
└─────────────────┬───────────────────────┘
|
||||
│
|
||||
┌─────────────────▼───────────────────────┐
|
||||
│ miyabi-tui │
|
||||
│ (Terminal UI, Ratatui widgets) │
|
||||
└─────────────────┬───────────────────────┘
|
||||
│
|
||||
┌─────────────────▼───────────────────────┐
|
||||
│ miyabi-core │
|
||||
│ (LLM client, Tool system, State) │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.2 Dependencies
|
||||
|
||||
**Core**:
|
||||
- tokio: Async runtime
|
||||
- ratatui: TUI framework
|
||||
- crossterm: Terminal backend
|
||||
- clap: CLI parsing
|
||||
|
||||
**LLM**:
|
||||
- reqwest: HTTP client
|
||||
- serde_json: JSON handling
|
||||
|
||||
**Text**:
|
||||
- pulldown-cmark: Markdown parsing
|
||||
- syntect: Syntax highlighting
|
||||
|
||||
### 4.3 Configuration
|
||||
|
||||
**Config File**: `~/.miyabi/config.toml`
|
||||
|
||||
```toml
|
||||
[general]
|
||||
theme = "dark"
|
||||
editor = "vim"
|
||||
|
||||
[llm]
|
||||
model = "claude-sonnet-4-20250514"
|
||||
max_tokens = 4096
|
||||
temperature = 0.7
|
||||
|
||||
[tools]
|
||||
timeout = 120000
|
||||
auto_approve = ["read_file", "glob"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. User Interface Specifications
|
||||
|
||||
### 5.1 Layout
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ miyabi v1.0.0 Tokens: 1.2K/200K ⚡ │ Header
|
||||
├─────────────────────────────────────────┤
|
||||
│ │
|
||||
│ User: How do I implement... │
|
||||
│ │
|
||||
│ Assistant: Here's how you can... │
|
||||
│ ```rust │ Chat History
|
||||
│ fn main() { │
|
||||
│ println!("Hello"); │
|
||||
│ } │
|
||||
│ ``` │
|
||||
│ │
|
||||
├─────────────────────────────────────────┤
|
||||
│ > Type your message... │ Input
|
||||
│ │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Ctrl+C: Cancel Ctrl+L: Clear ?: Help │ Status Bar
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5.2 Color Palette
|
||||
|
||||
| Element | Light | Dark |
|
||||
|---------|-------|------|
|
||||
| Background | #FFFFFF | #0D1117 |
|
||||
| Text | #24292F | #C9D1D9 |
|
||||
| Code | #F6F8FA | #161B22 |
|
||||
| Accent | #0969DA | #58A6FF |
|
||||
| Success | #1A7F37 | #3FB950 |
|
||||
| Error | #CF222E | #F85149 |
|
||||
| Warning | #9A6700 | #D29922 |
|
||||
|
||||
---
|
||||
|
||||
## 6. API Specifications
|
||||
|
||||
### 6.1 CLI Interface
|
||||
|
||||
```bash
|
||||
miyabi [OPTIONS] [COMMAND]
|
||||
|
||||
Commands:
|
||||
chat Start interactive chat (default)
|
||||
run Execute a single prompt
|
||||
resume Resume previous session
|
||||
config Manage configuration
|
||||
version Show version
|
||||
|
||||
Options:
|
||||
-m, --model <MODEL> Model to use
|
||||
-s, --system <PROMPT> System prompt
|
||||
-v, --verbose Verbose output
|
||||
-h, --help Show help
|
||||
```
|
||||
|
||||
### 6.2 Exit Codes
|
||||
|
||||
| Code | Meaning |
|
||||
|------|---------|
|
||||
| 0 | Success |
|
||||
| 1 | General error |
|
||||
| 2 | Invalid arguments |
|
||||
| 3 | API error |
|
||||
| 4 | Tool execution error |
|
||||
|
||||
---
|
||||
|
||||
## 7. Testing Requirements
|
||||
|
||||
### 7.1 Unit Tests
|
||||
|
||||
- Coverage: > 80%
|
||||
- All public functions
|
||||
- Edge cases covered
|
||||
|
||||
### 7.2 Integration Tests
|
||||
|
||||
- LLM API mocking
|
||||
- Full conversation flow
|
||||
- Tool execution
|
||||
|
||||
### 7.3 E2E Tests
|
||||
|
||||
- Complete user scenarios
|
||||
- Performance benchmarks
|
||||
|
||||
---
|
||||
|
||||
## 8. Documentation Requirements
|
||||
|
||||
- README.md
|
||||
- CHANGELOG.md
|
||||
- API documentation (rustdoc)
|
||||
- User guide
|
||||
- Contributing guide
|
||||
|
||||
---
|
||||
|
||||
## 9. Glossary
|
||||
|
||||
| Term | Definition |
|
||||
|------|------------|
|
||||
| TUI | Terminal User Interface |
|
||||
| LLM | Large Language Model |
|
||||
| SSE | Server-Sent Events |
|
||||
| Tool | Function callable by LLM |
|
||||
|
||||
---
|
||||
|
||||
**Document Status**: Draft
|
||||
**Next Review**: Sprint 1 End
|
||||
427
docs/SPRINT_PLANNING.md
Normal file
427
docs/SPRINT_PLANNING.md
Normal file
|
|
@ -0,0 +1,427 @@
|
|||
# Sprint Planning - miyabi-cli-standalone
|
||||
|
||||
**Project**: miyabi-cli-standalone
|
||||
**Total Sprints**: 4
|
||||
**Sprint Duration**: 5 days (1 week)
|
||||
**Start Date**: 2025-11-25
|
||||
|
||||
---
|
||||
|
||||
## 📊 Overview
|
||||
|
||||
| Sprint | Period | Milestone | Goal |
|
||||
|--------|--------|-----------|------|
|
||||
| 1 | Nov 25-29 | v0.2.0 | Foundation |
|
||||
| 2 | Dec 2-6 | v0.2.0 | Parser & State |
|
||||
| 3 | Dec 9-13 | v0.3.0/v1.0.0 | Integration |
|
||||
| 4 | Dec 16-20 | v1.0.0 | Production Ready |
|
||||
|
||||
---
|
||||
|
||||
# Sprint 1: Foundation
|
||||
|
||||
**Period**: November 25-29, 2025
|
||||
**Goal**: Core structures for all streams
|
||||
|
||||
## 🎯 Sprint Goal
|
||||
|
||||
> 全3ストリーム(TUI、LLM、Tools)の基盤構造を確立する
|
||||
|
||||
## 📋 Sprint Backlog
|
||||
|
||||
| Issue | Task | Priority | Points | Agent |
|
||||
|-------|------|----------|--------|-------|
|
||||
| #10 | MarkdownStream core structure | P0 | 3 | CodeGen |
|
||||
| #15 | DiffRender core structure | P1 | 3 | CodeGen |
|
||||
| #19 | Anthropic API client | P0 | 5 | CodeGen |
|
||||
| #24 | Tool trait and registry | P0 | 5 | CodeGen |
|
||||
|
||||
**Total Points**: 16
|
||||
|
||||
## 📅 Daily Breakdown
|
||||
|
||||
### Day 1 (Mon) - Kickoff
|
||||
|
||||
**Morning**
|
||||
```bash
|
||||
# 全タスク並列開始
|
||||
miyabi agent run coordinator --issue 10 &
|
||||
miyabi agent run coordinator --issue 15 &
|
||||
miyabi agent run coordinator --issue 19 &
|
||||
miyabi agent run coordinator --issue 24 &
|
||||
```
|
||||
|
||||
**Tasks**:
|
||||
- [ ] #10 開始 - MarkdownStream struct定義
|
||||
- [ ] #15 開始 - DiffRender struct定義
|
||||
- [ ] #19 開始 - AnthropicClient struct定義
|
||||
- [ ] #24 開始 - Tool trait定義
|
||||
|
||||
**End of Day**: 基本struct完成
|
||||
|
||||
### Day 2 (Tue) - Core Implementation
|
||||
|
||||
**Tasks**:
|
||||
- [ ] #10 完了 - State enum、buffer管理
|
||||
- [ ] #15 完了 - Diff parsing logic
|
||||
- [ ] #19 継続 - Streaming SSE処理
|
||||
- [ ] #24 継続 - Registry実装
|
||||
|
||||
**Reviews**:
|
||||
```bash
|
||||
gh pr list --state open
|
||||
gh pr review <番号> --approve
|
||||
```
|
||||
|
||||
### Day 3 (Wed) - Integration
|
||||
|
||||
**Tasks**:
|
||||
- [ ] #19 完了 - Error handling、retry
|
||||
- [ ] #24 完了 - Schema generation
|
||||
|
||||
**Code Review**:
|
||||
- [ ] #10 PR レビュー・マージ
|
||||
- [ ] #15 PR レビュー・マージ
|
||||
|
||||
### Day 4 (Thu) - Testing
|
||||
|
||||
**Tasks**:
|
||||
- [ ] 統合テスト実行
|
||||
- [ ] #19 PR レビュー・マージ
|
||||
- [ ] #24 PR レビュー・マージ
|
||||
|
||||
```bash
|
||||
cargo test --all
|
||||
cargo clippy --all-targets
|
||||
```
|
||||
|
||||
### Day 5 (Fri) - Sprint Review
|
||||
|
||||
**Tasks**:
|
||||
- [ ] 全PRマージ確認
|
||||
- [ ] デモ準備
|
||||
- [ ] Sprint 2準備
|
||||
|
||||
## ✅ Acceptance Criteria
|
||||
|
||||
- [ ] `MarkdownStream` が文字を受け取り状態遷移できる
|
||||
- [ ] `DiffRender` がunified diffをパースできる
|
||||
- [ ] `AnthropicClient` がAPIに接続しストリーム受信できる
|
||||
- [ ] `Tool` traitが定義され、registryに登録できる
|
||||
- [ ] 全テストがパス
|
||||
- [ ] Clippyエラーなし
|
||||
|
||||
## 🚧 Risks & Mitigations
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| API接続失敗 | モック作成、retry実装 |
|
||||
| 設計変更 | 早期レビュー |
|
||||
|
||||
---
|
||||
|
||||
# Sprint 2: Parser & State
|
||||
|
||||
**Period**: December 2-6, 2025
|
||||
**Goal**: Incremental parsing and state management
|
||||
|
||||
## 🎯 Sprint Goal
|
||||
|
||||
> パーサーと状態管理を実装し、基盤構造を完成させる
|
||||
|
||||
## 📋 Sprint Backlog
|
||||
|
||||
| Issue | Task | Priority | Points | Depends |
|
||||
|-------|------|----------|--------|---------|
|
||||
| #11 | Incremental markdown parser | P0 | 5 | #10 |
|
||||
| #16 | Diff visualization | P1 | 5 | #15 |
|
||||
| #20 | Conversation state | P0 | 5 | #19 |
|
||||
| #25 | File operation tools | P0 | 5 | #24 |
|
||||
|
||||
**Total Points**: 20
|
||||
|
||||
## 📅 Daily Breakdown
|
||||
|
||||
### Day 1 (Mon) - Kickoff
|
||||
|
||||
```bash
|
||||
miyabi agent run coordinator --issue 11 &
|
||||
miyabi agent run coordinator --issue 16 &
|
||||
miyabi agent run coordinator --issue 20 &
|
||||
miyabi agent run coordinator --issue 25 &
|
||||
```
|
||||
|
||||
**Tasks**:
|
||||
- [ ] #11 開始 - pulldown-cmark統合
|
||||
- [ ] #16 開始 - Color scheme実装
|
||||
- [ ] #20 開始 - Message history構造
|
||||
- [ ] #25 開始 - ReadTool実装
|
||||
|
||||
### Day 2 (Tue) - Core Features
|
||||
|
||||
**Tasks**:
|
||||
- [ ] #11 継続 - Partial parsing
|
||||
- [ ] #16 継続 - Line numbers、indicators
|
||||
- [ ] #20 継続 - Serialization
|
||||
- [ ] #25 継続 - WriteTool、EditTool
|
||||
|
||||
### Day 3 (Wed) - Completion
|
||||
|
||||
**Tasks**:
|
||||
- [ ] #11 完了 - Event→Span変換
|
||||
- [ ] #16 完了 - 全視覚要素
|
||||
- [ ] #20 完了 - Persistence
|
||||
- [ ] #25 完了 - 全File tools
|
||||
|
||||
### Day 4 (Thu) - Review
|
||||
|
||||
**Tasks**:
|
||||
- [ ] PRレビュー
|
||||
- [ ] 統合テスト
|
||||
- [ ] Bug fix
|
||||
|
||||
### Day 5 (Fri) - Sprint Review
|
||||
|
||||
**Tasks**:
|
||||
- [ ] 全PRマージ
|
||||
- [ ] v0.2.0リリース準備
|
||||
- [ ] Sprint 3準備
|
||||
|
||||
## ✅ Acceptance Criteria
|
||||
|
||||
- [ ] Markdown streaming が部分コンテンツを正しくレンダリング
|
||||
- [ ] Diff表示が色分け、行番号付き
|
||||
- [ ] Conversation履歴が保存・復元可能
|
||||
- [ ] File tools (Read/Write/Edit) が全て動作
|
||||
- [ ] 全テストパス
|
||||
|
||||
---
|
||||
|
||||
# Sprint 3: Integration
|
||||
|
||||
**Period**: December 9-13, 2025
|
||||
**Goal**: LLM tools and advanced features
|
||||
|
||||
## 🎯 Sprint Goal
|
||||
|
||||
> LLMツール連携と高度な機能を実装する
|
||||
|
||||
## 📋 Sprint Backlog
|
||||
|
||||
| Issue | Task | Priority | Points | Depends |
|
||||
|-------|------|----------|--------|---------|
|
||||
| #12 | Code block handling | P1 | 3 | #11 |
|
||||
| #17 | Syntax highlighting in diff | P2 | 3 | #16 |
|
||||
| #21 | Token management | P1 | 5 | #20 |
|
||||
| #22 | Tool definitions | P0 | 5 | #20 |
|
||||
| #26 | Bash tool | P0 | 5 | #25 |
|
||||
|
||||
**Total Points**: 21
|
||||
|
||||
## 📅 Daily Breakdown
|
||||
|
||||
### Day 1 (Mon) - Kickoff
|
||||
|
||||
```bash
|
||||
miyabi agent run coordinator --issue 12 &
|
||||
miyabi agent run coordinator --issue 17 &
|
||||
miyabi agent run coordinator --issue 21 &
|
||||
miyabi agent run coordinator --issue 22 &
|
||||
miyabi agent run coordinator --issue 26 &
|
||||
```
|
||||
|
||||
### Day 2 (Tue) - Implementation
|
||||
|
||||
**Focus**: #22 (Tool definitions) - CRITICAL PATH
|
||||
|
||||
### Day 3 (Wed) - Integration
|
||||
|
||||
**Tasks**:
|
||||
- [ ] Tool definitions と API client統合
|
||||
- [ ] Bash tool と File tools統合
|
||||
|
||||
### Day 4 (Thu) - Testing
|
||||
|
||||
**Tasks**:
|
||||
- [ ] End-to-end テスト
|
||||
- [ ] Tool実行テスト
|
||||
|
||||
### Day 5 (Fri) - Sprint Review
|
||||
|
||||
**Milestone**: v0.3.0 機能フリーズ
|
||||
|
||||
## ✅ Acceptance Criteria
|
||||
|
||||
- [ ] Code blockがシンタックスハイライト付きでレンダリング
|
||||
- [ ] DiffにもSyntax highlighting適用
|
||||
- [ ] Token count表示、自動pruning動作
|
||||
- [ ] Tool definitionsがAPI requestに含まれる
|
||||
- [ ] Bash toolがコマンド実行、結果返却
|
||||
|
||||
---
|
||||
|
||||
# Sprint 4: Production Ready
|
||||
|
||||
**Period**: December 16-20, 2025
|
||||
**Goal**: Polish and production readiness
|
||||
|
||||
## 🎯 Sprint Goal
|
||||
|
||||
> プロダクション品質に仕上げ、v1.0.0をリリースする
|
||||
|
||||
## 📋 Sprint Backlog
|
||||
|
||||
| Issue | Task | Priority | Points | Depends |
|
||||
|-------|------|----------|--------|---------|
|
||||
| #13 | Cursor tracking | P2 | 2 | #12 |
|
||||
| #14 | Markdown tests | P2 | 3 | #13 |
|
||||
| #18 | Diff navigation | P2 | 2 | #17 |
|
||||
| #23 | Rate limiting | P2 | 3 | #22 |
|
||||
| #27 | Search tools | P1 | 5 | #26 |
|
||||
| #28 | Result formatting | P2 | 3 | #27 |
|
||||
|
||||
**Total Points**: 18
|
||||
|
||||
## 📅 Daily Breakdown
|
||||
|
||||
### Day 1 (Mon) - Kickoff
|
||||
|
||||
```bash
|
||||
miyabi agent run coordinator --issue 13 &
|
||||
miyabi agent run coordinator --issue 18 &
|
||||
miyabi agent run coordinator --issue 23 &
|
||||
miyabi agent run coordinator --issue 27 &
|
||||
```
|
||||
|
||||
### Day 2 (Tue) - Completion
|
||||
|
||||
**Tasks**:
|
||||
- [ ] #13 完了
|
||||
- [ ] #14 開始・完了
|
||||
- [ ] #18 完了
|
||||
- [ ] #23 完了
|
||||
- [ ] #27 完了
|
||||
- [ ] #28 開始
|
||||
|
||||
### Day 3 (Wed) - Final Integration
|
||||
|
||||
**Tasks**:
|
||||
- [ ] #28 完了
|
||||
- [ ] Full integration test
|
||||
- [ ] Performance testing
|
||||
|
||||
### Day 4 (Thu) - QA
|
||||
|
||||
**Tasks**:
|
||||
- [ ] Bug fixes
|
||||
- [ ] Documentation
|
||||
- [ ] Release notes
|
||||
|
||||
### Day 5 (Fri) - Release
|
||||
|
||||
**Tasks**:
|
||||
- [ ] v1.0.0 タグ作成
|
||||
- [ ] Release作成
|
||||
- [ ] 🎉 Celebration!
|
||||
|
||||
## ✅ Acceptance Criteria
|
||||
|
||||
- [ ] 全機能が動作
|
||||
- [ ] ドキュメント完備
|
||||
- [ ] パフォーマンス基準達成
|
||||
- [ ] セキュリティチェック完了
|
||||
- [ ] v1.0.0 リリース
|
||||
|
||||
---
|
||||
|
||||
## 📊 Sprint Metrics
|
||||
|
||||
### Velocity Tracking
|
||||
|
||||
| Sprint | Planned | Completed | Velocity |
|
||||
|--------|---------|-----------|----------|
|
||||
| 1 | 16 | - | - |
|
||||
| 2 | 20 | - | - |
|
||||
| 3 | 21 | - | - |
|
||||
| 4 | 18 | - | - |
|
||||
|
||||
**Total**: 75 points
|
||||
|
||||
### Burndown
|
||||
|
||||
Sprint終了時に更新
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Ceremonies
|
||||
|
||||
### Daily Standup (10min)
|
||||
|
||||
```bash
|
||||
# 毎朝実行
|
||||
miyabi status
|
||||
gh issue list --label "🏗️ state:implementing"
|
||||
```
|
||||
|
||||
### Sprint Planning (始め)
|
||||
|
||||
1. Sprint Goal確認
|
||||
2. Backlog確定
|
||||
3. タスク割り当て
|
||||
4. リスク確認
|
||||
|
||||
### Sprint Review (終わり)
|
||||
|
||||
1. 完了タスクデモ
|
||||
2. フィードバック収集
|
||||
3. 次Sprint調整
|
||||
|
||||
### Sprint Retrospective
|
||||
|
||||
- What went well?
|
||||
- What to improve?
|
||||
- Action items
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Execution Commands
|
||||
|
||||
### Sprint 1 Quick Start
|
||||
|
||||
```bash
|
||||
cd /Users/shunsuke/Dev/miyabi-cli-standalone
|
||||
|
||||
# Critical Path開始
|
||||
miyabi agent run coordinator --issue 19 # API Client
|
||||
miyabi agent run coordinator --issue 24 # Tool Trait
|
||||
|
||||
# Parallel tasks
|
||||
miyabi agent run coordinator --issue 10 # Markdown Core
|
||||
miyabi agent run coordinator --issue 15 # Diff Core
|
||||
```
|
||||
|
||||
### Progress Check
|
||||
|
||||
```bash
|
||||
# 完了タスク
|
||||
gh issue list --state closed --label "✅ state:done"
|
||||
|
||||
# 進行中
|
||||
gh issue list --label "🏗️ state:implementing"
|
||||
|
||||
# PRs
|
||||
gh pr list --state open
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
- 各SprintでCritical Pathを優先
|
||||
- ブロッカーは即座にエスカレーション
|
||||
- PRは24時間以内にレビュー
|
||||
- テストは継続的に実行
|
||||
|
||||
---
|
||||
|
||||
**Let's build something amazing! 🚀**
|
||||
278
docs/TROUBLESHOOTING.md
Normal file
278
docs/TROUBLESHOOTING.md
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
# Troubleshooting Guide
|
||||
|
||||
Miyabi使用中に発生する可能性のある問題と解決策をまとめています。
|
||||
|
||||
## 🔧 環境関連
|
||||
|
||||
### GITHUB_TOKENが設定されていない
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Error: GITHUB_TOKEN not set
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
1. トークンを取得: https://github.com/settings/tokens/new
|
||||
2. 環境変数を設定:
|
||||
```bash
|
||||
export GITHUB_TOKEN=ghp_xxxxx
|
||||
```
|
||||
3. シェルプロファイルに追加(永続化):
|
||||
```bash
|
||||
echo 'export GITHUB_TOKEN=ghp_xxxxx' >> ~/.zshrc
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
### ANTHROPIC_API_KEYが設定されていない
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Error: ANTHROPIC_API_KEY not set
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
1. Anthropic Consoleでキー取得: https://console.anthropic.com/
|
||||
2. 環境変数を設定:
|
||||
```bash
|
||||
export ANTHROPIC_API_KEY=sk-ant-xxxxx
|
||||
```
|
||||
|
||||
## 🐛 Git関連
|
||||
|
||||
### Git repositoryが見つからない
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Error: Not a git repository
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
```bash
|
||||
cd your-project
|
||||
git init
|
||||
```
|
||||
|
||||
### Worktreeが残ったまま
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Error: Worktree already exists: .worktrees/issue-123
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
```bash
|
||||
# Worktree一覧確認
|
||||
git worktree list
|
||||
|
||||
# 不要なWorktreeを削除
|
||||
git worktree remove .worktrees/issue-123
|
||||
|
||||
# すべてのstale Worktreeをクリーンアップ
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
### マージコンフリクト
|
||||
|
||||
**症状**:
|
||||
```
|
||||
CONFLICT (content): Merge conflict in src/main.rs
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
```bash
|
||||
# コンフリクトファイルを確認
|
||||
git status
|
||||
|
||||
# 手動でコンフリクトを解決
|
||||
# エディタでファイルを開き、<<<<<<<, =======, >>>>>>> マーカーを削除
|
||||
|
||||
# 解決後
|
||||
git add src/main.rs
|
||||
git commit -m "fix: resolve merge conflict"
|
||||
```
|
||||
|
||||
## 🤖 Agent関連
|
||||
|
||||
### Agent実行が失敗する
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Error: Agent execution failed
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
1. ログファイル確認:
|
||||
```bash
|
||||
tail -f logs/miyabi-$(date +%Y%m%d).log
|
||||
```
|
||||
2. Issue番号が正しいか確認:
|
||||
```bash
|
||||
gh issue list
|
||||
```
|
||||
3. Labelが正しく設定されているか確認
|
||||
|
||||
### Issue番号が見つからない
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Error: Issue #123 not found
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
```bash
|
||||
# Issue一覧確認
|
||||
gh issue list --limit 50
|
||||
|
||||
# 正しい番号で再実行
|
||||
miyabi agent run coordinator --issue 正しい番号
|
||||
```
|
||||
|
||||
## 📦 インストール関連
|
||||
|
||||
### `miyabi` コマンドが見つからない
|
||||
|
||||
**症状**:
|
||||
```
|
||||
command not found: miyabi
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
```bash
|
||||
# crates.ioから再インストール
|
||||
cargo install miyabi-cli --force
|
||||
|
||||
# パス確認
|
||||
which miyabi
|
||||
|
||||
# Cargo binディレクトリがPATHに含まれているか確認
|
||||
echo $PATH | grep -o "$HOME/.cargo/bin"
|
||||
|
||||
# なければ追加
|
||||
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.zshrc
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
### コンパイルエラー
|
||||
|
||||
**症状**:
|
||||
```
|
||||
error: failed to compile miyabi-cli
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
```bash
|
||||
# Rustを最新版にアップデート
|
||||
rustup update stable
|
||||
|
||||
# Cargoキャッシュをクリア
|
||||
rm -rf ~/.cargo/registry
|
||||
rm -rf ~/.cargo/git
|
||||
|
||||
# 再インストール
|
||||
cargo install miyabi-cli
|
||||
```
|
||||
|
||||
## 🌐 GitHub関連
|
||||
|
||||
### API Rate Limit
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Error: API rate limit exceeded
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
1. GitHubにログイン状態か確認:
|
||||
```bash
|
||||
gh auth status
|
||||
```
|
||||
2. Personal Access Tokenのスコープ確認
|
||||
3. しばらく待つ(Rate limitは1時間でリセット)
|
||||
|
||||
### Permission denied
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Error: Resource not accessible by personal access token
|
||||
```
|
||||
|
||||
**解決策**:
|
||||
1. トークンのスコープを確認: `repo`, `workflow` が必要
|
||||
2. 新しいトークンを生成
|
||||
3. 環境変数を更新
|
||||
|
||||
## 🔍 デバッグ方法
|
||||
|
||||
### 詳細ログを有効化
|
||||
|
||||
`.miyabi.yml` でログレベルを変更:
|
||||
```yaml
|
||||
logging:
|
||||
level: debug # info → debug
|
||||
directory: "./logs"
|
||||
```
|
||||
|
||||
### ログファイルの確認
|
||||
|
||||
```bash
|
||||
# 最新のログ
|
||||
tail -100 logs/miyabi-$(date +%Y%m%d).log
|
||||
|
||||
# エラーのみ抽出
|
||||
grep -i "error\|fail" logs/miyabi-*.log
|
||||
|
||||
# 特定のAgentのログ
|
||||
grep -i "CoordinatorAgent" logs/miyabi-*.log
|
||||
```
|
||||
|
||||
### miyabi status の活用
|
||||
|
||||
```bash
|
||||
miyabi status
|
||||
|
||||
# 出力例:
|
||||
# Miyabi Installation: ✅ or ❌
|
||||
# Environment: GITHUB_TOKEN, ANTHROPIC_API_KEY の状態
|
||||
# Git Repository: ブランチ、コミット状態
|
||||
# Worktrees: アクティブなWorktree数
|
||||
```
|
||||
|
||||
## 🆘 それでも解決しない場合
|
||||
|
||||
### サポートを受ける
|
||||
|
||||
1. **GitHub Issues**: https://github.com/ShunsukeHayashi/Miyabi/issues
|
||||
- 詳細なエラーメッセージを含めてください
|
||||
- `miyabi status` の出力を添付
|
||||
- ログファイルの関連部分を添付
|
||||
|
||||
2. **Discord Community**: (準備中)
|
||||
|
||||
3. **ドキュメント**:
|
||||
- [GETTING_STARTED.md](GETTING_STARTED.md)
|
||||
- [CLAUDE.md](../CLAUDE.md)
|
||||
- [GitHub Discussions](https://github.com/ShunsukeHayashi/Miyabi/discussions)
|
||||
|
||||
### 報告に含めるべき情報
|
||||
|
||||
```bash
|
||||
# システム情報
|
||||
uname -a
|
||||
|
||||
# Rustバージョン
|
||||
rustc --version
|
||||
cargo --version
|
||||
|
||||
# miyabiバージョン
|
||||
miyabi --version
|
||||
|
||||
# プロジェクト状態
|
||||
miyabi status
|
||||
|
||||
# 直近のログ
|
||||
tail -50 logs/miyabi-$(date +%Y%m%d).log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Miyabi** - Beauty in Autonomous Development 🌸
|
||||
178
docs/WBS.md
Normal file
178
docs/WBS.md
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
# Work Breakdown Structure (WBS)
|
||||
|
||||
**Project**: miyabi-cli-standalone
|
||||
**Version**: v1.0.0
|
||||
**Created**: 2025-11-22
|
||||
|
||||
---
|
||||
|
||||
## 1. TUI Foundation (v0.2.0)
|
||||
|
||||
### 1.1 Streaming Markdown Renderer (#2)
|
||||
- **1.1.1** Core structure and state management (#10) - P0 - 4h
|
||||
- **1.1.2** Incremental parser with pulldown-cmark (#11) - P0 - 6h
|
||||
- **1.1.3** Code block handling with syntax highlighting (#12) - P1 - 4h
|
||||
- **1.1.4** Cursor and scroll position tracking (#13) - P2 - 3h
|
||||
- **1.1.5** Unit tests (#14) - P2 - 4h
|
||||
|
||||
**Subtotal: ~700 lines, 21h**
|
||||
|
||||
### 1.2 Git Diff Visualization (#3)
|
||||
- **1.2.1** Core structure and diff parsing (#15) - P1 - 4h
|
||||
- **1.2.2** Visualization with colors and indicators (#16) - P1 - 6h
|
||||
- **1.2.3** Syntax highlighting in diff content (#17) - P2 - 4h
|
||||
- **1.2.4** Scrollable view with navigation (#18) - P2 - 3h
|
||||
|
||||
**Subtotal: ~650 lines, 17h**
|
||||
|
||||
---
|
||||
|
||||
## 2. Chat Composer (v0.3.0)
|
||||
|
||||
### 2.1 Chat Input Component (#4)
|
||||
- **2.1.1** Separate input handling from main app
|
||||
- **2.1.2** Multi-line input support
|
||||
- **2.1.3** Command history navigation
|
||||
- **2.1.4** Auto-completion
|
||||
- **2.1.5** Syntax highlighting in input
|
||||
|
||||
**Subtotal: ~3,938 lines**
|
||||
|
||||
### 2.2 Text Area Widget (#5)
|
||||
- **2.2.1** Full-featured text area widget
|
||||
- **2.2.2** Text selection support
|
||||
- **2.2.3** Copy/paste functionality
|
||||
- **2.2.4** Undo/redo stack
|
||||
|
||||
**Subtotal: ~2,213 lines**
|
||||
|
||||
---
|
||||
|
||||
## 3. Approval & Navigation (v0.4.0)
|
||||
|
||||
### 3.1 Approval Overlay (#6)
|
||||
- **3.1.1** Tool execution approval UI
|
||||
- **3.1.2** Y/N/Always/Never options
|
||||
- **3.1.3** Risk level display
|
||||
- **3.1.4** Preview of changes
|
||||
|
||||
**Subtotal: ~656 lines**
|
||||
|
||||
### 3.2 Session Resume (#7)
|
||||
- **3.2.1** Session resume selection
|
||||
- **3.2.2** Conversation history browser
|
||||
- **3.2.3** Search functionality
|
||||
- **3.2.4** Preview pane
|
||||
|
||||
**Subtotal: ~1,580 lines**
|
||||
|
||||
---
|
||||
|
||||
## 4. LLM Integration (v1.0.0)
|
||||
|
||||
### 4.1 Claude API Integration (#8)
|
||||
- **4.1.1** Anthropic API client with streaming (#19) - P0 - 8h
|
||||
- **4.1.2** Conversation state and message history (#20) - P0 - 6h
|
||||
- **4.1.3** Token counting and context window (#21) - P1 - 6h
|
||||
- **4.1.4** Tool definitions and function calling (#22) - P0 - 8h
|
||||
- **4.1.5** Rate limiting and retry logic (#23) - P2 - 4h
|
||||
|
||||
**Subtotal: ~1,600 lines, 32h**
|
||||
|
||||
---
|
||||
|
||||
## 5. Tool Execution System (v1.0.0)
|
||||
|
||||
### 5.1 Tool System (#9)
|
||||
- **5.1.1** Tool trait and registry system (#24) - P0 - 6h
|
||||
- **5.1.2** File operation tools (Read, Write, Edit) (#25) - P0 - 8h
|
||||
- **5.1.3** Bash tool with sandboxing (#26) - P0 - 8h
|
||||
- **5.1.4** Search tools (Glob, Grep) (#27) - P1 - 6h
|
||||
- **5.1.5** Result formatting and error handling (#28) - P2 - 4h
|
||||
|
||||
**Subtotal: ~1,800 lines, 32h**
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Phase | Milestone | Lines | Hours | Issues |
|
||||
|-------|-----------|-------|-------|--------|
|
||||
| 1 | v0.2.0 TUI Foundation | 1,350 | 38h | #2, #3, #10-18 |
|
||||
| 2 | v0.3.0 Chat Composer | 6,151 | - | #4, #5 |
|
||||
| 3 | v0.4.0 Approval & Nav | 2,236 | - | #6, #7 |
|
||||
| 4 | v1.0.0 Production | 3,400 | 64h | #8, #9, #19-28 |
|
||||
|
||||
**Total: ~13,137+ lines**
|
||||
|
||||
---
|
||||
|
||||
## Critical Path
|
||||
|
||||
```
|
||||
#19 → #20 → #22 → #24 → #25 → #26 → #27 → #28
|
||||
│ │
|
||||
API Tools
|
||||
```
|
||||
|
||||
**Critical Path Duration: ~42h**
|
||||
|
||||
---
|
||||
|
||||
## Dependencies Matrix
|
||||
|
||||
| Task | Depends On | Blocks |
|
||||
|------|------------|--------|
|
||||
| #10 | - | #11 |
|
||||
| #11 | #10 | #12 |
|
||||
| #12 | #11 | #13 |
|
||||
| #13 | #12 | #14 |
|
||||
| #14 | #13 | - |
|
||||
| #15 | - | #16 |
|
||||
| #16 | #15 | #17 |
|
||||
| #17 | #16 | #18 |
|
||||
| #18 | #17 | - |
|
||||
| #19 | - | #20, #23 |
|
||||
| #20 | #19 | #21, #22 |
|
||||
| #21 | #20 | - |
|
||||
| #22 | #20 | - |
|
||||
| #23 | #19 | - |
|
||||
| #24 | - | #25, #26, #27 |
|
||||
| #25 | #24 | #26 |
|
||||
| #26 | #25 | #27 |
|
||||
| #27 | #26 | #28 |
|
||||
| #28 | #27 | - |
|
||||
|
||||
---
|
||||
|
||||
## Resource Allocation
|
||||
|
||||
### Parallel Streams (Max 3)
|
||||
|
||||
**Stream A**: TUI (#10-14, #15-18)
|
||||
**Stream B**: LLM (#19-23)
|
||||
**Stream C**: Tools (#24-28)
|
||||
|
||||
### Sprint Allocation
|
||||
|
||||
| Sprint | Stream A | Stream B | Stream C |
|
||||
|--------|----------|----------|----------|
|
||||
| 1 | #10, #15 | #19 | #24 |
|
||||
| 2 | #11, #16 | #20 | #25 |
|
||||
| 3 | #12, #17 | #21, #22 | #26 |
|
||||
| 4 | #13, #14, #18 | #23 | #27, #28 |
|
||||
|
||||
---
|
||||
|
||||
## Risk Register
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
|------|--------|------------|
|
||||
| API rate limits | High | Implement caching, retry logic |
|
||||
| Complex streaming | Medium | Incremental implementation |
|
||||
| Tool security | High | Sandboxing, input validation |
|
||||
| Performance | Medium | Benchmarking, profiling |
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-11-22
|
||||
118
docs/gantt-chart.puml
Normal file
118
docs/gantt-chart.puml
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
@startgantt miyabi-cli-gantt
|
||||
|
||||
title miyabi-cli-standalone - Project Timeline
|
||||
project starts 2025-11-25
|
||||
|
||||
' === Milestones ===
|
||||
[v0.2.0 TUI Foundation] happens at 2025-12-06
|
||||
[v1.0.0 Production Ready] happens at 2025-12-20
|
||||
|
||||
' === Sprint 1: Foundation ===
|
||||
[Sprint 1] as [S1] lasts 5 days and is colored in LightBlue
|
||||
[S1] starts 2025-11-25
|
||||
|
||||
-- Sprint 1: Foundation --
|
||||
|
||||
[#10 Core Structure] as [T10] lasts 1 day
|
||||
[T10] starts at [S1]'s start
|
||||
[T10] is colored in Coral
|
||||
|
||||
[#15 Diff Core] as [T15] lasts 1 day
|
||||
[T15] starts at [S1]'s start
|
||||
[T15] is colored in Orange
|
||||
|
||||
[#19 API Client] as [T19] lasts 2 days
|
||||
[T19] starts at [S1]'s start
|
||||
[T19] is colored in Coral
|
||||
|
||||
[#24 Tool Trait] as [T24] lasts 2 days
|
||||
[T24] starts at [S1]'s start
|
||||
[T24] is colored in Coral
|
||||
|
||||
' === Sprint 2: Parser & State ===
|
||||
[Sprint 2] as [S2] lasts 5 days and is colored in LightGreen
|
||||
[S2] starts at [S1]'s end
|
||||
|
||||
-- Sprint 2: Parser & State --
|
||||
|
||||
[#11 Incremental Parser] as [T11] lasts 2 days
|
||||
[T11] starts at [T10]'s end
|
||||
[T11] is colored in Coral
|
||||
|
||||
[#16 Diff Visualization] as [T16] lasts 2 days
|
||||
[T16] starts at [T15]'s end
|
||||
[T16] is colored in Orange
|
||||
|
||||
[#20 Conversation State] as [T20] lasts 2 days
|
||||
[T20] starts at [T19]'s end
|
||||
[T20] is colored in Coral
|
||||
|
||||
[#25 File Tools] as [T25] lasts 2 days
|
||||
[T25] starts at [T24]'s end
|
||||
[T25] is colored in Coral
|
||||
|
||||
' === Sprint 3: Integration ===
|
||||
[Sprint 3] as [S3] lasts 5 days and is colored in LightYellow
|
||||
[S3] starts at [S2]'s end
|
||||
|
||||
-- Sprint 3: Integration --
|
||||
|
||||
[#12 Code Blocks] as [T12] lasts 1 day
|
||||
[T12] starts at [T11]'s end
|
||||
[T12] is colored in Orange
|
||||
|
||||
[#17 Syntax in Diff] as [T17] lasts 1 day
|
||||
[T17] starts at [T16]'s end
|
||||
[T17] is colored in Yellow
|
||||
|
||||
[#21 Token Management] as [T21] lasts 2 days
|
||||
[T21] starts at [T20]'s end
|
||||
[T21] is colored in Orange
|
||||
|
||||
[#22 Tool Definitions] as [T22] lasts 2 days
|
||||
[T22] starts at [T20]'s end
|
||||
[T22] is colored in Coral
|
||||
|
||||
[#26 Bash Tool] as [T26] lasts 2 days
|
||||
[T26] starts at [T25]'s end
|
||||
[T26] is colored in Coral
|
||||
|
||||
' === Sprint 4: Polish ===
|
||||
[Sprint 4] as [S4] lasts 5 days and is colored in LightCoral
|
||||
[S4] starts at [S3]'s end
|
||||
|
||||
-- Sprint 4: Polish --
|
||||
|
||||
[#13 Cursor Tracking] as [T13] lasts 1 day
|
||||
[T13] starts at [T12]'s end
|
||||
[T13] is colored in Yellow
|
||||
|
||||
[#14 Tests] as [T14] lasts 1 day
|
||||
[T14] starts at [T13]'s end
|
||||
[T14] is colored in Yellow
|
||||
|
||||
[#18 Navigation] as [T18] lasts 1 day
|
||||
[T18] starts at [T17]'s end
|
||||
[T18] is colored in Yellow
|
||||
|
||||
[#23 Rate Limiting] as [T23] lasts 1 day
|
||||
[T23] starts at [T22]'s end
|
||||
[T23] is colored in Yellow
|
||||
|
||||
[#27 Search Tools] as [T27] lasts 2 days
|
||||
[T27] starts at [T26]'s end
|
||||
[T27] is colored in Orange
|
||||
|
||||
[#28 Result Formatting] as [T28] lasts 1 day
|
||||
[T28] starts at [T27]'s end
|
||||
[T28] is colored in Yellow
|
||||
|
||||
' Critical path highlighting
|
||||
[T19] is colored in Red
|
||||
[T20] is colored in Red
|
||||
[T22] is colored in Red
|
||||
[T24] is colored in Red
|
||||
[T25] is colored in Red
|
||||
[T26] is colored in Red
|
||||
|
||||
@endgantt
|
||||
104
docs/wbs-diagram.puml
Normal file
104
docs/wbs-diagram.puml
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
@startuml miyabi-cli-wbs
|
||||
|
||||
!theme plain
|
||||
title miyabi-cli-standalone - Critical Path & WBS
|
||||
|
||||
' Define colors
|
||||
!$critical = "#FF6B6B"
|
||||
!$high = "#FFA94D"
|
||||
!$medium = "#69DB7C"
|
||||
!$low = "#74C0FC"
|
||||
|
||||
' Milestones
|
||||
rectangle "v0.2.0\nTUI Foundation" as M1 #LightBlue
|
||||
rectangle "v0.3.0\nChat Composer" as M2 #LightGreen
|
||||
rectangle "v0.4.0\nApproval & Nav" as M3 #LightYellow
|
||||
rectangle "v1.0.0\nProduction" as M4 #LightCoral
|
||||
|
||||
' === Stream A: TUI Rendering ===
|
||||
package "Stream A: TUI Rendering" {
|
||||
rectangle "#10\nCore Structure" as T10 $critical
|
||||
rectangle "#11\nParser" as T11 $critical
|
||||
rectangle "#12\nCode Blocks" as T12 $high
|
||||
rectangle "#13\nCursor" as T13 $medium
|
||||
rectangle "#14\nTests" as T14 $medium
|
||||
|
||||
rectangle "#15\nDiff Core" as T15 $high
|
||||
rectangle "#16\nVisualization" as T16 $high
|
||||
rectangle "#17\nSyntax" as T17 $medium
|
||||
rectangle "#18\nNavigation" as T18 $medium
|
||||
}
|
||||
|
||||
' === Stream B: LLM Integration ===
|
||||
package "Stream B: LLM Integration" #FFE4E1 {
|
||||
rectangle "#19\nAPI Client" as T19 $critical
|
||||
rectangle "#20\nConversation" as T20 $critical
|
||||
rectangle "#21\nTokens" as T21 $high
|
||||
rectangle "#22\nTool Defs" as T22 $critical
|
||||
rectangle "#23\nRate Limit" as T23 $medium
|
||||
}
|
||||
|
||||
' === Stream C: Tool System ===
|
||||
package "Stream C: Tool System" #E8F5E9 {
|
||||
rectangle "#24\nTool Trait" as T24 $critical
|
||||
rectangle "#25\nFile Tools" as T25 $critical
|
||||
rectangle "#26\nBash Tool" as T26 $critical
|
||||
rectangle "#27\nSearch" as T27 $high
|
||||
rectangle "#28\nFormatting" as T28 $medium
|
||||
}
|
||||
|
||||
' Dependencies - Stream A
|
||||
T10 --> T11
|
||||
T11 --> T12
|
||||
T12 --> T13
|
||||
T13 --> T14
|
||||
|
||||
T15 --> T16
|
||||
T16 --> T17
|
||||
T17 --> T18
|
||||
|
||||
' Dependencies - Stream B (CRITICAL PATH)
|
||||
T19 --> T20 : **CRITICAL**
|
||||
T20 --> T21
|
||||
T20 --> T22 : **CRITICAL**
|
||||
T19 --> T23
|
||||
|
||||
' Dependencies - Stream C
|
||||
T24 --> T25 : **CRITICAL**
|
||||
T25 --> T26 : **CRITICAL**
|
||||
T26 --> T27
|
||||
T27 --> T28
|
||||
|
||||
' Cross-stream dependencies
|
||||
T22 ..> T24 : "requires"
|
||||
|
||||
' Milestone connections
|
||||
T14 --> M1
|
||||
T18 --> M1
|
||||
M1 --> M2
|
||||
M2 --> M3
|
||||
T23 --> M4
|
||||
T28 --> M4
|
||||
|
||||
' Legend
|
||||
legend right
|
||||
|= Color |= Priority |
|
||||
| <$critical> | P0 Critical |
|
||||
| <$high> | P1 High |
|
||||
| <$medium> | P2 Medium |
|
||||
| <$low> | P3 Low |
|
||||
endlegend
|
||||
|
||||
note bottom of T19
|
||||
**Critical Path Start**
|
||||
API Client is the foundation
|
||||
for all LLM functionality
|
||||
end note
|
||||
|
||||
note bottom of T28
|
||||
**Critical Path End**
|
||||
Result formatting completes
|
||||
the tool system
|
||||
end note
|
||||
|
||||
@enduml
|
||||
Loading…
Add table
Add a link
Reference in a new issue